HAMMER 61C/Many: Stabilization
authorMatthew Dillon <dillon@dragonflybsd.org>
Fri, 11 Jul 2008 05:44:23 +0000 (05:44 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Fri, 11 Jul 2008 05:44:23 +0000 (05:44 +0000)
* Clean up flusher sequencing for the mirroring, pruning, and reblocking
  code.  Check free space and don't let the buffer cache implode.

sys/vfs/hammer/hammer.h
sys/vfs/hammer/hammer_flusher.c
sys/vfs/hammer/hammer_mirror.c
sys/vfs/hammer/hammer_prune.c
sys/vfs/hammer/hammer_reblock.c
sys/vfs/hammer/hammer_vnops.c

index 2f3f980..0023c7e 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.111 2008/07/11 01:22:29 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.112 2008/07/11 05:44:23 dillon Exp $
  */
 /*
  * This header file contains structures used internally by the HAMMERFS
@@ -722,10 +722,11 @@ struct hammer_sync_info {
 /*
  * checkspace slop (8MB chunks), higher numbers are more conservative.
  */
-#define HAMMER_CHECKSPACE_SLOP_REBLOCK 25
-#define HAMMER_CHECKSPACE_SLOP_WRITE   20
-#define HAMMER_CHECKSPACE_SLOP_CREATE  20
-#define HAMMER_CHECKSPACE_SLOP_REMOVE  10
+#define HAMMER_CHKSPC_REBLOCK  25
+#define HAMMER_CHKSPC_MIRROR   20
+#define HAMMER_CHKSPC_WRITE    20
+#define HAMMER_CHKSPC_CREATE   20
+#define HAMMER_CHKSPC_REMOVE   10
 
 #if defined(_KERNEL)
 
@@ -1081,8 +1082,10 @@ int hammer_signal_check(hammer_mount_t hmp);
 void hammer_flusher_create(hammer_mount_t hmp);
 void hammer_flusher_destroy(hammer_mount_t hmp);
 void hammer_flusher_sync(hammer_mount_t hmp);
-void hammer_flusher_async(hammer_mount_t hmp);
+int  hammer_flusher_async(hammer_mount_t hmp);
+void hammer_flusher_wait(hammer_mount_t hmp, int seq);
 int  hammer_flusher_meta_limit(hammer_mount_t hmp);
+int  hammer_flusher_meta_halflimit(hammer_mount_t hmp);
 int  hammer_flusher_undo_exhausted(hammer_transaction_t trans, int quarter);
 void hammer_flusher_clean_loose_ios(hammer_mount_t hmp);
 void hammer_flusher_finalize(hammer_transaction_t trans, int final);
index 9ffeb45..53513a9 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_flusher.c,v 1.35 2008/07/11 01:22:29 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_flusher.c,v 1.36 2008/07/11 05:44:23 dillon Exp $
  */
 /*
  * HAMMER dependancy flusher thread
@@ -81,13 +81,26 @@ hammer_flusher_sync(hammer_mount_t hmp)
 /*
  * Sync all inodes pending on the flusher - return immediately.
  */
-void
+int
 hammer_flusher_async(hammer_mount_t hmp)
 {
+       int seq;
+
        if (hmp->flusher.td) {
+               seq = hmp->flusher.next;
                if (hmp->flusher.signal++ == 0)
                        wakeup(&hmp->flusher.signal);
+       } else {
+               seq = hmp->flusher.done;
        }
+       return(seq);
+}
+
+void
+hammer_flusher_wait(hammer_mount_t hmp, int seq)
+{
+       while ((int)(seq - hmp->flusher.done) > 0)
+               tsleep(&hmp->flusher.done, 0, "hmrfls", 0);
 }
 
 void
@@ -597,3 +610,13 @@ hammer_flusher_meta_limit(hammer_mount_t hmp)
        return(0);
 }
 
+int
+hammer_flusher_meta_halflimit(hammer_mount_t hmp)
+{
+       if (hmp->locked_dirty_space + hmp->io_running_space >
+           hammer_limit_dirtybufspace / 2) {
+               return(1);
+       }
+       return(0);
+}
+
index 16df3fd..74daef4 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_mirror.c,v 1.11 2008/07/11 01:22:29 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_mirror.c,v 1.12 2008/07/11 05:44:23 dillon Exp $
  */
 /*
  * HAMMER mirroring ioctls - serialize and deserialize modifications made
@@ -132,6 +132,15 @@ retry:
 
        error = hammer_btree_first(&cursor);
        while (error == 0) {
+               /*
+                * Yield to more important tasks
+                */
+               if (error == 0) {
+                       error = hammer_signal_check(trans->hmp);
+                       if (error)
+                               break;
+               }
+
                /*
                 * An internal node can be returned in mirror-filtered
                 * mode and indicates that the scan is returning a skip
@@ -210,20 +219,6 @@ retry:
                        
                }
 
-               /*
-                * Yield to more important tasks
-                */
-               if ((error = hammer_signal_check(trans->hmp)) != 0)
-                       break;
-               if (trans->hmp->sync_lock.wanted) {
-                       tsleep(trans, 0, "hmrslo", hz / 10);
-               }
-               if (trans->hmp->locked_dirty_space +
-                   trans->hmp->io_running_space > hammer_limit_dirtybufspace) {
-                       hammer_flusher_async(trans->hmp);
-                       tsleep(trans, 0, "hmrslo", hz / 10);
-               }
-
                /*
                 * The core code exports the data to userland.
                 */
@@ -312,11 +307,14 @@ hammer_ioc_mirror_write(hammer_transaction_t trans, hammer_inode_t ip,
        union hammer_ioc_mrecord_any mrec;
        struct hammer_cursor cursor;
        u_int32_t localization;
+       int checkspace_count = 0;
        int error;
        int bytes;
        char *uptr;
+       int seq;
 
        localization = (u_int32_t)mirror->pfs_id << 16;
+       seq = trans->hmp->flusher.act;
 
        /*
         * Validate the mirror structure and relocalize the tracking keys.
@@ -350,7 +348,35 @@ hammer_ioc_mirror_write(hammer_transaction_t trans, hammer_inode_t ip,
         * Loop until our input buffer has been exhausted.
         */
        while (error == 0 &&
-              mirror->count + sizeof(mrec.head) <= mirror->size) {
+               mirror->count + sizeof(mrec.head) <= mirror->size) {
+
+               /*
+                * Don't blow out the buffer cache.  Leave room for frontend
+                * cache as well.
+                */
+               if (hammer_flusher_meta_halflimit(trans->hmp) ||
+                   hammer_flusher_undo_exhausted(trans, 1)) {
+                       hammer_unlock_cursor(&cursor, 0);
+                       hammer_flusher_wait(trans->hmp, seq);
+                       hammer_lock_cursor(&cursor, 0);
+                       seq = hammer_flusher_async(trans->hmp);
+               }
+
+               /*
+                * If there is insufficient free space it may be due to
+                * reserved bigblocks, which flushing might fix.
+                */
+               if (hammer_checkspace(trans->hmp, HAMMER_CHKSPC_MIRROR)) {
+                       if (++checkspace_count == 10) {
+                               error = ENOSPC;
+                               break;
+                       }
+                       hammer_unlock_cursor(&cursor, 0);
+                       hammer_flusher_wait(trans->hmp, seq);
+                       hammer_lock_cursor(&cursor, 0);
+                       seq = hammer_flusher_async(trans->hmp);
+               }
+
 
                /*
                 * Acquire and validate header
@@ -669,8 +695,6 @@ hammer_mirror_delete_at_cursor(hammer_cursor_t cursor,
        elm = &cursor->node->ondisk->elms[cursor->index];
        KKASSERT(elm->leaf.base.btype == HAMMER_BTREE_TYPE_RECORD);
 
-       kprintf("mirror_delete %016llx %016llx\n", elm->leaf.base.obj_id, elm->leaf.base.key);
-
        trans = cursor->trans;
        hammer_sync_lock_sh(trans);
 
index 3b83b7a..d92696e 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_prune.c,v 1.13 2008/07/11 01:22:29 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_prune.c,v 1.14 2008/07/11 05:44:23 dillon Exp $
  */
 
 #include "hammer.h"
@@ -60,6 +60,7 @@ hammer_ioc_prune(hammer_transaction_t trans, hammer_inode_t ip,
        int error;
        int isdir;
        int elm_array_size;
+       int seq;
 
        if (prune->nelms < 0 || prune->nelms > HAMMER_MAX_PRUNE_ELMS)
                return(EINVAL);
@@ -92,6 +93,8 @@ hammer_ioc_prune(hammer_transaction_t trans, hammer_inode_t ip,
                goto failed;
        prune->elms = copy_elms;
 
+       seq = trans->hmp->flusher.act;
+
        /*
         * Scan backwards.  Retries typically occur if a deadlock is detected.
         */
@@ -140,11 +143,6 @@ retry:
                 */
                if ((error = hammer_signal_check(trans->hmp)) != 0)
                        break;
-               if (hammer_flusher_meta_limit(trans->hmp) ||
-                   hammer_flusher_undo_exhausted(trans, 2)) {
-                       error = EWOULDBLOCK;
-                       break;
-               }
 
                if (prune->stat_oldest_tid > elm->base.create_tid)
                        prune->stat_oldest_tid = elm->base.create_tid;
@@ -204,15 +202,19 @@ retry:
                        }
                }
                ++prune->stat_scanrecords;
+
+               if (hammer_flusher_meta_halflimit(trans->hmp) ||
+                   hammer_flusher_undo_exhausted(trans, 1)) {
+                       hammer_unlock_cursor(&cursor, 0);
+                       hammer_flusher_wait(trans->hmp, seq);
+                       hammer_lock_cursor(&cursor, 0);
+                       seq = hammer_flusher_async(trans->hmp);
+               }
                error = hammer_btree_iterate_reverse(&cursor);
        }
        if (error == ENOENT)
                error = 0;
        hammer_done_cursor(&cursor);
-       if (error == EWOULDBLOCK) {
-               hammer_flusher_sync(trans->hmp);
-               goto retry;
-       }
        if (error == EDEADLK)
                goto retry;
        if (error == EINTR) {
index b60e3c3..8ae2a3e 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_reblock.c,v 1.26 2008/07/11 01:22:29 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_reblock.c,v 1.27 2008/07/11 05:44:23 dillon Exp $
  */
 /*
  * HAMMER reblocker - This code frees up fragmented physical space
@@ -61,8 +61,9 @@ hammer_ioc_reblock(hammer_transaction_t trans, hammer_inode_t ip,
 {
        struct hammer_cursor cursor;
        hammer_btree_elm_t elm;
-       int error;
        int checkspace_count;
+       int error;
+       int seq;
 
        if ((reblock->key_beg.localization | reblock->key_end.localization) &
            HAMMER_LOCALIZE_PSEUDOFS_MASK) {
@@ -77,6 +78,7 @@ hammer_ioc_reblock(hammer_transaction_t trans, hammer_inode_t ip,
        reblock->key_cur.localization += ip->obj_localization;
 
        checkspace_count = 0;
+       seq = trans->hmp->flusher.act;
 retry:
        error = hammer_init_cursor(trans, &cursor, NULL, NULL);
        if (error) {
@@ -126,27 +128,19 @@ retry:
                if ((error = hammer_signal_check(trans->hmp)) != 0)
                        break;
 
-               /*
-                * If we build up too much meta-data we have to wait for
-                * a flush cycle.
-                */
-               if (hammer_flusher_meta_limit(trans->hmp) ||
-                   hammer_flusher_undo_exhausted(trans, 2)) {
-                       error = EWOULDBLOCK;
-                       break;
-               }
-
                /*
                 * If there is insufficient free space it may be due to
                 * reserved bigblocks, which flushing might fix.
                 */
-               if (hammer_checkspace(trans->hmp, HAMMER_CHECKSPACE_SLOP_REBLOCK)) {
+               if (hammer_checkspace(trans->hmp, HAMMER_CHKSPC_REBLOCK)) {
                        if (++checkspace_count == 10) {
                                error = ENOSPC;
-                       } else {
-                               error = EWOULDBLOCK;
+                               break;
                        }
-                       break;
+                       hammer_unlock_cursor(&cursor, 0);
+                       hammer_flusher_wait(trans->hmp, seq);
+                       hammer_lock_cursor(&cursor, 0);
+                       seq = hammer_flusher_async(trans->hmp);
                }
 
                /*
@@ -158,6 +152,14 @@ retry:
                hammer_sync_lock_sh(trans);
                error = hammer_reblock_helper(reblock, &cursor, elm);
                hammer_sync_unlock(trans);
+
+               if (hammer_flusher_meta_halflimit(trans->hmp) ||
+                   hammer_flusher_undo_exhausted(trans, 1)) {
+                       hammer_unlock_cursor(&cursor, 0);
+                       hammer_flusher_wait(trans->hmp, seq);
+                       hammer_lock_cursor(&cursor, 0);
+                       seq = hammer_flusher_async(trans->hmp);
+               }
                if (error == 0) {
                        cursor.flags |= HAMMER_CURSOR_ATEDISK;
                        error = hammer_btree_iterate(&cursor);
index 9cffcc4..98bdcc1 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.85 2008/07/10 04:44:33 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.86 2008/07/11 05:44:23 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -352,7 +352,7 @@ hammer_vop_write(struct vop_write_args *ap)
                int blksize;
                int blkmask;
 
-               if ((error = hammer_checkspace(hmp, HAMMER_CHECKSPACE_SLOP_WRITE)) != 0)
+               if ((error = hammer_checkspace(hmp, HAMMER_CHKSPC_WRITE)) != 0)
                        break;
 
                blksize = hammer_blocksize(uio->uio_offset);
@@ -580,7 +580,7 @@ hammer_vop_ncreate(struct vop_ncreate_args *ap)
 
        if (dip->flags & HAMMER_INODE_RO)
                return (EROFS);
-       if ((error = hammer_checkspace(dip->hmp, HAMMER_CHECKSPACE_SLOP_CREATE)) != 0)
+       if ((error = hammer_checkspace(dip->hmp, HAMMER_CHKSPC_CREATE)) != 0)
                return (error);
 
        /*
@@ -977,7 +977,7 @@ hammer_vop_nlink(struct vop_nlink_args *ap)
                return (EROFS);
        if (ip->flags & HAMMER_INODE_RO)
                return (EROFS);
-       if ((error = hammer_checkspace(dip->hmp, HAMMER_CHECKSPACE_SLOP_CREATE)) != 0)
+       if ((error = hammer_checkspace(dip->hmp, HAMMER_CHKSPC_CREATE)) != 0)
                return (error);
 
        /*
@@ -1026,7 +1026,7 @@ hammer_vop_nmkdir(struct vop_nmkdir_args *ap)
 
        if (dip->flags & HAMMER_INODE_RO)
                return (EROFS);
-       if ((error = hammer_checkspace(dip->hmp, HAMMER_CHECKSPACE_SLOP_CREATE)) != 0)
+       if ((error = hammer_checkspace(dip->hmp, HAMMER_CHKSPC_CREATE)) != 0)
                return (error);
 
        /*
@@ -1095,7 +1095,7 @@ hammer_vop_nmknod(struct vop_nmknod_args *ap)
 
        if (dip->flags & HAMMER_INODE_RO)
                return (EROFS);
-       if ((error = hammer_checkspace(dip->hmp, HAMMER_CHECKSPACE_SLOP_CREATE)) != 0)
+       if ((error = hammer_checkspace(dip->hmp, HAMMER_CHKSPC_CREATE)) != 0)
                return (error);
 
        /*
@@ -1440,7 +1440,7 @@ hammer_vop_nremove(struct vop_nremove_args *ap)
        dip = VTOI(ap->a_dvp);
 
        if (hammer_nohistory(dip) == 0 &&
-           (error = hammer_checkspace(dip->hmp, HAMMER_CHECKSPACE_SLOP_REMOVE)) != 0) {
+           (error = hammer_checkspace(dip->hmp, HAMMER_CHKSPC_REMOVE)) != 0) {
                return (error);
        }
 
@@ -1481,7 +1481,7 @@ hammer_vop_nrename(struct vop_nrename_args *ap)
                return (EROFS);
        if (ip->flags & HAMMER_INODE_RO)
                return (EROFS);
-       if ((error = hammer_checkspace(fdip->hmp, HAMMER_CHECKSPACE_SLOP_CREATE)) != 0)
+       if ((error = hammer_checkspace(fdip->hmp, HAMMER_CHKSPC_CREATE)) != 0)
                return (error);
 
        hammer_start_transaction(&trans, fdip->hmp);
@@ -1597,7 +1597,7 @@ hammer_vop_nrmdir(struct vop_nrmdir_args *ap)
        dip = VTOI(ap->a_dvp);
 
        if (hammer_nohistory(dip) == 0 &&
-           (error = hammer_checkspace(dip->hmp, HAMMER_CHECKSPACE_SLOP_REMOVE)) != 0) {
+           (error = hammer_checkspace(dip->hmp, HAMMER_CHKSPC_REMOVE)) != 0) {
                return (error);
        }
 
@@ -1634,7 +1634,7 @@ hammer_vop_setattr(struct vop_setattr_args *ap)
        if (ip->flags & HAMMER_INODE_RO)
                return (EROFS);
        if (hammer_nohistory(ip) == 0 &&
-           (error = hammer_checkspace(ip->hmp, HAMMER_CHECKSPACE_SLOP_REMOVE)) != 0) {
+           (error = hammer_checkspace(ip->hmp, HAMMER_CHKSPC_REMOVE)) != 0) {
                return (error);
        }
 
@@ -1835,7 +1835,7 @@ hammer_vop_nsymlink(struct vop_nsymlink_args *ap)
 
        if (dip->flags & HAMMER_INODE_RO)
                return (EROFS);
-       if ((error = hammer_checkspace(dip->hmp, HAMMER_CHECKSPACE_SLOP_CREATE)) != 0)
+       if ((error = hammer_checkspace(dip->hmp, HAMMER_CHKSPC_CREATE)) != 0)
                return (error);
 
        /*
@@ -1923,7 +1923,7 @@ hammer_vop_nwhiteout(struct vop_nwhiteout_args *ap)
        dip = VTOI(ap->a_dvp);
 
        if (hammer_nohistory(dip) == 0 &&
-           (error = hammer_checkspace(dip->hmp, HAMMER_CHECKSPACE_SLOP_CREATE)) != 0) {
+           (error = hammer_checkspace(dip->hmp, HAMMER_CHKSPC_CREATE)) != 0) {
                return (error);
        }