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; }