HAMMER - Fix long stalls when writing out core files
authorMatthew Dillon <dillon@apollo.backplane.com>
Mon, 21 Feb 2011 02:26:17 +0000 (18:26 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Mon, 21 Feb 2011 02:26:17 +0000 (18:26 -0800)
* Fix a long-stall case (hmrwww) due to a broken pipelining algorithm when
  using large write()s to write out large files.

sys/vfs/hammer/hammer.h
sys/vfs/hammer/hammer_object.c
sys/vfs/hammer/hammer_vfsops.c
sys/vfs/hammer/hammer_vnops.c

index f85e6c5..a0bb98e 100644 (file)
@@ -437,7 +437,7 @@ typedef struct hammer_inode *hammer_inode_t;
 #define HAMMER_INODE_DELETED   0x0080  /* inode delete (backend) */
 #define HAMMER_INODE_DELONDISK 0x0100  /* delete synchronized to disk */
 #define HAMMER_INODE_RO                0x0200  /* read-only (because of as-of) */
-#define HAMMER_INODE_UNUSED0400        0x0400
+#define HAMMER_INODE_RECSW     0x0400  /* waiting on data record flush */
 #define HAMMER_INODE_DONDISK   0x0800  /* data records may be on disk */
 #define HAMMER_INODE_BUFS      0x1000  /* dirty high level bps present */
 #define HAMMER_INODE_REFLUSH   0x2000  /* flush on dependancy / reflush */
index 8786cc8..56b4a97 100644 (file)
@@ -447,8 +447,11 @@ hammer_rel_mem_record(struct hammer_record *record)
 
                                if (RB_EMPTY(&record->ip->rec_tree))
                                        hammer_test_inode(record->ip);
-                               if (ip->rsv_recs == hammer_limit_inode_recs - 1)
+                               if ((ip->flags & HAMMER_INODE_RECSW) &&
+                                   ip->rsv_recs <= hammer_limit_inode_recs/2) {
+                                       ip->flags &= ~HAMMER_INODE_RECSW;
                                        wakeup(&ip->rsv_recs);
+                               }
                        }
 
                        /*
index fd1e7d1..d83d900 100644 (file)
@@ -104,7 +104,7 @@ int hammer_count_io_locked;
 int hammer_limit_dirtybufspace;                /* per-mount */
 int hammer_limit_running_io;           /* per-mount */
 int hammer_limit_recs;                 /* as a whole XXX */
-int hammer_limit_inode_recs = 1024;    /* per inode */
+int hammer_limit_inode_recs = 2048;    /* per inode */
 int hammer_limit_reclaim;
 int hammer_live_dedup_cache_size = DEDUP_CACHE_SIZE;
 int hammer_limit_redo = 4096 * 1024;   /* per inode */
index 21e6106..fa1d68b 100644 (file)
@@ -581,15 +581,18 @@ hammer_vop_write(struct vop_write_args *ap)
                 * Control the number of pending records associated with
                 * this inode.  If too many have accumulated start a
                 * flush.  Try to maintain a pipeline with the flusher.
+                *
+                * NOTE: It is possible for other sources to grow the
+                *       records but not necessarily issue another flush,
+                *       so use a timeout and ensure that a re-flush occurs.
                 */
                if (ip->rsv_recs >= hammer_limit_inode_recs) {
                        hammer_flush_inode(ip, HAMMER_FLUSH_SIGNAL);
-               }
-               if (ip->rsv_recs >= hammer_limit_inode_recs * 2) {
-                       while (ip->rsv_recs >= hammer_limit_inode_recs) {
+                       while (ip->rsv_recs >= hammer_limit_inode_recs * 2) {
+                               ip->flags |= HAMMER_INODE_RECSW;
                                tsleep(&ip->rsv_recs, 0, "hmrwww", hz);
+                               hammer_flush_inode(ip, HAMMER_FLUSH_SIGNAL);
                        }
-                       hammer_flush_inode(ip, HAMMER_FLUSH_SIGNAL);
                }
 
 #if 0