Module Name: src
Committed By: manu
Date: Wed Jun 1 15:54:10 UTC 2011
Modified Files:
src/lib/libperfuse: ops.c
Log Message:
Fix race conditions between write and getattr/setattr, which lead to
inconsitencies between kernel and filesystem idea of file size during
writes with IO_APPEND.
At mine, this resulted in a configure script producing config.status
with ": clr\n" lines stripped (not 100% reproductible, but always this
specific string. That is of little interest except for my own future
reference).
When a write is in progress, getattr/setattr get/set the maximum size
among kernel idea (grown by write) and filesystem idea (not yet grown).
To generate a diff of this commit:
cvs rdiff -u -r1.29 -r1.30 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.29 src/lib/libperfuse/ops.c:1.30
--- src/lib/libperfuse/ops.c:1.29 Wed Jun 1 07:57:24 2011
+++ src/lib/libperfuse/ops.c Wed Jun 1 15:54:10 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: ops.c,v 1.29 2011/06/01 07:57:24 manu Exp $ */
+/* $NetBSD: ops.c,v 1.30 2011/06/01 15:54:10 manu Exp $ */
/*-
* Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -1439,12 +1439,14 @@
struct perfuse_state *ps;
struct fuse_getattr_in *fgi;
struct fuse_attr_out *fao;
+ u_quad_t va_size;
int error;
if (PERFUSE_NODE_DATA(opc)->pnd_flags & PND_REMOVED)
return ENOENT;
ps = puffs_getspecific(pu);
+ va_size = vap->va_size;
/*
* FUSE_GETATTR_FH must be set in fgi->flags
@@ -1476,6 +1478,13 @@
*/
fuse_attr_to_vap(ps, vap, &fao->attr);
+ /*
+ * If a write is in progress, do not trust filesystem opinion
+ * of file size, use the one from kernel.
+ */
+ if ((PERFUSE_NODE_DATA(opc)->pnd_flags & PND_INWRITE) &&
+ (va_size != (u_quad_t)PUFFS_VNOVAL))
+ vap->va_size = MAX(va_size, vap->va_size);;
out:
ps->ps_destroy_msg(pm);
@@ -1496,6 +1505,7 @@
struct fuse_setattr_in *fsi;
struct fuse_attr_out *fao;
struct vattr *old_va;
+ u_quad_t va_size;
int error;
ps = puffs_getspecific(pu);
@@ -1552,13 +1562,14 @@
return EACCES;
/*
- * It seems troublesome to resize a file while
- * a write is just beeing done. Wait for
- * it to finish.
- */
- if (vap->va_size != (u_quad_t)PUFFS_VNOVAL)
- while (pnd->pnd_flags & PND_INWRITE)
- requeue_request(pu, opc, PCQ_AFTERWRITE);
+ * If a write is in progress, set the highest
+ * value in the filesystem, otherwise we break
+ * IO_APPEND.
+ */
+ va_size = vap->va_size;
+ if ((pnd->pnd_flags & PND_INWRITE) &&
+ (va_size != (u_quad_t)PUFFS_VNOVAL))
+ va_size = MAX(va_size, old_va->va_size);
pm = ps->ps_new_msg(pu, opc, FUSE_SETATTR, sizeof(*fsi), pcr);
fsi = GET_INPAYLOAD(ps, pm, fuse_setattr_in);
@@ -1573,8 +1584,8 @@
fsi->valid |= FUSE_FATTR_FH;
}
- if (vap->va_size != (u_quad_t)PUFFS_VNOVAL) {
- fsi->size = vap->va_size;
+ if (va_size != (u_quad_t)PUFFS_VNOVAL) {
+ fsi->size = va_size;
fsi->valid |= FUSE_FATTR_SIZE;
}