diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2014-03-06 03:40:32 -0500 |
---|---|---|
committer | Yan, Zheng <zheng.z.yan@intel.com> | 2014-04-02 22:33:53 -0400 |
commit | 19913b4eac4a230dccb548931358398f45dabe4c (patch) | |
tree | ba858471538ae0b32fe42ab1c73bdaf559bbf2fd /fs/ceph | |
parent | 8996f4f23db735f0f3bab34352188b1ab21d7d7f (diff) |
ceph: add get_name() NFS export callback
Use the newly introduced LOOKUPNAME MDS request to connect child
inode to its parent directory.
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 | 40 | ||||
-rw-r--r-- | fs/ceph/inode.c | 51 | ||||
-rw-r--r-- | fs/ceph/strings.c | 1 |
3 files changed, 91 insertions, 1 deletions
diff --git a/fs/ceph/export.c b/fs/ceph/export.c index eb66408ff236..00d6af6a32ec 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c | |||
@@ -202,9 +202,49 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb, | |||
202 | return dentry; | 202 | return dentry; |
203 | } | 203 | } |
204 | 204 | ||
205 | static int ceph_get_name(struct dentry *parent, char *name, | ||
206 | struct dentry *child) | ||
207 | { | ||
208 | struct ceph_mds_client *mdsc; | ||
209 | struct ceph_mds_request *req; | ||
210 | int err; | ||
211 | |||
212 | mdsc = ceph_inode_to_client(child->d_inode)->mdsc; | ||
213 | req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPNAME, | ||
214 | USE_ANY_MDS); | ||
215 | if (IS_ERR(req)) | ||
216 | return PTR_ERR(req); | ||
217 | |||
218 | mutex_lock(&parent->d_inode->i_mutex); | ||
219 | |||
220 | req->r_inode = child->d_inode; | ||
221 | ihold(child->d_inode); | ||
222 | req->r_ino2 = ceph_vino(parent->d_inode); | ||
223 | req->r_locked_dir = parent->d_inode; | ||
224 | req->r_num_caps = 2; | ||
225 | err = ceph_mdsc_do_request(mdsc, NULL, req); | ||
226 | |||
227 | mutex_unlock(&parent->d_inode->i_mutex); | ||
228 | |||
229 | if (!err) { | ||
230 | struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info; | ||
231 | memcpy(name, rinfo->dname, rinfo->dname_len); | ||
232 | name[rinfo->dname_len] = 0; | ||
233 | dout("get_name %p ino %llx.%llx name %s\n", | ||
234 | child, ceph_vinop(child->d_inode), name); | ||
235 | } else { | ||
236 | dout("get_name %p ino %llx.%llx err %d\n", | ||
237 | child, ceph_vinop(child->d_inode), err); | ||
238 | } | ||
239 | |||
240 | ceph_mdsc_put_request(req); | ||
241 | return err; | ||
242 | } | ||
243 | |||
205 | const struct export_operations ceph_export_ops = { | 244 | const struct export_operations ceph_export_ops = { |
206 | .encode_fh = ceph_encode_fh, | 245 | .encode_fh = ceph_encode_fh, |
207 | .fh_to_dentry = ceph_fh_to_dentry, | 246 | .fh_to_dentry = ceph_fh_to_dentry, |
208 | .fh_to_parent = ceph_fh_to_parent, | 247 | .fh_to_parent = ceph_fh_to_parent, |
209 | .get_parent = ceph_get_parent, | 248 | .get_parent = ceph_get_parent, |
249 | .get_name = ceph_get_name, | ||
210 | }; | 250 | }; |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 8bf2384bd423..91d6c9d49e3e 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -1044,10 +1044,59 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, | |||
1044 | session, req->r_request_started, -1, | 1044 | session, req->r_request_started, -1, |
1045 | &req->r_caps_reservation); | 1045 | &req->r_caps_reservation); |
1046 | if (err < 0) | 1046 | if (err < 0) |
1047 | return err; | 1047 | goto done; |
1048 | } else { | 1048 | } else { |
1049 | WARN_ON_ONCE(1); | 1049 | WARN_ON_ONCE(1); |
1050 | } | 1050 | } |
1051 | |||
1052 | if (dir && req->r_op == CEPH_MDS_OP_LOOKUPNAME) { | ||
1053 | struct qstr dname; | ||
1054 | struct dentry *dn, *parent; | ||
1055 | |||
1056 | BUG_ON(!rinfo->head->is_target); | ||
1057 | BUG_ON(req->r_dentry); | ||
1058 | |||
1059 | parent = d_find_any_alias(dir); | ||
1060 | BUG_ON(!parent); | ||
1061 | |||
1062 | dname.name = rinfo->dname; | ||
1063 | dname.len = rinfo->dname_len; | ||
1064 | dname.hash = full_name_hash(dname.name, dname.len); | ||
1065 | vino.ino = le64_to_cpu(rinfo->targeti.in->ino); | ||
1066 | vino.snap = le64_to_cpu(rinfo->targeti.in->snapid); | ||
1067 | retry_lookup: | ||
1068 | dn = d_lookup(parent, &dname); | ||
1069 | dout("d_lookup on parent=%p name=%.*s got %p\n", | ||
1070 | parent, dname.len, dname.name, dn); | ||
1071 | |||
1072 | if (!dn) { | ||
1073 | dn = d_alloc(parent, &dname); | ||
1074 | dout("d_alloc %p '%.*s' = %p\n", parent, | ||
1075 | dname.len, dname.name, dn); | ||
1076 | if (dn == NULL) { | ||
1077 | dput(parent); | ||
1078 | err = -ENOMEM; | ||
1079 | goto done; | ||
1080 | } | ||
1081 | err = ceph_init_dentry(dn); | ||
1082 | if (err < 0) { | ||
1083 | dput(dn); | ||
1084 | dput(parent); | ||
1085 | goto done; | ||
1086 | } | ||
1087 | } else if (dn->d_inode && | ||
1088 | (ceph_ino(dn->d_inode) != vino.ino || | ||
1089 | ceph_snap(dn->d_inode) != vino.snap)) { | ||
1090 | dout(" dn %p points to wrong inode %p\n", | ||
1091 | dn, dn->d_inode); | ||
1092 | d_delete(dn); | ||
1093 | dput(dn); | ||
1094 | goto retry_lookup; | ||
1095 | } | ||
1096 | |||
1097 | req->r_dentry = dn; | ||
1098 | dput(parent); | ||
1099 | } | ||
1051 | } | 1100 | } |
1052 | 1101 | ||
1053 | if (rinfo->head->is_target) { | 1102 | if (rinfo->head->is_target) { |
diff --git a/fs/ceph/strings.c b/fs/ceph/strings.c index 4440f447fd3f..51cc23e48111 100644 --- a/fs/ceph/strings.c +++ b/fs/ceph/strings.c | |||
@@ -54,6 +54,7 @@ const char *ceph_mds_op_name(int op) | |||
54 | case CEPH_MDS_OP_LOOKUPHASH: return "lookuphash"; | 54 | case CEPH_MDS_OP_LOOKUPHASH: return "lookuphash"; |
55 | case CEPH_MDS_OP_LOOKUPPARENT: return "lookupparent"; | 55 | case CEPH_MDS_OP_LOOKUPPARENT: return "lookupparent"; |
56 | case CEPH_MDS_OP_LOOKUPINO: return "lookupino"; | 56 | case CEPH_MDS_OP_LOOKUPINO: return "lookupino"; |
57 | case CEPH_MDS_OP_LOOKUPNAME: return "lookupname"; | ||
57 | case CEPH_MDS_OP_GETATTR: return "getattr"; | 58 | case CEPH_MDS_OP_GETATTR: return "getattr"; |
58 | case CEPH_MDS_OP_SETXATTR: return "setxattr"; | 59 | case CEPH_MDS_OP_SETXATTR: return "setxattr"; |
59 | case CEPH_MDS_OP_SETATTR: return "setattr"; | 60 | case CEPH_MDS_OP_SETATTR: return "setattr"; |