summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Pierre André <jpandre@users.sourceforge.net>2013-06-23 11:56:01 +0200
committerJean-Pierre André <jpandre@users.sourceforge.net>2013-06-23 11:56:01 +0200
commit8eaabb6f6ee90fba52632cf92521e56540d76cb0 (patch)
tree5b5fbbb790685b1060ce24a789acd09742610d69
parent671532be7af3692b24b2d415e04efb316cb06cc2 (diff)
downloadillumos-fusefs-8eaabb6f6ee90fba52632cf92521e56540d76cb0.tar.gz
Kept track of mapped files and released them accordingly
-rw-r--r--kernel/fuse_vnops.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/kernel/fuse_vnops.c b/kernel/fuse_vnops.c
index 68dc0e4..3a40703 100644
--- a/kernel/fuse_vnops.c
+++ b/kernel/fuse_vnops.c
@@ -4047,14 +4047,28 @@ fuse_addmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
size_t len, uchar_t prot, uchar_t maxprot, uint_t flags,
cred_t *cr, caller_context_t *ct)
{
+ long oldcnt;
+ int err = 0;
+ struct fuse_file_handle *fhp;
+
if (vp->v_flag & VNOMAP)
return (ENOSYS);
mutex_enter(&VTOFD(vp)->f_lock);
+ oldcnt = VTOFD(vp)->f_mapcnt;
VTOFD(vp)->f_mapcnt += btopr(len);
mutex_exit(&VTOFD(vp)->f_lock);
+ if (!oldcnt) {
+ /*
+ * Increment the reference count on the vnode, so that
+ * the data associated will not be freed on close()
+ * and kept available for subsequent getapage().
+ */
+ err = get_filehandle(vp, FREAD | FWRITE, cr, &fhp,
+ CACHE_LIST_CHECK);
+ }
- return (0);
+ return (err);
}
/* ARGSUSED */
@@ -4063,6 +4077,8 @@ fuse_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
size_t len, uint_t prot, uint_t maxprot, uint_t flags,
cred_t *cr, caller_context_t *ct)
{
+ int err = 0;
+
if (vp->v_flag & VNOMAP)
return (ENOSYS);
@@ -4074,7 +4090,15 @@ fuse_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
vn_has_cached_data(vp))
(void) VOP_PUTPAGE(vp, off, len, B_ASYNC, cr, ct);
- return (0);
+ /*
+ * If there is no more reference to the vnode, we can
+ * now release the data which may have been delayed
+ * by incrementing the reference count in addmap().
+ */
+ if (!VTOFD(vp)->f_mapcnt)
+ err = fuse_close(vp, flags | FREAD | FWRITE, 1, 0, cr, ct);
+
+ return (err);
}
static void