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