Print this page
OS-5148 ftruncate at offset should emit proper events
Reviewed by: Bryan Cantrill <bryan@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
OS-5291 lxbrand inotify02 LTP regression
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
OS-4319 zfs mishandles partial writes
OS-3294 add support for inotify
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
        
@@ -21,11 +21,11 @@
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2014 Integros [integros.com]
- * Copyright 2015 Joyent, Inc.
+ * Copyright 2016 Joyent, Inc.
  */
 
 /* Portions Copyright 2007 Jeremy Teo */
 /* Portions Copyright 2010 Robert Milkowski */
 
@@ -662,10 +662,11 @@
         offset_t        woff;
         ssize_t         n, nbytes;
         rl_t            *rl;
         int             max_blksz = zfsvfs->z_max_blksz;
         int             error = 0;
+        int             prev_error;
         arc_buf_t       *abuf;
         iovec_t         *aiov = NULL;
         xuio_t          *xuio = NULL;
         int             i_iov = 0;
         int             iovcnt = uio->uio_iovcnt;
@@ -966,26 +967,30 @@
                  * account for possible concurrent updates.
                  */
                 while ((end_size = zp->z_size) < uio->uio_loffset) {
                         (void) atomic_cas_64(&zp->z_size, end_size,
                             uio->uio_loffset);
-                        ASSERT(error == 0);
                 }
                 /*
                  * If we are replaying and eof is non zero then force
                  * the file size to the specified eof. Note, there's no
                  * concurrency during replay.
                  */
                 if (zfsvfs->z_replay && zfsvfs->z_replay_eof != 0)
                         zp->z_size = zfsvfs->z_replay_eof;
 
+                /*
+                 * Keep track of a possible pre-existing error from a partial
+                 * write via dmu_write_uio_dbuf above.
+                 */
+                prev_error = error;
                 error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
 
                 zfs_log_write(zilog, tx, TX_WRITE, zp, woff, tx_bytes, ioflag);
                 dmu_tx_commit(tx);
 
-                if (error != 0)
+                if (prev_error != 0 || error != 0)
                         break;
                 ASSERT(tx_bytes == nbytes);
                 n -= nbytes;
 
                 if (!xuio && n > 0)
@@ -2830,13 +2835,16 @@
                 if (err) {
                         ZFS_EXIT(zfsvfs);
                         return (err);
                 }
 
-                if (vap->va_size == 0)
+                if (vap->va_size == 0) {
                         vnevent_truncate(ZTOV(zp), ct);
+                } else {
+                        vnevent_resize(ZTOV(zp), ct);
         }
+        }
 
         if (mask & (AT_ATIME|AT_MTIME) ||
             ((mask & AT_XVATTR) && (XVA_ISSET_REQ(xvap, XAT_HIDDEN) ||
             XVA_ISSET_REQ(xvap, XAT_READONLY) ||
             XVA_ISSET_REQ(xvap, XAT_ARCHIVE) ||
@@ -3759,13 +3767,11 @@
         if (tzp && rm_err == 0)
                 vnevent_rename_dest(ZTOV(tzp), tdvp, tnm, ct);
 
         if (error == 0) {
                 vnevent_rename_src(ZTOV(szp), sdvp, snm, ct);
-                /* notify the target dir if it is not the same as source dir */
-                if (tdvp != sdvp)
-                        vnevent_rename_dest_dir(tdvp, ct);
+                vnevent_rename_dest_dir(tdvp, ZTOV(szp), tnm, ct);
         }
 out:
         if (zl != NULL)
                 zfs_rename_unlock(&zl);
 
@@ -4857,12 +4863,17 @@
         off = bfp->l_start;
         len = bfp->l_len; /* 0 means from off to end of file */
 
         error = zfs_freesp(zp, off, len, flag, TRUE);
 
-        if (error == 0 && off == 0 && len == 0)
+        if (error == 0 && len == 0) {
+                if (off == 0) {
                 vnevent_truncate(ZTOV(zp), ct);
+                } else {
+                        vnevent_resize(ZTOV(zp), ct);
+                }
+        }
 
         ZFS_EXIT(zfsvfs);
         return (error);
 }