From 6ae4b933b253ba117f05b200107b720b1ffd5145 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 14 Jan 2008 10:13:06 -0800 Subject: [PATCH] use improved ceph_build_dentry_path --- src/kernel/dir.c | 129 ++++++++++++++++++++-------------------- src/kernel/file.c | 8 ++- src/kernel/mds_client.c | 7 ++- src/kernel/super.h | 3 +- 4 files changed, 75 insertions(+), 72 deletions(-) diff --git a/src/kernel/dir.c b/src/kernel/dir.c index da2adaecc6728..0795afda8ba53 100644 --- a/src/kernel/dir.c +++ b/src/kernel/dir.c @@ -7,78 +7,65 @@ const struct inode_operations ceph_dir_iops; const struct file_operations ceph_dir_fops; /* - * ugly hack. - * - no locking. - * - should stop at mount root or current's CWD? + * build a dentry's path, relative to sb root. allocate on + * heap; caller must kfree. */ -int ceph_get_dentry_path(struct dentry *dn, char *buf, struct dentry *base) -{ - int len; - dout(20, "get_dentry_path in dn %p bas %p\n", dn, base); - if (dn == base) - return 0; - - len = ceph_get_dentry_path(dn->d_parent, buf, base); - dout(20, "get_dentry_path out dn %p bas %p len %d adding %s\n", - dn, base, len, dn->d_name.name); - - if (len) buf[len++] = '/'; - memcpy(buf+len, dn->d_name.name, dn->d_name.len); - len += dn->d_name.len; - buf[len] = 0; - return len; -} - -int ceph_build_dentry_path(struct dentry *dentry, char **path, int *len) +char *ceph_build_dentry_path(struct dentry *dentry, int *plen) { struct dentry *temp; + char *path; + int len, pos; if (dentry == NULL) - return -EINVAL; /* not much we can do if dentry is freed and - we need to reopen the file after it was closed implicitly - when the server crashed */ + return ERR_PTR(-EINVAL); retry: - *len = 0; + len = 0; for (temp = dentry; !IS_ROOT(temp);) { - *len += (1 + temp->d_name.len); + len += 1 + temp->d_name.len; temp = temp->d_parent; if (temp == NULL) { - derr(1, "corrupt dentry"); - return -EINVAL; + derr(1, "corrupt dentry %p\n", dentry); + return ERR_PTR(-EINVAL); } } + if (len) len--; - *path = kmalloc(*len+1, GFP_KERNEL); - if (*path == NULL) - return -ENOMEM; - (*path)[*len] = 0; /* trailing null */ + path = kmalloc(len+1, GFP_KERNEL); + if (path == NULL) + return ERR_PTR(-ENOMEM); + pos = len; + path[pos] = 0; /* trailing null */ for (temp = dentry; !IS_ROOT(temp);) { - *len -= 1 + temp->d_name.len; - if (*len < 0) { + pos -= temp->d_name.len; + if (pos < 0) { break; } else { - (*path)[*len] = '/'; - strncpy(*path + *len + 1, temp->d_name.name, + strncpy(path + pos, temp->d_name.name, temp->d_name.len); - dout(0, "name: %s", *path + *len); + dout(30, "build_path_dentry path+%d: '%s'\n", pos, path + pos); + if (pos) + path[--pos] = '/'; } temp = temp->d_parent; if (temp == NULL) { - dout(1, "corrupt dentry"); - kfree(*path); - return -EINVAL; + derr(1, "corrupt dentry\n"); + kfree(path); + return ERR_PTR(-EINVAL); } } - if (*len != 0) { - derr(1, "did not end path lookup where expected namelen is %d", *len); + if (pos != 0) { + derr(1, "did not end path lookup where expected namelen is %d\n", len); /* 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); + 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; } - return 0; + + dout(10, "build_path_dentry on %p build '%s' len %d\n", dentry, path, len); + *plen = len; + return path; } @@ -224,7 +211,7 @@ static struct dentry *ceph_dir_lookup(struct inode *dir, struct dentry *dentry, { struct ceph_super_info *sbinfo = ceph_sbinfo(dir->i_sb); struct ceph_mds_client *mdsc = &sbinfo->sb_client->mdsc; - char path[200]; + char *path; int pathlen; struct ceph_msg *req; struct ceph_mds_reply_info rinfo; @@ -233,29 +220,30 @@ static struct dentry *ceph_dir_lookup(struct inode *dir, struct dentry *dentry, ino_t ino; dout(5, "dir_lookup inode %p dentry %p '%s'\n", dir, dentry, dentry->d_name.name); - pathlen = ceph_get_dentry_path(dentry, path, dir->i_sb->s_root); - - /* stat mds */ + path = ceph_build_dentry_path(dentry, &pathlen); + if (IS_ERR(path)) + return ERR_PTR(PTR_ERR(path)); req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_STAT, dir->i_sb->s_root->d_inode->i_ino, path, 0, 0); + kfree(path); if (IS_ERR(req)) return ERR_PTR(PTR_ERR(req)); - if ((err = ceph_mdsc_do_request(mdsc, req, &rinfo, -1)) < 0) + if ((err = ceph_mdsc_do_request(mdsc, req, &rinfo, -1)) < 0) return ERR_PTR(err); err = le32_to_cpu(rinfo.head->result); dout(20, "dir_lookup result=%d\n", err); /* if there was a previous inode associated with this dentry, now there isn't one */ - if (err == -ENOENT) { + if (err == -ENOENT) d_add(dentry, NULL); - } else if (err < 0) + else if (err < 0) return ERR_PTR(err); if (rinfo.trace_nr > 0) { ino = le64_to_cpu(rinfo.trace_in[rinfo.trace_nr-1].in->ino); dout(10, "got and parsed stat result, ino %lu\n", ino); inode = iget(dir->i_sb, ino); - if (!inode) + if (!inode) return ERR_PTR(-EACCES); if ((err = ceph_fill_inode(inode, rinfo.trace_in[rinfo.trace_nr-1].in)) < 0) { iput(inode); @@ -372,15 +360,17 @@ static int ceph_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) struct ceph_msg *req; struct ceph_mds_request_head *rhead; struct ceph_mds_reply_info rinfo; - char path[200]; /* FIXME dynamic */ + char *path; int pathlen; int err; dout(5, "dir_mkdir dir %p dentry %p mode %d\n", dir, dentry, mode); - pathlen = ceph_get_dentry_path(dentry, path, dir->i_sb->s_root); - + path = ceph_build_dentry_path(dentry, &pathlen); + if (IS_ERR(path)) + return PTR_ERR(path); req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_MKDIR, dir->i_sb->s_root->d_inode->i_ino, path, 0, 0); + kfree(path); if (IS_ERR(req)) { d_drop(dentry); return PTR_ERR(req); @@ -420,16 +410,18 @@ static int ceph_dir_unlink(struct inode *dir, struct dentry *dentry) struct inode *inode = dentry->d_inode; struct ceph_msg *req; struct ceph_mds_reply_info rinfo; - char path[200]; + char *path; int pathlen; int err; int op = ((dentry->d_inode->i_mode & S_IFMT) == S_IFDIR) ? CEPH_MDS_OP_RMDIR:CEPH_MDS_OP_UNLINK; dout(5, "dir_unlink/rmdir dir %p dentry %p inode %p\n", dir, dentry, inode); - pathlen = ceph_get_dentry_path(dentry, path, dir->i_sb->s_root); - + path = ceph_build_dentry_path(dentry, &pathlen); + if (IS_ERR(path)) + return PTR_ERR(path); req = ceph_mdsc_create_request(mdsc, op, dir->i_sb->s_root->d_inode->i_ino, path, 0, 0); + kfree(path); if (IS_ERR(req)) return PTR_ERR(req); if ((err = ceph_mdsc_do_request(mdsc, req, &rinfo, -1)) < 0) @@ -451,18 +443,25 @@ static int ceph_dir_rename(struct inode *old_dir, struct dentry *old_dentry, struct ceph_msg *req; struct ceph_mds_reply_info rinfo; struct dentry *root = old_dir->i_sb->s_root; - char oldpath[200], newpath[200]; + char *oldpath, *newpath; int oldpathlen, newpathlen; int err; dout(5, "dir_newname dir %p dentry %p to dir %p dentry %p\n", old_dir, old_dentry, new_dir, new_dentry); - oldpathlen = ceph_get_dentry_path(old_dentry, oldpath, root); - newpathlen = ceph_get_dentry_path(new_dentry, newpath, root); - + oldpath = ceph_build_dentry_path(old_dentry, &oldpathlen); + if (IS_ERR(oldpath)) + return PTR_ERR(oldpath); + newpath = ceph_build_dentry_path(new_dentry, &newpathlen); + if (IS_ERR(newpath)) { + kfree(oldpath); + return PTR_ERR(newpath); + } req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_RENAME, root->d_inode->i_ino, oldpath, root->d_inode->i_ino, newpath); + kfree(oldpath); + kfree(newpath); if (IS_ERR(req)) return PTR_ERR(req); if ((err = ceph_mdsc_do_request(mdsc, req, &rinfo, -1)) < 0) diff --git a/src/kernel/file.c b/src/kernel/file.c index c1df788249bf2..f7933f055f912 100644 --- a/src/kernel/file.c +++ b/src/kernel/file.c @@ -11,7 +11,7 @@ struct ceph_inode_cap *ceph_do_open(struct inode *inode, struct file *file) int flags = file->f_flags; struct ceph_mds_client *mdsc = &ceph_inode_to_client(inode)->mdsc; ceph_ino_t pathbase; - char path[PATH_MAX]; + char *path; int pathlen; struct ceph_msg *req; struct ceph_mds_request_head *rhead; @@ -25,9 +25,11 @@ struct ceph_inode_cap *ceph_do_open(struct inode *inode, struct file *file) dout(5, "open inode %p dentry %p name '%s' flags %d\n", inode, dentry, dentry->d_name.name, flags); pathbase = inode->i_sb->s_root->d_inode->i_ino; - pathlen = ceph_get_dentry_path(dentry, path, inode->i_sb->s_root); - + path = ceph_build_dentry_path(dentry, &pathlen); + if (IS_ERR(path)) + return ERR_PTR(PTR_ERR(path)); req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_OPEN, pathbase, path, 0, 0); + kfree(path); if (IS_ERR(req)) return ERR_PTR(PTR_ERR(req)); rhead = req->front.iov_base; diff --git a/src/kernel/mds_client.c b/src/kernel/mds_client.c index 94667d63b5959..3694feee8a585 100644 --- a/src/kernel/mds_client.c +++ b/src/kernel/mds_client.c @@ -748,8 +748,11 @@ void send_mds_reconnect(struct ceph_mds_client *mdsc, int mds) ceph_encode_timespec(&p, end, &cap->ci->vfs_inode.i_mtime); //i_wr_mtime ceph_encode_timespec(&p, end, &cap->ci->vfs_inode.i_atime); /* atime.. fixme */ dentry = list_entry(&cap->ci->vfs_inode.i_dentry, struct dentry, d_alias); - err = ceph_build_dentry_path(dentry, &path, &pathlen); - BUG_ON(err); + path = ceph_build_dentry_path(dentry, &pathlen); + if (IS_ERR(path)) { + err = PTR_ERR(path); + BUG_ON(err); + } if (p + pathlen + 4 + sizeof(struct ceph_mds_cap_reconnect) > end) { /* der, realloc front */ int off = end-p; diff --git a/src/kernel/super.h b/src/kernel/super.h index a3ac19c9a3a69..524bab44c09e0 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -189,8 +189,7 @@ extern int ceph_release(struct inode *inode, struct file *filp); /* dir.c */ extern const struct inode_operations ceph_dir_iops; extern const struct file_operations ceph_dir_fops; -extern int ceph_get_dentry_path(struct dentry *dn, char *buf, struct dentry *base); /* move me */ -extern int ceph_build_dentry_path(struct dentry *dentry, char **path, int *len); +extern char *ceph_build_dentry_path(struct dentry *dentry, int *len); #endif /* _FS_CEPH_CEPH_H */ -- 2.39.5