summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2009-02-18 16:35:45 -0800
committerSage Weil <sage@newdream.net>2009-02-19 11:58:25 -0800
commit0990d83f83a802b0c9de3646a95c0192c37d71c8 (patch)
tree7672e410f6e862a16060bada0b92b9c73e0f15b7
parent3dc43aa8e6606be15695d565715b6a7a1b2d38ea (diff)
downloadceph-0990d83f83a802b0c9de3646a95c0192c37d71c8.tar.gz
kclient: fix fh_to_dentry; move build_path to mds_client.c
-rw-r--r--src/kernel/dir.c81
-rw-r--r--src/kernel/export.c8
-rw-r--r--src/kernel/mds_client.c142
-rw-r--r--src/kernel/super.h1
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);