History

gfs2: gfs2_create_inode rework

When gfs2_lookup_by_inum() calls gfs2_inode_lookup() for an uncached inode, gfs2_inode_lookup() will place a new tentative inode into the inode cache before verifying that there is a valid inode at the given address. This can race with gfs2_create_inode() which doesn't check for duplicates inodes. gfs2_create_inode() will try to assign the new inode to the corresponding inode glock, and glock_set_object() will complain that the glock is still in use by gfs2_inode_lookup's tentative inode. We noticed this bug after adding commit 486408d690e1 ("gfs2: Cancel remote delete work asynchronously") which allowed delete_work_func() to race with gfs2_create_inode(), but the same race exists for open-by-handle. Fix that by switching from insert_inode_hash() to insert_inode_locked4(), which does check for duplicate inodes. We know we've just managed to to allocate the new inode, so an inode tentatively created by gfs2_inode_lookup() will eventually go away and insert_inode_locked4() will always succeed. In addition, don't flush the inode glock work anymore (this can now only make things worse) and clean up glock_{set,clear}_object for the inode glock somewhat.

Andreas Gruenbacher committed 4 years ago

Commit 3d36e571 parent 5f6e13b1 file · +10 −6Browse files

Unified · Split

fs/gfs2/inode.c+10−6
@@ -707,18 +707,19 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, · 706 unmodified lines
707707 error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
708708 if (error)
709709 goto fail_free_inode;
710− flush_delayed_work(&ip->i_gl->gl_work);
711710
712711 error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
713712 if (error)
714713 goto fail_free_inode;
715714 gfs2_cancel_delete_work(io_gl);
716715
716+ error = insert_inode_locked4(inode, ip->i_no_addr, iget_test, &ip->i_no_addr);
717+ BUG_ON(error);
718+
717719 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
718720 if (error)
719721 goto fail_gunlock2;
720722
721− glock_set_object(ip->i_gl, ip);
722723 error = gfs2_trans_begin(sdp, blocks, 0);
723724 if (error)
724725 goto fail_gunlock2;
@@ -734,9 +735,9 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, · 9 unmodified lines
734735 if (error)
735736 goto fail_gunlock2;
736737
738+ glock_set_object(ip->i_gl, ip);
737739 glock_set_object(io_gl, ip);
738740 gfs2_set_iop(inode);
739− insert_inode_hash(inode);
740741
741742 free_vfs_inode = 0; /* After this point, the inode is no longer
742743 considered free. Any failures need to undo
@@ -778,17 +779,17 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, · 35 unmodified lines
778779 gfs2_glock_dq_uninit(ghs + 1);
779780 gfs2_glock_put(io_gl);
780781 gfs2_qa_put(dip);
782+ unlock_new_inode(inode);
781783 return error;
782784
783785 fail_gunlock3:
786+ glock_clear_object(ip->i_gl, ip);
784787 glock_clear_object(io_gl, ip);
785788 gfs2_glock_dq_uninit(&ip->i_iopen_gh);
786789 fail_gunlock2:
787− glock_clear_object(io_gl, ip);
788790 gfs2_glock_put(io_gl);
789791 fail_free_inode:
790792 if (ip->i_gl) {
791− glock_clear_object(ip->i_gl, ip);
792793 if (free_vfs_inode) /* else evict will do the put for us */
793794 gfs2_glock_put(ip->i_gl);
794795 }
@@ -806,7 +807,10 @@ fail_gunlock: · 11 unmodified lines
806807 mark_inode_dirty(inode);
807808 set_bit(free_vfs_inode ? GIF_FREE_VFS_INODE : GIF_ALLOC_FAILED,
808809 &GFS2_I(inode)->i_flags);
809− iput(inode);
810+ if (inode->i_state & I_NEW)
811+ iget_failed(inode);
812+ else
813+ iput(inode);
810814 }
811815 if (gfs2_holder_initialized(ghs + 1))
812816 gfs2_glock_dq_uninit(ghs + 1);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t