Module Name: src Committed By: manu Date: Fri Dec 16 05:34:54 UTC 2011
Modified Files: src/lib/libperfuse: ops.c Log Message: Rework puffs_framebuf management toremove leaks and abusive reuses. On exchange error, the puffs_framebuf is now freed immediatly, before requeuing outstanding requests. To generate a diff of this commit: cvs rdiff -u -r1.47 -r1.48 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.47 src/lib/libperfuse/ops.c:1.48 --- src/lib/libperfuse/ops.c:1.47 Mon Nov 28 05:33:33 2011 +++ src/lib/libperfuse/ops.c Fri Dec 16 05:34:54 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ops.c,v 1.47 2011/11/28 05:33:33 manu Exp $ */ +/* $NetBSD: ops.c,v 1.48 2011/12/16 05:34:54 manu Exp $ */ /*- * Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved. @@ -187,21 +187,14 @@ perfuse_node_close_common(pu, opc, mode) if ((error = xchg_msg(pu, opc, pm, NO_PAYLOAD_REPLY_LEN, wait_reply)) != 0) - goto out; - - ps->ps_destroy_msg(pm); - - error = 0; - -out: - if (error != 0) DERRX(EX_SOFTWARE, "%s: freed fh = 0x%"PRIx64" but filesystem " "returned error = %d", __func__, fh, error); - return error; + ps->ps_destroy_msg(pm); + + return 0; } -/* ARGSUSED1 */ static int xchg_msg(pu, opc, pm, len, wait) struct puffs_usermount *pu; @@ -229,7 +222,8 @@ xchg_msg(pu, opc, pm, len, wait) if (pnd) pnd->pnd_flags |= PND_INXCHG; - error = ps->ps_xchg_msg(pu, pm, len, wait); + if ((error = ps->ps_xchg_msg(pu, pm, len, wait)) != 0) + ps->ps_destroy_msg(pm); if (pnd) { pnd->pnd_flags &= ~PND_INXCHG; @@ -523,7 +517,7 @@ node_lookup_common(pu, opc, path, pcr, p } /* FALLTHROUGH */ default: - goto out; + return error; /* NOTREACHED */ break; } @@ -534,7 +528,9 @@ node_lookup_common(pu, opc, path, pcr, p if (oldpnd->pnd_nodeid == feo->nodeid) { oldpnd->pnd_nlookup++; *pnp = oldpnd->pnd_pn; - goto out; + + ps->ps_destroy_msg(pm); + return 0; } else { oldpnd->pnd_flags |= PND_REMOVED; #ifdef PERFUSE_DEBUG @@ -563,10 +559,9 @@ node_lookup_common(pu, opc, path, pcr, p (void *)opc, pn, feo->nodeid, path); #endif -out: ps->ps_destroy_msg(pm); - return error; + return 0; } @@ -592,7 +587,7 @@ node_mk_common(pu, opc, pni, pcn, pm) ps = puffs_getspecific(pu); if ((error = xchg_msg(pu, opc, pm, sizeof(*feo), wait_reply)) != 0) - goto out; + return error; feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out); if (feo->nodeid == PERFUSE_UNKNOWN_NODEID) @@ -617,11 +612,6 @@ node_mk_common(pu, opc, pni, pcn, pm) ps->ps_destroy_msg(pm); return node_mk_common_final(pu, opc, pn, pcn); - -out: - ps->ps_destroy_msg(pm); - - return error; } /* @@ -664,7 +654,7 @@ node_mk_common_final(pu, opc, pn, pcn) if ((error = xchg_msg(pu, (puffs_cookie_t)pn, pm, sizeof(*fao), wait_reply)) != 0) - goto out; + return error; fao = GET_OUTPAYLOAD(ps, pm, fuse_attr_out); fuse_attr_to_vap(ps, &pn->pn_va, &fao->attr); @@ -675,11 +665,9 @@ node_mk_common_final(pu, opc, pn, pcn) */ PERFUSE_NODE_DATA(opc)->pnd_flags |= PND_DIRTY; -out: - if (pm != NULL) - ps->ps_destroy_msg(pm); + ps->ps_destroy_msg(pm); - return error; + return 0; } static uint64_t @@ -1022,7 +1010,11 @@ perfuse_fs_unmount(pu, flags) if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0){ DWARN("unmount %s", ps->ps_target); if (!(flags & MNT_FORCE)) - goto out; + return error; + else + error = 0; + } else { + ps->ps_destroy_msg(pm); } ps->ps_umount(pu); @@ -1031,10 +1023,6 @@ perfuse_fs_unmount(pu, flags) DPRINTF("%s unmounted, exit\n", ps->ps_target); return 0; -out: - ps->ps_destroy_msg(pm); - - return error; } int @@ -1058,7 +1046,7 @@ perfuse_fs_statvfs(pu, svfsb) pm = ps->ps_new_msg(pu, opc, FUSE_STATFS, 0, NULL); if ((error = xchg_msg(pu, opc, pm, sizeof(*fso), wait_reply)) != 0) - goto out; + return error; fso = GET_OUTPAYLOAD(ps, pm, fuse_statfs_out); svfsb->f_flag = ps->ps_mountflags; @@ -1097,10 +1085,10 @@ perfuse_fs_statvfs(pu, svfsb) strlcpy(svfsb->f_mntfromname, ps->ps_source, _VFS_NAMELEN); else strlcpy(svfsb->f_mntfromname, _PATH_FUSE, _VFS_NAMELEN); -out: + ps->ps_destroy_msg(pm); - - return error; + + return 0; } int @@ -1338,8 +1326,18 @@ perfuse_node_create(pu, opc, pni, pcn, v (void)strlcpy((char*)(void *)(fci + 1), name, namelen); len = sizeof(*feo) + sizeof(*foo); - if ((error = xchg_msg(pu, opc, pm, len, wait_reply)) != 0) - goto out; + if ((error = xchg_msg(pu, opc, pm, len, wait_reply)) != 0) { + /* + * create is unimplmented, remember it for later, + * and start over using mknod and open instead. + */ + if (error == ENOSYS) { + ps->ps_flags |= PS_NO_CREAT; + return perfuse_node_create(pu, opc, pni, pcn, vap); + } + + return error; + } feo = GET_OUTPAYLOAD(ps, pm, fuse_entry_out); foo = (struct fuse_open_out *)(void *)(feo + 1); @@ -1372,20 +1370,6 @@ perfuse_node_create(pu, opc, pni, pcn, v ps->ps_destroy_msg(pm); return node_mk_common_final(pu, opc, pn, pcn); - -out: - ps->ps_destroy_msg(pm); - - /* - * create is unimplmented, remember it for later, - * and start over using mknod and open instead. - */ - if (error == ENOSYS) { - ps->ps_flags |= PS_NO_CREAT; - return perfuse_node_create(pu, opc, pni, pcn, vap); - } - - return error; } @@ -1463,7 +1447,6 @@ perfuse_node_open(pu, opc, mode, pcr) ps = puffs_getspecific(pu); pn = (struct puffs_node *)opc; pnd = PERFUSE_NODE_DATA(opc); - pm = NULL; error = 0; if (pnd->pnd_flags & PND_REMOVED) @@ -1492,10 +1475,8 @@ perfuse_node_open(pu, opc, mode, pcr) */ if (((mode & FREAD) && (pnd->pnd_flags & PND_RFH)) || ((mode & FREAD) && (pnd->pnd_flags & PND_WFH)) || - ((mode & FWRITE) && (pnd->pnd_flags & PND_WFH))) { - error = 0; + ((mode & FWRITE) && (pnd->pnd_flags & PND_WFH))) goto out; - } /* * Queue open on a node so that we do not open @@ -1538,9 +1519,8 @@ perfuse_node_open(pu, opc, mode, pcr) mode & FWRITE ? "w" : "", foo->fh); #endif + ps->ps_destroy_msg(pm); out: - if (pm != NULL) - ps->ps_destroy_msg(pm); pnd->pnd_flags &= ~PND_INOPEN; (void)dequeue_requests(ps, opc, PCQ_OPEN, DEQUEUE_ALL); @@ -1703,9 +1683,8 @@ perfuse_node_getattr(pu, opc, vap, pcr) fuse_attr_to_vap(ps, vap, &fao->attr); set_expire(opc, NULL, fao); + ps->ps_destroy_msg(pm); out: - if (pm != NULL) - ps->ps_destroy_msg(pm); pnd->pnd_flags &= ~PND_INRESIZE; (void)dequeue_requests(ps, opc, PCQ_RESIZE, DEQUEUE_ALL); @@ -1735,7 +1714,6 @@ perfuse_node_setattr(pu, opc, vap, pcr) ps = puffs_getspecific(pu); pnd = PERFUSE_NODE_DATA(opc); - pm = NULL; /* * The only operation we can do once the file is removed @@ -1922,10 +1900,9 @@ perfuse_node_setattr(pu, opc, vap, pcr) fuse_attr_to_vap(ps, old_va, &fao->attr); set_expire(opc, NULL, fao); -out: - if (pm != NULL) - ps->ps_destroy_msg(pm); + ps->ps_destroy_msg(pm); +out: if (pnd->pnd_flags & PND_INRESIZE) { pnd->pnd_flags &= ~PND_INRESIZE; (void)dequeue_requests(ps, opc, PCQ_RESIZE, DEQUEUE_ALL); @@ -1966,19 +1943,19 @@ perfuse_node_poll(pu, opc, events) #ifdef PERFUSE_DEBUG if (perfuse_diagflags & PDF_FH) - DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", fh = 0x%"PRIx64"\n", - __func__, (void *)opc, + DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", " + "fh = 0x%"PRIx64"\n", __func__, (void *)opc, PERFUSE_NODE_DATA(opc)->pnd_nodeid, fpi->fh); #endif if ((error = xchg_msg(pu, opc, pm, sizeof(*fpo), wait_reply)) != 0) - goto out; + return error; fpo = GET_OUTPAYLOAD(ps, pm, fuse_poll_out); *events = fpo->revents; -out: + ps->ps_destroy_msg(pm); - return error; + return 0; } /* ARGSUSED0 */ @@ -2098,6 +2075,8 @@ perfuse_node_fsync(pu, opc, pcr, flags, __func__, (void*)opc, perfuse_node_path(opc)); #endif + ps->ps_destroy_msg(pm); + out: /* * ENOSYS is not returned to kernel, @@ -2105,9 +2084,6 @@ out: if (error == ENOSYS) error = 0; - if (pm != NULL) - ps->ps_destroy_msg(pm); - return error; } @@ -2170,7 +2146,7 @@ perfuse_node_remove(pu, opc, targ, pcn) (void)strlcpy(path, name, len); if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0) - goto out; + return error; PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED; if (!(PERFUSE_NODE_DATA(targ)->pnd_flags & PND_OPEN)) @@ -2187,10 +2163,9 @@ perfuse_node_remove(pu, opc, targ, pcn) __func__, PERFUSE_NODE_DATA(targ)->pnd_nodeid, pcn->pcn_name); #endif -out: ps->ps_destroy_msg(pm); - return error; + return 0; } int @@ -2221,11 +2196,12 @@ perfuse_node_link(pu, opc, targ, pcn) fli->oldnodeid = PERFUSE_NODE_DATA(pn)->pnd_nodeid; (void)strlcpy((char *)(void *)(fli + 1), name, len - sizeof(*fli)); - error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply); + if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0) + return error; ps->ps_destroy_msg(pm); - return error; + return 0; } int @@ -2283,7 +2259,7 @@ perfuse_node_rename(pu, opc, src, pcn_sr (void)strlcpy(np, newname, newname_len); if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0) - goto out; + return error; if (opc != targ_dir) { struct perfuse_node_data *srcdir_pnd; @@ -2323,11 +2299,9 @@ perfuse_node_rename(pu, opc, src, pcn_sr perfuse_node_path(targ_dir)); #endif -out: - if (pm != NULL) - ps->ps_destroy_msg(pm); + ps->ps_destroy_msg(pm); - return error; + return 0; } int @@ -2399,7 +2373,7 @@ perfuse_node_rmdir(pu, opc, targ, pcn) (void)strlcpy(path, name, len); if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0) - goto out; + return error; PERFUSE_NODE_DATA(targ)->pnd_flags |= PND_REMOVED; if (!(PERFUSE_NODE_DATA(targ)->pnd_flags & PND_OPEN)) @@ -2416,10 +2390,9 @@ perfuse_node_rmdir(pu, opc, targ, pcn) __func__, PERFUSE_NODE_DATA(targ)->pnd_nodeid, perfuse_node_path(targ)); #endif -out: ps->ps_destroy_msg(pm); - return error; + return 0; } /* vap is unused */ @@ -2484,7 +2457,6 @@ perfuse_node_readdir(pu, opc, dent, read int error; size_t fd_maxlen; - pm = NULL; error = 0; ps = puffs_getspecific(pu); @@ -2530,8 +2502,8 @@ perfuse_node_readdir(pu, opc, dent, read #ifdef PERFUSE_DEBUG if (perfuse_diagflags & PDF_FH) - DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", rfh = 0x%"PRIx64"\n", - __func__, (void *)opc, + DPRINTF("%s: opc = %p, nodeid = 0x%"PRIx64", " + "rfh = 0x%"PRIx64"\n", __func__, (void *)opc, PERFUSE_NODE_DATA(opc)->pnd_nodeid, fh); #endif @@ -2572,6 +2544,7 @@ perfuse_node_readdir(pu, opc, dent, read * Empty read: we reached the end of the buffer. */ if (foh_len == sizeof(*foh)) { + ps->ps_destroy_msg(pm); *eofflag = 1; break; } @@ -2580,6 +2553,7 @@ perfuse_node_readdir(pu, opc, dent, read * Check for corrupted message. */ if (foh_len < sizeof(*foh) + sizeof(*fd)) { + ps->ps_destroy_msg(pm); DWARNX("readdir reply too short"); error = EIO; goto out; @@ -2606,7 +2580,6 @@ perfuse_node_readdir(pu, opc, dent, read pnd->pnd_fd_cookie = readdir_last_cookie(fd, fd_len); ps->ps_destroy_msg(pm); - pm = NULL; } while (1 /* CONSTCOND */); if (pnd->pnd_all_fd != NULL) { @@ -2622,9 +2595,6 @@ out: pnd->pnd_all_fd_len = 0; } - if (pm != NULL) - ps->ps_destroy_msg(pm); - if (error == 0) error = readdir_buffered(opc, dent, readoff, reslen); @@ -2665,7 +2635,7 @@ perfuse_node_readlink(pu, opc, pcr, link pm = ps->ps_new_msg(pu, opc, FUSE_READLINK, 0, pcr); if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0) - goto out; + return error; foh = GET_OUTHDR(ps, pm); len = foh->len - sizeof(*foh); @@ -2680,10 +2650,10 @@ perfuse_node_readlink(pu, opc, pcr, link */ *linklen = len - 1; (void)memcpy(linkname, _GET_OUTPAYLOAD(ps, pm, char *), len); -out: + ps->ps_destroy_msg(pm); - return error; + return 0; } int @@ -2936,7 +2906,7 @@ perfuse_node_advlock(pu, opc, id, op, fl #endif if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0) - goto out; + return error; foh = GET_OUTHDR(ps, pm); len = foh->len - sizeof(*foh); @@ -2979,11 +2949,10 @@ perfuse_node_advlock(pu, opc, id, op, fl DERRX(EX_SOFTWARE, "%s: Unexpected op %d", __func__, op); break; } - -out: + ps->ps_destroy_msg(pm); - return error; + return 0; } int @@ -3008,7 +2977,6 @@ perfuse_node_read(pu, opc, buf, offset, ps = puffs_getspecific(pu); pnd = PERFUSE_NODE_DATA(opc); vap = puffs_pn_getvap((struct puffs_node *)opc); - pm = NULL; /* * NetBSD turns that into a getdents(2) output @@ -3046,9 +3014,8 @@ perfuse_node_read(pu, opc, buf, offset, __func__, (void *)opc, pnd->pnd_nodeid, fri->fh); #endif error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply); - if (error != 0) - goto out; + return error; foh = GET_OUTHDR(ps, pm); readen = foh->len - sizeof(*foh); @@ -3066,7 +3033,6 @@ perfuse_node_read(pu, opc, buf, offset, *resid -= readen; ps->ps_destroy_msg(pm); - pm = NULL; } while ((*resid != 0) && (readen != 0)); if (ioflag & (IO_SYNC|IO_DSYNC)) @@ -3074,11 +3040,7 @@ perfuse_node_read(pu, opc, buf, offset, else ps->ps_asyncreads++; -out: - if (pm != NULL) - ps->ps_destroy_msg(pm); - - return error; + return 0; } int @@ -3108,7 +3070,7 @@ perfuse_node_write(pu, opc, buf, offset, vap = puffs_pn_getvap((struct puffs_node *)opc); written = 0; inresize = 0; - pm = NULL; + error = 0; if (vap->va_type == VDIR) return EISDIR; @@ -3144,8 +3106,6 @@ perfuse_node_write(pu, opc, buf, offset, offset = vap->va_size; } - pm = NULL; - #ifdef PERFUSE_DEBUG if (perfuse_diagflags & PDF_RESIZE) DPRINTF(">> %s %p %" PRIu64 "\n", __func__, @@ -3208,7 +3168,6 @@ perfuse_node_write(pu, opc, buf, offset, buf += written; ps->ps_destroy_msg(pm); - pm = NULL; } while (*resid != 0); /* @@ -3262,10 +3221,8 @@ perfuse_node_write(pu, opc, buf, offset, DPRINTF("%s: DIRTY opc = %p, file = \"%s\"\n", __func__, (void*)opc, perfuse_node_path(opc)); #endif -out: - if (pm != NULL) - ps->ps_destroy_msg(pm); +out: /* * If there are no more queued write, we can resume * an operation awaiting write completion. @@ -3323,7 +3280,7 @@ perfuse_node_getextattr(pu, opc, attrns, (void)strlcpy(np, attrname, attrnamelen); if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0) - goto out; + return error; /* * We just get fuse_getattr_out with list size if we requested @@ -3335,7 +3292,8 @@ perfuse_node_getextattr(pu, opc, attrns, if (attrsize != NULL) *attrsize = fgo->size; - goto out; + ps->ps_destroy_msg(pm); + return 0; } /* @@ -3351,10 +3309,9 @@ perfuse_node_getextattr(pu, opc, attrns, *resid -= len; } -out: ps->ps_destroy_msg(pm); - return error; + return 0; } int @@ -3392,13 +3349,12 @@ perfuse_node_setextattr(pu, opc, attrns, if ((error = xchg_msg(pu, opc, pm, NO_PAYLOAD_REPLY_LEN, wait_reply)) != 0) - goto out; + return error; *resid = 0; -out: ps->ps_destroy_msg(pm); - return error; + return 0; } /* ARGSUSED2 */ @@ -3433,7 +3389,7 @@ perfuse_node_listextattr(pu, opc, attrns fgi->size = 0; if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0) - goto out; + return error; /* * We just get fuse_getattr_out with list size if we requested @@ -3445,7 +3401,9 @@ perfuse_node_listextattr(pu, opc, attrns if (attrsize != NULL) *attrsize = fgo->size; - goto out; + ps->ps_destroy_msg(pm); + + return 0; } /* @@ -3479,10 +3437,9 @@ perfuse_node_listextattr(pu, opc, attrns if (attrsize != NULL) *attrsize = puffs_len; -out: ps->ps_destroy_msg(pm); - return error; + return 0; } int