HAMMER 33C/many: features and bug fixes.
authorMatthew Dillon <dillon@dragonflybsd.org>
Thu, 20 Mar 2008 06:08:40 +0000 (06:08 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Thu, 20 Mar 2008 06:08:40 +0000 (06:08 +0000)
* Add a signal test for long-running ioctl's which allows them to be
  interrupted.

* Assert that a record update's delete_tid does not match it's create_tid
  and fix a case in the rename code and another case in the inode update
  code where this could occur.

* Add a feature to the pruning ioctl that the new snapshot softlink
  option for 'hammer prune' needs.

* Fix a minor overflow assertion in the transaction code.

sys/vfs/hammer/Makefile
sys/vfs/hammer/hammer.h
sys/vfs/hammer/hammer_inode.c
sys/vfs/hammer/hammer_ioctl.c
sys/vfs/hammer/hammer_ioctl.h
sys/vfs/hammer/hammer_object.c
sys/vfs/hammer/hammer_reblock.c
sys/vfs/hammer/hammer_signal.c [new file with mode: 0644]
sys/vfs/hammer/hammer_transaction.c

index 0a51042..98ab820 100644 (file)
@@ -1,9 +1,9 @@
 #
-# $DragonFly: src/sys/vfs/hammer/Makefile,v 1.9 2008/03/18 05:19:15 dillon Exp $
+# $DragonFly: src/sys/vfs/hammer/Makefile,v 1.10 2008/03/20 06:08:40 dillon Exp $
 
 KMOD=  hammer
 SRCS=  hammer_vfsops.c hammer_vnops.c hammer_inode.c \
-       hammer_subs.c hammer_ondisk.c hammer_io.c \
+       hammer_subs.c hammer_ondisk.c hammer_io.c hammer_signal.c \
        hammer_cursor.c hammer_btree.c hammer_transaction.c \
        hammer_object.c hammer_recover.c hammer_ioctl.c \
        hammer_blockmap.c hammer_freemap.c hammer_undo.c \
index 2d1ec44..bf8e3c6 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.41 2008/03/19 20:18:17 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.42 2008/03/20 06:08:40 dillon Exp $
  */
 /*
  * This header file contains structures used internally by the HAMMERFS
@@ -56,6 +56,7 @@
 #include <sys/globaldata.h>
 
 #include <sys/buf2.h>
+#include <sys/signal2.h>
 #include "hammer_disk.h"
 #include "hammer_mount.h"
 #include "hammer_ioctl.h"
@@ -162,6 +163,7 @@ struct hammer_inode {
        u_int64_t       obj_id;         /* (key) object identifier */
        hammer_tid_t    obj_asof;       /* (key) snapshot transid or 0 */
        hammer_tid_t    last_tid;       /* last modified tid (for fsync) */
+       hammer_tid_t    sync_tid;       /* last inode tid synced to disk */
        struct hammer_mount *hmp;
        int             flags;
        struct vnode    *vp;
@@ -413,6 +415,7 @@ struct hammer_mount {
        int     ronly;
        int     nvolumes;
        int     volume_iterator;
+       u_int   check_interrupt;
        uuid_t  fsid;
        udev_t  fsid_udev;
        hammer_tid_t asof;
@@ -661,6 +664,7 @@ int hammer_ioc_reblock(hammer_transaction_t trans, hammer_inode_t ip,
 
 void hammer_init_holes(hammer_mount_t hmp, hammer_holes_t holes);
 void hammer_free_holes(hammer_mount_t hmp, hammer_holes_t holes);
+int hammer_signal_check(hammer_mount_t hmp);
 
 #endif
 
index b907c1c..a853b50 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_inode.c,v 1.31 2008/03/19 20:18:17 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.32 2008/03/20 06:08:40 dillon Exp $
  */
 
 #include "hammer.h"
@@ -239,6 +239,7 @@ retry:
        if (*errorp == 0) {
                ip->ino_rec = cursor.record->inode;
                ip->ino_data = cursor.data->inode;
+               ip->sync_tid = ip->ino_rec.base.base.create_tid;
                hammer_cache_node(cursor.node, &ip->cache[0]);
                if (cache)
                        hammer_cache_node(cursor.node, cache);
@@ -367,7 +368,6 @@ hammer_update_inode(hammer_transaction_t trans, hammer_inode_t ip)
        struct hammer_cursor cursor;
        hammer_record_t record;
        int error;
-       hammer_tid_t last_tid;
 
        /*
         * Locate the record on-disk and mark it as deleted.  Both the B-Tree
@@ -380,7 +380,6 @@ hammer_update_inode(hammer_transaction_t trans, hammer_inode_t ip)
         * XXX Update the inode record and data in-place if the retention
         * policy allows it.
         */
-       last_tid = ip->last_tid;
 retry:
        error = 0;
 
@@ -399,7 +398,7 @@ retry:
                error = hammer_btree_lookup(&cursor);
 
                if (error == 0) {
-                       error = hammer_ip_delete_record(&cursor, last_tid);
+                       error = hammer_ip_delete_record(&cursor, trans->tid);
                        if (error == 0)
                                ip->flags |= HAMMER_INODE_DELONDISK;
                        hammer_cache_node(cursor.node, &ip->cache[0]);
@@ -420,7 +419,7 @@ retry:
        if (error == 0 && (ip->flags & HAMMER_INODE_DELETED) == 0) { 
                record = hammer_alloc_mem_record(ip);
                record->rec.inode = ip->ino_rec;
-               record->rec.inode.base.base.create_tid = last_tid;
+               record->rec.inode.base.base.create_tid = trans->tid;
                record->rec.inode.base.data_len = sizeof(ip->ino_data);
                record->data = (void *)&ip->ino_data;
                error = hammer_ip_sync_record(trans, record);
@@ -443,6 +442,7 @@ retry:
                         * we have written it out to disk.
                         */
                        ip->flags &= ~HAMMER_INODE_TIDLOCKED;
+                       ip->sync_tid = trans->tid;
                }
        }
        return(error);
@@ -626,9 +626,10 @@ hammer_sync_inode(hammer_inode_t ip, int waitfor, int handle_delete)
        hammer_lock_ex(&ip->lock);
 
        /*
-        * Use the transaction id of the last operation to sync.
+        * Use the transaction id of the last operation to sync.  But we
+        * can't reuse a previous sync TID.
         */
-       if (ip->last_tid)
+       if (ip->last_tid && ip->last_tid != ip->sync_tid)
                hammer_start_transaction_tid(&trans, ip->hmp, ip->last_tid);
        else
                hammer_start_transaction(&trans, ip->hmp);
index 8028eaa..075457d 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_ioctl.c,v 1.6 2008/03/19 20:18:17 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_ioctl.c,v 1.7 2008/03/20 06:08:40 dillon Exp $
  */
 
 #include "hammer.h"
@@ -134,6 +134,9 @@ retry:
                prune->cur_obj_id = elm->base.obj_id;
                prune->cur_key = elm->base.key;
 
+               if (prune->stat_oldest_tid > elm->leaf.base.create_tid)
+                       prune->stat_oldest_tid = elm->leaf.base.create_tid;
+
                if (check_prune(prune, elm, &realign_cre, &realign_del) == 0) {
                        if (hammer_debug_general & 0x0200) {
                                kprintf("check %016llx %016llx: DELETE\n",
@@ -173,6 +176,7 @@ retry:
                                        elm->base.obj_id, elm->base.key);
                        }
                }
+               error = hammer_signal_check(trans->hmp);
                if (error == 0)
                        error = hammer_btree_iterate_reverse(&cursor);
        }
index 8292f11..238e253 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_ioctl.h,v 1.4 2008/03/18 05:19:16 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_ioctl.h,v 1.5 2008/03/20 06:08:40 dillon Exp $
  */
 /*
  * HAMMER ioctl's.  This file can be #included from userland
@@ -70,7 +70,8 @@ struct hammer_ioc_prune {
        int64_t         stat_dirrecords; /* number of dir records pruned */
        int64_t         stat_bytes;      /* number of data bytes pruned */
        int64_t         stat_realignments; /* number of raw records realigned */
-       int64_t         reserved02[7];
+       hammer_tid_t    stat_oldest_tid; /* oldest create_tid encountered */
+       int64_t         reserved02[6];
        struct hammer_ioc_prune_elm elms[HAMMER_MAX_PRUNE_ELMS];
 };
 
index 99b2c1d..ca01bbf 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_object.c,v 1.36 2008/03/19 20:18:17 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.37 2008/03/20 06:08:40 dillon Exp $
  */
 
 #include "hammer.h"
@@ -399,6 +399,11 @@ hammer_ip_del_directory(struct hammer_transaction *trans,
         *
         * We have to terminate the cursor before syncing the inode to
         * avoid deadlocking against ourselves.
+        *
+        * XXX we can't sync the inode here because the encompassing
+        * transaction might be a rename and might update the inode
+        * again with a new link.  That would force the delete_tid to be
+        * the same as the create_tid and cause a panic.
         */
        if (error == 0) {
                --ip->ino_rec.ino_nlinks;
@@ -406,7 +411,7 @@ hammer_ip_del_directory(struct hammer_transaction *trans,
                if (ip->ino_rec.ino_nlinks == 0 &&
                    (ip->vp == NULL || (ip->vp->v_flag & VINACTIVE))) {
                        hammer_done_cursor(cursor);
-                       hammer_sync_inode(ip, MNT_NOWAIT, 1);
+                       /*hammer_sync_inode(ip, MNT_NOWAIT, 1);*/
                }
 
        }
@@ -879,6 +884,8 @@ hammer_ip_first(hammer_cursor_t cursor, struct hammer_inode *ip)
                error = hammer_btree_lookup(cursor);
                if (error == ENOENT || error == EDEADLK) {
                        cursor->flags &= ~HAMMER_CURSOR_ATEDISK;
+                       if (hammer_debug_general & 0x2000)
+                               kprintf("error %d node %p %016llx index %d\n", error, cursor->node, cursor->node->node_offset, cursor->index);
                        error = hammer_btree_iterate(cursor);
                }
                if (error && error != ENOENT) 
@@ -1294,6 +1301,13 @@ hammer_ip_delete_record(hammer_cursor_t cursor, hammer_tid_t tid)
                        hammer_modify_node(cursor->trans, cursor->node,
                                           elm, sizeof(*elm));
                        elm->leaf.base.delete_tid = tid;
+
+                       /*
+                        * An on-disk record cannot have the same delete_tid
+                        * as its create_tid.  In a chain of record updates
+                        * this could result in a duplicate record.
+                        */
+                       KKASSERT(elm->leaf.base.delete_tid != elm->leaf.base.create_tid);
                        hammer_modify_buffer(cursor->trans, cursor->record_buffer, &cursor->record->base.base.delete_tid, sizeof(hammer_tid_t));
                        cursor->record->base.base.delete_tid = tid;
                }
index 36b360f..159b811 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.3 2008/03/19 20:18:17 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_reblock.c,v 1.4 2008/03/20 06:08:40 dillon Exp $
  */
 /*
  * HAMMER reblocker - This code frees up fragmented physical space
@@ -100,6 +100,8 @@ retry:
                        cursor.flags |= HAMMER_CURSOR_ATEDISK;
                        error = hammer_btree_iterate(&cursor);
                }
+               if (error == 0)
+                       error = hammer_signal_check(trans->hmp);
        }
        if (error == ENOENT)
                error = 0;
diff --git a/sys/vfs/hammer/hammer_signal.c b/sys/vfs/hammer/hammer_signal.c
new file mode 100644 (file)
index 0000000..c0ad1bf
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
+ * 
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * $DragonFly: src/sys/vfs/hammer/hammer_signal.c,v 1.1 2008/03/20 06:08:40 dillon Exp $
+ */
+/*
+ * Check for interruption when doing a long ioctl operation.
+ */
+
+#include "hammer.h"
+
+int
+hammer_signal_check(hammer_mount_t hmp)
+{
+       int sig;
+
+       if (++hmp->check_interrupt < 100)
+               return(0);
+       hmp->check_interrupt = 0;
+
+       if ((sig = CURSIG(curthread->td_lwp)) != 0)
+               return(EINTR);
+       return(0);
+}
+
index f51a56a..b8b7ed0 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_transaction.c,v 1.10 2008/03/19 20:18:17 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_transaction.c,v 1.11 2008/03/20 06:08:40 dillon Exp $
  */
 
 #include "hammer.h"
@@ -102,7 +102,7 @@ hammer_alloc_tid(hammer_transaction_t trans)
        ondisk = trans->rootvol->ondisk;
        if (tid < ondisk->vol0_next_tid)
                tid = ondisk->vol0_next_tid;
-       if (tid == 0xFFFFFFFFFFFFFFFFULL)
+       if (tid >= 0xFFFFFFFFFFFFFFF0ULL)
                panic("hammer_start_transaction: Ran out of TIDs!");
        if (hammer_debug_tid) {
                kprintf("alloc_tid %016llx (0x%08x)\n",