[XFS] Put the correct offset in dirent d_off

The recent filldir regression fix was not putting the correct d_off in
each dirent. This was resulting in incorrect cookies being passed to dmapi
ioctls and the wrong offset appearing in the dirents. readdir was
unaffected as the filp->f_pos was being updated with the correct offset
and this was being written into the last dirent in each buffer. Fix the
XFS code to do the right thing.

SGI-PV: 973746
SGI-Modid: xfs-linux-melb:xfs-kern:30240a

Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>

+8 -13
+2 -2
fs/xfs/linux-2.6/xfs_file.c
··· 356 357 reclen = sizeof(struct hack_dirent) + de->namlen; 358 size -= reclen; 359 - curr_offset = de->offset /* & 0x7fffffff */; 360 de = (struct hack_dirent *)((char *)de + reclen); 361 } 362 } 363 364 done: 365 - if (!error) { 366 if (size == 0) 367 filp->f_pos = offset & 0x7fffffff; 368 else if (de)
··· 356 357 reclen = sizeof(struct hack_dirent) + de->namlen; 358 size -= reclen; 359 de = (struct hack_dirent *)((char *)de + reclen); 360 + curr_offset = de->offset /* & 0x7fffffff */; 361 } 362 } 363 364 done: 365 + if (!error) { 366 if (size == 0) 367 filp->f_pos = offset & 0x7fffffff; 368 else if (de)
+2 -4
fs/xfs/xfs_dir2_block.c
··· 508 continue; 509 510 cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, 511 - ptr - (char *)block); 512 ino = be64_to_cpu(dep->inumber); 513 #if XFS_BIG_INUMS 514 ino += mp->m_inoadd; ··· 519 */ 520 if (filldir(dirent, dep->name, dep->namelen, cook, 521 ino, DT_UNKNOWN)) { 522 - *offset = xfs_dir2_db_off_to_dataptr(mp, 523 - mp->m_dirdatablk, 524 - (char *)dep - (char *)block); 525 xfs_da_brelse(NULL, bp); 526 return 0; 527 }
··· 508 continue; 509 510 cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, 511 + (char *)dep - (char *)block); 512 ino = be64_to_cpu(dep->inumber); 513 #if XFS_BIG_INUMS 514 ino += mp->m_inoadd; ··· 519 */ 520 if (filldir(dirent, dep->name, dep->namelen, cook, 521 ino, DT_UNKNOWN)) { 522 + *offset = cook; 523 xfs_da_brelse(NULL, bp); 524 return 0; 525 }
+1 -1
fs/xfs/xfs_dir2_leaf.c
··· 1091 * Won't fit. Return to caller. 1092 */ 1093 if (filldir(dirent, dep->name, dep->namelen, 1094 - xfs_dir2_byte_to_dataptr(mp, curoff + length), 1095 ino, DT_UNKNOWN)) 1096 break; 1097
··· 1091 * Won't fit. Return to caller. 1092 */ 1093 if (filldir(dirent, dep->name, dep->namelen, 1094 + xfs_dir2_byte_to_dataptr(mp, curoff), 1095 ino, DT_UNKNOWN)) 1096 break; 1097
+3 -6
fs/xfs/xfs_dir2_sf.c
··· 752 #if XFS_BIG_INUMS 753 ino += mp->m_inoadd; 754 #endif 755 - if (filldir(dirent, ".", 1, dotdot_offset, ino, DT_DIR)) { 756 *offset = dot_offset; 757 return 0; 758 } ··· 762 * Put .. entry unless we're starting past it. 763 */ 764 if (*offset <= dotdot_offset) { 765 - off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, 766 - XFS_DIR2_DATA_FIRST_OFFSET); 767 ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent); 768 #if XFS_BIG_INUMS 769 ino += mp->m_inoadd; 770 #endif 771 - if (filldir(dirent, "..", 2, off, ino, DT_DIR)) { 772 *offset = dotdot_offset; 773 return 0; 774 } ··· 791 #endif 792 793 if (filldir(dirent, sfep->name, sfep->namelen, 794 - off + xfs_dir2_data_entsize(sfep->namelen), 795 - ino, DT_UNKNOWN)) { 796 *offset = off; 797 return 0; 798 }
··· 752 #if XFS_BIG_INUMS 753 ino += mp->m_inoadd; 754 #endif 755 + if (filldir(dirent, ".", 1, dot_offset, ino, DT_DIR)) { 756 *offset = dot_offset; 757 return 0; 758 } ··· 762 * Put .. entry unless we're starting past it. 763 */ 764 if (*offset <= dotdot_offset) { 765 ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent); 766 #if XFS_BIG_INUMS 767 ino += mp->m_inoadd; 768 #endif 769 + if (filldir(dirent, "..", 2, dotdot_offset, ino, DT_DIR)) { 770 *offset = dotdot_offset; 771 return 0; 772 } ··· 793 #endif 794 795 if (filldir(dirent, sfep->name, sfep->namelen, 796 + off, ino, DT_UNKNOWN)) { 797 *offset = off; 798 return 0; 799 }