Module Name: src Committed By: manu Date: Mon Jul 18 02:14:01 UTC 2011
Modified Files: src/lib/libperfuse: ops.c Log Message: ftruncate(2) cause a SETATTR with only va_size set, and some filesystems (e.g.: glusterfs) will do a custom handling in such a situation. This breaks because libpuffs folds a metadata (va_atime and va_mtime) update in each SETATTR. We try to identify SETATTR caused by ftruncate(2) and remove va_atime and va_mtime in such situation. This fixes a bug with glusterfs, where parts of a file downloaded by FTP was filled with zeros because of a ftruncate(2) sent out of order with write(2) requests. glusterfs behavior depends on the undocumented FUSE rule that ftruncate(2) will only set va_size in SETATTR. To generate a diff of this commit: cvs rdiff -u -r1.33 -r1.34 src/lib/libperfuse/ops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libperfuse/ops.c diff -u src/lib/libperfuse/ops.c:1.33 src/lib/libperfuse/ops.c:1.34 --- src/lib/libperfuse/ops.c:1.33 Thu Jul 14 15:37:32 2011 +++ src/lib/libperfuse/ops.c Mon Jul 18 02:14:01 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ops.c,v 1.33 2011/07/14 15:37:32 manu Exp $ */ +/* $NetBSD: ops.c,v 1.34 2011/07/18 02:14:01 manu Exp $ */ /*- * Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved. @@ -1652,6 +1652,27 @@ } /* + * ftruncate() sends only va_size, and metadata cache + * flush adds va_atime and va_mtime. Some FUSE + * filesystems will attempt to detect ftruncate by + * checking for FATTR_SIZE being set without + * FATTR_UID|FATTR_GID|FATTR_ATIME|FATTR_MTIME|FATTR_MODE + * + * Try to adapt and remove FATTR_ATIME|FATTR_MTIME + * if we suspect a ftruncate(). + */ + if ((va_size != (u_quad_t)PUFFS_VNOVAL) && + ((vap->va_mode == (mode_t)PUFFS_VNOVAL) && + (vap->va_uid == (uid_t)PUFFS_VNOVAL) && + (vap->va_gid == (gid_t)PUFFS_VNOVAL))) { + fsi->atime = 0; + fsi->atimensec = 0; + fsi->mtime = 0; + fsi->mtimensec = 0; + fsi->valid &= ~(FUSE_FATTR_ATIME|FUSE_FATTR_MTIME); + } + + /* * If nothing remain, discard the operation. */ if (!(fsi->valid & (FUSE_FATTR_SIZE|FUSE_FATTR_ATIME|FUSE_FATTR_MTIME|