aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse/dir.c')
-rw-r--r--fs/fuse/dir.c56
1 files changed, 30 insertions, 26 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 8d7546e832e8..72a74cde6de8 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1,6 +1,6 @@
1/* 1/*
2 FUSE: Filesystem in Userspace 2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu> 3 Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
4 4
5 This program can be distributed under the terms of the GNU GPL. 5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING. 6 See the file COPYING.
@@ -79,7 +79,6 @@ static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
79{ 79{
80 req->in.h.opcode = FUSE_LOOKUP; 80 req->in.h.opcode = FUSE_LOOKUP;
81 req->in.h.nodeid = get_node_id(dir); 81 req->in.h.nodeid = get_node_id(dir);
82 req->inode = dir;
83 req->in.numargs = 1; 82 req->in.numargs = 1;
84 req->in.args[0].size = entry->d_name.len + 1; 83 req->in.args[0].size = entry->d_name.len + 1;
85 req->in.args[0].value = entry->d_name.name; 84 req->in.args[0].value = entry->d_name.name;
@@ -225,6 +224,20 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
225} 224}
226 225
227/* 226/*
227 * Synchronous release for the case when something goes wrong in CREATE_OPEN
228 */
229static void fuse_sync_release(struct fuse_conn *fc, struct fuse_file *ff,
230 u64 nodeid, int flags)
231{
232 struct fuse_req *req;
233
234 req = fuse_release_fill(ff, nodeid, flags, FUSE_RELEASE);
235 req->force = 1;
236 request_send(fc, req);
237 fuse_put_request(fc, req);
238}
239
240/*
228 * Atomic create+open operation 241 * Atomic create+open operation
229 * 242 *
230 * If the filesystem doesn't support this, then fall back to separate 243 * If the filesystem doesn't support this, then fall back to separate
@@ -237,6 +250,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
237 struct inode *inode; 250 struct inode *inode;
238 struct fuse_conn *fc = get_fuse_conn(dir); 251 struct fuse_conn *fc = get_fuse_conn(dir);
239 struct fuse_req *req; 252 struct fuse_req *req;
253 struct fuse_req *forget_req;
240 struct fuse_open_in inarg; 254 struct fuse_open_in inarg;
241 struct fuse_open_out outopen; 255 struct fuse_open_out outopen;
242 struct fuse_entry_out outentry; 256 struct fuse_entry_out outentry;
@@ -247,9 +261,14 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
247 if (fc->no_create) 261 if (fc->no_create)
248 return -ENOSYS; 262 return -ENOSYS;
249 263
264 forget_req = fuse_get_req(fc);
265 if (IS_ERR(forget_req))
266 return PTR_ERR(forget_req);
267
250 req = fuse_get_req(fc); 268 req = fuse_get_req(fc);
269 err = PTR_ERR(req);
251 if (IS_ERR(req)) 270 if (IS_ERR(req))
252 return PTR_ERR(req); 271 goto out_put_forget_req;
253 272
254 err = -ENOMEM; 273 err = -ENOMEM;
255 ff = fuse_file_alloc(); 274 ff = fuse_file_alloc();
@@ -262,7 +281,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
262 inarg.mode = mode; 281 inarg.mode = mode;
263 req->in.h.opcode = FUSE_CREATE; 282 req->in.h.opcode = FUSE_CREATE;
264 req->in.h.nodeid = get_node_id(dir); 283 req->in.h.nodeid = get_node_id(dir);
265 req->inode = dir;
266 req->in.numargs = 2; 284 req->in.numargs = 2;
267 req->in.args[0].size = sizeof(inarg); 285 req->in.args[0].size = sizeof(inarg);
268 req->in.args[0].value = &inarg; 286 req->in.args[0].value = &inarg;
@@ -285,25 +303,23 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
285 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) 303 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
286 goto out_free_ff; 304 goto out_free_ff;
287 305
306 fuse_put_request(fc, req);
288 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, 307 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
289 &outentry.attr); 308 &outentry.attr);
290 err = -ENOMEM;
291 if (!inode) { 309 if (!inode) {
292 flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 310 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
293 ff->fh = outopen.fh; 311 ff->fh = outopen.fh;
294 /* Special release, with inode = NULL, this will 312 fuse_sync_release(fc, ff, outentry.nodeid, flags);
295 trigger a 'forget' request when the release is 313 fuse_send_forget(fc, forget_req, outentry.nodeid, 1);
296 complete */ 314 return -ENOMEM;
297 fuse_send_release(fc, ff, outentry.nodeid, NULL, flags, 0);
298 goto out_put_request;
299 } 315 }
300 fuse_put_request(fc, req); 316 fuse_put_request(fc, forget_req);
301 d_instantiate(entry, inode); 317 d_instantiate(entry, inode);
302 fuse_change_timeout(entry, &outentry); 318 fuse_change_timeout(entry, &outentry);
303 file = lookup_instantiate_filp(nd, entry, generic_file_open); 319 file = lookup_instantiate_filp(nd, entry, generic_file_open);
304 if (IS_ERR(file)) { 320 if (IS_ERR(file)) {
305 ff->fh = outopen.fh; 321 ff->fh = outopen.fh;
306 fuse_send_release(fc, ff, outentry.nodeid, inode, flags, 0); 322 fuse_sync_release(fc, ff, outentry.nodeid, flags);
307 return PTR_ERR(file); 323 return PTR_ERR(file);
308 } 324 }
309 fuse_finish_open(inode, file, ff, &outopen); 325 fuse_finish_open(inode, file, ff, &outopen);
@@ -313,6 +329,8 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
313 fuse_file_free(ff); 329 fuse_file_free(ff);
314 out_put_request: 330 out_put_request:
315 fuse_put_request(fc, req); 331 fuse_put_request(fc, req);
332 out_put_forget_req:
333 fuse_put_request(fc, forget_req);
316 return err; 334 return err;
317} 335}
318 336
@@ -328,7 +346,6 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
328 int err; 346 int err;
329 347
330 req->in.h.nodeid = get_node_id(dir); 348 req->in.h.nodeid = get_node_id(dir);
331 req->inode = dir;
332 req->out.numargs = 1; 349 req->out.numargs = 1;
333 req->out.args[0].size = sizeof(outarg); 350 req->out.args[0].size = sizeof(outarg);
334 req->out.args[0].value = &outarg; 351 req->out.args[0].value = &outarg;
@@ -448,7 +465,6 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
448 465
449 req->in.h.opcode = FUSE_UNLINK; 466 req->in.h.opcode = FUSE_UNLINK;
450 req->in.h.nodeid = get_node_id(dir); 467 req->in.h.nodeid = get_node_id(dir);
451 req->inode = dir;
452 req->in.numargs = 1; 468 req->in.numargs = 1;
453 req->in.args[0].size = entry->d_name.len + 1; 469 req->in.args[0].size = entry->d_name.len + 1;
454 req->in.args[0].value = entry->d_name.name; 470 req->in.args[0].value = entry->d_name.name;
@@ -480,7 +496,6 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
480 496
481 req->in.h.opcode = FUSE_RMDIR; 497 req->in.h.opcode = FUSE_RMDIR;
482 req->in.h.nodeid = get_node_id(dir); 498 req->in.h.nodeid = get_node_id(dir);
483 req->inode = dir;
484 req->in.numargs = 1; 499 req->in.numargs = 1;
485 req->in.args[0].size = entry->d_name.len + 1; 500 req->in.args[0].size = entry->d_name.len + 1;
486 req->in.args[0].value = entry->d_name.name; 501 req->in.args[0].value = entry->d_name.name;
@@ -510,8 +525,6 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent,
510 inarg.newdir = get_node_id(newdir); 525 inarg.newdir = get_node_id(newdir);
511 req->in.h.opcode = FUSE_RENAME; 526 req->in.h.opcode = FUSE_RENAME;
512 req->in.h.nodeid = get_node_id(olddir); 527 req->in.h.nodeid = get_node_id(olddir);
513 req->inode = olddir;
514 req->inode2 = newdir;
515 req->in.numargs = 3; 528 req->in.numargs = 3;
516 req->in.args[0].size = sizeof(inarg); 529 req->in.args[0].size = sizeof(inarg);
517 req->in.args[0].value = &inarg; 530 req->in.args[0].value = &inarg;
@@ -558,7 +571,6 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
558 memset(&inarg, 0, sizeof(inarg)); 571 memset(&inarg, 0, sizeof(inarg));
559 inarg.oldnodeid = get_node_id(inode); 572 inarg.oldnodeid = get_node_id(inode);
560 req->in.h.opcode = FUSE_LINK; 573 req->in.h.opcode = FUSE_LINK;
561 req->inode2 = inode;
562 req->in.numargs = 2; 574 req->in.numargs = 2;
563 req->in.args[0].size = sizeof(inarg); 575 req->in.args[0].size = sizeof(inarg);
564 req->in.args[0].value = &inarg; 576 req->in.args[0].value = &inarg;
@@ -587,7 +599,6 @@ int fuse_do_getattr(struct inode *inode)
587 599
588 req->in.h.opcode = FUSE_GETATTR; 600 req->in.h.opcode = FUSE_GETATTR;
589 req->in.h.nodeid = get_node_id(inode); 601 req->in.h.nodeid = get_node_id(inode);
590 req->inode = inode;
591 req->out.numargs = 1; 602 req->out.numargs = 1;
592 req->out.args[0].size = sizeof(arg); 603 req->out.args[0].size = sizeof(arg);
593 req->out.args[0].value = &arg; 604 req->out.args[0].value = &arg;
@@ -679,7 +690,6 @@ static int fuse_access(struct inode *inode, int mask)
679 inarg.mask = mask; 690 inarg.mask = mask;
680 req->in.h.opcode = FUSE_ACCESS; 691 req->in.h.opcode = FUSE_ACCESS;
681 req->in.h.nodeid = get_node_id(inode); 692 req->in.h.nodeid = get_node_id(inode);
682 req->inode = inode;
683 req->in.numargs = 1; 693 req->in.numargs = 1;
684 req->in.args[0].size = sizeof(inarg); 694 req->in.args[0].size = sizeof(inarg);
685 req->in.args[0].value = &inarg; 695 req->in.args[0].value = &inarg;
@@ -820,7 +830,6 @@ static char *read_link(struct dentry *dentry)
820 } 830 }
821 req->in.h.opcode = FUSE_READLINK; 831 req->in.h.opcode = FUSE_READLINK;
822 req->in.h.nodeid = get_node_id(inode); 832 req->in.h.nodeid = get_node_id(inode);
823 req->inode = inode;
824 req->out.argvar = 1; 833 req->out.argvar = 1;
825 req->out.numargs = 1; 834 req->out.numargs = 1;
826 req->out.args[0].size = PAGE_SIZE - 1; 835 req->out.args[0].size = PAGE_SIZE - 1;
@@ -939,7 +948,6 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
939 iattr_to_fattr(attr, &inarg); 948 iattr_to_fattr(attr, &inarg);
940 req->in.h.opcode = FUSE_SETATTR; 949 req->in.h.opcode = FUSE_SETATTR;
941 req->in.h.nodeid = get_node_id(inode); 950 req->in.h.nodeid = get_node_id(inode);
942 req->inode = inode;
943 req->in.numargs = 1; 951 req->in.numargs = 1;
944 req->in.args[0].size = sizeof(inarg); 952 req->in.args[0].size = sizeof(inarg);
945 req->in.args[0].value = &inarg; 953 req->in.args[0].value = &inarg;
@@ -1002,7 +1010,6 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
1002 inarg.flags = flags; 1010 inarg.flags = flags;
1003 req->in.h.opcode = FUSE_SETXATTR; 1011 req->in.h.opcode = FUSE_SETXATTR;
1004 req->in.h.nodeid = get_node_id(inode); 1012 req->in.h.nodeid = get_node_id(inode);
1005 req->inode = inode;
1006 req->in.numargs = 3; 1013 req->in.numargs = 3;
1007 req->in.args[0].size = sizeof(inarg); 1014 req->in.args[0].size = sizeof(inarg);
1008 req->in.args[0].value = &inarg; 1015 req->in.args[0].value = &inarg;
@@ -1041,7 +1048,6 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
1041 inarg.size = size; 1048 inarg.size = size;
1042 req->in.h.opcode = FUSE_GETXATTR; 1049 req->in.h.opcode = FUSE_GETXATTR;
1043 req->in.h.nodeid = get_node_id(inode); 1050 req->in.h.nodeid = get_node_id(inode);
1044 req->inode = inode;
1045 req->in.numargs = 2; 1051 req->in.numargs = 2;
1046 req->in.args[0].size = sizeof(inarg); 1052 req->in.args[0].size = sizeof(inarg);
1047 req->in.args[0].value = &inarg; 1053 req->in.args[0].value = &inarg;
@@ -1091,7 +1097,6 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1091 inarg.size = size; 1097 inarg.size = size;
1092 req->in.h.opcode = FUSE_LISTXATTR; 1098 req->in.h.opcode = FUSE_LISTXATTR;
1093 req->in.h.nodeid = get_node_id(inode); 1099 req->in.h.nodeid = get_node_id(inode);
1094 req->inode = inode;
1095 req->in.numargs = 1; 1100 req->in.numargs = 1;
1096 req->in.args[0].size = sizeof(inarg); 1101 req->in.args[0].size = sizeof(inarg);
1097 req->in.args[0].value = &inarg; 1102 req->in.args[0].value = &inarg;
@@ -1135,7 +1140,6 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
1135 1140
1136 req->in.h.opcode = FUSE_REMOVEXATTR; 1141 req->in.h.opcode = FUSE_REMOVEXATTR;
1137 req->in.h.nodeid = get_node_id(inode); 1142 req->in.h.nodeid = get_node_id(inode);
1138 req->inode = inode;
1139 req->in.numargs = 1; 1143 req->in.numargs = 1;
1140 req->in.args[0].size = strlen(name) + 1; 1144 req->in.args[0].size = strlen(name) + 1;
1141 req->in.args[0].value = name; 1145 req->in.args[0].value = name;