From: Stef B. <st...@gm...> - 2014-04-06 09:47:51
|
Add the sending of a fsnotify message to userspace, and the first step of handling the FUSE_NOTIFY_CREATE message. Signed-off-by: Stef Bon <st...@gm...> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 0a648bb..2cad706 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1187,6 +1187,39 @@ __releases(fc->lock) return fuse_read_batch_forget(fc, cs, nbytes); } +void fuse_send_fsnotify_mark(struct inode *inode) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_inode *fi = get_fuse_inode(inode); + + if (fc) { + struct fuse_req *req=fuse_get_req_nopages(fc); + + if (! IS_ERR(req) ) { + struct fuse_fsnotify_in *inarg=&req->misc.fsnotify_in; + + memset(inarg, 0, sizeof(struct fuse_fsnotify_in)); + inarg->mask = inode->i_fsnotify_mask; + + req->in.h.opcode = FUSE_FSNOTIFY; + req->in.h.nodeid = fi->nodeid; + req->in.numargs = 1; + req->in.args[0].size = sizeof(struct fuse_fsnotify_in); + req->in.args[0].value = inarg; + req->out.numargs = 0; + req->isreply = 1; + req->background = 1; + + printk(KERN_INFO "fuse_send_fsnotify_mark: mask %i\n", inode->i_fsnotify_mask); + + fuse_request_send_background(fc, req); + + } + + } + +} + /* * Read a single request into the userspace filesystem's buffer. This * function waits until a request is available, then removes it from @@ -1526,6 +1559,58 @@ err: return err; } +static int fuse_notify_create(struct fuse_conn *fc, unsigned int size, + struct fuse_copy_state *cs) +{ + struct fuse_notify_create_out outarg; + int err = -ENOMEM; + char *buf; + struct qstr name; + + buf = kzalloc(FUSE_NAME_MAX + 1, GFP_KERNEL); + if (!buf) + goto err; + + err = -EINVAL; + if (size < sizeof(outarg)) + goto err; + + err = fuse_copy_one(cs, &outarg, sizeof(outarg)); + if (err) + goto err; + + err = -ENAMETOOLONG; + if (outarg.namelen > FUSE_NAME_MAX) + goto err; + + err = -EINVAL; + if (size != sizeof(outarg) + outarg.namelen + 1) + goto err; + + name.name = buf; + name.len = outarg.namelen; + err = fuse_copy_one(cs, buf, outarg.namelen + 1); + if (err) + goto err; + fuse_copy_finish(cs); + buf[outarg.namelen] = 0; + name.hash = full_name_hash(name.name, name.len); + + down_read(&fc->killsb); + err = -ENOENT; + + if (fc->sb) err = fuse_reverse_create_entry(fc->sb, &outarg, &name); + + up_read(&fc->killsb); + kfree(buf); + return err; + +err: + kfree(buf); + fuse_copy_finish(cs); + return err; +} + static int fuse_notify_store(struct fuse_conn *fc, unsigned int size, struct fuse_copy_state *cs) { @@ -1745,6 +1830,9 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, case FUSE_NOTIFY_DELETE: return fuse_notify_delete(fc, size, cs); + case FUSE_NOTIFY_CREATE: + return fuse_notify_create(fc, size, cs); + default: fuse_copy_finish(cs); return -EINVAL; |