From 1758d14e8bf8af6abbeb87e5564424f8577c4494 Mon Sep 17 00:00:00 2001 From: Emoly Liu Date: Wed, 5 Dec 2012 15:25:21 +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. port of master patch 8d334f67052ccf77713c780a8040593728977599 Signed-off-by: Fan Yong Signed-off-by: Liu Ying Change-Id: I4013eb764485c282ed2443d02556c3377e16c936 Reviewed-on: http://review.whamcloud.com/4743 Tested-by: Hudson Tested-by: Maloo Reviewed-by: Niu Yawei Reviewed-by: Oleg Drokin --- lustre/autoconf/lustre-core.m4 | 23 +++++++++++++++++++++++ lustre/lvfs/fsfilt_ext3.c | 25 +++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 index 96a873e..297b3a5 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 @@ -2277,6 +2277,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 @@ -2440,6 +2460,9 @@ AC_DEFUN([LC_PROG_LINUX], # 2.6.39 LC_HAVE_FSTYPE_MOUNT + # 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 9f84125..d80f894 100644 --- a/lustre/lvfs/fsfilt_ext3.c +++ b/lustre/lvfs/fsfilt_ext3.c @@ -252,6 +252,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 @@ -329,10 +346,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: + LASSERT(logs == 1); + /* blocks for log header bitmap update OR - * blocks for catalog header bitmap update + unlink of logs */ + * blocks for catalog header bitmap update + unlink of logs + + * blocks for delete the inode (include blocks truncating). */ nblocks = (LLOG_CHUNK_SIZE >> inode->i_blkbits) + - FSFILT_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