Commit 4c793d4c authored by Jeff Layton's avatar Jeff Layton Committed by Ilya Dryomov

ceph: make ceph_msdc_build_path use ref-walk

Encryption potentially requires allocation, at which point we'll need to
be in a non-atomic context. Convert ceph_msdc_build_path to take dentry
spinlocks and references instead of using rcu_read_lock to walk the
path.

This is slightly less efficient, and we may want to eventually allow
using RCU when the leaf dentry isn't encrypted.
Signed-off-by: default avatarJeff Layton <jlayton@kernel.org>
Reviewed-by: default avatarXiubo Li <xiubli@redhat.com>
Reviewed-and-tested-by: default avatarLuís Henriques <lhenriques@suse.de>
Reviewed-by: default avatarMilind Changire <mchangir@redhat.com>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent ec9595c0
...@@ -2387,7 +2387,8 @@ static inline u64 __get_oldest_tid(struct ceph_mds_client *mdsc) ...@@ -2387,7 +2387,8 @@ static inline u64 __get_oldest_tid(struct ceph_mds_client *mdsc)
char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase,
int stop_on_nosnap) int stop_on_nosnap)
{ {
struct dentry *temp; struct dentry *cur;
struct inode *inode;
char *path; char *path;
int pos; int pos;
unsigned seq; unsigned seq;
...@@ -2404,34 +2405,35 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, ...@@ -2404,34 +2405,35 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase,
path[pos] = '\0'; path[pos] = '\0';
seq = read_seqbegin(&rename_lock); seq = read_seqbegin(&rename_lock);
rcu_read_lock(); cur = dget(dentry);
temp = dentry;
for (;;) { for (;;) {
struct inode *inode; struct dentry *temp;
spin_lock(&temp->d_lock); spin_lock(&cur->d_lock);
inode = d_inode(temp); inode = d_inode(cur);
if (inode && ceph_snap(inode) == CEPH_SNAPDIR) { if (inode && ceph_snap(inode) == CEPH_SNAPDIR) {
dout("build_path path+%d: %p SNAPDIR\n", dout("build_path path+%d: %p SNAPDIR\n",
pos, temp); pos, cur);
} else if (stop_on_nosnap && inode && dentry != temp && } else if (stop_on_nosnap && inode && dentry != cur &&
ceph_snap(inode) == CEPH_NOSNAP) { ceph_snap(inode) == CEPH_NOSNAP) {
spin_unlock(&temp->d_lock); spin_unlock(&cur->d_lock);
pos++; /* get rid of any prepended '/' */ pos++; /* get rid of any prepended '/' */
break; break;
} else { } else {
pos -= temp->d_name.len; pos -= cur->d_name.len;
if (pos < 0) { if (pos < 0) {
spin_unlock(&temp->d_lock); spin_unlock(&cur->d_lock);
break; break;
} }
memcpy(path + pos, temp->d_name.name, temp->d_name.len); memcpy(path + pos, cur->d_name.name, cur->d_name.len);
} }
temp = cur;
spin_unlock(&temp->d_lock); spin_unlock(&temp->d_lock);
temp = READ_ONCE(temp->d_parent); cur = dget_parent(temp);
dput(temp);
/* Are we at the root? */ /* Are we at the root? */
if (IS_ROOT(temp)) if (IS_ROOT(cur))
break; break;
/* Are we out of buffer? */ /* Are we out of buffer? */
...@@ -2440,8 +2442,9 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, ...@@ -2440,8 +2442,9 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase,
path[pos] = '/'; path[pos] = '/';
} }
base = ceph_ino(d_inode(temp)); inode = d_inode(cur);
rcu_read_unlock(); base = inode ? ceph_ino(inode) : 0;
dput(cur);
if (read_seqretry(&rename_lock, seq)) if (read_seqretry(&rename_lock, seq))
goto retry; goto retry;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment