Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libperfuse ftruncate(2) cause a SETATTR with only va_siz...



details:   https://anonhg.NetBSD.org/src/rev/4e7014190cf6
branches:  trunk
changeset: 767414:4e7014190cf6
user:      manu <manu%NetBSD.org@localhost>
date:      Mon Jul 18 02:14:01 2011 +0000

description:
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.

diffstat:

 lib/libperfuse/ops.c |  23 ++++++++++++++++++++++-
 1 files changed, 22 insertions(+), 1 deletions(-)

diffs (37 lines):

diff -r 2913c302e64f -r 4e7014190cf6 lib/libperfuse/ops.c
--- a/lib/libperfuse/ops.c      Mon Jul 18 01:52:55 2011 +0000
+++ b/lib/libperfuse/ops.c      Mon Jul 18 02:14:01 2011 +0000
@@ -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|



Home | Main Index | Thread Index | Old Index