Whamcloud - gitweb
LU-1648 llog: prevent journal to restart for llog cancel
authorEmoly Liu <emoly.liu@intel.com>
Wed, 5 Dec 2012 07:25:21 +0000 (15:25 +0800)
committerOleg Drokin <green@whamcloud.com>
Thu, 6 Dec 2012 21:25:03 +0000 (16:25 -0500)
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 <yong.fan@whamcloud.com>
Signed-off-by: Liu Ying <emoly.liu@intel.com>
Change-Id: I4013eb764485c282ed2443d02556c3377e16c936
Reviewed-on: http://review.whamcloud.com/4743
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Niu Yawei <niu@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/autoconf/lustre-core.m4
lustre/lvfs/fsfilt_ext3.c

index 96a873e..297b3a5 100644 (file)
@@ -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 <linux/fs.h>
+       #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])
index 9f84125..d80f894 100644 (file)
@@ -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 <ext4/truncate.h>
+#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();