diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2014-03-01 09:11:45 -0500 |
---|---|---|
committer | Yan, Zheng <zheng.z.yan@intel.com> | 2014-04-02 22:33:53 -0400 |
commit | 9017c2ec78c730fb3ecd703d44e4a9061de2ba52 (patch) | |
tree | d0c15467898545ee127ad8f93d059f7d83503bd4 /fs/ceph | |
parent | 4f32b42dca660208c7556e13ebd84c510ad91840 (diff) |
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')
-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, | |||
121 | return __fh_to_dentry(sb, fh->ino); | 121 | return __fh_to_dentry(sb, fh->ino); |
122 | } | 122 | } |
123 | 123 | ||
124 | static struct dentry *__get_parent(struct super_block *sb, | ||
125 | struct dentry *child, u64 ino) | ||
126 | { | ||
127 | struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; | ||
128 | struct ceph_mds_request *req; | ||
129 | struct inode *inode; | ||
130 | struct dentry *dentry; | ||
131 | int err; | ||
132 | |||
133 | req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPPARENT, | ||
134 | USE_ANY_MDS); | ||
135 | if (IS_ERR(req)) | ||
136 | return ERR_CAST(req); | ||
137 | |||
138 | if (child) { | ||
139 | req->r_inode = child->d_inode; | ||
140 | ihold(child->d_inode); | ||
141 | } else { | ||
142 | req->r_ino1 = (struct ceph_vino) { | ||
143 | .ino = ino, | ||
144 | .snap = CEPH_NOSNAP, | ||
145 | }; | ||
146 | } | ||
147 | req->r_num_caps = 1; | ||
148 | err = ceph_mdsc_do_request(mdsc, NULL, req); | ||
149 | inode = req->r_target_inode; | ||
150 | if (inode) | ||
151 | ihold(inode); | ||
152 | ceph_mdsc_put_request(req); | ||
153 | if (!inode) | ||
154 | return ERR_PTR(-ENOENT); | ||
155 | |||
156 | dentry = d_obtain_alias(inode); | ||
157 | if (IS_ERR(dentry)) { | ||
158 | iput(inode); | ||
159 | return dentry; | ||
160 | } | ||
161 | err = ceph_init_dentry(dentry); | ||
162 | if (err < 0) { | ||
163 | dput(dentry); | ||
164 | return ERR_PTR(err); | ||
165 | } | ||
166 | dout("__get_parent ino %llx parent %p ino %llx.%llx\n", | ||
167 | child ? ceph_ino(child->d_inode) : ino, | ||
168 | dentry, ceph_vinop(inode)); | ||
169 | return dentry; | ||
170 | } | ||
171 | |||
172 | struct dentry *ceph_get_parent(struct dentry *child) | ||
173 | { | ||
174 | /* don't re-export snaps */ | ||
175 | if (ceph_snap(child->d_inode) != CEPH_NOSNAP) | ||
176 | return ERR_PTR(-EINVAL); | ||
177 | |||
178 | dout("get_parent %p ino %llx.%llx\n", | ||
179 | child, ceph_vinop(child->d_inode)); | ||
180 | return __get_parent(child->d_sb, child, 0); | ||
181 | } | ||
182 | |||
124 | /* | 183 | /* |
125 | * get parent, if possible. | 184 | * get parent, if possible. |
126 | * | 185 | * |
@@ -171,4 +230,5 @@ const struct export_operations ceph_export_ops = { | |||
171 | .encode_fh = ceph_encode_fh, | 230 | .encode_fh = ceph_encode_fh, |
172 | .fh_to_dentry = ceph_fh_to_dentry, | 231 | .fh_to_dentry = ceph_fh_to_dentry, |
173 | .fh_to_parent = ceph_fh_to_parent, | 232 | .fh_to_parent = ceph_fh_to_parent, |
233 | .get_parent = ceph_get_parent, | ||
174 | }; | 234 | }; |