[readdir] convert ceph

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2013-05-17 16:52:26 -04:00
parent 23db862060
commit 77acfa29e1
1 changed files with 48 additions and 51 deletions

View File

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