aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/fuse.h2
-rw-r--r--kernel/file.c14
-rw-r--r--lib/fuse.c16
3 files changed, 22 insertions, 10 deletions
diff --git a/include/fuse.h b/include/fuse.h
index f92914f..30d5f80 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -102,7 +102,7 @@ struct fuse_operations {
int (*read) (const char *, char *, size_t, off_t);
int (*write) (const char *, const char *, size_t, off_t);
int (*statfs) (struct fuse_statfs *);
- int (*release) (const char *);
+ int (*release) (const char *, int);
};
/** Extra context that may be needed by some filesystems */
diff --git a/kernel/file.c b/kernel/file.c
index 0ba4892..f4688f7 100644
--- a/kernel/file.c
+++ b/kernel/file.c
@@ -44,18 +44,30 @@ static int fuse_release(struct inode *inode, struct file *file)
{
struct fuse_conn *fc = INO_FC(inode);
struct fuse_in *in = NULL;
+ struct fuse_open_in *inarg = NULL;
in = kmalloc(sizeof(struct fuse_in), GFP_NOFS);
if(!in)
return -ENOMEM;
-
memset(in, 0, sizeof(struct fuse_in));
+
+ inarg = kmalloc(sizeof(struct fuse_open_in), GFP_NOFS);
+ if(!inarg)
+ goto out_free;
+ memset(inarg, 0, sizeof(struct fuse_open_in));
+
+ inarg->flags = file->f_flags & ~O_EXCL;
in->h.opcode = FUSE_RELEASE;
in->h.ino = inode->i_ino;
+ in->numargs = 1;
+ in->args[0].size = sizeof(struct fuse_open_in);
+ in->args[0].value = inarg;
if(!request_send_noreply(fc, in))
return 0;
+ out_free:
+ kfree(inarg);
kfree(in);
return 0;
}
diff --git a/lib/fuse.c b/lib/fuse.c
index 4919965..efe9e97 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -758,19 +758,20 @@ static void do_open(struct fuse *f, struct fuse_in_header *in,
if(path != NULL) {
/* The open syscall was interrupted, so it must be cancelled */
if(res == 0 && res2 == -ENOENT && f->op.release)
- f->op.release(path);
+ f->op.release(path, arg->flags);
free(path);
}
}
-static void do_release(struct fuse *f, struct fuse_in_header *in)
+static void do_release(struct fuse *f, struct fuse_in_header *in,
+ struct fuse_open_in *arg)
{
char *path;
path = get_path(f, in->ino);
if(path != NULL) {
if(f->op.release)
- f->op.release(path);
+ f->op.release(path, arg->flags);
free(path);
}
}
@@ -943,6 +944,10 @@ void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
do_open(f, in, (struct fuse_open_in *) inarg);
break;
+ case FUSE_RELEASE:
+ do_release(f, in, (struct fuse_open_in *) inarg);
+ break;
+
case FUSE_READ:
do_read(f, in, (struct fuse_read_in *) inarg);
break;
@@ -955,12 +960,7 @@ void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
do_statfs(f, in);
break;
- case FUSE_RELEASE:
- do_release(f, in);
- break;
-
default:
- fprintf(stderr, "Operation %i not implemented\n", in->opcode);
send_reply(f, in, -ENOSYS, NULL, 0);
}