Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib/libperfuse Fix race conditions between write and getattr...
details: https://anonhg.NetBSD.org/src/rev/a4d0a7537268
branches: trunk
changeset: 765656:a4d0a7537268
user: manu <manu%NetBSD.org@localhost>
date: Wed Jun 01 15:54:10 2011 +0000
description:
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).
diffstat:
lib/libperfuse/ops.c | 29 ++++++++++++++++++++---------
1 files changed, 20 insertions(+), 9 deletions(-)
diffs (78 lines):
diff -r 6ff1e2caf445 -r a4d0a7537268 lib/libperfuse/ops.c
--- a/lib/libperfuse/ops.c Wed Jun 01 15:52:48 2011 +0000
+++ b/lib/libperfuse/ops.c Wed Jun 01 15:54:10 2011 +0000
@@ -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 a write is in progress, set the highest
+ * value in the filesystem, otherwise we break
+ * IO_APPEND.
*/
- if (vap->va_size != (u_quad_t)PUFFS_VNOVAL)
- while (pnd->pnd_flags & PND_INWRITE)
- requeue_request(pu, opc, PCQ_AFTERWRITE);
+ 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;
}
Home |
Main Index |
Thread Index |
Old Index