Message ID | 4ABC7FC5.5070803@rs.jp.nec.com |
---|---|
State | Superseded, archived |
Headers | show |
On Sep 25, 2009 17:31 +0900, Akira Fujita wrote: > ext4: Add checks whether two inodes are different to move_extent.c > > From: Akira Fujita <a-fujita@rs.jp.nec.com> > > If same inode is set to orig and donor in ext4_move_extensts(), > this leads to the deadlock in mext_double_down_{read, write}. > This patch adds checks to mext_double_{down, up}_{read, write} > and if inodes are same, we take/release one semaphore from them. Wouldn't it make more sense to just return an error (or no error but do nothing) in the case of source/target inode being the same? I don't see how that would be good to "defragment" the inode onto itself, just like "cp f f" and "rename f f" don't make sense either. > Signed-off-by: Akira Fujita <a-fujita@rs.jp.nec.com> > --- > fs/ext4/move_extent.c | 14 +++++++++----- > 1 files changed, 9 insertions(+), 5 deletions(-) > > diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c > index c07a291..e1346cb 100644 > --- a/fs/ext4/move_extent.c > +++ b/fs/ext4/move_extent.c > @@ -177,7 +177,8 @@ mext_double_down_read(struct inode *orig_inode, struct inode *donor_inode) > } > > down_read(&EXT4_I(first)->i_data_sem); > - down_read(&EXT4_I(second)->i_data_sem); > + if (first != second) > + down_read(&EXT4_I(second)->i_data_sem); > } > > /** > @@ -203,7 +204,8 @@ mext_double_down_write(struct inode *orig_inode, struct inode *donor_inode) > } > > down_write(&EXT4_I(first)->i_data_sem); > - down_write(&EXT4_I(second)->i_data_sem); > + if (first != second) > + down_write(&EXT4_I(second)->i_data_sem); > } > > /** > @@ -217,7 +219,8 @@ static void > mext_double_up_read(struct inode *orig_inode, struct inode *donor_inode) > { > up_read(&EXT4_I(orig_inode)->i_data_sem); > - up_read(&EXT4_I(donor_inode)->i_data_sem); > + if (orig_inode != donor_inode) > + up_read(&EXT4_I(donor_inode)->i_data_sem); > } > > /** > @@ -231,7 +234,8 @@ static void > mext_double_up_write(struct inode *orig_inode, struct inode *donor_inode) > { > up_write(&EXT4_I(orig_inode)->i_data_sem); > - up_write(&EXT4_I(donor_inode)->i_data_sem); > + if (orig_inode != donor_inode) > + up_write(&EXT4_I(donor_inode)->i_data_sem); > } > > /** > @@ -1002,7 +1006,7 @@ mext_check_arguments(struct inode *orig_inode, > } > > /* orig and donor should be different file */ > - if (orig_inode->i_ino == donor_inode->i_ino) { > + if (orig_inode == donor_inode) { > ext4_debug("ext4 move extent: The argument files should not " > "be same file [ino:orig %lu, donor %lu]\n", > orig_inode->i_ino, donor_inode->i_ino); > > -- > To unsubscribe from this list: send the line "unsubscribe linux-ext4" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html Cheers, Andreas -- Andreas Dilger Sr. Staff Engineer, Lustre Group Sun Microsystems of Canada, Inc. -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index c07a291..e1346cb 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -177,7 +177,8 @@ mext_double_down_read(struct inode *orig_inode, struct inode *donor_inode) } down_read(&EXT4_I(first)->i_data_sem); - down_read(&EXT4_I(second)->i_data_sem); + if (first != second) + down_read(&EXT4_I(second)->i_data_sem); } /** @@ -203,7 +204,8 @@ mext_double_down_write(struct inode *orig_inode, struct inode *donor_inode) } down_write(&EXT4_I(first)->i_data_sem); - down_write(&EXT4_I(second)->i_data_sem); + if (first != second) + down_write(&EXT4_I(second)->i_data_sem); } /** @@ -217,7 +219,8 @@ static void mext_double_up_read(struct inode *orig_inode, struct inode *donor_inode) { up_read(&EXT4_I(orig_inode)->i_data_sem); - up_read(&EXT4_I(donor_inode)->i_data_sem); + if (orig_inode != donor_inode) + up_read(&EXT4_I(donor_inode)->i_data_sem); } /** @@ -231,7 +234,8 @@ static void mext_double_up_write(struct inode *orig_inode, struct inode *donor_inode) { up_write(&EXT4_I(orig_inode)->i_data_sem); - up_write(&EXT4_I(donor_inode)->i_data_sem); + if (orig_inode != donor_inode) + up_write(&EXT4_I(donor_inode)->i_data_sem); } /** @@ -1002,7 +1006,7 @@ mext_check_arguments(struct inode *orig_inode, } /* orig and donor should be different file */ - if (orig_inode->i_ino == donor_inode->i_ino) { + if (orig_inode == donor_inode) { ext4_debug("ext4 move extent: The argument files should not " "be same file [ino:orig %lu, donor %lu]\n", orig_inode->i_ino, donor_inode->i_ino);