This spin_lock(&dentry->d_lock); if (di->lease_session && di->lease_session->s_mds == mds) force = 1; if (!dir) { parent = dget(dentry->d_parent); dir = d_inode(parent); } spin_unlock(&dentry->d_lock); has a problem if we ever get called with dir == NULL. The thing is, dget(dentry->d_parent) will spin if dentry->d_parent->d_lock is held. IOW, the whole thing is an equivalent of spin_lock(&dentry->d_lock); spin_lock(&dentry->d_parent->d_lock); which takes them in the wrong order. Said that, I'm not sure it ever gets called with dir == NULL; we have two callers - if (req->r_dentry_drop) { ret = ceph_encode_dentry_release(&p, req->r_dentry, req->r_parent, mds, req->r_dentry_drop, req->r_dentry_unless); if (ret < 0) goto out_err; releases += ret; } and if (req->r_old_dentry_drop) { ret = ceph_encode_dentry_release(&p, req->r_old_dentry, req->r_old_dentry_dir, mds, req->r_old_dentry_drop, req->r_old_dentry_unless); if (ret < 0) goto out_err; releases += ret; } Now, ->r_dentry_drop is set in ceph_mknod(), ceph_symlink(), ceph_mkdir(), ceph_link(), ceph_unlink(), all with req->r_parent = dir; ihold(dir); ceph_rename(), with req->r_parent = new_dir; ihold(new_dir); and ceph_atomic_open(), with req->r_parent = dir; if (req->r_op == CEPH_MDS_OP_CREATE) req->r_mnt_idmap = mnt_idmap_get(idmap); ihold(dir); All of that will oops if ->r_parent set to NULL. ->r_old_dentry_drop() is set in ceph_rename(), with struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(old_dir->i_sb); ... req->r_old_dentry_dir = old_dir; which also can't manage to leave ->r_old_dentry_dir set to NULL. Am I missing something subtle here? Looks like that dget() is never reached...