Illumos #3006
[zfs.git] / module / zfs / zfs_vnops.c
index 89f0f60..3b671b4 100644 (file)
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 /* Portions Copyright 2007 Jeremy Teo */
@@ -1523,7 +1524,7 @@ top:
            &xattr_obj, sizeof (xattr_obj));
        if (error == 0 && xattr_obj) {
                error = zfs_zget(zsb, xattr_obj, &xzp);
-               ASSERT3U(error, ==, 0);
+               ASSERT0(error);
                dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE);
                dmu_tx_hold_sa(tx, xzp->z_sa_hdl, B_FALSE);
        }
@@ -2837,7 +2838,7 @@ top:
                zp->z_mode = new_mode;
                ASSERT3P(aclp, !=, NULL);
                err = zfs_aclset_common(zp, aclp, cr, tx);
-               ASSERT3U(err, ==, 0);
+               ASSERT0(err);
                if (zp->z_acl_cached)
                        zfs_acl_free(zp->z_acl_cached);
                zp->z_acl_cached = aclp;
@@ -3346,7 +3347,7 @@ top:
 
                        error = sa_update(szp->z_sa_hdl, SA_ZPL_FLAGS(zsb),
                            (void *)&szp->z_pflags, sizeof (uint64_t), tx);
-                       ASSERT3U(error, ==, 0);
+                       ASSERT0(error);
 
                        error = zfs_link_destroy(sdl, szp, tx, ZRENAMING, NULL);
                        if (error == 0) {
@@ -3790,7 +3791,8 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc)
        zfs_sb_t        *zsb = ITOZSB(ip);
        loff_t          offset;
        loff_t          pgoff;
-        unsigned int   pglen;
+       unsigned int    pglen;
+       rl_t            *rl;
        dmu_tx_t        *tx;
        caddr_t         va;
        int             err = 0;
@@ -3799,6 +3801,8 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc)
        int             cnt = 0;
        int             sync;
 
+       ZFS_ENTER(zsb);
+       ZFS_VERIFY_ZP(zp);
 
        ASSERT(PageLocked(pp));
 
@@ -3810,6 +3814,7 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc)
        /* Page is beyond end of file */
        if (pgoff >= offset) {
                unlock_page(pp);
+               ZFS_EXIT(zsb);
                return (0);
        }
 
@@ -3832,6 +3837,7 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc)
        set_page_writeback(pp);
        unlock_page(pp);
 
+       rl = zfs_range_lock(zp, pgoff, pglen, RL_WRITER);
        tx = dmu_tx_create(zsb->z_os);
 
        sync = ((zsb->z_os->os_sync == ZFS_SYNC_ALWAYS) ||
@@ -3858,6 +3864,8 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc)
                if (sync)
                        zfs_putpage_commit_cb(pp, ECANCELED);
 
+               zfs_range_unlock(rl);
+               ZFS_EXIT(zsb);
                return (err);
        }
 
@@ -3869,20 +3877,79 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc)
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MTIME(zsb), NULL, &mtime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CTIME(zsb), NULL, &ctime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_FLAGS(zsb), NULL, &zp->z_pflags, 8);
-       zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime, B_TRUE);
-       zfs_log_write(zsb->z_log, tx, TX_WRITE, zp, pgoff, pglen, 0);
 
+       /* Preserve the mtime and ctime provided by the inode */
+       ZFS_TIME_ENCODE(&ip->i_mtime, mtime);
+       ZFS_TIME_ENCODE(&ip->i_ctime, ctime);
+       zp->z_atime_dirty = 0;
+       zp->z_seq++;
+
+       err = sa_bulk_update(zp->z_sa_hdl, bulk, cnt, tx);
+
+       zfs_log_write(zsb->z_log, tx, TX_WRITE, zp, pgoff, pglen, 0);
        dmu_tx_commit(tx);
-       ASSERT3S(err, ==, 0);
+
+       zfs_range_unlock(rl);
 
        if (sync) {
                zil_commit(zsb->z_log, zp->z_id);
                zfs_putpage_commit_cb(pp, err);
        }
 
+       ZFS_EXIT(zsb);
        return (err);
 }
 
+/*
+ * Update the system attributes when the inode has been dirtied.  For the
+ * moment we're conservative and only update the atime, mtime, and ctime.
+ */
+int
+zfs_dirty_inode(struct inode *ip, int flags)
+{
+       znode_t         *zp = ITOZ(ip);
+       zfs_sb_t        *zsb = ITOZSB(ip);
+       dmu_tx_t        *tx;
+       uint64_t        atime[2], mtime[2], ctime[2];
+       sa_bulk_attr_t  bulk[3];
+       int             error;
+       int             cnt = 0;
+
+       ZFS_ENTER(zsb);
+       ZFS_VERIFY_ZP(zp);
+
+       tx = dmu_tx_create(zsb->z_os);
+
+       dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
+       zfs_sa_upgrade_txholds(tx, zp);
+
+       error = dmu_tx_assign(tx, TXG_WAIT);
+       if (error) {
+               dmu_tx_abort(tx);
+               goto out;
+       }
+
+       mutex_enter(&zp->z_lock);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_ATIME(zsb), NULL, &atime, 16);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MTIME(zsb), NULL, &mtime, 16);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CTIME(zsb), NULL, &ctime, 16);
+
+       /* Preserve the mtime and ctime provided by the inode */
+       ZFS_TIME_ENCODE(&ip->i_atime, atime);
+       ZFS_TIME_ENCODE(&ip->i_mtime, mtime);
+       ZFS_TIME_ENCODE(&ip->i_ctime, ctime);
+       zp->z_atime_dirty = 0;
+
+       error = sa_bulk_update(zp->z_sa_hdl, bulk, cnt, tx);
+       mutex_exit(&zp->z_lock);
+
+       dmu_tx_commit(tx);
+out:
+       ZFS_EXIT(zsb);
+       return (error);
+}
+EXPORT_SYMBOL(zfs_dirty_inode);
+
 /*ARGSUSED*/
 void
 zfs_inactive(struct inode *ip)