diff options
Diffstat (limited to 'fs/ntfs/dir.c')
-rw-r--r-- | fs/ntfs/dir.c | 84 |
1 files changed, 27 insertions, 57 deletions
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index aa411c3f20e9..9e38dafa3bc7 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c | |||
@@ -1004,13 +1004,11 @@ dir_err_out: | |||
1004 | /** | 1004 | /** |
1005 | * ntfs_filldir - ntfs specific filldir method | 1005 | * ntfs_filldir - ntfs specific filldir method |
1006 | * @vol: current ntfs volume | 1006 | * @vol: current ntfs volume |
1007 | * @fpos: position in the directory | ||
1008 | * @ndir: ntfs inode of current directory | 1007 | * @ndir: ntfs inode of current directory |
1009 | * @ia_page: page in which the index allocation buffer @ie is in resides | 1008 | * @ia_page: page in which the index allocation buffer @ie is in resides |
1010 | * @ie: current index entry | 1009 | * @ie: current index entry |
1011 | * @name: buffer to use for the converted name | 1010 | * @name: buffer to use for the converted name |
1012 | * @dirent: vfs filldir callback context | 1011 | * @actor: what to feed the entries to |
1013 | * @filldir: vfs filldir callback | ||
1014 | * | 1012 | * |
1015 | * Convert the Unicode @name to the loaded NLS and pass it to the @filldir | 1013 | * Convert the Unicode @name to the loaded NLS and pass it to the @filldir |
1016 | * callback. | 1014 | * callback. |
@@ -1024,12 +1022,12 @@ dir_err_out: | |||
1024 | * retake the lock if we are returning a non-zero value as ntfs_readdir() | 1022 | * retake the lock if we are returning a non-zero value as ntfs_readdir() |
1025 | * would need to drop the lock immediately anyway. | 1023 | * would need to drop the lock immediately anyway. |
1026 | */ | 1024 | */ |
1027 | static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos, | 1025 | static inline int ntfs_filldir(ntfs_volume *vol, |
1028 | ntfs_inode *ndir, struct page *ia_page, INDEX_ENTRY *ie, | 1026 | ntfs_inode *ndir, struct page *ia_page, INDEX_ENTRY *ie, |
1029 | u8 *name, void *dirent, filldir_t filldir) | 1027 | u8 *name, struct dir_context *actor) |
1030 | { | 1028 | { |
1031 | unsigned long mref; | 1029 | unsigned long mref; |
1032 | int name_len, rc; | 1030 | int name_len; |
1033 | unsigned dt_type; | 1031 | unsigned dt_type; |
1034 | FILE_NAME_TYPE_FLAGS name_type; | 1032 | FILE_NAME_TYPE_FLAGS name_type; |
1035 | 1033 | ||
@@ -1068,13 +1066,14 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos, | |||
1068 | if (ia_page) | 1066 | if (ia_page) |
1069 | unlock_page(ia_page); | 1067 | unlock_page(ia_page); |
1070 | ntfs_debug("Calling filldir for %s with len %i, fpos 0x%llx, inode " | 1068 | ntfs_debug("Calling filldir for %s with len %i, fpos 0x%llx, inode " |
1071 | "0x%lx, DT_%s.", name, name_len, fpos, mref, | 1069 | "0x%lx, DT_%s.", name, name_len, actor->pos, mref, |
1072 | dt_type == DT_DIR ? "DIR" : "REG"); | 1070 | dt_type == DT_DIR ? "DIR" : "REG"); |
1073 | rc = filldir(dirent, name, name_len, fpos, mref, dt_type); | 1071 | if (!dir_emit(actor, name, name_len, mref, dt_type)) |
1072 | return 1; | ||
1074 | /* Relock the page but not if we are aborting ->readdir. */ | 1073 | /* Relock the page but not if we are aborting ->readdir. */ |
1075 | if (!rc && ia_page) | 1074 | if (ia_page) |
1076 | lock_page(ia_page); | 1075 | lock_page(ia_page); |
1077 | return rc; | 1076 | return 0; |
1078 | } | 1077 | } |
1079 | 1078 | ||
1080 | /* | 1079 | /* |
@@ -1097,11 +1096,11 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos, | |||
1097 | * removes them again after the write is complete after which it | 1096 | * removes them again after the write is complete after which it |
1098 | * unlocks the page. | 1097 | * unlocks the page. |
1099 | */ | 1098 | */ |
1100 | static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 1099 | static int ntfs_readdir(struct file *file, struct dir_context *actor) |
1101 | { | 1100 | { |
1102 | s64 ia_pos, ia_start, prev_ia_pos, bmp_pos; | 1101 | s64 ia_pos, ia_start, prev_ia_pos, bmp_pos; |
1103 | loff_t fpos, i_size; | 1102 | loff_t i_size; |
1104 | struct inode *bmp_vi, *vdir = file_inode(filp); | 1103 | struct inode *bmp_vi, *vdir = file_inode(file); |
1105 | struct super_block *sb = vdir->i_sb; | 1104 | struct super_block *sb = vdir->i_sb; |
1106 | ntfs_inode *ndir = NTFS_I(vdir); | 1105 | ntfs_inode *ndir = NTFS_I(vdir); |
1107 | ntfs_volume *vol = NTFS_SB(sb); | 1106 | ntfs_volume *vol = NTFS_SB(sb); |
@@ -1116,33 +1115,16 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1116 | u8 *kaddr, *bmp, *index_end; | 1115 | u8 *kaddr, *bmp, *index_end; |
1117 | ntfs_attr_search_ctx *ctx; | 1116 | ntfs_attr_search_ctx *ctx; |
1118 | 1117 | ||
1119 | fpos = filp->f_pos; | ||
1120 | ntfs_debug("Entering for inode 0x%lx, fpos 0x%llx.", | 1118 | ntfs_debug("Entering for inode 0x%lx, fpos 0x%llx.", |
1121 | vdir->i_ino, fpos); | 1119 | vdir->i_ino, actor->pos); |
1122 | rc = err = 0; | 1120 | rc = err = 0; |
1123 | /* Are we at end of dir yet? */ | 1121 | /* Are we at end of dir yet? */ |
1124 | i_size = i_size_read(vdir); | 1122 | i_size = i_size_read(vdir); |
1125 | if (fpos >= i_size + vol->mft_record_size) | 1123 | if (actor->pos >= i_size + vol->mft_record_size) |
1126 | goto done; | 1124 | return 0; |
1127 | /* Emulate . and .. for all directories. */ | 1125 | /* Emulate . and .. for all directories. */ |
1128 | if (!fpos) { | 1126 | if (!dir_emit_dots(file, actor)) |
1129 | ntfs_debug("Calling filldir for . with len 1, fpos 0x0, " | 1127 | return 0; |
1130 | "inode 0x%lx, DT_DIR.", vdir->i_ino); | ||
1131 | rc = filldir(dirent, ".", 1, fpos, vdir->i_ino, DT_DIR); | ||
1132 | if (rc) | ||
1133 | goto done; | ||
1134 | fpos++; | ||
1135 | } | ||
1136 | if (fpos == 1) { | ||
1137 | ntfs_debug("Calling filldir for .. with len 2, fpos 0x1, " | ||
1138 | "inode 0x%lx, DT_DIR.", | ||
1139 | (unsigned long)parent_ino(filp->f_path.dentry)); | ||
1140 | rc = filldir(dirent, "..", 2, fpos, | ||
1141 | parent_ino(filp->f_path.dentry), DT_DIR); | ||
1142 | if (rc) | ||
1143 | goto done; | ||
1144 | fpos++; | ||
1145 | } | ||
1146 | m = NULL; | 1128 | m = NULL; |
1147 | ctx = NULL; | 1129 | ctx = NULL; |
1148 | /* | 1130 | /* |
@@ -1155,7 +1137,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1155 | goto err_out; | 1137 | goto err_out; |
1156 | } | 1138 | } |
1157 | /* Are we jumping straight into the index allocation attribute? */ | 1139 | /* Are we jumping straight into the index allocation attribute? */ |
1158 | if (fpos >= vol->mft_record_size) | 1140 | if (actor->pos >= vol->mft_record_size) |
1159 | goto skip_index_root; | 1141 | goto skip_index_root; |
1160 | /* Get hold of the mft record for the directory. */ | 1142 | /* Get hold of the mft record for the directory. */ |
1161 | m = map_mft_record(ndir); | 1143 | m = map_mft_record(ndir); |
@@ -1170,7 +1152,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1170 | goto err_out; | 1152 | goto err_out; |
1171 | } | 1153 | } |
1172 | /* Get the offset into the index root attribute. */ | 1154 | /* Get the offset into the index root attribute. */ |
1173 | ir_pos = (s64)fpos; | 1155 | ir_pos = (s64)actor->pos; |
1174 | /* Find the index root attribute in the mft record. */ | 1156 | /* Find the index root attribute in the mft record. */ |
1175 | err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, | 1157 | err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, |
1176 | 0, ctx); | 1158 | 0, ctx); |
@@ -1226,10 +1208,9 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1226 | if (ir_pos > (u8*)ie - (u8*)ir) | 1208 | if (ir_pos > (u8*)ie - (u8*)ir) |
1227 | continue; | 1209 | continue; |
1228 | /* Advance the position even if going to skip the entry. */ | 1210 | /* Advance the position even if going to skip the entry. */ |
1229 | fpos = (u8*)ie - (u8*)ir; | 1211 | actor->pos = (u8*)ie - (u8*)ir; |
1230 | /* Submit the name to the filldir callback. */ | 1212 | /* Submit the name to the filldir callback. */ |
1231 | rc = ntfs_filldir(vol, fpos, ndir, NULL, ie, name, dirent, | 1213 | rc = ntfs_filldir(vol, ndir, NULL, ie, name, actor); |
1232 | filldir); | ||
1233 | if (rc) { | 1214 | if (rc) { |
1234 | kfree(ir); | 1215 | kfree(ir); |
1235 | goto abort; | 1216 | goto abort; |
@@ -1242,12 +1223,12 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1242 | if (!NInoIndexAllocPresent(ndir)) | 1223 | if (!NInoIndexAllocPresent(ndir)) |
1243 | goto EOD; | 1224 | goto EOD; |
1244 | /* Advance fpos to the beginning of the index allocation. */ | 1225 | /* Advance fpos to the beginning of the index allocation. */ |
1245 | fpos = vol->mft_record_size; | 1226 | actor->pos = vol->mft_record_size; |
1246 | skip_index_root: | 1227 | skip_index_root: |
1247 | kaddr = NULL; | 1228 | kaddr = NULL; |
1248 | prev_ia_pos = -1LL; | 1229 | prev_ia_pos = -1LL; |
1249 | /* Get the offset into the index allocation attribute. */ | 1230 | /* Get the offset into the index allocation attribute. */ |
1250 | ia_pos = (s64)fpos - vol->mft_record_size; | 1231 | ia_pos = (s64)actor->pos - vol->mft_record_size; |
1251 | ia_mapping = vdir->i_mapping; | 1232 | ia_mapping = vdir->i_mapping; |
1252 | ntfs_debug("Inode 0x%lx, getting index bitmap.", vdir->i_ino); | 1233 | ntfs_debug("Inode 0x%lx, getting index bitmap.", vdir->i_ino); |
1253 | bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4); | 1234 | bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4); |
@@ -1409,7 +1390,7 @@ find_next_index_buffer: | |||
1409 | if (ia_pos - ia_start > (u8*)ie - (u8*)ia) | 1390 | if (ia_pos - ia_start > (u8*)ie - (u8*)ia) |
1410 | continue; | 1391 | continue; |
1411 | /* Advance the position even if going to skip the entry. */ | 1392 | /* Advance the position even if going to skip the entry. */ |
1412 | fpos = (u8*)ie - (u8*)ia + | 1393 | actor->pos = (u8*)ie - (u8*)ia + |
1413 | (sle64_to_cpu(ia->index_block_vcn) << | 1394 | (sle64_to_cpu(ia->index_block_vcn) << |
1414 | ndir->itype.index.vcn_size_bits) + | 1395 | ndir->itype.index.vcn_size_bits) + |
1415 | vol->mft_record_size; | 1396 | vol->mft_record_size; |
@@ -1419,8 +1400,7 @@ find_next_index_buffer: | |||
1419 | * before returning, unless a non-zero value is returned in | 1400 | * before returning, unless a non-zero value is returned in |
1420 | * which case the page is left unlocked. | 1401 | * which case the page is left unlocked. |
1421 | */ | 1402 | */ |
1422 | rc = ntfs_filldir(vol, fpos, ndir, ia_page, ie, name, dirent, | 1403 | rc = ntfs_filldir(vol, ndir, ia_page, ie, name, actor); |
1423 | filldir); | ||
1424 | if (rc) { | 1404 | if (rc) { |
1425 | /* @ia_page is already unlocked in this case. */ | 1405 | /* @ia_page is already unlocked in this case. */ |
1426 | ntfs_unmap_page(ia_page); | 1406 | ntfs_unmap_page(ia_page); |
@@ -1439,18 +1419,9 @@ unm_EOD: | |||
1439 | iput(bmp_vi); | 1419 | iput(bmp_vi); |
1440 | EOD: | 1420 | EOD: |
1441 | /* We are finished, set fpos to EOD. */ | 1421 | /* We are finished, set fpos to EOD. */ |
1442 | fpos = i_size + vol->mft_record_size; | 1422 | actor->pos = i_size + vol->mft_record_size; |
1443 | abort: | 1423 | abort: |
1444 | kfree(name); | 1424 | kfree(name); |
1445 | done: | ||
1446 | #ifdef DEBUG | ||
1447 | if (!rc) | ||
1448 | ntfs_debug("EOD, fpos 0x%llx, returning 0.", fpos); | ||
1449 | else | ||
1450 | ntfs_debug("filldir returned %i, fpos 0x%llx, returning 0.", | ||
1451 | rc, fpos); | ||
1452 | #endif | ||
1453 | filp->f_pos = fpos; | ||
1454 | return 0; | 1425 | return 0; |
1455 | err_out: | 1426 | err_out: |
1456 | if (bmp_page) { | 1427 | if (bmp_page) { |
@@ -1471,7 +1442,6 @@ iput_err_out: | |||
1471 | if (!err) | 1442 | if (!err) |
1472 | err = -EIO; | 1443 | err = -EIO; |
1473 | ntfs_debug("Failed. Returning error code %i.", -err); | 1444 | ntfs_debug("Failed. Returning error code %i.", -err); |
1474 | filp->f_pos = fpos; | ||
1475 | return err; | 1445 | return err; |
1476 | } | 1446 | } |
1477 | 1447 | ||
@@ -1571,7 +1541,7 @@ static int ntfs_dir_fsync(struct file *filp, loff_t start, loff_t end, | |||
1571 | const struct file_operations ntfs_dir_ops = { | 1541 | const struct file_operations ntfs_dir_ops = { |
1572 | .llseek = generic_file_llseek, /* Seek inside directory. */ | 1542 | .llseek = generic_file_llseek, /* Seek inside directory. */ |
1573 | .read = generic_read_dir, /* Return -EISDIR. */ | 1543 | .read = generic_read_dir, /* Return -EISDIR. */ |
1574 | .readdir = ntfs_readdir, /* Read directory contents. */ | 1544 | .iterate = ntfs_readdir, /* Read directory contents. */ |
1575 | #ifdef NTFS_RW | 1545 | #ifdef NTFS_RW |
1576 | .fsync = ntfs_dir_fsync, /* Sync a directory to disk. */ | 1546 | .fsync = ntfs_dir_fsync, /* Sync a directory to disk. */ |
1577 | /*.aio_fsync = ,*/ /* Sync all outstanding async | 1547 | /*.aio_fsync = ,*/ /* Sync all outstanding async |