Whamcloud - gitweb
LU-1648 llog: prevent journal to restart for llog cancel
authorFan Yong <yong.fan@whamcloud.com>
Sun, 5 Aug 2012 15:59:38 +0000 (23:59 +0800)
committerOleg Drokin <green@whamcloud.com>
Thu, 9 Aug 2012 02:13:34 +0000 (22:13 -0400)
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 <yong.fan@whamcloud.com>
Change-Id: I157093cbe9e625715ec033f59dde325e81ec6b71
Reviewed-on: http://review.whamcloud.com/3463
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.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 1168898..9603e50 100644 (file)
@@ -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 <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
@@ -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])
index b341502..5ac2add 100644 (file)
@@ -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 <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
@@ -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();