]> git.kernelconcepts.de Git - karo-tx-linux.git/commit
ceph: clean up unsafe d_parent access in __choose_mds
authorJeff Layton <jlayton@redhat.com>
Thu, 15 Dec 2016 13:37:56 +0000 (08:37 -0500)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 20 Feb 2017 11:16:04 +0000 (12:16 +0100)
commit30c71233a1d4b5c23ad6652847285bf6b57086e2
tree3ed1964e1609b732139cb6a58f2ac3f11d789025
parentc470abd4fde40ea6a0846a2beab642a578c0b8cd
ceph: clean up unsafe d_parent access in __choose_mds

__choose_mds exists to pick an MDS to use when issuing a call. Doing
that typically involves picking an inode and using the authoritative
MDS for it. In most cases, that's pretty straightforward, as we are
using an inode to which we hold a reference (usually represented by
r_dentry or r_inode in the request).

In the case of a snapshotted directory however, we need to fetch
the non-snapped parent, which involves walking back up the parents
in the tree. The dentries in the snapshot dir are effectively frozen
but the overall parent is _not_, and could vanish if a concurrent
rename were to occur.

Clean this code up and take special care to ensure the validity of
the entries we're working with. First, try to use the inode in
r_locked_dir if one exists. If not and all we have is r_dentry,
then we have to walk back up the tree. Use the rcu_read_lock for
this so we can ensure that any d_parent we find won't go away, and
take extra care to deal with the possibility that the dentries could
go negative.

Change get_nonsnap_parent to return an inode, and take a reference to
that inode before returning (if any). Change all of the other places
where we set "inode" in __choose_mds to also take a reference, and then
call iput on that inode before exiting the function.

Link: http://tracker.ceph.com/issues/18148
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Reviewed-by: Yan, Zheng <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/mds_client.c