forked from Minki/linux
[readdir] convert ceph
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
23db862060
commit
77acfa29e1
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user