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.
This commit is contained in:
parent
c751831386
commit
7541af315c
|
@ -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.
|
||||
|
@ -1651,6 +1651,27 @@ perfuse_node_setattr(pu, opc, vap, pcr)
|
|||
fsi->valid |= FUSE_FATTR_LOCKOWNER;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue