[readdir] convert ntfs

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2013-05-17 21:22:31 -04:00
parent bfee7169c0
commit 956ce2083c

View File

@ -1004,13 +1004,11 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
/** /**
* ntfs_filldir - ntfs specific filldir method * ntfs_filldir - ntfs specific filldir method
* @vol: current ntfs volume * @vol: current ntfs volume
* @fpos: position in the directory
* @ndir: ntfs inode of current directory * @ndir: ntfs inode of current directory
* @ia_page: page in which the index allocation buffer @ie is in resides * @ia_page: page in which the index allocation buffer @ie is in resides
* @ie: current index entry * @ie: current index entry
* @name: buffer to use for the converted name * @name: buffer to use for the converted name
* @dirent: vfs filldir callback context * @actor: what to feed the entries to
* @filldir: vfs filldir callback
* *
* Convert the Unicode @name to the loaded NLS and pass it to the @filldir * Convert the Unicode @name to the loaded NLS and pass it to the @filldir
* callback. * callback.
@ -1024,12 +1022,12 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
* retake the lock if we are returning a non-zero value as ntfs_readdir() * retake the lock if we are returning a non-zero value as ntfs_readdir()
* would need to drop the lock immediately anyway. * would need to drop the lock immediately anyway.
*/ */
static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos, static inline int ntfs_filldir(ntfs_volume *vol,
ntfs_inode *ndir, struct page *ia_page, INDEX_ENTRY *ie, ntfs_inode *ndir, struct page *ia_page, INDEX_ENTRY *ie,
u8 *name, void *dirent, filldir_t filldir) u8 *name, struct dir_context *actor)
{ {
unsigned long mref; unsigned long mref;
int name_len, rc; int name_len;
unsigned dt_type; unsigned dt_type;
FILE_NAME_TYPE_FLAGS name_type; FILE_NAME_TYPE_FLAGS name_type;
@ -1068,13 +1066,14 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos,
if (ia_page) if (ia_page)
unlock_page(ia_page); unlock_page(ia_page);
ntfs_debug("Calling filldir for %s with len %i, fpos 0x%llx, inode " ntfs_debug("Calling filldir for %s with len %i, fpos 0x%llx, inode "
"0x%lx, DT_%s.", name, name_len, fpos, mref, "0x%lx, DT_%s.", name, name_len, actor->pos, mref,
dt_type == DT_DIR ? "DIR" : "REG"); dt_type == DT_DIR ? "DIR" : "REG");
rc = filldir(dirent, name, name_len, fpos, mref, dt_type); if (!dir_emit(actor, name, name_len, mref, dt_type))
return 1;
/* Relock the page but not if we are aborting ->readdir. */ /* Relock the page but not if we are aborting ->readdir. */
if (!rc && ia_page) if (ia_page)
lock_page(ia_page); lock_page(ia_page);
return rc; return 0;
} }
/* /*
@ -1097,11 +1096,11 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos,
* removes them again after the write is complete after which it * removes them again after the write is complete after which it
* unlocks the page. * unlocks the page.
*/ */
static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) static int ntfs_readdir(struct file *file, struct dir_context *actor)
{ {
s64 ia_pos, ia_start, prev_ia_pos, bmp_pos; s64 ia_pos, ia_start, prev_ia_pos, bmp_pos;
loff_t fpos, i_size; loff_t i_size;
struct inode *bmp_vi, *vdir = file_inode(filp); struct inode *bmp_vi, *vdir = file_inode(file);
struct super_block *sb = vdir->i_sb; struct super_block *sb = vdir->i_sb;
ntfs_inode *ndir = NTFS_I(vdir); ntfs_inode *ndir = NTFS_I(vdir);
ntfs_volume *vol = NTFS_SB(sb); ntfs_volume *vol = NTFS_SB(sb);
@ -1116,33 +1115,16 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
u8 *kaddr, *bmp, *index_end; u8 *kaddr, *bmp, *index_end;
ntfs_attr_search_ctx *ctx; ntfs_attr_search_ctx *ctx;
fpos = filp->f_pos;
ntfs_debug("Entering for inode 0x%lx, fpos 0x%llx.", ntfs_debug("Entering for inode 0x%lx, fpos 0x%llx.",
vdir->i_ino, fpos); vdir->i_ino, actor->pos);
rc = err = 0; rc = err = 0;
/* Are we at end of dir yet? */ /* Are we at end of dir yet? */
i_size = i_size_read(vdir); i_size = i_size_read(vdir);
if (fpos >= i_size + vol->mft_record_size) if (actor->pos >= i_size + vol->mft_record_size)
goto done; return 0;
/* Emulate . and .. for all directories. */ /* Emulate . and .. for all directories. */
if (!fpos) { if (!dir_emit_dots(file, actor))
ntfs_debug("Calling filldir for . with len 1, fpos 0x0, " return 0;
"inode 0x%lx, DT_DIR.", vdir->i_ino);
rc = filldir(dirent, ".", 1, fpos, vdir->i_ino, DT_DIR);
if (rc)
goto done;
fpos++;
}
if (fpos == 1) {
ntfs_debug("Calling filldir for .. with len 2, fpos 0x1, "
"inode 0x%lx, DT_DIR.",
(unsigned long)parent_ino(filp->f_path.dentry));
rc = filldir(dirent, "..", 2, fpos,
parent_ino(filp->f_path.dentry), DT_DIR);
if (rc)
goto done;
fpos++;
}
m = NULL; m = NULL;
ctx = NULL; ctx = NULL;
/* /*
@ -1155,7 +1137,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto err_out; goto err_out;
} }
/* Are we jumping straight into the index allocation attribute? */ /* Are we jumping straight into the index allocation attribute? */
if (fpos >= vol->mft_record_size) if (actor->pos >= vol->mft_record_size)
goto skip_index_root; goto skip_index_root;
/* Get hold of the mft record for the directory. */ /* Get hold of the mft record for the directory. */
m = map_mft_record(ndir); m = map_mft_record(ndir);
@ -1170,7 +1152,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto err_out; goto err_out;
} }
/* Get the offset into the index root attribute. */ /* Get the offset into the index root attribute. */
ir_pos = (s64)fpos; ir_pos = (s64)actor->pos;
/* Find the index root attribute in the mft record. */ /* Find the index root attribute in the mft record. */
err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL,
0, ctx); 0, ctx);
@ -1226,10 +1208,9 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (ir_pos > (u8*)ie - (u8*)ir) if (ir_pos > (u8*)ie - (u8*)ir)
continue; continue;
/* Advance the position even if going to skip the entry. */ /* Advance the position even if going to skip the entry. */
fpos = (u8*)ie - (u8*)ir; actor->pos = (u8*)ie - (u8*)ir;
/* Submit the name to the filldir callback. */ /* Submit the name to the filldir callback. */
rc = ntfs_filldir(vol, fpos, ndir, NULL, ie, name, dirent, rc = ntfs_filldir(vol, ndir, NULL, ie, name, actor);
filldir);
if (rc) { if (rc) {
kfree(ir); kfree(ir);
goto abort; goto abort;
@ -1242,12 +1223,12 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (!NInoIndexAllocPresent(ndir)) if (!NInoIndexAllocPresent(ndir))
goto EOD; goto EOD;
/* Advance fpos to the beginning of the index allocation. */ /* Advance fpos to the beginning of the index allocation. */
fpos = vol->mft_record_size; actor->pos = vol->mft_record_size;
skip_index_root: skip_index_root:
kaddr = NULL; kaddr = NULL;
prev_ia_pos = -1LL; prev_ia_pos = -1LL;
/* Get the offset into the index allocation attribute. */ /* Get the offset into the index allocation attribute. */
ia_pos = (s64)fpos - vol->mft_record_size; ia_pos = (s64)actor->pos - vol->mft_record_size;
ia_mapping = vdir->i_mapping; ia_mapping = vdir->i_mapping;
ntfs_debug("Inode 0x%lx, getting index bitmap.", vdir->i_ino); ntfs_debug("Inode 0x%lx, getting index bitmap.", vdir->i_ino);
bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4); bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4);
@ -1409,7 +1390,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (ia_pos - ia_start > (u8*)ie - (u8*)ia) if (ia_pos - ia_start > (u8*)ie - (u8*)ia)
continue; continue;
/* Advance the position even if going to skip the entry. */ /* Advance the position even if going to skip the entry. */
fpos = (u8*)ie - (u8*)ia + actor->pos = (u8*)ie - (u8*)ia +
(sle64_to_cpu(ia->index_block_vcn) << (sle64_to_cpu(ia->index_block_vcn) <<
ndir->itype.index.vcn_size_bits) + ndir->itype.index.vcn_size_bits) +
vol->mft_record_size; vol->mft_record_size;
@ -1419,8 +1400,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
* before returning, unless a non-zero value is returned in * before returning, unless a non-zero value is returned in
* which case the page is left unlocked. * which case the page is left unlocked.
*/ */
rc = ntfs_filldir(vol, fpos, ndir, ia_page, ie, name, dirent, rc = ntfs_filldir(vol, ndir, ia_page, ie, name, actor);
filldir);
if (rc) { if (rc) {
/* @ia_page is already unlocked in this case. */ /* @ia_page is already unlocked in this case. */
ntfs_unmap_page(ia_page); ntfs_unmap_page(ia_page);
@ -1439,18 +1419,9 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
iput(bmp_vi); iput(bmp_vi);
EOD: EOD:
/* We are finished, set fpos to EOD. */ /* We are finished, set fpos to EOD. */
fpos = i_size + vol->mft_record_size; actor->pos = i_size + vol->mft_record_size;
abort: abort:
kfree(name); kfree(name);
done:
#ifdef DEBUG
if (!rc)
ntfs_debug("EOD, fpos 0x%llx, returning 0.", fpos);
else
ntfs_debug("filldir returned %i, fpos 0x%llx, returning 0.",
rc, fpos);
#endif
filp->f_pos = fpos;
return 0; return 0;
err_out: err_out:
if (bmp_page) { if (bmp_page) {
@ -1471,7 +1442,6 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (!err) if (!err)
err = -EIO; err = -EIO;
ntfs_debug("Failed. Returning error code %i.", -err); ntfs_debug("Failed. Returning error code %i.", -err);
filp->f_pos = fpos;
return err; return err;
} }
@ -1571,7 +1541,7 @@ static int ntfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
const struct file_operations ntfs_dir_ops = { const struct file_operations ntfs_dir_ops = {
.llseek = generic_file_llseek, /* Seek inside directory. */ .llseek = generic_file_llseek, /* Seek inside directory. */
.read = generic_read_dir, /* Return -EISDIR. */ .read = generic_read_dir, /* Return -EISDIR. */
.readdir = ntfs_readdir, /* Read directory contents. */ .iterate = ntfs_readdir, /* Read directory contents. */
#ifdef NTFS_RW #ifdef NTFS_RW
.fsync = ntfs_dir_fsync, /* Sync a directory to disk. */ .fsync = ntfs_dir_fsync, /* Sync a directory to disk. */
/*.aio_fsync = ,*/ /* Sync all outstanding async /*.aio_fsync = ,*/ /* Sync all outstanding async