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,31 ****
  /*
   * 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.
   */
  
  /* Portions Copyright 2007 Jeremy Teo */
  /* Portions Copyright 2010 Robert Milkowski */
  
--- 21,31 ----
  /*
   * 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 2016 Joyent, Inc.
   */
  
  /* Portions Copyright 2007 Jeremy Teo */
  /* Portions Copyright 2010 Robert Milkowski */
  
*** 662,671 ****
--- 662,672 ----
          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,991 ****
                   * 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;
  
                  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)
                          break;
                  ASSERT(tx_bytes == nbytes);
                  n -= nbytes;
  
                  if (!xuio && n > 0)
--- 967,996 ----
                   * 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);
                  }
                  /*
                   * 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 (prev_error != 0 || error != 0)
                          break;
                  ASSERT(tx_bytes == nbytes);
                  n -= nbytes;
  
                  if (!xuio && n > 0)
*** 2830,2842 ****
                  if (err) {
                          ZFS_EXIT(zfsvfs);
                          return (err);
                  }
  
!                 if (vap->va_size == 0)
                          vnevent_truncate(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) ||
--- 2835,2850 ----
                  if (err) {
                          ZFS_EXIT(zfsvfs);
                          return (err);
                  }
  
!                 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,3771 ****
          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);
          }
  out:
          if (zl != NULL)
                  zfs_rename_unlock(&zl);
  
--- 3767,3777 ----
          if (tzp && rm_err == 0)
                  vnevent_rename_dest(ZTOV(tzp), tdvp, tnm, ct);
  
          if (error == 0) {
                  vnevent_rename_src(ZTOV(szp), sdvp, snm, ct);
!                 vnevent_rename_dest_dir(tdvp, ZTOV(szp), tnm, ct);
          }
  out:
          if (zl != NULL)
                  zfs_rename_unlock(&zl);
  
*** 4857,4868 ****
          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)
                  vnevent_truncate(ZTOV(zp), ct);
  
          ZFS_EXIT(zfsvfs);
          return (error);
  }
  
--- 4863,4879 ----
          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 && len == 0) {
!                 if (off == 0) {
                          vnevent_truncate(ZTOV(zp), ct);
+                 } else {
+                         vnevent_resize(ZTOV(zp), ct);
+                 }
+         }
  
          ZFS_EXIT(zfsvfs);
          return (error);
  }