diff options
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 49 |
1 files changed, 17 insertions, 32 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 087f3b734f40..1d59af306b28 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -30,7 +30,6 @@ static int fuse_send_open(struct inode *inode, struct file *file, int isdir, | |||
30 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); | 30 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); |
31 | req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; | 31 | req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; |
32 | req->in.h.nodeid = get_node_id(inode); | 32 | req->in.h.nodeid = get_node_id(inode); |
33 | req->inode = inode; | ||
34 | req->in.numargs = 1; | 33 | req->in.numargs = 1; |
35 | req->in.args[0].size = sizeof(inarg); | 34 | req->in.args[0].size = sizeof(inarg); |
36 | req->in.args[0].value = &inarg; | 35 | req->in.args[0].value = &inarg; |
@@ -113,37 +112,22 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) | |||
113 | return err; | 112 | return err; |
114 | } | 113 | } |
115 | 114 | ||
116 | /* Special case for failed iget in CREATE */ | 115 | struct fuse_req *fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, |
117 | static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) | 116 | int opcode) |
118 | { | 117 | { |
119 | /* If called from end_io_requests(), req has more than one | 118 | struct fuse_req *req = ff->release_req; |
120 | reference and fuse_reset_request() cannot work */ | ||
121 | if (fc->connected) { | ||
122 | u64 nodeid = req->in.h.nodeid; | ||
123 | fuse_reset_request(req); | ||
124 | fuse_send_forget(fc, req, nodeid, 1); | ||
125 | } else | ||
126 | fuse_put_request(fc, req); | ||
127 | } | ||
128 | |||
129 | void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff, | ||
130 | u64 nodeid, struct inode *inode, int flags, int isdir) | ||
131 | { | ||
132 | struct fuse_req * req = ff->release_req; | ||
133 | struct fuse_release_in *inarg = &req->misc.release_in; | 119 | struct fuse_release_in *inarg = &req->misc.release_in; |
134 | 120 | ||
135 | inarg->fh = ff->fh; | 121 | inarg->fh = ff->fh; |
136 | inarg->flags = flags; | 122 | inarg->flags = flags; |
137 | req->in.h.opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE; | 123 | req->in.h.opcode = opcode; |
138 | req->in.h.nodeid = nodeid; | 124 | req->in.h.nodeid = nodeid; |
139 | req->inode = inode; | ||
140 | req->in.numargs = 1; | 125 | req->in.numargs = 1; |
141 | req->in.args[0].size = sizeof(struct fuse_release_in); | 126 | req->in.args[0].size = sizeof(struct fuse_release_in); |
142 | req->in.args[0].value = inarg; | 127 | req->in.args[0].value = inarg; |
143 | request_send_background(fc, req); | ||
144 | if (!inode) | ||
145 | req->end = fuse_release_end; | ||
146 | kfree(ff); | 128 | kfree(ff); |
129 | |||
130 | return req; | ||
147 | } | 131 | } |
148 | 132 | ||
149 | int fuse_release_common(struct inode *inode, struct file *file, int isdir) | 133 | int fuse_release_common(struct inode *inode, struct file *file, int isdir) |
@@ -151,8 +135,15 @@ int fuse_release_common(struct inode *inode, struct file *file, int isdir) | |||
151 | struct fuse_file *ff = file->private_data; | 135 | struct fuse_file *ff = file->private_data; |
152 | if (ff) { | 136 | if (ff) { |
153 | struct fuse_conn *fc = get_fuse_conn(inode); | 137 | struct fuse_conn *fc = get_fuse_conn(inode); |
154 | u64 nodeid = get_node_id(inode); | 138 | struct fuse_req *req; |
155 | fuse_send_release(fc, ff, nodeid, inode, file->f_flags, isdir); | 139 | |
140 | req = fuse_release_fill(ff, get_node_id(inode), file->f_flags, | ||
141 | isdir ? FUSE_RELEASEDIR : FUSE_RELEASE); | ||
142 | |||
143 | /* Hold vfsmount and dentry until release is finished */ | ||
144 | req->vfsmount = mntget(file->f_vfsmnt); | ||
145 | req->dentry = dget(file->f_dentry); | ||
146 | request_send_background(fc, req); | ||
156 | } | 147 | } |
157 | 148 | ||
158 | /* Return value is ignored by VFS */ | 149 | /* Return value is ignored by VFS */ |
@@ -192,8 +183,6 @@ static int fuse_flush(struct file *file, fl_owner_t id) | |||
192 | inarg.fh = ff->fh; | 183 | inarg.fh = ff->fh; |
193 | req->in.h.opcode = FUSE_FLUSH; | 184 | req->in.h.opcode = FUSE_FLUSH; |
194 | req->in.h.nodeid = get_node_id(inode); | 185 | req->in.h.nodeid = get_node_id(inode); |
195 | req->inode = inode; | ||
196 | req->file = file; | ||
197 | req->in.numargs = 1; | 186 | req->in.numargs = 1; |
198 | req->in.args[0].size = sizeof(inarg); | 187 | req->in.args[0].size = sizeof(inarg); |
199 | req->in.args[0].value = &inarg; | 188 | req->in.args[0].value = &inarg; |
@@ -232,8 +221,6 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync, | |||
232 | inarg.fsync_flags = datasync ? 1 : 0; | 221 | inarg.fsync_flags = datasync ? 1 : 0; |
233 | req->in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC; | 222 | req->in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC; |
234 | req->in.h.nodeid = get_node_id(inode); | 223 | req->in.h.nodeid = get_node_id(inode); |
235 | req->inode = inode; | ||
236 | req->file = file; | ||
237 | req->in.numargs = 1; | 224 | req->in.numargs = 1; |
238 | req->in.args[0].size = sizeof(inarg); | 225 | req->in.args[0].size = sizeof(inarg); |
239 | req->in.args[0].value = &inarg; | 226 | req->in.args[0].value = &inarg; |
@@ -266,8 +253,6 @@ void fuse_read_fill(struct fuse_req *req, struct file *file, | |||
266 | inarg->size = count; | 253 | inarg->size = count; |
267 | req->in.h.opcode = opcode; | 254 | req->in.h.opcode = opcode; |
268 | req->in.h.nodeid = get_node_id(inode); | 255 | req->in.h.nodeid = get_node_id(inode); |
269 | req->inode = inode; | ||
270 | req->file = file; | ||
271 | req->in.numargs = 1; | 256 | req->in.numargs = 1; |
272 | req->in.args[0].size = sizeof(struct fuse_read_in); | 257 | req->in.args[0].size = sizeof(struct fuse_read_in); |
273 | req->in.args[0].value = inarg; | 258 | req->in.args[0].value = inarg; |
@@ -342,6 +327,8 @@ static void fuse_send_readpages(struct fuse_req *req, struct file *file, | |||
342 | req->out.page_zeroing = 1; | 327 | req->out.page_zeroing = 1; |
343 | fuse_read_fill(req, file, inode, pos, count, FUSE_READ); | 328 | fuse_read_fill(req, file, inode, pos, count, FUSE_READ); |
344 | if (fc->async_read) { | 329 | if (fc->async_read) { |
330 | get_file(file); | ||
331 | req->file = file; | ||
345 | req->end = fuse_readpages_end; | 332 | req->end = fuse_readpages_end; |
346 | request_send_background(fc, req); | 333 | request_send_background(fc, req); |
347 | } else { | 334 | } else { |
@@ -420,8 +407,6 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file, | |||
420 | inarg.size = count; | 407 | inarg.size = count; |
421 | req->in.h.opcode = FUSE_WRITE; | 408 | req->in.h.opcode = FUSE_WRITE; |
422 | req->in.h.nodeid = get_node_id(inode); | 409 | req->in.h.nodeid = get_node_id(inode); |
423 | req->inode = inode; | ||
424 | req->file = file; | ||
425 | req->in.argpages = 1; | 410 | req->in.argpages = 1; |
426 | req->in.numargs = 2; | 411 | req->in.numargs = 2; |
427 | req->in.args[0].size = sizeof(struct fuse_write_in); | 412 | req->in.args[0].size = sizeof(struct fuse_write_in); |