[PATCH] FUSE: pass file handle in setattr
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / fs / fuse / dir.c
blobc045cc70c74931864e01763c3573eeae19c2d1e8
1 /*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7 */
9 #include "fuse_i.h"
11 #include <linux/pagemap.h>
12 #include <linux/file.h>
13 #include <linux/gfp.h>
14 #include <linux/sched.h>
15 #include <linux/namei.h>
16 #include <linux/mount.h>
18 static inline unsigned long time_to_jiffies(unsigned long sec,
19 unsigned long nsec)
21 struct timespec ts = {sec, nsec};
22 return jiffies + timespec_to_jiffies(&ts);
25 static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
26 struct dentry *entry,
27 struct fuse_entry_out *outarg)
29 req->in.h.opcode = FUSE_LOOKUP;
30 req->in.h.nodeid = get_node_id(dir);
31 req->inode = dir;
32 req->in.numargs = 1;
33 req->in.args[0].size = entry->d_name.len + 1;
34 req->in.args[0].value = entry->d_name.name;
35 req->out.numargs = 1;
36 req->out.args[0].size = sizeof(struct fuse_entry_out);
37 req->out.args[0].value = outarg;
40 static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
42 if (!entry->d_inode || is_bad_inode(entry->d_inode))
43 return 0;
44 else if (time_after(jiffies, entry->d_time)) {
45 int err;
46 struct fuse_entry_out outarg;
47 struct inode *inode = entry->d_inode;
48 struct fuse_inode *fi = get_fuse_inode(inode);
49 struct fuse_conn *fc = get_fuse_conn(inode);
50 struct fuse_req *req = fuse_get_request(fc);
51 if (!req)
52 return 0;
54 fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg);
55 request_send(fc, req);
56 err = req->out.h.error;
57 if (!err) {
58 if (outarg.nodeid != get_node_id(inode)) {
59 fuse_send_forget(fc, req, outarg.nodeid, 1);
60 return 0;
62 fi->nlookup ++;
64 fuse_put_request(fc, req);
65 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
66 return 0;
68 fuse_change_attributes(inode, &outarg.attr);
69 entry->d_time = time_to_jiffies(outarg.entry_valid,
70 outarg.entry_valid_nsec);
71 fi->i_time = time_to_jiffies(outarg.attr_valid,
72 outarg.attr_valid_nsec);
74 return 1;
77 static struct dentry_operations fuse_dentry_operations = {
78 .d_revalidate = fuse_dentry_revalidate,
81 static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
82 struct inode **inodep)
84 int err;
85 struct fuse_entry_out outarg;
86 struct inode *inode = NULL;
87 struct fuse_conn *fc = get_fuse_conn(dir);
88 struct fuse_req *req;
90 if (entry->d_name.len > FUSE_NAME_MAX)
91 return -ENAMETOOLONG;
93 req = fuse_get_request(fc);
94 if (!req)
95 return -EINTR;
97 fuse_lookup_init(req, dir, entry, &outarg);
98 request_send(fc, req);
99 err = req->out.h.error;
100 if (!err && (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID))
101 err = -EIO;
102 if (!err) {
103 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
104 &outarg.attr);
105 if (!inode) {
106 fuse_send_forget(fc, req, outarg.nodeid, 1);
107 return -ENOMEM;
110 fuse_put_request(fc, req);
111 if (err && err != -ENOENT)
112 return err;
114 if (inode) {
115 struct fuse_inode *fi = get_fuse_inode(inode);
116 entry->d_time = time_to_jiffies(outarg.entry_valid,
117 outarg.entry_valid_nsec);
118 fi->i_time = time_to_jiffies(outarg.attr_valid,
119 outarg.attr_valid_nsec);
122 entry->d_op = &fuse_dentry_operations;
123 *inodep = inode;
124 return 0;
127 void fuse_invalidate_attr(struct inode *inode)
129 get_fuse_inode(inode)->i_time = jiffies - 1;
132 static void fuse_invalidate_entry(struct dentry *entry)
134 d_invalidate(entry);
135 entry->d_time = jiffies - 1;
138 static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
139 struct nameidata *nd)
141 int err;
142 struct inode *inode;
143 struct fuse_conn *fc = get_fuse_conn(dir);
144 struct fuse_req *req;
145 struct fuse_open_in inarg;
146 struct fuse_open_out outopen;
147 struct fuse_entry_out outentry;
148 struct fuse_inode *fi;
149 struct fuse_file *ff;
150 struct file *file;
151 int flags = nd->intent.open.flags - 1;
153 err = -ENOSYS;
154 if (fc->no_create)
155 goto out;
157 err = -ENAMETOOLONG;
158 if (entry->d_name.len > FUSE_NAME_MAX)
159 goto out;
161 err = -EINTR;
162 req = fuse_get_request(fc);
163 if (!req)
164 goto out;
166 ff = fuse_file_alloc();
167 if (!ff)
168 goto out_put_request;
170 flags &= ~O_NOCTTY;
171 memset(&inarg, 0, sizeof(inarg));
172 inarg.flags = flags;
173 inarg.mode = mode;
174 req->in.h.opcode = FUSE_CREATE;
175 req->in.h.nodeid = get_node_id(dir);
176 req->inode = dir;
177 req->in.numargs = 2;
178 req->in.args[0].size = sizeof(inarg);
179 req->in.args[0].value = &inarg;
180 req->in.args[1].size = entry->d_name.len + 1;
181 req->in.args[1].value = entry->d_name.name;
182 req->out.numargs = 2;
183 req->out.args[0].size = sizeof(outentry);
184 req->out.args[0].value = &outentry;
185 req->out.args[1].size = sizeof(outopen);
186 req->out.args[1].value = &outopen;
187 request_send(fc, req);
188 err = req->out.h.error;
189 if (err) {
190 if (err == -ENOSYS)
191 fc->no_create = 1;
192 goto out_free_ff;
195 err = -EIO;
196 if (!S_ISREG(outentry.attr.mode))
197 goto out_free_ff;
199 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
200 &outentry.attr);
201 err = -ENOMEM;
202 if (!inode) {
203 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
204 ff->fh = outopen.fh;
205 fuse_send_release(fc, ff, outentry.nodeid, NULL, flags, 0);
206 goto out_put_request;
208 fuse_put_request(fc, req);
209 entry->d_time = time_to_jiffies(outentry.entry_valid,
210 outentry.entry_valid_nsec);
211 fi = get_fuse_inode(inode);
212 fi->i_time = time_to_jiffies(outentry.attr_valid,
213 outentry.attr_valid_nsec);
215 d_instantiate(entry, inode);
216 file = lookup_instantiate_filp(nd, entry, generic_file_open);
217 if (IS_ERR(file)) {
218 ff->fh = outopen.fh;
219 fuse_send_release(fc, ff, outentry.nodeid, inode, flags, 0);
220 return PTR_ERR(file);
222 fuse_finish_open(inode, file, ff, &outopen);
223 return 0;
225 out_free_ff:
226 fuse_file_free(ff);
227 out_put_request:
228 fuse_put_request(fc, req);
229 out:
230 return err;
233 static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
234 struct inode *dir, struct dentry *entry,
235 int mode)
237 struct fuse_entry_out outarg;
238 struct inode *inode;
239 struct fuse_inode *fi;
240 int err;
242 req->in.h.nodeid = get_node_id(dir);
243 req->inode = dir;
244 req->out.numargs = 1;
245 req->out.args[0].size = sizeof(outarg);
246 req->out.args[0].value = &outarg;
247 request_send(fc, req);
248 err = req->out.h.error;
249 if (err) {
250 fuse_put_request(fc, req);
251 return err;
253 if (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID) {
254 fuse_put_request(fc, req);
255 return -EIO;
257 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
258 &outarg.attr);
259 if (!inode) {
260 fuse_send_forget(fc, req, outarg.nodeid, 1);
261 return -ENOMEM;
263 fuse_put_request(fc, req);
265 /* Don't allow userspace to do really stupid things... */
266 if ((inode->i_mode ^ mode) & S_IFMT) {
267 iput(inode);
268 return -EIO;
271 entry->d_time = time_to_jiffies(outarg.entry_valid,
272 outarg.entry_valid_nsec);
274 fi = get_fuse_inode(inode);
275 fi->i_time = time_to_jiffies(outarg.attr_valid,
276 outarg.attr_valid_nsec);
278 d_instantiate(entry, inode);
279 fuse_invalidate_attr(dir);
280 return 0;
283 static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
284 dev_t rdev)
286 struct fuse_mknod_in inarg;
287 struct fuse_conn *fc = get_fuse_conn(dir);
288 struct fuse_req *req = fuse_get_request(fc);
289 if (!req)
290 return -EINTR;
292 memset(&inarg, 0, sizeof(inarg));
293 inarg.mode = mode;
294 inarg.rdev = new_encode_dev(rdev);
295 req->in.h.opcode = FUSE_MKNOD;
296 req->in.numargs = 2;
297 req->in.args[0].size = sizeof(inarg);
298 req->in.args[0].value = &inarg;
299 req->in.args[1].size = entry->d_name.len + 1;
300 req->in.args[1].value = entry->d_name.name;
301 return create_new_entry(fc, req, dir, entry, mode);
304 static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
305 struct nameidata *nd)
307 if (nd && (nd->flags & LOOKUP_CREATE)) {
308 int err = fuse_create_open(dir, entry, mode, nd);
309 if (err != -ENOSYS)
310 return err;
311 /* Fall back on mknod */
313 return fuse_mknod(dir, entry, mode, 0);
316 static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
318 struct fuse_mkdir_in inarg;
319 struct fuse_conn *fc = get_fuse_conn(dir);
320 struct fuse_req *req = fuse_get_request(fc);
321 if (!req)
322 return -EINTR;
324 memset(&inarg, 0, sizeof(inarg));
325 inarg.mode = mode;
326 req->in.h.opcode = FUSE_MKDIR;
327 req->in.numargs = 2;
328 req->in.args[0].size = sizeof(inarg);
329 req->in.args[0].value = &inarg;
330 req->in.args[1].size = entry->d_name.len + 1;
331 req->in.args[1].value = entry->d_name.name;
332 return create_new_entry(fc, req, dir, entry, S_IFDIR);
335 static int fuse_symlink(struct inode *dir, struct dentry *entry,
336 const char *link)
338 struct fuse_conn *fc = get_fuse_conn(dir);
339 unsigned len = strlen(link) + 1;
340 struct fuse_req *req;
342 if (len > FUSE_SYMLINK_MAX)
343 return -ENAMETOOLONG;
345 req = fuse_get_request(fc);
346 if (!req)
347 return -EINTR;
349 req->in.h.opcode = FUSE_SYMLINK;
350 req->in.numargs = 2;
351 req->in.args[0].size = entry->d_name.len + 1;
352 req->in.args[0].value = entry->d_name.name;
353 req->in.args[1].size = len;
354 req->in.args[1].value = link;
355 return create_new_entry(fc, req, dir, entry, S_IFLNK);
358 static int fuse_unlink(struct inode *dir, struct dentry *entry)
360 int err;
361 struct fuse_conn *fc = get_fuse_conn(dir);
362 struct fuse_req *req = fuse_get_request(fc);
363 if (!req)
364 return -EINTR;
366 req->in.h.opcode = FUSE_UNLINK;
367 req->in.h.nodeid = get_node_id(dir);
368 req->inode = dir;
369 req->in.numargs = 1;
370 req->in.args[0].size = entry->d_name.len + 1;
371 req->in.args[0].value = entry->d_name.name;
372 request_send(fc, req);
373 err = req->out.h.error;
374 fuse_put_request(fc, req);
375 if (!err) {
376 struct inode *inode = entry->d_inode;
378 /* Set nlink to zero so the inode can be cleared, if
379 the inode does have more links this will be
380 discovered at the next lookup/getattr */
381 inode->i_nlink = 0;
382 fuse_invalidate_attr(inode);
383 fuse_invalidate_attr(dir);
384 } else if (err == -EINTR)
385 fuse_invalidate_entry(entry);
386 return err;
389 static int fuse_rmdir(struct inode *dir, struct dentry *entry)
391 int err;
392 struct fuse_conn *fc = get_fuse_conn(dir);
393 struct fuse_req *req = fuse_get_request(fc);
394 if (!req)
395 return -EINTR;
397 req->in.h.opcode = FUSE_RMDIR;
398 req->in.h.nodeid = get_node_id(dir);
399 req->inode = dir;
400 req->in.numargs = 1;
401 req->in.args[0].size = entry->d_name.len + 1;
402 req->in.args[0].value = entry->d_name.name;
403 request_send(fc, req);
404 err = req->out.h.error;
405 fuse_put_request(fc, req);
406 if (!err) {
407 entry->d_inode->i_nlink = 0;
408 fuse_invalidate_attr(dir);
409 } else if (err == -EINTR)
410 fuse_invalidate_entry(entry);
411 return err;
414 static int fuse_rename(struct inode *olddir, struct dentry *oldent,
415 struct inode *newdir, struct dentry *newent)
417 int err;
418 struct fuse_rename_in inarg;
419 struct fuse_conn *fc = get_fuse_conn(olddir);
420 struct fuse_req *req = fuse_get_request(fc);
421 if (!req)
422 return -EINTR;
424 memset(&inarg, 0, sizeof(inarg));
425 inarg.newdir = get_node_id(newdir);
426 req->in.h.opcode = FUSE_RENAME;
427 req->in.h.nodeid = get_node_id(olddir);
428 req->inode = olddir;
429 req->inode2 = newdir;
430 req->in.numargs = 3;
431 req->in.args[0].size = sizeof(inarg);
432 req->in.args[0].value = &inarg;
433 req->in.args[1].size = oldent->d_name.len + 1;
434 req->in.args[1].value = oldent->d_name.name;
435 req->in.args[2].size = newent->d_name.len + 1;
436 req->in.args[2].value = newent->d_name.name;
437 request_send(fc, req);
438 err = req->out.h.error;
439 fuse_put_request(fc, req);
440 if (!err) {
441 fuse_invalidate_attr(olddir);
442 if (olddir != newdir)
443 fuse_invalidate_attr(newdir);
444 } else if (err == -EINTR) {
445 /* If request was interrupted, DEITY only knows if the
446 rename actually took place. If the invalidation
447 fails (e.g. some process has CWD under the renamed
448 directory), then there can be inconsistency between
449 the dcache and the real filesystem. Tough luck. */
450 fuse_invalidate_entry(oldent);
451 if (newent->d_inode)
452 fuse_invalidate_entry(newent);
455 return err;
458 static int fuse_link(struct dentry *entry, struct inode *newdir,
459 struct dentry *newent)
461 int err;
462 struct fuse_link_in inarg;
463 struct inode *inode = entry->d_inode;
464 struct fuse_conn *fc = get_fuse_conn(inode);
465 struct fuse_req *req = fuse_get_request(fc);
466 if (!req)
467 return -EINTR;
469 memset(&inarg, 0, sizeof(inarg));
470 inarg.oldnodeid = get_node_id(inode);
471 req->in.h.opcode = FUSE_LINK;
472 req->inode2 = inode;
473 req->in.numargs = 2;
474 req->in.args[0].size = sizeof(inarg);
475 req->in.args[0].value = &inarg;
476 req->in.args[1].size = newent->d_name.len + 1;
477 req->in.args[1].value = newent->d_name.name;
478 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
479 /* Contrary to "normal" filesystems it can happen that link
480 makes two "logical" inodes point to the same "physical"
481 inode. We invalidate the attributes of the old one, so it
482 will reflect changes in the backing inode (link count,
483 etc.)
485 if (!err || err == -EINTR)
486 fuse_invalidate_attr(inode);
487 return err;
490 int fuse_do_getattr(struct inode *inode)
492 int err;
493 struct fuse_attr_out arg;
494 struct fuse_conn *fc = get_fuse_conn(inode);
495 struct fuse_req *req = fuse_get_request(fc);
496 if (!req)
497 return -EINTR;
499 req->in.h.opcode = FUSE_GETATTR;
500 req->in.h.nodeid = get_node_id(inode);
501 req->inode = inode;
502 req->out.numargs = 1;
503 req->out.args[0].size = sizeof(arg);
504 req->out.args[0].value = &arg;
505 request_send(fc, req);
506 err = req->out.h.error;
507 fuse_put_request(fc, req);
508 if (!err) {
509 if ((inode->i_mode ^ arg.attr.mode) & S_IFMT) {
510 make_bad_inode(inode);
511 err = -EIO;
512 } else {
513 struct fuse_inode *fi = get_fuse_inode(inode);
514 fuse_change_attributes(inode, &arg.attr);
515 fi->i_time = time_to_jiffies(arg.attr_valid,
516 arg.attr_valid_nsec);
519 return err;
523 * Calling into a user-controlled filesystem gives the filesystem
524 * daemon ptrace-like capabilities over the requester process. This
525 * means, that the filesystem daemon is able to record the exact
526 * filesystem operations performed, and can also control the behavior
527 * of the requester process in otherwise impossible ways. For example
528 * it can delay the operation for arbitrary length of time allowing
529 * DoS against the requester.
531 * For this reason only those processes can call into the filesystem,
532 * for which the owner of the mount has ptrace privilege. This
533 * excludes processes started by other users, suid or sgid processes.
535 static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
537 if (fc->flags & FUSE_ALLOW_OTHER)
538 return 1;
540 if (task->euid == fc->user_id &&
541 task->suid == fc->user_id &&
542 task->uid == fc->user_id &&
543 task->egid == fc->group_id &&
544 task->sgid == fc->group_id &&
545 task->gid == fc->group_id)
546 return 1;
548 return 0;
551 static int fuse_revalidate(struct dentry *entry)
553 struct inode *inode = entry->d_inode;
554 struct fuse_inode *fi = get_fuse_inode(inode);
555 struct fuse_conn *fc = get_fuse_conn(inode);
557 if (!fuse_allow_task(fc, current))
558 return -EACCES;
559 if (get_node_id(inode) != FUSE_ROOT_ID &&
560 time_before_eq(jiffies, fi->i_time))
561 return 0;
563 return fuse_do_getattr(inode);
566 static int fuse_access(struct inode *inode, int mask)
568 struct fuse_conn *fc = get_fuse_conn(inode);
569 struct fuse_req *req;
570 struct fuse_access_in inarg;
571 int err;
573 if (fc->no_access)
574 return 0;
576 req = fuse_get_request(fc);
577 if (!req)
578 return -EINTR;
580 memset(&inarg, 0, sizeof(inarg));
581 inarg.mask = mask;
582 req->in.h.opcode = FUSE_ACCESS;
583 req->in.h.nodeid = get_node_id(inode);
584 req->inode = inode;
585 req->in.numargs = 1;
586 req->in.args[0].size = sizeof(inarg);
587 req->in.args[0].value = &inarg;
588 request_send(fc, req);
589 err = req->out.h.error;
590 fuse_put_request(fc, req);
591 if (err == -ENOSYS) {
592 fc->no_access = 1;
593 err = 0;
595 return err;
598 static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
600 struct fuse_conn *fc = get_fuse_conn(inode);
602 if (!fuse_allow_task(fc, current))
603 return -EACCES;
604 else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
605 int err = generic_permission(inode, mask, NULL);
607 /* If permission is denied, try to refresh file
608 attributes. This is also needed, because the root
609 node will at first have no permissions */
610 if (err == -EACCES) {
611 err = fuse_do_getattr(inode);
612 if (!err)
613 err = generic_permission(inode, mask, NULL);
616 /* FIXME: Need some mechanism to revoke permissions:
617 currently if the filesystem suddenly changes the
618 file mode, we will not be informed about it, and
619 continue to allow access to the file/directory.
621 This is actually not so grave, since the user can
622 simply keep access to the file/directory anyway by
623 keeping it open... */
625 return err;
626 } else {
627 int mode = inode->i_mode;
628 if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
629 return -EACCES;
631 if (nd && (nd->flags & LOOKUP_ACCESS))
632 return fuse_access(inode, mask);
633 return 0;
637 static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
638 void *dstbuf, filldir_t filldir)
640 while (nbytes >= FUSE_NAME_OFFSET) {
641 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
642 size_t reclen = FUSE_DIRENT_SIZE(dirent);
643 int over;
644 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
645 return -EIO;
646 if (reclen > nbytes)
647 break;
649 over = filldir(dstbuf, dirent->name, dirent->namelen,
650 file->f_pos, dirent->ino, dirent->type);
651 if (over)
652 break;
654 buf += reclen;
655 nbytes -= reclen;
656 file->f_pos = dirent->off;
659 return 0;
662 static inline size_t fuse_send_readdir(struct fuse_req *req, struct file *file,
663 struct inode *inode, loff_t pos,
664 size_t count)
666 return fuse_send_read_common(req, file, inode, pos, count, 1);
669 static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
671 int err;
672 size_t nbytes;
673 struct page *page;
674 struct inode *inode = file->f_dentry->d_inode;
675 struct fuse_conn *fc = get_fuse_conn(inode);
676 struct fuse_req *req = fuse_get_request(fc);
677 if (!req)
678 return -EINTR;
680 page = alloc_page(GFP_KERNEL);
681 if (!page) {
682 fuse_put_request(fc, req);
683 return -ENOMEM;
685 req->num_pages = 1;
686 req->pages[0] = page;
687 nbytes = fuse_send_readdir(req, file, inode, file->f_pos, PAGE_SIZE);
688 err = req->out.h.error;
689 fuse_put_request(fc, req);
690 if (!err)
691 err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
692 filldir);
694 __free_page(page);
695 fuse_invalidate_attr(inode); /* atime changed */
696 return err;
699 static char *read_link(struct dentry *dentry)
701 struct inode *inode = dentry->d_inode;
702 struct fuse_conn *fc = get_fuse_conn(inode);
703 struct fuse_req *req = fuse_get_request(fc);
704 char *link;
706 if (!req)
707 return ERR_PTR(-EINTR);
709 link = (char *) __get_free_page(GFP_KERNEL);
710 if (!link) {
711 link = ERR_PTR(-ENOMEM);
712 goto out;
714 req->in.h.opcode = FUSE_READLINK;
715 req->in.h.nodeid = get_node_id(inode);
716 req->inode = inode;
717 req->out.argvar = 1;
718 req->out.numargs = 1;
719 req->out.args[0].size = PAGE_SIZE - 1;
720 req->out.args[0].value = link;
721 request_send(fc, req);
722 if (req->out.h.error) {
723 free_page((unsigned long) link);
724 link = ERR_PTR(req->out.h.error);
725 } else
726 link[req->out.args[0].size] = '\0';
727 out:
728 fuse_put_request(fc, req);
729 fuse_invalidate_attr(inode); /* atime changed */
730 return link;
733 static void free_link(char *link)
735 if (!IS_ERR(link))
736 free_page((unsigned long) link);
739 static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
741 nd_set_link(nd, read_link(dentry));
742 return NULL;
745 static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
747 free_link(nd_get_link(nd));
750 static int fuse_dir_open(struct inode *inode, struct file *file)
752 return fuse_open_common(inode, file, 1);
755 static int fuse_dir_release(struct inode *inode, struct file *file)
757 return fuse_release_common(inode, file, 1);
760 static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
762 /* nfsd can call this with no file */
763 return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
766 static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
768 unsigned ivalid = iattr->ia_valid;
770 if (ivalid & ATTR_MODE)
771 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
772 if (ivalid & ATTR_UID)
773 arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid;
774 if (ivalid & ATTR_GID)
775 arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid;
776 if (ivalid & ATTR_SIZE)
777 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
778 /* You can only _set_ these together (they may change by themselves) */
779 if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
780 arg->valid |= FATTR_ATIME | FATTR_MTIME;
781 arg->atime = iattr->ia_atime.tv_sec;
782 arg->mtime = iattr->ia_mtime.tv_sec;
784 if (ivalid & ATTR_FILE) {
785 struct fuse_file *ff = iattr->ia_file->private_data;
786 arg->valid |= FATTR_FH;
787 arg->fh = ff->fh;
791 static int fuse_setattr(struct dentry *entry, struct iattr *attr)
793 struct inode *inode = entry->d_inode;
794 struct fuse_conn *fc = get_fuse_conn(inode);
795 struct fuse_inode *fi = get_fuse_inode(inode);
796 struct fuse_req *req;
797 struct fuse_setattr_in inarg;
798 struct fuse_attr_out outarg;
799 int err;
800 int is_truncate = 0;
802 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
803 err = inode_change_ok(inode, attr);
804 if (err)
805 return err;
808 if (attr->ia_valid & ATTR_SIZE) {
809 unsigned long limit;
810 is_truncate = 1;
811 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
812 if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
813 send_sig(SIGXFSZ, current, 0);
814 return -EFBIG;
818 req = fuse_get_request(fc);
819 if (!req)
820 return -EINTR;
822 memset(&inarg, 0, sizeof(inarg));
823 iattr_to_fattr(attr, &inarg);
824 req->in.h.opcode = FUSE_SETATTR;
825 req->in.h.nodeid = get_node_id(inode);
826 req->inode = inode;
827 req->in.numargs = 1;
828 req->in.args[0].size = sizeof(inarg);
829 req->in.args[0].value = &inarg;
830 req->out.numargs = 1;
831 req->out.args[0].size = sizeof(outarg);
832 req->out.args[0].value = &outarg;
833 request_send(fc, req);
834 err = req->out.h.error;
835 fuse_put_request(fc, req);
836 if (!err) {
837 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
838 make_bad_inode(inode);
839 err = -EIO;
840 } else {
841 if (is_truncate) {
842 loff_t origsize = i_size_read(inode);
843 i_size_write(inode, outarg.attr.size);
844 if (origsize > outarg.attr.size)
845 vmtruncate(inode, outarg.attr.size);
847 fuse_change_attributes(inode, &outarg.attr);
848 fi->i_time = time_to_jiffies(outarg.attr_valid,
849 outarg.attr_valid_nsec);
851 } else if (err == -EINTR)
852 fuse_invalidate_attr(inode);
854 return err;
857 static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
858 struct kstat *stat)
860 struct inode *inode = entry->d_inode;
861 int err = fuse_revalidate(entry);
862 if (!err)
863 generic_fillattr(inode, stat);
865 return err;
868 static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
869 struct nameidata *nd)
871 struct inode *inode;
872 int err;
874 err = fuse_lookup_iget(dir, entry, &inode);
875 if (err)
876 return ERR_PTR(err);
877 if (inode && S_ISDIR(inode->i_mode)) {
878 /* Don't allow creating an alias to a directory */
879 struct dentry *alias = d_find_alias(inode);
880 if (alias) {
881 dput(alias);
882 iput(inode);
883 return ERR_PTR(-EIO);
886 d_add(entry, inode);
887 return NULL;
890 static int fuse_setxattr(struct dentry *entry, const char *name,
891 const void *value, size_t size, int flags)
893 struct inode *inode = entry->d_inode;
894 struct fuse_conn *fc = get_fuse_conn(inode);
895 struct fuse_req *req;
896 struct fuse_setxattr_in inarg;
897 int err;
899 if (size > FUSE_XATTR_SIZE_MAX)
900 return -E2BIG;
902 if (fc->no_setxattr)
903 return -EOPNOTSUPP;
905 req = fuse_get_request(fc);
906 if (!req)
907 return -EINTR;
909 memset(&inarg, 0, sizeof(inarg));
910 inarg.size = size;
911 inarg.flags = flags;
912 req->in.h.opcode = FUSE_SETXATTR;
913 req->in.h.nodeid = get_node_id(inode);
914 req->inode = inode;
915 req->in.numargs = 3;
916 req->in.args[0].size = sizeof(inarg);
917 req->in.args[0].value = &inarg;
918 req->in.args[1].size = strlen(name) + 1;
919 req->in.args[1].value = name;
920 req->in.args[2].size = size;
921 req->in.args[2].value = value;
922 request_send(fc, req);
923 err = req->out.h.error;
924 fuse_put_request(fc, req);
925 if (err == -ENOSYS) {
926 fc->no_setxattr = 1;
927 err = -EOPNOTSUPP;
929 return err;
932 static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
933 void *value, size_t size)
935 struct inode *inode = entry->d_inode;
936 struct fuse_conn *fc = get_fuse_conn(inode);
937 struct fuse_req *req;
938 struct fuse_getxattr_in inarg;
939 struct fuse_getxattr_out outarg;
940 ssize_t ret;
942 if (fc->no_getxattr)
943 return -EOPNOTSUPP;
945 req = fuse_get_request(fc);
946 if (!req)
947 return -EINTR;
949 memset(&inarg, 0, sizeof(inarg));
950 inarg.size = size;
951 req->in.h.opcode = FUSE_GETXATTR;
952 req->in.h.nodeid = get_node_id(inode);
953 req->inode = inode;
954 req->in.numargs = 2;
955 req->in.args[0].size = sizeof(inarg);
956 req->in.args[0].value = &inarg;
957 req->in.args[1].size = strlen(name) + 1;
958 req->in.args[1].value = name;
959 /* This is really two different operations rolled into one */
960 req->out.numargs = 1;
961 if (size) {
962 req->out.argvar = 1;
963 req->out.args[0].size = size;
964 req->out.args[0].value = value;
965 } else {
966 req->out.args[0].size = sizeof(outarg);
967 req->out.args[0].value = &outarg;
969 request_send(fc, req);
970 ret = req->out.h.error;
971 if (!ret)
972 ret = size ? req->out.args[0].size : outarg.size;
973 else {
974 if (ret == -ENOSYS) {
975 fc->no_getxattr = 1;
976 ret = -EOPNOTSUPP;
979 fuse_put_request(fc, req);
980 return ret;
983 static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
985 struct inode *inode = entry->d_inode;
986 struct fuse_conn *fc = get_fuse_conn(inode);
987 struct fuse_req *req;
988 struct fuse_getxattr_in inarg;
989 struct fuse_getxattr_out outarg;
990 ssize_t ret;
992 if (fc->no_listxattr)
993 return -EOPNOTSUPP;
995 req = fuse_get_request(fc);
996 if (!req)
997 return -EINTR;
999 memset(&inarg, 0, sizeof(inarg));
1000 inarg.size = size;
1001 req->in.h.opcode = FUSE_LISTXATTR;
1002 req->in.h.nodeid = get_node_id(inode);
1003 req->inode = inode;
1004 req->in.numargs = 1;
1005 req->in.args[0].size = sizeof(inarg);
1006 req->in.args[0].value = &inarg;
1007 /* This is really two different operations rolled into one */
1008 req->out.numargs = 1;
1009 if (size) {
1010 req->out.argvar = 1;
1011 req->out.args[0].size = size;
1012 req->out.args[0].value = list;
1013 } else {
1014 req->out.args[0].size = sizeof(outarg);
1015 req->out.args[0].value = &outarg;
1017 request_send(fc, req);
1018 ret = req->out.h.error;
1019 if (!ret)
1020 ret = size ? req->out.args[0].size : outarg.size;
1021 else {
1022 if (ret == -ENOSYS) {
1023 fc->no_listxattr = 1;
1024 ret = -EOPNOTSUPP;
1027 fuse_put_request(fc, req);
1028 return ret;
1031 static int fuse_removexattr(struct dentry *entry, const char *name)
1033 struct inode *inode = entry->d_inode;
1034 struct fuse_conn *fc = get_fuse_conn(inode);
1035 struct fuse_req *req;
1036 int err;
1038 if (fc->no_removexattr)
1039 return -EOPNOTSUPP;
1041 req = fuse_get_request(fc);
1042 if (!req)
1043 return -EINTR;
1045 req->in.h.opcode = FUSE_REMOVEXATTR;
1046 req->in.h.nodeid = get_node_id(inode);
1047 req->inode = inode;
1048 req->in.numargs = 1;
1049 req->in.args[0].size = strlen(name) + 1;
1050 req->in.args[0].value = name;
1051 request_send(fc, req);
1052 err = req->out.h.error;
1053 fuse_put_request(fc, req);
1054 if (err == -ENOSYS) {
1055 fc->no_removexattr = 1;
1056 err = -EOPNOTSUPP;
1058 return err;
1061 static struct inode_operations fuse_dir_inode_operations = {
1062 .lookup = fuse_lookup,
1063 .mkdir = fuse_mkdir,
1064 .symlink = fuse_symlink,
1065 .unlink = fuse_unlink,
1066 .rmdir = fuse_rmdir,
1067 .rename = fuse_rename,
1068 .link = fuse_link,
1069 .setattr = fuse_setattr,
1070 .create = fuse_create,
1071 .mknod = fuse_mknod,
1072 .permission = fuse_permission,
1073 .getattr = fuse_getattr,
1074 .setxattr = fuse_setxattr,
1075 .getxattr = fuse_getxattr,
1076 .listxattr = fuse_listxattr,
1077 .removexattr = fuse_removexattr,
1080 static struct file_operations fuse_dir_operations = {
1081 .llseek = generic_file_llseek,
1082 .read = generic_read_dir,
1083 .readdir = fuse_readdir,
1084 .open = fuse_dir_open,
1085 .release = fuse_dir_release,
1086 .fsync = fuse_dir_fsync,
1089 static struct inode_operations fuse_common_inode_operations = {
1090 .setattr = fuse_setattr,
1091 .permission = fuse_permission,
1092 .getattr = fuse_getattr,
1093 .setxattr = fuse_setxattr,
1094 .getxattr = fuse_getxattr,
1095 .listxattr = fuse_listxattr,
1096 .removexattr = fuse_removexattr,
1099 static struct inode_operations fuse_symlink_inode_operations = {
1100 .setattr = fuse_setattr,
1101 .follow_link = fuse_follow_link,
1102 .put_link = fuse_put_link,
1103 .readlink = generic_readlink,
1104 .getattr = fuse_getattr,
1105 .setxattr = fuse_setxattr,
1106 .getxattr = fuse_getxattr,
1107 .listxattr = fuse_listxattr,
1108 .removexattr = fuse_removexattr,
1111 void fuse_init_common(struct inode *inode)
1113 inode->i_op = &fuse_common_inode_operations;
1116 void fuse_init_dir(struct inode *inode)
1118 inode->i_op = &fuse_dir_inode_operations;
1119 inode->i_fop = &fuse_dir_operations;
1122 void fuse_init_symlink(struct inode *inode)
1124 inode->i_op = &fuse_symlink_inode_operations;