From 8d334f67052ccf77713c780a8040593728977599 Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Sun, 5 Aug 2012 23:59:38 +0800 Subject: [PATCH] LU-1648 llog: prevent journal to restart for llog cancel Journal credit for llog cancel should include the blocks for deleting the inode. Otherwise the journal handle may need to be restarted during the transaction for more credit. Then it may be blocked with holding llog_handle::lgh_lock, which may cause deadlock with other llog operations those have started journal handle but waiting for the llog_handle::lgh_lock. Signed-off-by: Fan Yong Change-Id: I157093cbe9e625715ec033f59dde325e81ec6b71 Reviewed-on: http://review.whamcloud.com/3463 Tested-by: Hudson Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Niu Yawei Reviewed-by: Oleg Drokin --- lustre/autoconf/lustre-core.m4 | 23 +++++++++++++++++++++++ lustre/lvfs/fsfilt_ext3.c | 27 ++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 index 1168898..9603e50 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 @@ -1848,6 +1848,26 @@ LB_LINUX_TRY_COMPILE([ ]) # +# 3.1.1 has ext4_blocks_for_truncate +# +AC_DEFUN([LC_BLOCKS_FOR_TRUNCATE], +[AC_MSG_CHECKING([if kernel has ext4_blocks_for_truncate]) +LB_LINUX_TRY_COMPILE([ + #include + #include "$LINUX/fs/ext4/ext4_jbd2.h" + #include "$LINUX/fs/ext4/truncate.h" +],[ + ext4_blocks_for_truncate(NULL); +],[ + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_BLOCKS_FOR_TRUNCATE, 1, + [kernel has ext4_blocks_for_truncate]) +],[ + AC_MSG_RESULT([no]) +]) +]) + +# # LC_PROG_LINUX # # Lustre linux kernel checks @@ -1994,6 +2014,9 @@ AC_DEFUN([LC_PROG_LINUX], LC_HAVE_MIGRATE_HEADER LC_MIGRATEPAGE_4ARGS + # 3.1.1 + LC_BLOCKS_FOR_TRUNCATE + # if test x$enable_server = xyes ; then AC_DEFINE(HAVE_SERVER_SUPPORT, 1, [support server]) diff --git a/lustre/lvfs/fsfilt_ext3.c b/lustre/lvfs/fsfilt_ext3.c index b341502..5ac2add 100644 --- a/lustre/lvfs/fsfilt_ext3.c +++ b/lustre/lvfs/fsfilt_ext3.c @@ -221,6 +221,23 @@ static __u64 fsfilt_ext3_set_version(struct inode *inode, __u64 new_version) #endif +/* kernel has ext4_blocks_for_truncate since linux-3.1.1 */ +#ifdef HAVE_BLOCKS_FOR_TRUNCATE +# include +#else +static inline unsigned long ext4_blocks_for_truncate(struct inode *inode) +{ + ext4_lblk_t needed; + + needed = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9); + if (needed < 2) + needed = 2; + if (needed > EXT4_MAX_TRANS_DATA) + needed = EXT4_MAX_TRANS_DATA; + return EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + needed; +} +#endif + /* * We don't currently need any additional blocks for rmdir and * unlink transactions because we are storing the OST oa_id inside @@ -283,10 +300,14 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private, FSFILT_SINGLEDATA_TRANS_BLOCKS(inode->i_sb)) * logs; break; case FSFILT_OP_CANCEL_UNLINK: - /* blocks for log header bitmap update OR - * blocks for catalog header bitmap update + unlink of logs */ + LASSERT(logs == 1); + + /* blocks for log header bitmap update OR + * blocks for catalog header bitmap update + unlink of logs + + * blocks for delete the inode (include blocks truncating). */ nblocks = (LLOG_CHUNK_SIZE >> inode->i_blkbits) + - EXT3_DELETE_TRANS_BLOCKS(inode->i_sb) * logs; + EXT3_DELETE_TRANS_BLOCKS(inode->i_sb) + + ext4_blocks_for_truncate(inode) + 3; break; default: CERROR("unknown transaction start op %d\n", op); LBUG(); -- 1.8.3.1