diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 4055ab4..4679566 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -47,12 +47,28 @@ static int ceph_set_ino_cb(struct inode *inode, void *data) return 0; } -struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino) +struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino, bool release_fill_lock, struct mutex *fill_lock, + bool release_s_mutex, struct mutex *s_mutex, bool release_snap_rwsem, struct rw_semaphore *snap_rwsem) { struct inode *inode; ino_t t = ceph_vino_to_ino(vino); + if (release_fill_lock) + mutex_unlock(fill_lock); + if (release_s_mutex) + mutex_unlock(s_mutex); + if (release_snap_rwsem) + up_read(snap_rwsem); + inode = iget5_locked(sb, t, ceph_ino_compare, ceph_set_ino_cb, &vino); + + if (release_fill_lock) + mutex_lock(fill_lock); + if (release_s_mutex) + mutex_lock(s_mutex); + if (release_snap_rwsem) + down_read(snap_rwsem); + if (!inode) return ERR_PTR(-ENOMEM); if (inode->i_state & I_NEW) { @@ -75,7 +91,7 @@ struct inode *ceph_get_snapdir(struct inode *parent) .ino = ceph_ino(parent), .snap = CEPH_SNAPDIR, }; - struct inode *inode = ceph_get_inode(parent->i_sb, vino); + struct inode *inode = ceph_get_inode(parent->i_sb, vino, false, NULL, false, NULL, false, NULL); struct ceph_inode_info *ci = ceph_inode(inode); BUG_ON(!S_ISDIR(parent->i_mode)); @@ -1250,7 +1266,7 @@ retry_lookup: tvino.ino = le64_to_cpu(rinfo->targeti.in->ino); tvino.snap = le64_to_cpu(rinfo->targeti.in->snapid); - in = ceph_get_inode(sb, tvino); + in = ceph_get_inode(sb, tvino, true, &req->r_fill_mutex, true, &session->s_mutex, true, &session->s_mdsc->snap_rwsem); if (IS_ERR(in)) { err = PTR_ERR(in); goto done; @@ -1448,7 +1464,7 @@ static int readdir_prepopulate_inodes_only(struct ceph_mds_request *req, vino.ino = le64_to_cpu(rde->inode.in->ino); vino.snap = le64_to_cpu(rde->inode.in->snapid); - in = ceph_get_inode(req->r_dentry->d_sb, vino); + in = ceph_get_inode(req->r_dentry->d_sb, vino, false, NULL, true, &session->s_mutex, true, &session->s_mdsc->snap_rwsem); if (IS_ERR(in)) { err = PTR_ERR(in); dout("new_inode badness got %d\n", err); @@ -1644,7 +1660,7 @@ retry_lookup: if (d_really_is_positive(dn)) { in = d_inode(dn); } else { - in = ceph_get_inode(parent->d_sb, tvino); + in = ceph_get_inode(parent->d_sb, tvino, false, NULL, true, &session->s_mutex, true, &session->s_mdsc->snap_rwsem); if (IS_ERR(in)) { dout("new_inode badness\n"); d_drop(dn); diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 582e28f..6c8f375 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -853,7 +853,10 @@ extern void ceph_destroy_inode(struct inode *inode); extern int ceph_drop_inode(struct inode *inode); extern struct inode *ceph_get_inode(struct super_block *sb, - struct ceph_vino vino); + struct ceph_vino vino, + bool release_fill_lock, struct mutex* fill_lock, + bool release_s_mutex, struct mutex* s_mutex, + bool release_snap_rwsem, struct rw_semaphore* snap_rwsem); extern struct inode *ceph_get_snapdir(struct inode *parent); extern int ceph_fill_file_size(struct inode *inode, int issued, u32 truncate_seq, u64 truncate_size, u64 size);