diff options
author | Sage Weil <sage@newdream.net> | 2009-02-18 16:35:45 -0800 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2009-02-19 11:58:25 -0800 |
commit | 0990d83f83a802b0c9de3646a95c0192c37d71c8 (patch) | |
tree | 7672e410f6e862a16060bada0b92b9c73e0f15b7 | |
parent | 3dc43aa8e6606be15695d565715b6a7a1b2d38ea (diff) | |
download | ceph-0990d83f83a802b0c9de3646a95c0192c37d71c8.tar.gz |
kclient: fix fh_to_dentry; move build_path to mds_client.c
-rw-r--r-- | src/kernel/dir.c | 81 | ||||
-rw-r--r-- | src/kernel/export.c | 8 | ||||
-rw-r--r-- | src/kernel/mds_client.c | 142 | ||||
-rw-r--r-- | src/kernel/super.h | 1 |
4 files changed, 121 insertions, 111 deletions
diff --git a/src/kernel/dir.c b/src/kernel/dir.c index 636fed7c02a..918f933eec9 100644 --- a/src/kernel/dir.c +++ b/src/kernel/dir.c @@ -30,87 +30,6 @@ struct dentry_operations ceph_dentry_ops; static int ceph_dentry_revalidate(struct dentry *dentry, struct nameidata *nd); /* - * build a dentry's path. allocate on heap; caller must kfree. based - * on build_path_from_dentry in fs/cifs/dir.c. - * - * encode hidden .snap dirs as a double /, i.e. - * foo/.snap/bar -> foo//bar - */ -char *ceph_build_path(struct dentry *dentry, int *plen, u64 *base, - int mds) -{ - struct dentry *temp; - char *path; - int len, pos; - - if (dentry == NULL) - return ERR_PTR(-EINVAL); - -retry: - len = 0; - for (temp = dentry; !IS_ROOT(temp);) { - struct inode *inode = temp->d_inode; - if (inode && ceph_snap(inode) == CEPH_SNAPDIR) - len++; /* slash only */ - else - len += 1 + temp->d_name.len; - temp = temp->d_parent; - if (temp == NULL) { - derr(1, "corrupt dentry %p\n", dentry); - return ERR_PTR(-EINVAL); - } - } - if (len) - len--; /* no leading '/' */ - - path = kmalloc(len+1, GFP_NOFS); - if (path == NULL) - return ERR_PTR(-ENOMEM); - pos = len; - path[pos] = 0; /* trailing null */ - for (temp = dentry; !IS_ROOT(temp) && pos != 0; ) { - if (temp->d_inode && - ceph_snap(temp->d_inode) == CEPH_SNAPDIR) { - dout(50, "build_path_dentry path+%d: %p SNAPDIR\n", - pos, temp); - } else { - pos -= temp->d_name.len; - if (pos < 0) - break; - strncpy(path + pos, temp->d_name.name, - temp->d_name.len); - dout(50, "build_path_dentry path+%d: %p '%.*s'\n", - pos, temp, temp->d_name.len, path + pos); - } - if (pos) - path[--pos] = '/'; - temp = temp->d_parent; - if (temp == NULL) { - derr(1, "corrupt dentry\n"); - kfree(path); - return ERR_PTR(-EINVAL); - } - } - if (pos != 0) { - derr(1, "did not end path lookup where expected, " - "namelen is %d, pos is %d\n", len, pos); - /* presumably this is only possible if racing with a - rename of one of the parent directories (we can not - lock the dentries above us to prevent this, but - retrying should be harmless) */ - kfree(path); - goto retry; - } - - *base = ceph_ino(temp->d_inode); - *plen = len; - dout(10, "build_path_dentry on %p %d built %llx '%.*s'\n", - dentry, atomic_read(&dentry->d_count), *base, len, path); - return path; -} - - -/* * for readdir, encoding the directory frag and offset within that frag * into f_pos. */ diff --git a/src/kernel/export.c b/src/kernel/export.c index 5c9783d39b6..a6e3537fd05 100644 --- a/src/kernel/export.c +++ b/src/kernel/export.c @@ -79,19 +79,17 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, inode = ceph_find_inode(sb, vino); if (!inode) { -#warning fixme - /* struct ceph_mds_request *req; derr(10, "fh_to_dentry %llx.%x -- no inode\n", vino.ino, hash); req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_FINDINODE, - len, (char *)fh, 0, NULL, - NULL, USE_ANY_MDS); + NULL, NULL, + (char *)fh, (void *)&len, + USE_ANY_MDS); if (IS_ERR(req)) return ERR_PTR(PTR_ERR(req)); err = ceph_mdsc_do_request(mdsc, NULL, req); ceph_mdsc_put_request(req); - */ inode = ceph_find_inode(sb, vino); if (!inode) return ERR_PTR(err ? err : -ESTALE); diff --git a/src/kernel/mds_client.c b/src/kernel/mds_client.c index 7753a59505e..df01837c6d8 100644 --- a/src/kernel/mds_client.c +++ b/src/kernel/mds_client.c @@ -869,7 +869,7 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, if (old_dentry) req->r_old_dentry = dget(old_dentry); req->r_path1 = path1; - req->r_path2 = path2; + req->r_path2 = path2; req->r_direct_mode = mode; return req; } @@ -889,6 +889,86 @@ static u64 __get_oldest_tid(struct ceph_mds_client *mdsc) } /* + * build a dentry's path. allocate on heap; caller must kfree. based + * on build_path_from_dentry in fs/cifs/dir.c. + * + * encode hidden .snap dirs as a double /, i.e. + * foo/.snap/bar -> foo//bar + */ +static char *build_path(struct dentry *dentry, int *plen, u64 *base, int mds) +{ + struct dentry *temp; + char *path; + int len, pos; + + if (dentry == NULL) + return ERR_PTR(-EINVAL); + +retry: + len = 0; + for (temp = dentry; !IS_ROOT(temp);) { + struct inode *inode = temp->d_inode; + if (inode && ceph_snap(inode) == CEPH_SNAPDIR) + len++; /* slash only */ + else + len += 1 + temp->d_name.len; + temp = temp->d_parent; + if (temp == NULL) { + derr(1, "corrupt dentry %p\n", dentry); + return ERR_PTR(-EINVAL); + } + } + if (len) + len--; /* no leading '/' */ + + path = kmalloc(len+1, GFP_NOFS); + if (path == NULL) + return ERR_PTR(-ENOMEM); + pos = len; + path[pos] = 0; /* trailing null */ + for (temp = dentry; !IS_ROOT(temp) && pos != 0; ) { + if (temp->d_inode && + ceph_snap(temp->d_inode) == CEPH_SNAPDIR) { + dout(50, "build_path_dentry path+%d: %p SNAPDIR\n", + pos, temp); + } else { + pos -= temp->d_name.len; + if (pos < 0) + break; + strncpy(path + pos, temp->d_name.name, + temp->d_name.len); + dout(50, "build_path_dentry path+%d: %p '%.*s'\n", + pos, temp, temp->d_name.len, path + pos); + } + if (pos) + path[--pos] = '/'; + temp = temp->d_parent; + if (temp == NULL) { + derr(1, "corrupt dentry\n"); + kfree(path); + return ERR_PTR(-EINVAL); + } + } + if (pos != 0) { + derr(1, "did not end path lookup where expected, " + "namelen is %d, pos is %d\n", len, pos); + /* presumably this is only possible if racing with a + rename of one of the parent directories (we can not + lock the dentries above us to prevent this, but + retrying should be harmless) */ + kfree(path); + goto retry; + } + + *base = ceph_ino(temp->d_inode); + *plen = len; + dout(10, "build_path_dentry on %p %d built %llx '%.*s'\n", + dentry, atomic_read(&dentry->d_count), *base, len, path); + return path; +} + + +/* * called under mdsc->mutex */ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc, @@ -901,21 +981,30 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc, const char *path2 = req->r_path2; u64 ino1 = 1, ino2 = 0; int pathlen1 = 0, pathlen2 = 0; + int pathlen; void *p, *end; + u32 fhlen = 0; - if (path1) - pathlen1 = strlen(path1); - else - path1 = ceph_build_path(req->r_dentry, &pathlen1, &ino1, mds); - if (path2) - pathlen2 = strlen(path2); - else if (req->r_old_dentry) - path2 = ceph_build_path(req->r_old_dentry, &pathlen2, &ino2, - mds); - - msg = ceph_msg_new(CEPH_MSG_CLIENT_REQUEST, - sizeof(*head) + pathlen1 + pathlen2 + - 2*(sizeof(u32)+sizeof(u64)), 0, 0, NULL); + if (req->r_op == CEPH_MDS_OP_FINDINODE) { + fhlen = *(int *)req->r_path2; + path2 = 0; + pathlen = sizeof(u32) + fhlen*sizeof(struct ceph_inopath_item); + } else { + if (path1) + pathlen1 = strlen(path1); + else + path1 = build_path(req->r_dentry, &pathlen1, &ino1, + mds); + if (path2) + pathlen2 = strlen(path2); + else if (req->r_old_dentry) + path2 = build_path(req->r_old_dentry, &pathlen2, &ino2, + mds); + pathlen = pathlen1 + pathlen2 + 2*(sizeof(u32) + sizeof(u64)); + } + + msg = ceph_msg_new(CEPH_MSG_CLIENT_REQUEST, sizeof(*head) + pathlen, + 0, 0, NULL); if (IS_ERR(msg)) goto out; @@ -931,14 +1020,20 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc, head->caller_gid = cpu_to_le32(current->fsgid); head->args = req->r_args; - ceph_encode_filepath(&p, end, ino1, path1); - ceph_encode_filepath(&p, end, ino2, path2); - if (path1) - dout(10, "create_request_message path1 %llx/%s\n", - ino1, path1); - if (path2) - dout(10, "create_request_message path2 %llx/%s\n", - ino2, path2); + if (req->r_op == CEPH_MDS_OP_FINDINODE) { + ceph_encode_32(&p, fhlen); + memcpy(p, path1, fhlen * sizeof(struct ceph_inopath_item)); + p += fhlen * sizeof(struct ceph_inopath_item); + } else { + ceph_encode_filepath(&p, end, ino1, path1); + ceph_encode_filepath(&p, end, ino2, path2); + if (path1) + dout(10, "create_request_message path1 %llx/%s\n", + ino1, path1); + if (path2) + dout(10, "create_request_message path2 %llx/%s\n", + ino2, path2); + } BUG_ON(p != end); @@ -1584,8 +1679,7 @@ retry: dentry = d_find_alias(inode); if (dentry) { - path = ceph_build_path(dentry, &pathlen, - &pathbase, 9999); + path = build_path(dentry, &pathlen, &pathbase, -1); if (IS_ERR(path)) { err = PTR_ERR(path); BUG_ON(err); diff --git a/src/kernel/super.h b/src/kernel/super.h index 136ed6e183d..84aa5e0fe4f 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -760,7 +760,6 @@ extern const struct inode_operations ceph_dir_iops; extern struct dentry_operations ceph_dentry_ops, ceph_snap_dentry_ops, ceph_snapdir_dentry_ops; -extern char *ceph_build_path(struct dentry *dn, int *len, u64 *base, int min); extern struct dentry *ceph_do_lookup(struct super_block *sb, struct dentry *dentry, int mask, int on_inode, int locked_dir); |