aboutsummaryrefslogtreecommitdiffstats
path: root/lib/fuse_lowlevel.c
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2011-12-06 18:06:18 +0100
committerMiklos Szeredi <mszeredi@suse.cz>2011-12-06 18:06:18 +0100
commit4b2157c44e6ad7e692fcffb7450143e83151d36b (patch)
tree9b75b0fdab1ea4be8f435a69a1497cc744ad56eb /lib/fuse_lowlevel.c
parente3f95263a703d45f091dcf9655806978d2577797 (diff)
downloadandroid_external_fuse-4b2157c44e6ad7e692fcffb7450143e83151d36b.tar.gz
android_external_fuse-4b2157c44e6ad7e692fcffb7450143e83151d36b.tar.bz2
android_external_fuse-4b2157c44e6ad7e692fcffb7450143e83151d36b.zip
Add mmap() and munmap() methods to low level API
Currently this is only useful for CUSE. Also update retrieve_reply() method.
Diffstat (limited to 'lib/fuse_lowlevel.c')
-rw-r--r--lib/fuse_lowlevel.c70
1 files changed, 64 insertions, 6 deletions
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 8012d49..f69b2b1 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -437,7 +437,18 @@ static int fuse_send_data_iov_fallback(struct fuse_ll *f, struct fuse_chan *ch,
void *mbuf;
int res;
- /* FIXME: Avoid memory copy if none of the buffers contain an fd */
+ /* Optimize common case */
+ if (buf->count == 1 && buf->idx == 0 && buf->off == 0 &&
+ !(buf->buf[0].flags & FUSE_BUF_IS_FD)) {
+ /* FIXME: also avoid memory copy if there are multiple buffers
+ but none of them contain an fd */
+
+ iov[iov_count].iov_base = buf->buf[0].mem;
+ iov[iov_count].iov_len = len;
+ iov_count++;
+ return fuse_send_msg(f, ch, iov, iov_count);
+ }
+
res = posix_memalign(&mbuf, pagesize, len);
if (res != 0)
return res;
@@ -956,6 +967,17 @@ int fuse_reply_poll(fuse_req_t req, unsigned revents)
return send_reply_ok(req, &arg, sizeof(arg));
}
+int fuse_reply_mmap(fuse_req_t req, uint64_t map_id, size_t length)
+{
+ struct fuse_mmap_out arg;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.mapid = map_id;
+ arg.size = length;
+
+ return send_reply_ok(req, &arg, sizeof(arg));
+}
+
static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
char *name = (char *) inarg;
@@ -1704,6 +1726,38 @@ static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
+static void do_mmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+ struct fuse_mmap_in *arg = (struct fuse_mmap_in *) inarg;
+ struct fuse_file_info fi;
+
+ memset(&fi, 0, sizeof(fi));
+ fi.fh = arg->fh;
+ fi.fh_old = fi.fh;
+
+ if (req->f->op.mmap)
+ req->f->op.mmap(req, nodeid, arg->addr, arg->len, arg->prot,
+ arg->flags, arg->offset, &fi);
+ else
+ fuse_reply_err(req, ENOSYS);
+
+}
+
+static void do_munmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+ struct fuse_munmap_in *arg = (struct fuse_munmap_in *) inarg;
+ struct fuse_file_info fi;
+
+ memset(&fi, 0, sizeof(fi));
+ fi.fh = arg->fh;
+ fi.fh_old = fi.fh;
+
+ if (req->f->op.munmap)
+ req->f->op.munmap(req, nodeid, arg->mapid, arg->size, &fi);
+ else
+ fuse_reply_err(req, ENOSYS);
+}
+
static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
@@ -2069,12 +2123,14 @@ static void fuse_ll_retrieve_reply(struct fuse_notify_req *nreq,
}
bufv.buf[0].size = arg->size;
- if (req->f->op.retrieve_reply)
- req->f->op.retrieve_reply(rreq->cookie, ino, arg->offset, &bufv);
- fuse_reply_none(req);
- free(rreq);
-
+ if (req->f->op.retrieve_reply) {
+ req->f->op.retrieve_reply(req, rreq->cookie, ino,
+ arg->offset, &bufv);
+ } else {
+ fuse_reply_none(req);
+ }
out:
+ free(rreq);
if ((ibuf->flags & FUSE_BUF_IS_FD) && bufv.idx < bufv.count)
fuse_ll_clear_pipe(f);
}
@@ -2218,6 +2274,8 @@ static struct {
[FUSE_DESTROY] = { do_destroy, "DESTROY" },
[FUSE_NOTIFY_REPLY] = { (void *) 1, "NOTIFY_REPLY" },
[FUSE_BATCH_FORGET] = { do_batch_forget, "BATCH_FORGET" },
+ [FUSE_MMAP] = { do_mmap, "MMAP" },
+ [FUSE_MUNMAP] = { do_munmap, "MUNMAP" },
[CUSE_INIT] = { cuse_lowlevel_init, "CUSE_INIT" },
};