@@ -2466,8 +2466,8 @@ static u8 *get_fscrypt_altname(const struct ceph_mds_request *req, u32 *plen)
*/
char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, int for_wire)
{
- struct dentry *cur;
- struct inode *inode;
+ struct dentry *cur, *parent;
+ struct inode *inode, *pinode;
char *path;
int pos;
unsigned seq;
@@ -2480,13 +2480,16 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, int for
if (!path)
return ERR_PTR(-ENOMEM);
retry:
+ pinode = NULL;
+ parent = NULL;
pos = PATH_MAX - 1;
path[pos] = '\0';
seq = read_seqbegin(&rename_lock);
cur = dget(dentry);
for (;;) {
- struct dentry *parent;
+ parent = dget_parent(cur);
+ pinode = ceph_get_snap_parent_inode(d_inode(parent));
spin_lock(&cur->d_lock);
inode = d_inode(cur);
@@ -2494,12 +2497,11 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, int for
dout("build_path path+%d: %p SNAPDIR\n",
pos, cur);
spin_unlock(&cur->d_lock);
- parent = dget_parent(cur);
} else if (for_wire && inode && dentry != cur && ceph_snap(inode) == CEPH_NOSNAP) {
spin_unlock(&cur->d_lock);
pos++; /* get rid of any prepended '/' */
break;
- } else if (!for_wire || !IS_ENCRYPTED(d_inode(cur->d_parent))) {
+ } else if (!for_wire || !IS_ENCRYPTED(pinode)) {
pos -= cur->d_name.len;
if (pos < 0) {
spin_unlock(&cur->d_lock);
@@ -2507,7 +2509,6 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, int for
}
memcpy(path + pos, cur->d_name.name, cur->d_name.len);
spin_unlock(&cur->d_lock);
- parent = dget_parent(cur);
} else {
int len, ret;
char buf[FSCRYPT_BASE64URL_CHARS(NAME_MAX)];
@@ -2519,32 +2520,32 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, int for
memcpy(buf, cur->d_name.name, cur->d_name.len);
len = cur->d_name.len;
spin_unlock(&cur->d_lock);
- parent = dget_parent(cur);
- ret = __fscrypt_prepare_readdir(d_inode(parent));
+ ret = __fscrypt_prepare_readdir(pinode);
if (ret < 0) {
dput(parent);
dput(cur);
+ iput(pinode);
return ERR_PTR(ret);
}
- if (fscrypt_has_encryption_key(d_inode(parent))) {
- len = ceph_encode_encrypted_fname(d_inode(parent), cur, buf);
+ if (fscrypt_has_encryption_key(pinode)) {
+ len = ceph_encode_encrypted_fname(pinode, cur, buf);
if (len < 0) {
dput(parent);
dput(cur);
+ iput(pinode);
return ERR_PTR(len);
}
}
pos -= len;
- if (pos < 0) {
- dput(parent);
+ if (pos < 0)
break;
- }
memcpy(path + pos, buf, len);
}
dput(cur);
cur = parent;
+ parent = NULL;
/* Are we at the root? */
if (IS_ROOT(cur))
@@ -2555,7 +2556,13 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, int for
break;
path[pos] = '/';
+ iput(pinode);
+ pinode = NULL;
}
+ if (pinode)
+ iput(pinode);
+ if (parent)
+ dput(parent);
inode = d_inode(cur);
base = inode ? ceph_ino(inode) : 0;
dput(cur);