Commit 77acfa29 authored by Al Viro's avatar Al Viro

[readdir] convert ceph

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 23db8620
...@@ -111,11 +111,10 @@ static unsigned fpos_off(loff_t p) ...@@ -111,11 +111,10 @@ static unsigned fpos_off(loff_t p)
* defined IFF we hold CEPH_CAP_FILE_SHARED (which will be revoked by * defined IFF we hold CEPH_CAP_FILE_SHARED (which will be revoked by
* the MDS if/when the directory is modified). * the MDS if/when the directory is modified).
*/ */
static int __dcache_readdir(struct file *filp, static int __dcache_readdir(struct file *file, struct dir_context *ctx)
void *dirent, filldir_t filldir)
{ {
struct ceph_file_info *fi = filp->private_data; struct ceph_file_info *fi = file->private_data;
struct dentry *parent = filp->f_dentry; struct dentry *parent = file->f_dentry;
struct inode *dir = parent->d_inode; struct inode *dir = parent->d_inode;
struct list_head *p; struct list_head *p;
struct dentry *dentry, *last; struct dentry *dentry, *last;
...@@ -126,14 +125,14 @@ static int __dcache_readdir(struct file *filp, ...@@ -126,14 +125,14 @@ static int __dcache_readdir(struct file *filp,
last = fi->dentry; last = fi->dentry;
fi->dentry = NULL; fi->dentry = NULL;
dout("__dcache_readdir %p at %llu (last %p)\n", dir, filp->f_pos, dout("__dcache_readdir %p at %llu (last %p)\n", dir, ctx->pos,
last); last);
spin_lock(&parent->d_lock); spin_lock(&parent->d_lock);
/* start at beginning? */ /* start at beginning? */
if (filp->f_pos == 2 || last == NULL || if (ctx->pos == 2 || last == NULL ||
filp->f_pos < ceph_dentry(last)->offset) { ctx->pos < ceph_dentry(last)->offset) {
if (list_empty(&parent->d_subdirs)) if (list_empty(&parent->d_subdirs))
goto out_unlock; goto out_unlock;
p = parent->d_subdirs.prev; p = parent->d_subdirs.prev;
...@@ -157,11 +156,11 @@ static int __dcache_readdir(struct file *filp, ...@@ -157,11 +156,11 @@ static int __dcache_readdir(struct file *filp,
if (!d_unhashed(dentry) && dentry->d_inode && if (!d_unhashed(dentry) && dentry->d_inode &&
ceph_snap(dentry->d_inode) != CEPH_SNAPDIR && ceph_snap(dentry->d_inode) != CEPH_SNAPDIR &&
ceph_ino(dentry->d_inode) != CEPH_INO_CEPH && ceph_ino(dentry->d_inode) != CEPH_INO_CEPH &&
filp->f_pos <= di->offset) ctx->pos <= di->offset)
break; break;
dout(" skipping %p %.*s at %llu (%llu)%s%s\n", dentry, dout(" skipping %p %.*s at %llu (%llu)%s%s\n", dentry,
dentry->d_name.len, dentry->d_name.name, di->offset, dentry->d_name.len, dentry->d_name.name, di->offset,
filp->f_pos, d_unhashed(dentry) ? " unhashed" : "", ctx->pos, d_unhashed(dentry) ? " unhashed" : "",
!dentry->d_inode ? " null" : ""); !dentry->d_inode ? " null" : "");
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
p = p->prev; p = p->prev;
...@@ -173,29 +172,27 @@ static int __dcache_readdir(struct file *filp, ...@@ -173,29 +172,27 @@ static int __dcache_readdir(struct file *filp,
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
spin_unlock(&parent->d_lock); spin_unlock(&parent->d_lock);
dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, filp->f_pos, dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, ctx->pos,
dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
filp->f_pos = di->offset; ctx->pos = di->offset;
err = filldir(dirent, dentry->d_name.name, if (!dir_emit(ctx, dentry->d_name.name,
dentry->d_name.len, di->offset, dentry->d_name.len,
ceph_translate_ino(dentry->d_sb, dentry->d_inode->i_ino), ceph_translate_ino(dentry->d_sb, dentry->d_inode->i_ino),
dentry->d_inode->i_mode >> 12); dentry->d_inode->i_mode >> 12)) {
if (last) { if (last) {
if (err < 0) {
/* remember our position */ /* remember our position */
fi->dentry = last; fi->dentry = last;
fi->next_offset = di->offset; fi->next_offset = di->offset;
} else {
dput(last);
} }
dput(dentry);
return 0;
} }
last = dentry;
if (err < 0) if (last)
goto out; dput(last);
last = dentry;
filp->f_pos++; ctx->pos++;
/* make sure a dentry wasn't dropped while we didn't have parent lock */ /* make sure a dentry wasn't dropped while we didn't have parent lock */
if (!ceph_dir_is_complete(dir)) { if (!ceph_dir_is_complete(dir)) {
...@@ -235,59 +232,59 @@ static int note_last_dentry(struct ceph_file_info *fi, const char *name, ...@@ -235,59 +232,59 @@ static int note_last_dentry(struct ceph_file_info *fi, const char *name,
return 0; return 0;
} }
static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) static int ceph_readdir(struct file *file, struct dir_context *ctx)
{ {
struct ceph_file_info *fi = filp->private_data; struct ceph_file_info *fi = file->private_data;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_inode_to_client(inode); struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
struct ceph_mds_client *mdsc = fsc->mdsc; struct ceph_mds_client *mdsc = fsc->mdsc;
unsigned frag = fpos_frag(filp->f_pos); unsigned frag = fpos_frag(ctx->pos);
int off = fpos_off(filp->f_pos); int off = fpos_off(ctx->pos);
int err; int err;
u32 ftype; u32 ftype;
struct ceph_mds_reply_info_parsed *rinfo; struct ceph_mds_reply_info_parsed *rinfo;
const int max_entries = fsc->mount_options->max_readdir; const int max_entries = fsc->mount_options->max_readdir;
const int max_bytes = fsc->mount_options->max_readdir_bytes; const int max_bytes = fsc->mount_options->max_readdir_bytes;
dout("readdir %p filp %p frag %u off %u\n", inode, filp, frag, off); dout("readdir %p file %p frag %u off %u\n", inode, file, frag, off);
if (fi->flags & CEPH_F_ATEND) if (fi->flags & CEPH_F_ATEND)
return 0; return 0;
/* always start with . and .. */ /* always start with . and .. */
if (filp->f_pos == 0) { if (ctx->pos == 0) {
/* note dir version at start of readdir so we can tell /* note dir version at start of readdir so we can tell
* if any dentries get dropped */ * if any dentries get dropped */
fi->dir_release_count = atomic_read(&ci->i_release_count); fi->dir_release_count = atomic_read(&ci->i_release_count);
dout("readdir off 0 -> '.'\n"); dout("readdir off 0 -> '.'\n");
if (filldir(dirent, ".", 1, ceph_make_fpos(0, 0), if (!dir_emit(ctx, ".", 1,
ceph_translate_ino(inode->i_sb, inode->i_ino), ceph_translate_ino(inode->i_sb, inode->i_ino),
inode->i_mode >> 12) < 0) inode->i_mode >> 12))
return 0; return 0;
filp->f_pos = 1; ctx->pos = 1;
off = 1; off = 1;
} }
if (filp->f_pos == 1) { if (ctx->pos == 1) {
ino_t ino = parent_ino(filp->f_dentry); ino_t ino = parent_ino(file->f_dentry);
dout("readdir off 1 -> '..'\n"); dout("readdir off 1 -> '..'\n");
if (filldir(dirent, "..", 2, ceph_make_fpos(0, 1), if (!dir_emit(ctx, "..", 2,
ceph_translate_ino(inode->i_sb, ino), ceph_translate_ino(inode->i_sb, ino),
inode->i_mode >> 12) < 0) inode->i_mode >> 12))
return 0; return 0;
filp->f_pos = 2; ctx->pos = 2;
off = 2; off = 2;
} }
/* can we use the dcache? */ /* can we use the dcache? */
spin_lock(&ci->i_ceph_lock); spin_lock(&ci->i_ceph_lock);
if ((filp->f_pos == 2 || fi->dentry) && if ((ctx->pos == 2 || fi->dentry) &&
!ceph_test_mount_opt(fsc, NOASYNCREADDIR) && !ceph_test_mount_opt(fsc, NOASYNCREADDIR) &&
ceph_snap(inode) != CEPH_SNAPDIR && ceph_snap(inode) != CEPH_SNAPDIR &&
__ceph_dir_is_complete(ci) && __ceph_dir_is_complete(ci) &&
__ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) { __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) {
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
err = __dcache_readdir(filp, dirent, filldir); err = __dcache_readdir(file, ctx);
if (err != -EAGAIN) if (err != -EAGAIN)
return err; return err;
} else { } else {
...@@ -327,7 +324,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -327,7 +324,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
return PTR_ERR(req); return PTR_ERR(req);
req->r_inode = inode; req->r_inode = inode;
ihold(inode); ihold(inode);
req->r_dentry = dget(filp->f_dentry); req->r_dentry = dget(file->f_dentry);
/* hints to request -> mds selection code */ /* hints to request -> mds selection code */
req->r_direct_mode = USE_AUTH_MDS; req->r_direct_mode = USE_AUTH_MDS;
req->r_direct_hash = ceph_frag_value(frag); req->r_direct_hash = ceph_frag_value(frag);
...@@ -379,15 +376,16 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -379,15 +376,16 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
rinfo = &fi->last_readdir->r_reply_info; rinfo = &fi->last_readdir->r_reply_info;
dout("readdir frag %x num %d off %d chunkoff %d\n", frag, dout("readdir frag %x num %d off %d chunkoff %d\n", frag,
rinfo->dir_nr, off, fi->offset); rinfo->dir_nr, off, fi->offset);
ctx->pos = ceph_make_fpos(frag, off);
while (off >= fi->offset && off - fi->offset < rinfo->dir_nr) { while (off >= fi->offset && off - fi->offset < rinfo->dir_nr) {
u64 pos = ceph_make_fpos(frag, off);
struct ceph_mds_reply_inode *in = struct ceph_mds_reply_inode *in =
rinfo->dir_in[off - fi->offset].in; rinfo->dir_in[off - fi->offset].in;
struct ceph_vino vino; struct ceph_vino vino;
ino_t ino; ino_t ino;
dout("readdir off %d (%d/%d) -> %lld '%.*s' %p\n", dout("readdir off %d (%d/%d) -> %lld '%.*s' %p\n",
off, off - fi->offset, rinfo->dir_nr, pos, off, off - fi->offset, rinfo->dir_nr, ctx->pos,
rinfo->dir_dname_len[off - fi->offset], rinfo->dir_dname_len[off - fi->offset],
rinfo->dir_dname[off - fi->offset], in); rinfo->dir_dname[off - fi->offset], in);
BUG_ON(!in); BUG_ON(!in);
...@@ -395,16 +393,15 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -395,16 +393,15 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
vino.ino = le64_to_cpu(in->ino); vino.ino = le64_to_cpu(in->ino);
vino.snap = le64_to_cpu(in->snapid); vino.snap = le64_to_cpu(in->snapid);
ino = ceph_vino_to_ino(vino); ino = ceph_vino_to_ino(vino);
if (filldir(dirent, if (!dir_emit(ctx,
rinfo->dir_dname[off - fi->offset], rinfo->dir_dname[off - fi->offset],
rinfo->dir_dname_len[off - fi->offset], rinfo->dir_dname_len[off - fi->offset],
pos, ceph_translate_ino(inode->i_sb, ino), ftype)) {
ceph_translate_ino(inode->i_sb, ino), ftype) < 0) {
dout("filldir stopping us...\n"); dout("filldir stopping us...\n");
return 0; return 0;
} }
off++; off++;
filp->f_pos = pos + 1; ctx->pos++;
} }
if (fi->last_name) { if (fi->last_name) {
...@@ -417,7 +414,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -417,7 +414,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (!ceph_frag_is_rightmost(frag)) { if (!ceph_frag_is_rightmost(frag)) {
frag = ceph_frag_next(frag); frag = ceph_frag_next(frag);
off = 0; off = 0;
filp->f_pos = ceph_make_fpos(frag, off); ctx->pos = ceph_make_fpos(frag, off);
dout("readdir next frag is %x\n", frag); dout("readdir next frag is %x\n", frag);
goto more; goto more;
} }
...@@ -432,11 +429,11 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -432,11 +429,11 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (atomic_read(&ci->i_release_count) == fi->dir_release_count) { if (atomic_read(&ci->i_release_count) == fi->dir_release_count) {
dout(" marking %p complete\n", inode); dout(" marking %p complete\n", inode);
__ceph_dir_set_complete(ci, fi->dir_release_count); __ceph_dir_set_complete(ci, fi->dir_release_count);
ci->i_max_offset = filp->f_pos; ci->i_max_offset = ctx->pos;
} }
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
dout("readdir %p filp %p done.\n", inode, filp); dout("readdir %p file %p done.\n", inode, file);
return 0; return 0;
} }
...@@ -1268,7 +1265,7 @@ unsigned ceph_dentry_hash(struct inode *dir, struct dentry *dn) ...@@ -1268,7 +1265,7 @@ unsigned ceph_dentry_hash(struct inode *dir, struct dentry *dn)
const struct file_operations ceph_dir_fops = { const struct file_operations ceph_dir_fops = {
.read = ceph_read_dir, .read = ceph_read_dir,
.readdir = ceph_readdir, .iterate = ceph_readdir,
.llseek = ceph_dir_llseek, .llseek = ceph_dir_llseek,
.open = ceph_open, .open = ceph_open,
.release = ceph_release, .release = ceph_release,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment