simplify udf_iget, fix race
Subsystems (2)
PATCH 1/1 simplify udf_iget, fix race
udf_iget calls __udf_read_inode after the inode has been unlocked and other threads could access it. Switching to iget_locked() fixes this race and nicely simplifies the code.
fs/udf/inode.c +15 -69
@@ -920,30 +902,6 @@unlock_kernel (); } -/* -* udf_read_inode -* -* PURPOSE -* Read an inode. -* -* DESCRIPTION -* This routine is called by iget() [which is called by udf_iget()] -* (clean_inode() will have been called first) -* when an inode is first read into memory. -* -* HISTORY -* July 1, 1997 - Andrew E. Mileski -* Written, tested, and released. -* -* 12/19/98 dgb Updated to fix size problems. -*/ - -void -udf_read_inode (struct inode *inode) -{ -memset (&UDF_I_LOCATION (inode),0xFF ,sizeof (kernel_lb_addr)); -} -static void __udf_read_inode (struct inode *inode) {
@@ -1567,66 +1525,36 @@return err; } -/* -* udf_iget -* -* PURPOSE -* Get an inode. -* -* DESCRIPTION -* This routine replaces iget() and read_inode(). -* -* HISTORY -* October 3, 1997 - Andrew E. Mileski -* Written, tested, and released. -* -* 12/19/98 dgb Added semaphore and changed to be a wrapper of iget -*/ struct inode *udf_iget (struct super_block *sb,kernel_lb_addr ino) { -struct inode *inode; -unsigned long block; - - block =udf_get_lb_pblock (sb, ino,0 ); - -/* Get the inode */ - - inode =iget (sb, block); -/* calls udf_read_inode() ! */ +unsigned long block =udf_get_lb_pblock (sb, ino,0 ); +struct inode *inode =iget_locked (sb, block);if (!inode) - { -printk (KERN_ERR "udf: iget() failed\n" );return NULL ; - } -else if (is_bad_inode (inode)) - { -iput (inode); -return NULL ; - } -else if (UDF_I_LOCATION (inode).logicalBlockNum ==0xFFFFFFFF && -UDF_I_LOCATION (inode).partitionReferenceNum ==0xFFFF ) - { + +if (inode->i_state &I_NEW ) {memcpy (&UDF_I_LOCATION (inode), &ino,sizeof (kernel_lb_addr));__udf_read_inode (inode); -if (is_bad_inode (inode)) - { -iput (inode); -return NULL ; - } +unlock_new_inode (inode); } -if ( ino.logicalBlockNum >=UDF_SB_PARTLEN (sb, ino.partitionReferenceNum) ) - { +if (is_bad_inode (inode)) + goto out_iput; + +if (ino.logicalBlockNum >=UDF_SB_PARTLEN (sb, ino.partitionReferenceNum)) {udf_debug ("block=%d, partition=%d out of range\n" , ino.logicalBlockNum, ino.partitionReferenceNum);make_bad_inode (inode); -iput (inode); -return NULL ; - } + goto out_iput; + }return inode; + + out_iput: +iput (inode); +return NULL ; } int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
fs/udf/super.c +0 -1
@@ -162,7 +162,6 @@static struct super_operations udf_sb_ops = { .alloc_inode = udf_alloc_inode, .destroy_inode = udf_destroy_inode, - .read_inode = udf_read_inode, .write_inode = udf_write_inode, .put_inode = udf_put_inode, .delete_inode = udf_delete_inode,