Skip to content
  • Jeff Layton's avatar
    ceph: clean up unsafe d_parent access in __choose_mds · 30c71233
    Jeff Layton authored
    __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: default avatarJeff Layton <jlayton@redhat.com>
    Reviewed-by: default avatarYan, Zheng <zyan@redhat.com>
    Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
    30c71233