diff options
author | Christoph Hellwig <hch@lst.de> | 2005-01-04 05:35:19 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-01-04 05:35:19 -0800 |
commit | 55521f5093f9ee5fe20b69f73fed4d4ba153918a (patch) | |
tree | a30bb6956bc99f9ebfda9a4df5f96b088626f02b /fs | |
parent | f2f1b44c75c478f541d87234c98606d7686c4209 (diff) | |
download | history-55521f5093f9ee5fe20b69f73fed4d4ba153918a.tar.gz |
[PATCH] udf: 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.
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/udf/inode.c | 84 | ||||
-rw-r--r-- | fs/udf/super.c | 1 |
2 files changed, 15 insertions, 70 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 47a58121dd3f06..a77b41ad72b121 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -920,30 +920,6 @@ void udf_truncate(struct inode * inode) 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 +1543,36 @@ udf_update_inode(struct inode *inode, int do_sync) 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, diff --git a/fs/udf/super.c b/fs/udf/super.c index f18fe61b48537d..2681bca58cc710 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -162,7 +162,6 @@ static void destroy_inodecache(void) 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, |