]> git.karo-electronics.de Git - linux-beck.git/commit
[GFS2] Alternate gfs2_iget to avoid looking up inodes being freed
authorBenjamin Marzinski <bmarzins@redhat.com>
Tue, 18 Sep 2007 18:33:18 +0000 (13:33 -0500)
committerSteven Whitehouse <swhiteho@redhat.com>
Wed, 10 Oct 2007 07:56:29 +0000 (08:56 +0100)
commit7a9f53b3c1875bef22ad4588e818bc046ef183da
tree0b23b5b8a667d0d57c695c47f6b4eb6d50c2d661
parentde986e859a29097fb9211b052d86a9a2c868f6cd
[GFS2] Alternate gfs2_iget to avoid looking up inodes being freed

There is a possible deadlock between two processes on the same node, where one
process is deleting an inode, and another process is looking for allocated but
unused inodes to delete in order to create more space.

process A does an iput() on inode X, and it's i_count drops to 0. This causes
iput_final() to be called, which puts an inode into state I_FREEING at
generic_delete_inode(). There no point between when iput_final() is called, and
when I_FREEING is set where GFS2 could acquire any glocks. Once I_FREEING is
set, no other process on that node can successfully look up that inode until
the delete finishes.

process B locks the the resource group for the same inode in get_local_rgrp(),
which is called by gfs2_inplace_reserve_i()

process A tries to lock the resource group for the inode in
gfs2_dinode_dealloc(), but it's already locked by process B

process B waits in find_inode for the inode to have the I_FREEING state cleared.

Deadlock.

This patch solves the problem by adding an alternative to gfs2_iget(),
gfs2_iget_skip(), that simply skips any inodes that are in the I_FREEING
state.o The alternate test function is just like the original one, except that
it fails if the inode is being freed, and sets a skipped flag. The alternate
set function is just like the original, except that it fails if the skipped
flag is set. Only try_rgrp_unlink() calls gfs2_iget_skip() instead of
gfs2_iget().

Signed-off-by: Benjamin E. Marzinski <bmarzins@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
fs/gfs2/dir.c
fs/gfs2/inode.c
fs/gfs2/inode.h
fs/gfs2/ops_export.c
fs/gfs2/ops_fstype.c
fs/gfs2/rgrp.c