HAMMER: MFC all changes through 20080924
authorMatthew Dillon <dillon@dragonflybsd.org>
Thu, 25 Sep 2008 01:42:52 +0000 (25 01:42 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Thu, 25 Sep 2008 01:42:52 +0000 (25 01:42 +0000)
* Flush performance adjustments.
* Unlink performance adjustments (remove double flush).
* Improved reclaim performance.
* Snapshots[] path configuration support in PFS data.
* Add disk cache flush support.
* NFS support.

sys/vfs/hammer/hammer.h
sys/vfs/hammer/hammer_disk.h
sys/vfs/hammer/hammer_inode.c
sys/vfs/hammer/hammer_io.c
sys/vfs/hammer/hammer_mount.h
sys/vfs/hammer/hammer_object.c
sys/vfs/hammer/hammer_ondisk.c
sys/vfs/hammer/hammer_prune.c
sys/vfs/hammer/hammer_transaction.c
sys/vfs/hammer/hammer_vfsops.c
sys/vfs/hammer/hammer_vnops.c

index 4b18b63..c300c32 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.117.2.6 2008/08/02 21:24:27 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.117.2.7 2008/09/25 01:42:52 dillon Exp $
  */
 /*
  * This header file contains structures used internally by the HAMMERFS
@@ -110,11 +110,14 @@ struct hammer_transaction {
        u_int64_t       time;
        u_int32_t       time32;
        int             sync_lock_refs;
+       int             flags;
        struct hammer_volume *rootvol;
 };
 
 typedef struct hammer_transaction *hammer_transaction_t;
 
+#define HAMMER_TRANSF_NEWINODE 0x0001
+
 /*
  * HAMMER locks
  */
@@ -484,6 +487,7 @@ struct hammer_io {
        struct hammer_lock      lock;
        enum hammer_io_type     type;
        struct hammer_mount     *hmp;
+       struct hammer_volume    *volume;
        TAILQ_ENTRY(hammer_io)  mod_entry; /* list entry if modified */
        hammer_io_list_t        mod_list;
        struct buf              *bp;
@@ -541,7 +545,6 @@ struct hammer_buffer {
        struct hammer_io io;
        RB_ENTRY(hammer_buffer) rb_node;
        void *ondisk;
-       struct hammer_volume *volume;
        hammer_off_t zoneX_offset;
        hammer_off_t zone2_offset;
        struct hammer_reserve *resv;
@@ -821,6 +824,7 @@ extern int hammer_bio_count;
 extern int hammer_verify_zone;
 extern int hammer_verify_data;
 extern int hammer_write_mode;
+extern int hammer_autoflush;
 extern int64_t hammer_contention_count;
 
 void   hammer_critical_error(hammer_mount_t hmp, hammer_inode_t ip,
@@ -1099,7 +1103,7 @@ void hammer_rel_pseudofs(hammer_mount_t hmp, hammer_pseudofs_inmem_t pfsm);
 int hammer_ioctl(hammer_inode_t ip, u_long com, caddr_t data, int fflag,
                        struct ucred *cred);
 
-void hammer_io_init(hammer_io_t io, hammer_mount_t hmp,
+void hammer_io_init(hammer_io_t io, hammer_volume_t volume,
                        enum hammer_io_type type);
 int hammer_io_read(struct vnode *devvp, struct hammer_io *io,
                        hammer_off_t limit);
@@ -1120,6 +1124,8 @@ void hammer_io_write_interlock(hammer_io_t io);
 void hammer_io_done_interlock(hammer_io_t io);
 void hammer_io_clear_modify(struct hammer_io *io, int inval);
 void hammer_io_clear_modlist(struct hammer_io *io);
+void hammer_io_flush_sync(hammer_mount_t hmp);
+
 void hammer_modify_volume(hammer_transaction_t trans, hammer_volume_t volume,
                        void *base, int len);
 void hammer_modify_buffer(hammer_transaction_t trans, hammer_buffer_t buffer,
index 9a5e4f5..6d0ee7e 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_disk.h,v 1.50.2.2 2008/08/02 21:24:28 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_disk.h,v 1.50.2.3 2008/09/25 01:42:52 dillon Exp $
  */
 
 #ifndef VFS_HAMMER_DISK_H_
@@ -518,6 +518,7 @@ typedef struct hammer_volume_ondisk *hammer_volume_ondisk_t;
 
 #define HAMMER_VOLF_VALID              0x0001  /* valid entry */
 #define HAMMER_VOLF_OPEN               0x0002  /* volume is open */
+#define HAMMER_VOLF_NEEDFLUSH          0x0004  /* volume needs flush */
 
 #define HAMMER_VOL_CRCSIZE1    \
        offsetof(struct hammer_volume_ondisk, vol_crc)
@@ -684,7 +685,7 @@ struct hammer_pseudofs_data {
        int32_t         reserved01;     /* reserved for future master_id */
        int32_t         mirror_flags;   /* misc flags */
        char            label[64];      /* filesystem space label */
-       char            prune_path[64]; /* softlink dir for pruning */
+       char            snapshots[64];  /* softlink dir for pruning */
        int16_t         prune_time;     /* how long to spend pruning */
        int16_t         prune_freq;     /* how often we prune */
        int16_t         reblock_time;   /* how long to spend reblocking */
index cbded3a..e0657d2 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.103.2.5 2008/08/10 17:01:08 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_inode.c,v 1.103.2.6 2008/09/25 01:42:52 dillon Exp $
  */
 
 #include "hammer.h"
@@ -220,15 +220,6 @@ hammer_vop_reclaim(struct vop_reclaim_args *ap)
                        ++hammer_count_reclaiming;
                        ++hmp->inode_reclaims;
                        ip->flags |= HAMMER_INODE_RECLAIM;
-
-                       /*
-                        * Poke the flusher.  If we don't do this programs
-                        * will start to stall on the reclaiming count.
-                        */
-                       if (hmp->inode_reclaims > HAMMER_RECLAIM_FLUSH &&
-                          (hmp->inode_reclaims & 255) == 0) {
-                              hammer_flusher_async(hmp, NULL);
-                       }
                }
                hammer_rel_inode(ip, 1);
        }
@@ -293,12 +284,16 @@ hammer_get_vnode(struct hammer_inode *ip, struct vnode **vpp)
                         * confused.  The other half of the special handling
                         * is in hammer_vop_nlookupdotdot().
                         *
-                        * Pseudo-filesystem roots also do not count.
+                        * Pseudo-filesystem roots can be accessed via
+                        * non-root filesystem paths and setting VROOT may
+                        * confuse the namecache.  Set VPFSROOT instead.
                         */
                        if (ip->obj_id == HAMMER_OBJID_ROOT &&
-                           ip->obj_asof == hmp->asof &&
-                           ip->obj_localization == 0) {
-                               vp->v_flag |= VROOT;
+                           ip->obj_asof == hmp->asof) {
+                               if (ip->obj_localization == 0)
+                                       vp->v_flag |= VROOT;
+                               else
+                                       vp->v_flag |= VPFSROOT;
                        }
 
                        vp->v_data = (void *)ip;
@@ -489,6 +484,7 @@ retry:
                ip = NULL;
        }
        hammer_done_cursor(&cursor);
+       trans->flags |= HAMMER_TRANSF_NEWINODE;
        return (ip);
 }
 
@@ -1163,7 +1159,7 @@ retry:
 void
 hammer_rel_inode(struct hammer_inode *ip, int flush)
 {
-       hammer_mount_t hmp = ip->hmp;
+       /*hammer_mount_t hmp = ip->hmp;*/
 
        /*
         * Handle disposition when dropping the last ref.
@@ -1177,12 +1173,7 @@ hammer_rel_inode(struct hammer_inode *ip, int flush)
                        KKASSERT(ip->vp == NULL);
                        hammer_inode_unloadable_check(ip, 0);
                        if (ip->flags & HAMMER_INODE_MODMASK) {
-                               if (hmp->rsv_inodes > desiredvnodes) {
-                                       hammer_flush_inode(ip,
-                                                          HAMMER_FLUSH_SIGNAL);
-                               } else {
-                                       hammer_flush_inode(ip, 0);
-                               }
+                               hammer_flush_inode(ip, 0);
                        } else if (ip->lock.refs == 1) {
                                hammer_unload_inode(ip);
                                break;
@@ -1662,6 +1653,13 @@ hammer_flush_inode_core(hammer_inode_t ip, hammer_flush_group_t flg, int flags)
        ++flg->total_count;
 
        /*
+        * If the flush group reaches the autoflush limit we want to signal
+        * the flusher.  This is particularly important for remove()s.
+        */
+       if (flg->total_count == hammer_autoflush)
+               flags |= HAMMER_FLUSH_SIGNAL;
+
+       /*
         * We need to be able to vfsync/truncate from the backend.
         */
        KKASSERT((ip->flags & HAMMER_INODE_VHELD) == 0);
@@ -2059,9 +2057,17 @@ hammer_flush_inode_done(hammer_inode_t ip, int error)
        /*
         * Do not lose track of inodes which no longer have vnode
         * assocations, otherwise they may never get flushed again.
+        *
+        * The reflush flag can be set superfluously, causing extra pain
+        * for no reason.  If the inode is no longer modified it no longer
+        * needs to be flushed.
         */
-       if ((ip->flags & HAMMER_INODE_MODMASK) && ip->vp == NULL)
-               ip->flags |= HAMMER_INODE_REFLUSH;
+       if (ip->flags & HAMMER_INODE_MODMASK) {
+               if (ip->vp == NULL)
+                       ip->flags |= HAMMER_INODE_REFLUSH;
+       } else {
+               ip->flags &= ~HAMMER_INODE_REFLUSH;
+       }
 
        /*
         * Adjust the flush state.
@@ -2641,9 +2647,14 @@ hammer_inode_unloadable_check(hammer_inode_t ip, int getvp)
         * The backend will clear DELETING (a mod flag) and set DELETED
         * (a state flag) when it is actually able to perform the
         * operation.
+        *
+        * Don't reflag the deletion if the flusher is currently syncing
+        * one that was already flagged.  A previously set DELETING flag
+        * may bounce around flags and sync_flags until the operation is
+        * completely done.
         */
        if (ip->ino_data.nlinks == 0 &&
-           (ip->flags & (HAMMER_INODE_DELETING|HAMMER_INODE_DELETED)) == 0) {
+           ((ip->flags | ip->sync_flags) & (HAMMER_INODE_DELETING|HAMMER_INODE_DELETED)) == 0) {
                ip->flags |= HAMMER_INODE_DELETING;
                ip->flags |= HAMMER_INODE_TRUNCATED;
                ip->trunc_off = 0;
@@ -2738,7 +2749,7 @@ hammer_inode_waitreclaims(hammer_mount_t hmp)
 
        if (reclaim.okydoky == 0) {
                delay = (hmp->inode_reclaims - HAMMER_RECLAIM_WAIT) * hz /
-                       HAMMER_RECLAIM_WAIT;
+                       (HAMMER_RECLAIM_WAIT * 5);
                if (delay >= 0)
                        tsleep(&reclaim, 0, "hmrrcm", delay + 1);
                if (reclaim.okydoky == 0)
index 2f71c5b..c49809b 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_io.c,v 1.49.2.5 2008/09/15 17:10:03 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_io.c,v 1.49.2.6 2008/09/25 01:42:52 dillon Exp $
  */
 /*
  * IO Primitives and buffer cache management
@@ -60,15 +60,19 @@ static void hammer_io_direct_read_complete(struct bio *nbio);
 static void hammer_io_direct_write_complete(struct bio *nbio);
 static int hammer_io_direct_uncache_callback(hammer_inode_t ip, void *data);
 static void hammer_io_set_modlist(struct hammer_io *io);
+static void hammer_io_flush_mark(hammer_volume_t volume);
+static void hammer_io_flush_sync_done(struct bio *bio);
+
 
 /*
  * Initialize a new, already-zero'd hammer_io structure, or reinitialize
  * an existing hammer_io structure which may have switched to another type.
  */
 void
-hammer_io_init(hammer_io_t io, hammer_mount_t hmp, enum hammer_io_type type)
+hammer_io_init(hammer_io_t io, hammer_volume_t volume, enum hammer_io_type type)
 {
-       io->hmp = hmp;
+       io->volume = volume;
+       io->hmp = volume->io.hmp;
        io->type = type;
 }
 
@@ -150,6 +154,7 @@ hammer_io_wait(hammer_io_t io)
 void
 hammer_io_wait_all(hammer_mount_t hmp, const char *ident)
 {
+       hammer_io_flush_sync(hmp);
        crit_enter();
        while (hmp->io_running_space)
                tsleep(&hmp->io_running_space, 0, ident, 0);
@@ -509,6 +514,7 @@ hammer_io_flush(struct hammer_io *io)
        io->hmp->io_running_space += io->bytes;
        hammer_count_io_running_write += io->bytes;
        bawrite(bp);
+       hammer_io_flush_mark(io->volume);
 }
 
 /************************************************************************
@@ -1203,6 +1209,7 @@ hammer_io_direct_write(hammer_mount_t hmp, hammer_record_t record,
                                           zone2_offset;
                        hammer_stats_disk_write += bp->b_bufsize;
                        vn_strategy(volume->devvp, nbio);
+                       hammer_io_flush_mark(volume);
                }
                hammer_rel_volume(volume, 0);
        } else {
@@ -1392,3 +1399,66 @@ hammer_io_direct_uncache_callback(hammer_inode_t ip, void *data)
        return(0);
 }
 
+
+/*
+ * This function is called when writes may have occured on the volume,
+ * indicating that the device may be holding cached writes.
+ */
+static void
+hammer_io_flush_mark(hammer_volume_t volume)
+{
+       volume->vol_flags |= HAMMER_VOLF_NEEDFLUSH;
+}
+
+/*
+ * This function ensures that the device has flushed any cached writes out.
+ */
+void
+hammer_io_flush_sync(hammer_mount_t hmp)
+{
+       hammer_volume_t volume;
+       struct buf *bp_base = NULL;
+       struct buf *bp;
+
+       RB_FOREACH(volume, hammer_vol_rb_tree, &hmp->rb_vols_root) {
+               if (volume->vol_flags & HAMMER_VOLF_NEEDFLUSH) {
+                       volume->vol_flags &= ~HAMMER_VOLF_NEEDFLUSH;
+                       bp = getpbuf(NULL);
+                       bp->b_bio1.bio_offset = 0;
+                       bp->b_bufsize = 0;
+                       bp->b_bcount = 0;
+                       bp->b_cmd = BUF_CMD_FLUSH;
+                       bp->b_bio1.bio_caller_info1.cluster_head = bp_base;
+                       bp->b_bio1.bio_done = hammer_io_flush_sync_done;
+                       bp->b_flags |= B_ASYNC;
+                       bp_base = bp;
+                       vn_strategy(volume->devvp, &bp->b_bio1);
+               }
+       }
+       while ((bp = bp_base) != NULL) {
+               bp_base = bp->b_bio1.bio_caller_info1.cluster_head;
+               while (bp->b_cmd != BUF_CMD_DONE) {
+                       crit_enter();
+                       tsleep_interlock(&bp->b_cmd);
+                       if (bp->b_cmd != BUF_CMD_DONE)
+                               tsleep(&bp->b_cmd, 0, "hmrFLS", 0);
+                       crit_exit();
+               }
+               bp->b_flags &= ~B_ASYNC;
+               relpbuf(bp, NULL);
+       }
+}
+
+/*
+ * Callback to deal with completed flush commands to the device.
+ */
+static void
+hammer_io_flush_sync_done(struct bio *bio)
+{
+       struct buf *bp;
+
+       bp = bio->bio_buf;
+       bp->b_cmd = BUF_CMD_DONE;
+       wakeup(&bp->b_cmd);
+}
+
index 1d03143..7d7fefe 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_mount.h,v 1.9.2.2 2008/08/02 21:24:28 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_mount.h,v 1.9.2.3 2008/09/25 01:42:52 dillon Exp $
  */
 
 #ifndef _SYS_TYPES_H_
@@ -51,8 +51,8 @@ struct hammer_mount_info {
        int             hflags;         /* extended hammer mount flags */
        int             master_id;      /* -1=no-mirror mode, or 0-15 */
        u_int64_t       asof;           /* asof - HAMMER_MAX_TID is current */
-       struct export_args export;      /* export arguments */
-       u_int64_t       reserved[15];
+       char            reserved1[136]; /* was struct export_args */
+       u_int64_t       reserved2[15];
 };
 
 #define HMNT_NOHISTORY 0x00000001
index e84592a..a686d7f 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.90.2.5 2008/08/10 17:01:08 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.90.2.6 2008/09/25 01:42:52 dillon Exp $
  */
 
 #include "hammer.h"
@@ -778,6 +778,8 @@ hammer_ip_del_directory(struct hammer_transaction *trans,
         */
        if (error == 0) {
                --ip->ino_data.nlinks;
+               dip->ino_data.mtime = trans->time;
+               hammer_modify_inode(dip, HAMMER_INODE_MTIME);
                hammer_modify_inode(ip, HAMMER_INODE_DDIRTY);
                if (ip->ino_data.nlinks == 0 &&
                    (ip->vp == NULL || (ip->vp->v_flag & VINACTIVE))) {
@@ -785,8 +787,6 @@ hammer_ip_del_directory(struct hammer_transaction *trans,
                        hammer_inode_unloadable_check(ip, 1);
                        hammer_flush_inode(ip, 0);
                }
-               dip->ino_data.mtime = trans->time;
-               hammer_modify_inode(dip, HAMMER_INODE_MTIME);
 
        }
        return(error);
index 021cddf..a6364a2 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_ondisk.c,v 1.69.2.5 2008/08/06 15:41:56 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_ondisk.c,v 1.69.2.6 2008/09/25 01:42:52 dillon Exp $
  */
 /*
  * Manage HAMMER's on-disk structures.  These routines are primarily
@@ -119,7 +119,8 @@ hammer_install_volume(struct hammer_mount *hmp, const char *volname,
        ++hammer_count_volumes;
        volume = kmalloc(sizeof(*volume), M_HAMMER, M_WAITOK|M_ZERO);
        volume->vol_name = kstrdup(volname, M_HAMMER);
-       hammer_io_init(&volume->io, hmp, HAMMER_STRUCTURE_VOLUME);
+       volume->io.hmp = hmp;   /* bootstrap */
+       hammer_io_init(&volume->io, volume, HAMMER_STRUCTURE_VOLUME);
        volume->io.offset = 0LL;
        volume->io.bytes = HAMMER_BUFSIZE;
 
@@ -614,9 +615,8 @@ again:
                         M_WAITOK|M_ZERO|M_USE_RESERVE);
        buffer->zone2_offset = zone2_offset;
        buffer->zoneX_offset = buf_offset;
-       buffer->volume = volume;
 
-       hammer_io_init(&buffer->io, hmp, iotype);
+       hammer_io_init(&buffer->io, volume, iotype);
        buffer->io.offset = volume->ondisk->vol_buf_beg +
                            (zone2_offset & HAMMER_OFF_SHORT_MASK);
        buffer->io.bytes = bytes;
@@ -723,7 +723,7 @@ hammer_del_buffers(hammer_mount_t hmp, hammer_off_t base_offset,
                                hammer_io_clear_modify(&buffer->io, 1);
                                buffer->io.reclaim = 1;
                                buffer->io.waitdep = 1;
-                               KKASSERT(buffer->volume == volume);
+                               KKASSERT(buffer->io.volume == volume);
                                hammer_rel_buffer(buffer, 0);
                        }
                } else {
@@ -745,7 +745,7 @@ hammer_load_buffer(hammer_buffer_t buffer, int isnew)
        /*
         * Load the buffer's on-disk info
         */
-       volume = buffer->volume;
+       volume = buffer->io.volume;
        ++buffer->io.loading;
        hammer_lock_ex(&buffer->io.lock);
 
@@ -885,8 +885,8 @@ hammer_rel_buffer(hammer_buffer_t buffer, int flush)
                                RB_REMOVE(hammer_buf_rb_tree,
                                          &buffer->io.hmp->rb_bufs_root,
                                          buffer);
-                               volume = buffer->volume;
-                               buffer->volume = NULL; /* sanity */
+                               volume = buffer->io.volume;
+                               buffer->io.volume = NULL; /* sanity */
                                hammer_rel_volume(volume, 0);
                                hammer_io_clear_modlist(&buffer->io);
                                hammer_flush_buffer_nodes(buffer);
index ec56d5d..a43d00c 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.18.2.1 2008/08/02 21:24:28 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_prune.c,v 1.18.2.2 2008/09/25 01:42:52 dillon Exp $
  */
 
 #include "hammer.h"
@@ -319,6 +319,7 @@ prune_check_nlinks(hammer_cursor_t cursor, hammer_btree_leaf_elm_t elm)
                                elm->base.obj_id);
                }
                hammer_rel_inode(ip, 0);
+               hammer_inode_waitreclaims(cursor->trans->hmp);
        } else {
                kprintf("unable to prune disconnected inode %016llx\n",
                        elm->base.obj_id);
index 5c722af..5f994f6 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.22.2.3 2008/08/02 21:24:28 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_transaction.c,v 1.22.2.4 2008/09/25 01:42:52 dillon Exp $
  */
 
 #include "hammer.h"
@@ -55,6 +55,7 @@ hammer_start_transaction(struct hammer_transaction *trans,
        KKASSERT(error == 0);
        trans->tid = 0;
        trans->sync_lock_refs = 0;
+       trans->flags = 0;
 
        getmicrotime(&tv);
        trans->time = (unsigned long)tv.tv_sec * 1000000ULL + tv.tv_usec;
@@ -77,6 +78,7 @@ hammer_simple_transaction(struct hammer_transaction *trans,
        KKASSERT(error == 0);
        trans->tid = 0;
        trans->sync_lock_refs = 0;
+       trans->flags = 0;
 
        getmicrotime(&tv);
        trans->time = (unsigned long)tv.tv_sec * 1000000ULL + tv.tv_usec;
@@ -106,6 +108,7 @@ hammer_start_transaction_fls(struct hammer_transaction *trans,
        KKASSERT(error == 0);
        trans->tid = hammer_alloc_tid(hmp, 1);
        trans->sync_lock_refs = 1;
+       trans->flags = 0;
 
        getmicrotime(&tv);
        trans->time = (unsigned long)tv.tv_sec * 1000000ULL + tv.tv_usec;
@@ -122,6 +125,8 @@ hammer_done_transaction(struct hammer_transaction *trans)
        expected_lock_refs = (trans->type == HAMMER_TRANS_FLS) ? 1 : 0;
        KKASSERT(trans->sync_lock_refs == expected_lock_refs);
        trans->sync_lock_refs = 0;
+       if (trans->flags & HAMMER_TRANSF_NEWINODE)
+               hammer_inode_waitreclaims(trans->hmp);
 }
 
 /*
index 406e4b0..463b539 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_vfsops.c,v 1.63.2.6 2008/08/02 21:24:28 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_vfsops.c,v 1.63.2.7 2008/09/25 01:42:52 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -94,6 +94,7 @@ int hammer_count_io_locked;
 int hammer_limit_dirtybufspace;                /* per-mount */
 int hammer_limit_recs;                 /* as a whole XXX */
 int hammer_limit_iqueued;              /* per-mount */
+int hammer_autoflush = 2000;           /* auto flush */
 int hammer_bio_count;
 int hammer_verify_zone;
 int hammer_verify_data = 1;
@@ -201,6 +202,8 @@ SYSCTL_QUAD(_vfs_hammer, OID_AUTO, zone_limit, CTLFLAG_RW,
           &hammer_zone_limit, 0, "");
 SYSCTL_QUAD(_vfs_hammer, OID_AUTO, contention_count, CTLFLAG_RW,
           &hammer_contention_count, 0, "");
+SYSCTL_INT(_vfs_hammer, OID_AUTO, autoflush, CTLFLAG_RW,
+          &hammer_autoflush, 0, "");
 SYSCTL_INT(_vfs_hammer, OID_AUTO, verify_zone, CTLFLAG_RW,
           &hammer_verify_zone, 0, "");
 SYSCTL_INT(_vfs_hammer, OID_AUTO, verify_data, CTLFLAG_RW,
@@ -227,8 +230,8 @@ static int  hammer_vfs_sync(struct mount *mp, int waitfor);
 static int     hammer_vfs_vget(struct mount *mp, ino_t ino,
                                struct vnode **vpp);
 static int     hammer_vfs_init(struct vfsconf *conf);
-static int     hammer_vfs_fhtovp(struct mount *mp, struct fid *fhp,
-                               struct vnode **vpp);
+static int     hammer_vfs_fhtovp(struct mount *mp, struct vnode *rootvp,
+                               struct fid *fhp, struct vnode **vpp);
 static int     hammer_vfs_vptofh(struct vnode *vp, struct fid *fhp);
 static int     hammer_vfs_checkexp(struct mount *mp, struct sockaddr *nam,
                                int *exflagsp, struct ucred **credanonp);
@@ -900,9 +903,13 @@ hammer_vfs_vptofh(struct vnode *vp, struct fid *fhp)
 
 /*
  * Convert a file handle back to a vnode.
+ *
+ * Use rootvp to enforce PFS isolation when a PFS is exported via a
+ * null mount.
  */
 static int
-hammer_vfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
+hammer_vfs_fhtovp(struct mount *mp, struct vnode *rootvp,
+                 struct fid *fhp, struct vnode **vpp)
 {
        struct hammer_transaction trans;
        struct hammer_inode *ip;
@@ -912,7 +919,10 @@ hammer_vfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
 
        bcopy(fhp->fid_data + 0, &info.obj_id, sizeof(info.obj_id));
        bcopy(fhp->fid_data + 8, &info.obj_asof, sizeof(info.obj_asof));
-       localization = (u_int32_t)fhp->fid_ext << 16;
+       if (rootvp)
+               localization = VTOI(rootvp)->obj_localization;
+       else
+               localization = (u_int32_t)fhp->fid_ext << 16;
 
        hammer_simple_transaction(&trans, (void *)mp->mnt_data);
 
index 2ff9f11..5beecb0 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.91.2.5 2008/08/10 17:01:09 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.91.2.6 2008/09/25 01:42:52 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -186,8 +186,11 @@ hammer_vop_fsync(struct vop_fsync_args *ap)
        ++hammer_count_fsyncs;
        vfsync(ap->a_vp, ap->a_waitfor, 1, NULL, NULL);
        hammer_flush_inode(ip, HAMMER_FLUSH_SIGNAL);
-       if (ap->a_waitfor == MNT_WAIT)
+       if (ap->a_waitfor == MNT_WAIT) {
+               vn_unlock(ap->a_vp);
                hammer_wait_inode(ip);
+               vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
+       }
        return (ip->error);
 }
 
@@ -565,10 +568,7 @@ static
 int
 hammer_vop_close(struct vop_close_args *ap)
 {
-       hammer_inode_t ip = VTOI(ap->a_vp);
-
-       if ((ip->flags | ip->sync_flags) & HAMMER_INODE_MODMASK)
-               hammer_inode_waitreclaims(ip->hmp);
+       /*hammer_inode_t ip = VTOI(ap->a_vp);*/
        return (vop_stdclose(ap));
 }
 
@@ -2027,7 +2027,8 @@ hammer_vop_mountctl(struct vop_mountctl_args *ap)
        case MOUNTCTL_SET_EXPORT:
                if (ap->a_ctllen != sizeof(struct export_args))
                        error = EINVAL;
-               error = hammer_vfs_export(mp, ap->a_op,
+               else
+                       error = hammer_vfs_export(mp, ap->a_op,
                                      (const struct export_args *)ap->a_ctl);
                break;
        default:
@@ -2577,8 +2578,13 @@ hammer_vop_strategy_write(struct vop_strategy_args *ap)
         * topology visibility).  If we queue new IO while trying to
         * destroy the inode we can deadlock the vtrunc call in
         * hammer_inode_unloadable_check().
+        *
+        * Besides, there's no point flushing a bp associated with an
+        * inode that is being destroyed on-media and has no kernel
+        * references.
         */
-       if (ip->flags & (HAMMER_INODE_DELETING|HAMMER_INODE_DELETED)) {
+       if ((ip->flags | ip->sync_flags) &
+           (HAMMER_INODE_DELETING|HAMMER_INODE_DELETED)) {
                bp->b_resid = 0;
                biodone(ap->a_bio);
                return(0);
@@ -2764,7 +2770,6 @@ retry:
        } else {
                hammer_done_cursor(&cursor);
        }
-       hammer_inode_waitreclaims(dip->hmp);
        if (error == EDEADLK)
                goto retry;