diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2006-06-25 08:48:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-25 13:01:19 -0400 |
commit | 33649c91a3df57c1090a657637d44b896de367e7 (patch) | |
tree | 1ee4871a65f2b37a931c796463eb39737a32cbaa /fs/fuse/file.c | |
parent | 7142125937e1482ad3ae4366594c6586153dfc86 (diff) |
[PATCH] fuse: ensure FLUSH reaches userspace
All POSIX locks owned by the current task are removed on close(). If the
FLUSH request resulting initiated by close() fails to reach userspace, there
might be locks remaining, which cannot be removed.
The only reason it could fail, is if allocating the request fails. In this
case use the request reserved for RELEASE, or if that is currently used by
another FLUSH, wait for it to become available.
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 13 |
1 files changed, 5 insertions, 8 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index d9a8289297c0..ce759414cff9 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -48,8 +48,8 @@ struct fuse_file *fuse_file_alloc(void) | |||
48 | struct fuse_file *ff; | 48 | struct fuse_file *ff; |
49 | ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); | 49 | ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); |
50 | if (ff) { | 50 | if (ff) { |
51 | ff->release_req = fuse_request_alloc(); | 51 | ff->reserved_req = fuse_request_alloc(); |
52 | if (!ff->release_req) { | 52 | if (!ff->reserved_req) { |
53 | kfree(ff); | 53 | kfree(ff); |
54 | ff = NULL; | 54 | ff = NULL; |
55 | } | 55 | } |
@@ -59,7 +59,7 @@ struct fuse_file *fuse_file_alloc(void) | |||
59 | 59 | ||
60 | void fuse_file_free(struct fuse_file *ff) | 60 | void fuse_file_free(struct fuse_file *ff) |
61 | { | 61 | { |
62 | fuse_request_free(ff->release_req); | 62 | fuse_request_free(ff->reserved_req); |
63 | kfree(ff); | 63 | kfree(ff); |
64 | } | 64 | } |
65 | 65 | ||
@@ -115,7 +115,7 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) | |||
115 | struct fuse_req *fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, | 115 | struct fuse_req *fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, |
116 | int opcode) | 116 | int opcode) |
117 | { | 117 | { |
118 | struct fuse_req *req = ff->release_req; | 118 | struct fuse_req *req = ff->reserved_req; |
119 | struct fuse_release_in *inarg = &req->misc.release_in; | 119 | struct fuse_release_in *inarg = &req->misc.release_in; |
120 | 120 | ||
121 | inarg->fh = ff->fh; | 121 | inarg->fh = ff->fh; |
@@ -187,10 +187,7 @@ static int fuse_flush(struct file *file, fl_owner_t id) | |||
187 | if (fc->no_flush) | 187 | if (fc->no_flush) |
188 | return 0; | 188 | return 0; |
189 | 189 | ||
190 | req = fuse_get_req(fc); | 190 | req = fuse_get_req_nofail(fc, file); |
191 | if (IS_ERR(req)) | ||
192 | return PTR_ERR(req); | ||
193 | |||
194 | memset(&inarg, 0, sizeof(inarg)); | 191 | memset(&inarg, 0, sizeof(inarg)); |
195 | inarg.fh = ff->fh; | 192 | inarg.fh = ff->fh; |
196 | inarg.lock_owner = fuse_lock_owner_id(id); | 193 | inarg.lock_owner = fuse_lock_owner_id(id); |