fuse: add file kernel handle
The file handle, fuse_file->fh, is opaque value supplied by userland
FUSE server and uniqueness is not guaranteed. Add file kernel handle,
fuse_file->kh, which is allocated by the kernel on file allocation and
guaranteed to be unique.
This will be used by poll to match notification to the respective file
but can be used for other purposes where unique file handle is
necessary.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 9e7c538..16ae55d 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -408,7 +408,7 @@
goto out_put_forget_req;
err = -ENOMEM;
- ff = fuse_file_alloc();
+ ff = fuse_file_alloc(fc);
if (!ff)
goto out_put_request;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index baed06e..a28ced6 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -46,7 +46,7 @@
return err;
}
-struct fuse_file *fuse_file_alloc(void)
+struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
{
struct fuse_file *ff;
ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL);
@@ -58,6 +58,9 @@
} else {
INIT_LIST_HEAD(&ff->write_entry);
atomic_set(&ff->count, 0);
+ spin_lock(&fc->lock);
+ ff->kh = ++fc->khctr;
+ spin_unlock(&fc->lock);
}
}
return ff;
@@ -108,6 +111,7 @@
int fuse_open_common(struct inode *inode, struct file *file, int isdir)
{
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_open_out outarg;
struct fuse_file *ff;
int err;
@@ -120,7 +124,7 @@
if (err)
return err;
- ff = fuse_file_alloc();
+ ff = fuse_file_alloc(fc);
if (!ff)
return -ENOMEM;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 4fc5131..86f0133 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -100,6 +100,9 @@
/** Request reserved for flush and release */
struct fuse_req *reserved_req;
+ /** Kernel file handle guaranteed to be unique */
+ u64 kh;
+
/** File handle used by userspace */
u64 fh;
@@ -322,6 +325,9 @@
/** The list of requests under I/O */
struct list_head io;
+ /** The next unique kernel file handle */
+ u64 khctr;
+
/** Number of requests currently in the background */
unsigned num_background;
@@ -499,7 +505,7 @@
*/
int fuse_open_common(struct inode *inode, struct file *file, int isdir);
-struct fuse_file *fuse_file_alloc(void);
+struct fuse_file *fuse_file_alloc(struct fuse_conn *fc);
void fuse_file_free(struct fuse_file *ff);
void fuse_finish_open(struct inode *inode, struct file *file,
struct fuse_file *ff, struct fuse_open_out *outarg);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index fa47498..0e15bc2 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -485,6 +485,7 @@
fc->bdi.unplug_io_fn = default_unplug_io_fn;
/* fuse does it's own writeback accounting */
fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB;
+ fc->khctr = 0;
fc->dev = sb->s_dev;
err = bdi_init(&fc->bdi);
if (err)