diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2014-03-01 18:11:45 +0400 |
---|---|---|
committer | Yan, Zheng <zheng.z.yan@intel.com> | 2014-04-03 06:33:53 +0400 |
commit | 9017c2ec78c730fb3ecd703d44e4a9061de2ba52 (patch) | |
tree | d0c15467898545ee127ad8f93d059f7d83503bd4 /fs/ceph/export.c | |
parent | 4f32b42dca660208c7556e13ebd84c510ad91840 (diff) | |
download | linux-9017c2ec78c730fb3ecd703d44e4a9061de2ba52.tar.xz |
ceph: add get_parent() NFS export callback
The callback uses LOOKUPPARENT MDS request to find parent.
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Reviewed-by: Sage Weil <sage@inktank.com>
Diffstat (limited to 'fs/ceph/export.c')
-rw-r--r-- | fs/ceph/export.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 976d3411d5ed..9c28b6abe885 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -121,6 +121,65 @@ static struct dentry *ceph_fh_to_dentry(struct super_block *sb, return __fh_to_dentry(sb, fh->ino); } +static struct dentry *__get_parent(struct super_block *sb, + struct dentry *child, u64 ino) +{ + struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; + struct ceph_mds_request *req; + struct inode *inode; + struct dentry *dentry; + int err; + + req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPPARENT, + USE_ANY_MDS); + if (IS_ERR(req)) + return ERR_CAST(req); + + if (child) { + req->r_inode = child->d_inode; + ihold(child->d_inode); + } else { + req->r_ino1 = (struct ceph_vino) { + .ino = ino, + .snap = CEPH_NOSNAP, + }; + } + req->r_num_caps = 1; + err = ceph_mdsc_do_request(mdsc, NULL, req); + inode = req->r_target_inode; + if (inode) + ihold(inode); + ceph_mdsc_put_request(req); + if (!inode) + return ERR_PTR(-ENOENT); + + dentry = d_obtain_alias(inode); + if (IS_ERR(dentry)) { + iput(inode); + return dentry; + } + err = ceph_init_dentry(dentry); + if (err < 0) { + dput(dentry); + return ERR_PTR(err); + } + dout("__get_parent ino %llx parent %p ino %llx.%llx\n", + child ? ceph_ino(child->d_inode) : ino, + dentry, ceph_vinop(inode)); + return dentry; +} + +struct dentry *ceph_get_parent(struct dentry *child) +{ + /* don't re-export snaps */ + if (ceph_snap(child->d_inode) != CEPH_NOSNAP) + return ERR_PTR(-EINVAL); + + dout("get_parent %p ino %llx.%llx\n", + child, ceph_vinop(child->d_inode)); + return __get_parent(child->d_sb, child, 0); +} + /* * get parent, if possible. * @@ -171,4 +230,5 @@ const struct export_operations ceph_export_ops = { .encode_fh = ceph_encode_fh, .fh_to_dentry = ceph_fh_to_dentry, .fh_to_parent = ceph_fh_to_parent, + .get_parent = ceph_get_parent, }; |