HAMMER: Fix a couple of minor non-corrupting bugs in HAMMER.
authorMatthew Dillon <dillon@dragonflybsd.org>
Sun, 21 Sep 2008 02:58:31 +0000 (02:58 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Sun, 21 Sep 2008 02:58:31 +0000 (02:58 +0000)
* Fix a few cases where the kmalloc space for hammer inodes can become
  exhausted.  Add calls to hammer_inode_waitreclaims() in several places
  where modified inodes can build up without the related vnodes
  necessarily being VOP_OPEN()'d or VOP_CLOSE()'d.

* Fix a deadlock which can occur in fsync().  fsync() was holding the vnode
  lock while waiting for the inode to sync.  The inode sync can be held up
  indefinitely by dependancies on other vnodes, so holding the lock can
  result in a deadlock.

* Fix a bug where ap->a_ctllen test results were being ignored.  This
  path is only used by mountd.

Reported-by: Francois Tigeot <ftigeot@wolfpond.org>,
Damian Lubosch <dl@pless.xiqit.de>

sys/vfs/hammer/hammer_vnops.c

index 8732fe2..3f725b4 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.96 2008/08/09 07:04:16 dillon Exp $
+ * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.97 2008/09/21 02:58:31 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);
 }
 
@@ -1038,6 +1041,7 @@ hammer_vop_nlink(struct vop_nlink_args *ap)
                cache_setvp(nch, ap->a_vp);
        }
        hammer_done_transaction(&trans);
+       hammer_inode_waitreclaims(dip->hmp);
        return (error);
 }
 
@@ -1108,6 +1112,7 @@ hammer_vop_nmkdir(struct vop_nmkdir_args *ap)
                }
        }
        hammer_done_transaction(&trans);
+       hammer_inode_waitreclaims(dip->hmp);
        return (error);
 }
 
@@ -1873,6 +1878,8 @@ done:
        if (error == 0)
                hammer_modify_inode(ip, modflags);
        hammer_done_transaction(&trans);
+       if (ap->a_vp->v_opencount == 0)
+               hammer_inode_waitreclaims(ip->hmp);
        return (error);
 }
 
@@ -2027,7 +2034,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: