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: Jeff Layton <jlayton@kernel.org> Reviewed-by: Xiubo Li <xiubli@redhat.com> Reviewed-and-tested-by: Luís Henriques <lhenriques@suse.de> Reviewed-by: Milind Changire <mchangir@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
ec9595c080
commit
4c793d4c58
|
@ -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,
|
||||
int stop_on_nosnap)
|
||||
{
|
||||
struct dentry *temp;
|
||||
struct dentry *cur;
|
||||
struct inode *inode;
|
||||
char *path;
|
||||
int pos;
|
||||
unsigned seq;
|
||||
|
@ -2404,34 +2405,35 @@ retry:
|
|||
path[pos] = '\0';
|
||||
|
||||
seq = read_seqbegin(&rename_lock);
|
||||
rcu_read_lock();
|
||||
temp = dentry;
|
||||
cur = dget(dentry);
|
||||
for (;;) {
|
||||
struct inode *inode;
|
||||
struct dentry *temp;
|
||||
|
||||
spin_lock(&temp->d_lock);
|
||||
inode = d_inode(temp);
|
||||
spin_lock(&cur->d_lock);
|
||||
inode = d_inode(cur);
|
||||
if (inode && ceph_snap(inode) == CEPH_SNAPDIR) {
|
||||
dout("build_path path+%d: %p SNAPDIR\n",
|
||||
pos, temp);
|
||||
} else if (stop_on_nosnap && inode && dentry != temp &&
|
||||
pos, cur);
|
||||
} else if (stop_on_nosnap && inode && dentry != cur &&
|
||||
ceph_snap(inode) == CEPH_NOSNAP) {
|
||||
spin_unlock(&temp->d_lock);
|
||||
spin_unlock(&cur->d_lock);
|
||||
pos++; /* get rid of any prepended '/' */
|
||||
break;
|
||||
} else {
|
||||
pos -= temp->d_name.len;
|
||||
pos -= cur->d_name.len;
|
||||
if (pos < 0) {
|
||||
spin_unlock(&temp->d_lock);
|
||||
spin_unlock(&cur->d_lock);
|
||||
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);
|
||||
temp = READ_ONCE(temp->d_parent);
|
||||
cur = dget_parent(temp);
|
||||
dput(temp);
|
||||
|
||||
/* Are we at the root? */
|
||||
if (IS_ROOT(temp))
|
||||
if (IS_ROOT(cur))
|
||||
break;
|
||||
|
||||
/* Are we out of buffer? */
|
||||
|
@ -2440,8 +2442,9 @@ retry:
|
|||
|
||||
path[pos] = '/';
|
||||
}
|
||||
base = ceph_ino(d_inode(temp));
|
||||
rcu_read_unlock();
|
||||
inode = d_inode(cur);
|
||||
base = inode ? ceph_ino(inode) : 0;
|
||||
dput(cur);
|
||||
|
||||
if (read_seqretry(&rename_lock, seq))
|
||||
goto retry;
|
||||
|
|
Loading…
Reference in New Issue