[PATCH] fuse: clean up dead code related to nfs exporting
[deliverable/linux.git] / fs / fuse / dir.c
CommitLineData
e5e5558e
MS
1/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7*/
8
9#include "fuse_i.h"
10
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
17static inline unsigned long time_to_jiffies(unsigned long sec,
18 unsigned long nsec)
19{
20 struct timespec ts = {sec, nsec};
21 return jiffies + timespec_to_jiffies(&ts);
22}
23
24static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
25 struct dentry *entry,
26 struct fuse_entry_out *outarg)
27{
28 req->in.h.opcode = FUSE_LOOKUP;
29 req->in.h.nodeid = get_node_id(dir);
30 req->inode = dir;
31 req->in.numargs = 1;
32 req->in.args[0].size = entry->d_name.len + 1;
33 req->in.args[0].value = entry->d_name.name;
34 req->out.numargs = 1;
35 req->out.args[0].size = sizeof(struct fuse_entry_out);
36 req->out.args[0].value = outarg;
37}
38
39static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
40{
41 if (!entry->d_inode || is_bad_inode(entry->d_inode))
42 return 0;
43 else if (time_after(jiffies, entry->d_time)) {
44 int err;
e5e5558e
MS
45 struct fuse_entry_out outarg;
46 struct inode *inode = entry->d_inode;
47 struct fuse_inode *fi = get_fuse_inode(inode);
48 struct fuse_conn *fc = get_fuse_conn(inode);
7c352bdf 49 struct fuse_req *req = fuse_get_request(fc);
e5e5558e
MS
50 if (!req)
51 return 0;
52
53 fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg);
7c352bdf 54 request_send(fc, req);
e5e5558e 55 err = req->out.h.error;
9e6268db
MS
56 if (!err) {
57 if (outarg.nodeid != get_node_id(inode)) {
58 fuse_send_forget(fc, req, outarg.nodeid, 1);
59 return 0;
60 }
61 fi->nlookup ++;
62 }
e5e5558e 63 fuse_put_request(fc, req);
9e6268db 64 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
e5e5558e
MS
65 return 0;
66
67 fuse_change_attributes(inode, &outarg.attr);
e5e5558e
MS
68 entry->d_time = time_to_jiffies(outarg.entry_valid,
69 outarg.entry_valid_nsec);
70 fi->i_time = time_to_jiffies(outarg.attr_valid,
71 outarg.attr_valid_nsec);
72 }
73 return 1;
74}
75
76static struct dentry_operations fuse_dentry_operations = {
77 .d_revalidate = fuse_dentry_revalidate,
78};
79
80static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
81 struct inode **inodep)
82{
83 int err;
e5e5558e
MS
84 struct fuse_entry_out outarg;
85 struct inode *inode = NULL;
86 struct fuse_conn *fc = get_fuse_conn(dir);
87 struct fuse_req *req;
88
89 if (entry->d_name.len > FUSE_NAME_MAX)
90 return -ENAMETOOLONG;
91
92 req = fuse_get_request(fc);
93 if (!req)
7c352bdf 94 return -EINTR;
e5e5558e
MS
95
96 fuse_lookup_init(req, dir, entry, &outarg);
97 request_send(fc, req);
e5e5558e 98 err = req->out.h.error;
ee4e5271
MS
99 if (!err && (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID))
100 err = -EIO;
e5e5558e
MS
101 if (!err) {
102 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
9e6268db 103 &outarg.attr);
e5e5558e 104 if (!inode) {
9e6268db 105 fuse_send_forget(fc, req, outarg.nodeid, 1);
e5e5558e
MS
106 return -ENOMEM;
107 }
108 }
109 fuse_put_request(fc, req);
110 if (err && err != -ENOENT)
111 return err;
112
113 if (inode) {
114 struct fuse_inode *fi = get_fuse_inode(inode);
115 entry->d_time = time_to_jiffies(outarg.entry_valid,
116 outarg.entry_valid_nsec);
117 fi->i_time = time_to_jiffies(outarg.attr_valid,
118 outarg.attr_valid_nsec);
119 }
120
121 entry->d_op = &fuse_dentry_operations;
122 *inodep = inode;
123 return 0;
124}
125
9e6268db
MS
126void fuse_invalidate_attr(struct inode *inode)
127{
128 get_fuse_inode(inode)->i_time = jiffies - 1;
129}
130
131static void fuse_invalidate_entry(struct dentry *entry)
132{
133 d_invalidate(entry);
134 entry->d_time = jiffies - 1;
135}
136
137static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
138 struct inode *dir, struct dentry *entry,
139 int mode)
140{
141 struct fuse_entry_out outarg;
142 struct inode *inode;
143 struct fuse_inode *fi;
144 int err;
145
146 req->in.h.nodeid = get_node_id(dir);
147 req->inode = dir;
148 req->out.numargs = 1;
149 req->out.args[0].size = sizeof(outarg);
150 req->out.args[0].value = &outarg;
151 request_send(fc, req);
152 err = req->out.h.error;
153 if (err) {
154 fuse_put_request(fc, req);
155 return err;
156 }
ee4e5271
MS
157 if (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID) {
158 fuse_put_request(fc, req);
159 return -EIO;
160 }
9e6268db
MS
161 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
162 &outarg.attr);
163 if (!inode) {
164 fuse_send_forget(fc, req, outarg.nodeid, 1);
165 return -ENOMEM;
166 }
167 fuse_put_request(fc, req);
168
169 /* Don't allow userspace to do really stupid things... */
170 if ((inode->i_mode ^ mode) & S_IFMT) {
171 iput(inode);
172 return -EIO;
173 }
174
175 entry->d_time = time_to_jiffies(outarg.entry_valid,
176 outarg.entry_valid_nsec);
177
178 fi = get_fuse_inode(inode);
179 fi->i_time = time_to_jiffies(outarg.attr_valid,
180 outarg.attr_valid_nsec);
181
182 d_instantiate(entry, inode);
183 fuse_invalidate_attr(dir);
184 return 0;
185}
186
187static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
188 dev_t rdev)
189{
190 struct fuse_mknod_in inarg;
191 struct fuse_conn *fc = get_fuse_conn(dir);
192 struct fuse_req *req = fuse_get_request(fc);
193 if (!req)
7c352bdf 194 return -EINTR;
9e6268db
MS
195
196 memset(&inarg, 0, sizeof(inarg));
197 inarg.mode = mode;
198 inarg.rdev = new_encode_dev(rdev);
199 req->in.h.opcode = FUSE_MKNOD;
200 req->in.numargs = 2;
201 req->in.args[0].size = sizeof(inarg);
202 req->in.args[0].value = &inarg;
203 req->in.args[1].size = entry->d_name.len + 1;
204 req->in.args[1].value = entry->d_name.name;
205 return create_new_entry(fc, req, dir, entry, mode);
206}
207
208static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
209 struct nameidata *nd)
210{
211 return fuse_mknod(dir, entry, mode, 0);
212}
213
214static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
215{
216 struct fuse_mkdir_in inarg;
217 struct fuse_conn *fc = get_fuse_conn(dir);
218 struct fuse_req *req = fuse_get_request(fc);
219 if (!req)
7c352bdf 220 return -EINTR;
9e6268db
MS
221
222 memset(&inarg, 0, sizeof(inarg));
223 inarg.mode = mode;
224 req->in.h.opcode = FUSE_MKDIR;
225 req->in.numargs = 2;
226 req->in.args[0].size = sizeof(inarg);
227 req->in.args[0].value = &inarg;
228 req->in.args[1].size = entry->d_name.len + 1;
229 req->in.args[1].value = entry->d_name.name;
230 return create_new_entry(fc, req, dir, entry, S_IFDIR);
231}
232
233static int fuse_symlink(struct inode *dir, struct dentry *entry,
234 const char *link)
235{
236 struct fuse_conn *fc = get_fuse_conn(dir);
237 unsigned len = strlen(link) + 1;
238 struct fuse_req *req;
239
240 if (len > FUSE_SYMLINK_MAX)
241 return -ENAMETOOLONG;
242
243 req = fuse_get_request(fc);
244 if (!req)
7c352bdf 245 return -EINTR;
9e6268db
MS
246
247 req->in.h.opcode = FUSE_SYMLINK;
248 req->in.numargs = 2;
249 req->in.args[0].size = entry->d_name.len + 1;
250 req->in.args[0].value = entry->d_name.name;
251 req->in.args[1].size = len;
252 req->in.args[1].value = link;
253 return create_new_entry(fc, req, dir, entry, S_IFLNK);
254}
255
256static int fuse_unlink(struct inode *dir, struct dentry *entry)
257{
258 int err;
259 struct fuse_conn *fc = get_fuse_conn(dir);
260 struct fuse_req *req = fuse_get_request(fc);
261 if (!req)
7c352bdf 262 return -EINTR;
9e6268db
MS
263
264 req->in.h.opcode = FUSE_UNLINK;
265 req->in.h.nodeid = get_node_id(dir);
266 req->inode = dir;
267 req->in.numargs = 1;
268 req->in.args[0].size = entry->d_name.len + 1;
269 req->in.args[0].value = entry->d_name.name;
270 request_send(fc, req);
271 err = req->out.h.error;
272 fuse_put_request(fc, req);
273 if (!err) {
274 struct inode *inode = entry->d_inode;
275
276 /* Set nlink to zero so the inode can be cleared, if
277 the inode does have more links this will be
278 discovered at the next lookup/getattr */
279 inode->i_nlink = 0;
280 fuse_invalidate_attr(inode);
281 fuse_invalidate_attr(dir);
282 } else if (err == -EINTR)
283 fuse_invalidate_entry(entry);
284 return err;
285}
286
287static int fuse_rmdir(struct inode *dir, struct dentry *entry)
288{
289 int err;
290 struct fuse_conn *fc = get_fuse_conn(dir);
291 struct fuse_req *req = fuse_get_request(fc);
292 if (!req)
7c352bdf 293 return -EINTR;
9e6268db
MS
294
295 req->in.h.opcode = FUSE_RMDIR;
296 req->in.h.nodeid = get_node_id(dir);
297 req->inode = dir;
298 req->in.numargs = 1;
299 req->in.args[0].size = entry->d_name.len + 1;
300 req->in.args[0].value = entry->d_name.name;
301 request_send(fc, req);
302 err = req->out.h.error;
303 fuse_put_request(fc, req);
304 if (!err) {
305 entry->d_inode->i_nlink = 0;
306 fuse_invalidate_attr(dir);
307 } else if (err == -EINTR)
308 fuse_invalidate_entry(entry);
309 return err;
310}
311
312static int fuse_rename(struct inode *olddir, struct dentry *oldent,
313 struct inode *newdir, struct dentry *newent)
314{
315 int err;
316 struct fuse_rename_in inarg;
317 struct fuse_conn *fc = get_fuse_conn(olddir);
318 struct fuse_req *req = fuse_get_request(fc);
319 if (!req)
7c352bdf 320 return -EINTR;
9e6268db
MS
321
322 memset(&inarg, 0, sizeof(inarg));
323 inarg.newdir = get_node_id(newdir);
324 req->in.h.opcode = FUSE_RENAME;
325 req->in.h.nodeid = get_node_id(olddir);
326 req->inode = olddir;
327 req->inode2 = newdir;
328 req->in.numargs = 3;
329 req->in.args[0].size = sizeof(inarg);
330 req->in.args[0].value = &inarg;
331 req->in.args[1].size = oldent->d_name.len + 1;
332 req->in.args[1].value = oldent->d_name.name;
333 req->in.args[2].size = newent->d_name.len + 1;
334 req->in.args[2].value = newent->d_name.name;
335 request_send(fc, req);
336 err = req->out.h.error;
337 fuse_put_request(fc, req);
338 if (!err) {
339 fuse_invalidate_attr(olddir);
340 if (olddir != newdir)
341 fuse_invalidate_attr(newdir);
342 } else if (err == -EINTR) {
343 /* If request was interrupted, DEITY only knows if the
344 rename actually took place. If the invalidation
345 fails (e.g. some process has CWD under the renamed
346 directory), then there can be inconsistency between
347 the dcache and the real filesystem. Tough luck. */
348 fuse_invalidate_entry(oldent);
349 if (newent->d_inode)
350 fuse_invalidate_entry(newent);
351 }
352
353 return err;
354}
355
356static int fuse_link(struct dentry *entry, struct inode *newdir,
357 struct dentry *newent)
358{
359 int err;
360 struct fuse_link_in inarg;
361 struct inode *inode = entry->d_inode;
362 struct fuse_conn *fc = get_fuse_conn(inode);
363 struct fuse_req *req = fuse_get_request(fc);
364 if (!req)
7c352bdf 365 return -EINTR;
9e6268db
MS
366
367 memset(&inarg, 0, sizeof(inarg));
368 inarg.oldnodeid = get_node_id(inode);
369 req->in.h.opcode = FUSE_LINK;
370 req->inode2 = inode;
371 req->in.numargs = 2;
372 req->in.args[0].size = sizeof(inarg);
373 req->in.args[0].value = &inarg;
374 req->in.args[1].size = newent->d_name.len + 1;
375 req->in.args[1].value = newent->d_name.name;
376 err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
377 /* Contrary to "normal" filesystems it can happen that link
378 makes two "logical" inodes point to the same "physical"
379 inode. We invalidate the attributes of the old one, so it
380 will reflect changes in the backing inode (link count,
381 etc.)
382 */
383 if (!err || err == -EINTR)
384 fuse_invalidate_attr(inode);
385 return err;
386}
387
e5e5558e
MS
388int fuse_do_getattr(struct inode *inode)
389{
390 int err;
391 struct fuse_attr_out arg;
392 struct fuse_conn *fc = get_fuse_conn(inode);
393 struct fuse_req *req = fuse_get_request(fc);
394 if (!req)
7c352bdf 395 return -EINTR;
e5e5558e
MS
396
397 req->in.h.opcode = FUSE_GETATTR;
398 req->in.h.nodeid = get_node_id(inode);
399 req->inode = inode;
400 req->out.numargs = 1;
401 req->out.args[0].size = sizeof(arg);
402 req->out.args[0].value = &arg;
403 request_send(fc, req);
404 err = req->out.h.error;
405 fuse_put_request(fc, req);
406 if (!err) {
407 if ((inode->i_mode ^ arg.attr.mode) & S_IFMT) {
408 make_bad_inode(inode);
409 err = -EIO;
410 } else {
411 struct fuse_inode *fi = get_fuse_inode(inode);
412 fuse_change_attributes(inode, &arg.attr);
413 fi->i_time = time_to_jiffies(arg.attr_valid,
414 arg.attr_valid_nsec);
415 }
416 }
417 return err;
418}
419
87729a55
MS
420/*
421 * Calling into a user-controlled filesystem gives the filesystem
422 * daemon ptrace-like capabilities over the requester process. This
423 * means, that the filesystem daemon is able to record the exact
424 * filesystem operations performed, and can also control the behavior
425 * of the requester process in otherwise impossible ways. For example
426 * it can delay the operation for arbitrary length of time allowing
427 * DoS against the requester.
428 *
429 * For this reason only those processes can call into the filesystem,
430 * for which the owner of the mount has ptrace privilege. This
431 * excludes processes started by other users, suid or sgid processes.
432 */
433static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
434{
435 if (fc->flags & FUSE_ALLOW_OTHER)
436 return 1;
437
438 if (task->euid == fc->user_id &&
439 task->suid == fc->user_id &&
440 task->uid == fc->user_id &&
441 task->egid == fc->group_id &&
442 task->sgid == fc->group_id &&
443 task->gid == fc->group_id)
444 return 1;
445
446 return 0;
447}
448
e5e5558e
MS
449static int fuse_revalidate(struct dentry *entry)
450{
451 struct inode *inode = entry->d_inode;
452 struct fuse_inode *fi = get_fuse_inode(inode);
453 struct fuse_conn *fc = get_fuse_conn(inode);
454
87729a55
MS
455 if (!fuse_allow_task(fc, current))
456 return -EACCES;
457 if (get_node_id(inode) != FUSE_ROOT_ID &&
458 time_before_eq(jiffies, fi->i_time))
e5e5558e
MS
459 return 0;
460
461 return fuse_do_getattr(inode);
462}
463
464static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
465{
466 struct fuse_conn *fc = get_fuse_conn(inode);
467
87729a55 468 if (!fuse_allow_task(fc, current))
e5e5558e 469 return -EACCES;
1e9a4ed9
MS
470 else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
471 int err = generic_permission(inode, mask, NULL);
472
473 /* If permission is denied, try to refresh file
474 attributes. This is also needed, because the root
475 node will at first have no permissions */
476 if (err == -EACCES) {
477 err = fuse_do_getattr(inode);
478 if (!err)
479 err = generic_permission(inode, mask, NULL);
480 }
481
482 /* FIXME: Need some mechanism to revoke permissions:
483 currently if the filesystem suddenly changes the
484 file mode, we will not be informed about it, and
485 continue to allow access to the file/directory.
486
487 This is actually not so grave, since the user can
488 simply keep access to the file/directory anyway by
489 keeping it open... */
490
491 return err;
492 } else {
e5e5558e
MS
493 int mode = inode->i_mode;
494 if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
495 (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
496 return -EROFS;
497 if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
498 return -EACCES;
499 return 0;
500 }
501}
502
503static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
504 void *dstbuf, filldir_t filldir)
505{
506 while (nbytes >= FUSE_NAME_OFFSET) {
507 struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
508 size_t reclen = FUSE_DIRENT_SIZE(dirent);
509 int over;
510 if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
511 return -EIO;
512 if (reclen > nbytes)
513 break;
514
515 over = filldir(dstbuf, dirent->name, dirent->namelen,
516 file->f_pos, dirent->ino, dirent->type);
517 if (over)
518 break;
519
520 buf += reclen;
521 nbytes -= reclen;
522 file->f_pos = dirent->off;
523 }
524
525 return 0;
526}
527
04730fef
MS
528static inline size_t fuse_send_readdir(struct fuse_req *req, struct file *file,
529 struct inode *inode, loff_t pos,
530 size_t count)
e5e5558e 531{
04730fef 532 return fuse_send_read_common(req, file, inode, pos, count, 1);
e5e5558e
MS
533}
534
04730fef 535static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
e5e5558e 536{
04730fef
MS
537 int err;
538 size_t nbytes;
539 struct page *page;
e5e5558e
MS
540 struct inode *inode = file->f_dentry->d_inode;
541 struct fuse_conn *fc = get_fuse_conn(inode);
7c352bdf 542 struct fuse_req *req = fuse_get_request(fc);
e5e5558e 543 if (!req)
04730fef 544 return -EINTR;
e5e5558e 545
04730fef
MS
546 page = alloc_page(GFP_KERNEL);
547 if (!page) {
548 fuse_put_request(fc, req);
549 return -ENOMEM;
550 }
551 req->num_pages = 1;
552 req->pages[0] = page;
553 nbytes = fuse_send_readdir(req, file, inode, file->f_pos, PAGE_SIZE);
e5e5558e
MS
554 err = req->out.h.error;
555 fuse_put_request(fc, req);
556 if (!err)
04730fef
MS
557 err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
558 filldir);
e5e5558e 559
04730fef 560 __free_page(page);
b36c31ba 561 fuse_invalidate_attr(inode); /* atime changed */
04730fef 562 return err;
e5e5558e
MS
563}
564
565static char *read_link(struct dentry *dentry)
566{
567 struct inode *inode = dentry->d_inode;
568 struct fuse_conn *fc = get_fuse_conn(inode);
569 struct fuse_req *req = fuse_get_request(fc);
570 char *link;
571
572 if (!req)
7c352bdf 573 return ERR_PTR(-EINTR);
e5e5558e
MS
574
575 link = (char *) __get_free_page(GFP_KERNEL);
576 if (!link) {
577 link = ERR_PTR(-ENOMEM);
578 goto out;
579 }
580 req->in.h.opcode = FUSE_READLINK;
581 req->in.h.nodeid = get_node_id(inode);
582 req->inode = inode;
583 req->out.argvar = 1;
584 req->out.numargs = 1;
585 req->out.args[0].size = PAGE_SIZE - 1;
586 req->out.args[0].value = link;
587 request_send(fc, req);
588 if (req->out.h.error) {
589 free_page((unsigned long) link);
590 link = ERR_PTR(req->out.h.error);
591 } else
592 link[req->out.args[0].size] = '\0';
593 out:
594 fuse_put_request(fc, req);
b36c31ba 595 fuse_invalidate_attr(inode); /* atime changed */
e5e5558e
MS
596 return link;
597}
598
599static void free_link(char *link)
600{
601 if (!IS_ERR(link))
602 free_page((unsigned long) link);
603}
604
605static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
606{
607 nd_set_link(nd, read_link(dentry));
608 return NULL;
609}
610
611static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
612{
613 free_link(nd_get_link(nd));
614}
615
616static int fuse_dir_open(struct inode *inode, struct file *file)
617{
04730fef 618 return fuse_open_common(inode, file, 1);
e5e5558e
MS
619}
620
621static int fuse_dir_release(struct inode *inode, struct file *file)
622{
04730fef 623 return fuse_release_common(inode, file, 1);
e5e5558e
MS
624}
625
82547981
MS
626static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
627{
628 /* nfsd can call this with no file */
629 return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
630}
631
9e6268db
MS
632static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
633{
634 unsigned ivalid = iattr->ia_valid;
635 unsigned fvalid = 0;
636
637 memset(fattr, 0, sizeof(*fattr));
638
639 if (ivalid & ATTR_MODE)
640 fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode;
641 if (ivalid & ATTR_UID)
642 fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid;
643 if (ivalid & ATTR_GID)
644 fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid;
645 if (ivalid & ATTR_SIZE)
646 fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size;
647 /* You can only _set_ these together (they may change by themselves) */
648 if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
649 fvalid |= FATTR_ATIME | FATTR_MTIME;
650 fattr->atime = iattr->ia_atime.tv_sec;
651 fattr->mtime = iattr->ia_mtime.tv_sec;
652 }
653
654 return fvalid;
655}
656
657static int fuse_setattr(struct dentry *entry, struct iattr *attr)
658{
659 struct inode *inode = entry->d_inode;
660 struct fuse_conn *fc = get_fuse_conn(inode);
661 struct fuse_inode *fi = get_fuse_inode(inode);
662 struct fuse_req *req;
663 struct fuse_setattr_in inarg;
664 struct fuse_attr_out outarg;
665 int err;
666 int is_truncate = 0;
667
1e9a4ed9
MS
668 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
669 err = inode_change_ok(inode, attr);
670 if (err)
671 return err;
672 }
673
9e6268db
MS
674 if (attr->ia_valid & ATTR_SIZE) {
675 unsigned long limit;
676 is_truncate = 1;
677 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
678 if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
679 send_sig(SIGXFSZ, current, 0);
680 return -EFBIG;
681 }
682 }
683
684 req = fuse_get_request(fc);
685 if (!req)
7c352bdf 686 return -EINTR;
9e6268db
MS
687
688 memset(&inarg, 0, sizeof(inarg));
689 inarg.valid = iattr_to_fattr(attr, &inarg.attr);
690 req->in.h.opcode = FUSE_SETATTR;
691 req->in.h.nodeid = get_node_id(inode);
692 req->inode = inode;
693 req->in.numargs = 1;
694 req->in.args[0].size = sizeof(inarg);
695 req->in.args[0].value = &inarg;
696 req->out.numargs = 1;
697 req->out.args[0].size = sizeof(outarg);
698 req->out.args[0].value = &outarg;
699 request_send(fc, req);
700 err = req->out.h.error;
701 fuse_put_request(fc, req);
702 if (!err) {
703 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
704 make_bad_inode(inode);
705 err = -EIO;
706 } else {
707 if (is_truncate) {
708 loff_t origsize = i_size_read(inode);
709 i_size_write(inode, outarg.attr.size);
710 if (origsize > outarg.attr.size)
711 vmtruncate(inode, outarg.attr.size);
712 }
713 fuse_change_attributes(inode, &outarg.attr);
714 fi->i_time = time_to_jiffies(outarg.attr_valid,
715 outarg.attr_valid_nsec);
716 }
717 } else if (err == -EINTR)
718 fuse_invalidate_attr(inode);
719
720 return err;
721}
722
e5e5558e
MS
723static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
724 struct kstat *stat)
725{
726 struct inode *inode = entry->d_inode;
727 int err = fuse_revalidate(entry);
728 if (!err)
729 generic_fillattr(inode, stat);
730
731 return err;
732}
733
734static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
735 struct nameidata *nd)
736{
737 struct inode *inode;
738 int err = fuse_lookup_iget(dir, entry, &inode);
739 if (err)
740 return ERR_PTR(err);
741 if (inode && S_ISDIR(inode->i_mode)) {
742 /* Don't allow creating an alias to a directory */
743 struct dentry *alias = d_find_alias(inode);
f12ec440 744 if (alias) {
e5e5558e
MS
745 dput(alias);
746 iput(inode);
747 return ERR_PTR(-EIO);
748 }
749 }
f12ec440
MS
750 d_add(entry, inode);
751 return NULL;
e5e5558e
MS
752}
753
92a8780e
MS
754static int fuse_setxattr(struct dentry *entry, const char *name,
755 const void *value, size_t size, int flags)
756{
757 struct inode *inode = entry->d_inode;
758 struct fuse_conn *fc = get_fuse_conn(inode);
759 struct fuse_req *req;
760 struct fuse_setxattr_in inarg;
761 int err;
762
763 if (size > FUSE_XATTR_SIZE_MAX)
764 return -E2BIG;
765
766 if (fc->no_setxattr)
767 return -EOPNOTSUPP;
768
769 req = fuse_get_request(fc);
770 if (!req)
7c352bdf 771 return -EINTR;
92a8780e
MS
772
773 memset(&inarg, 0, sizeof(inarg));
774 inarg.size = size;
775 inarg.flags = flags;
776 req->in.h.opcode = FUSE_SETXATTR;
777 req->in.h.nodeid = get_node_id(inode);
778 req->inode = inode;
779 req->in.numargs = 3;
780 req->in.args[0].size = sizeof(inarg);
781 req->in.args[0].value = &inarg;
782 req->in.args[1].size = strlen(name) + 1;
783 req->in.args[1].value = name;
784 req->in.args[2].size = size;
785 req->in.args[2].value = value;
786 request_send(fc, req);
787 err = req->out.h.error;
788 fuse_put_request(fc, req);
789 if (err == -ENOSYS) {
790 fc->no_setxattr = 1;
791 err = -EOPNOTSUPP;
792 }
793 return err;
794}
795
796static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
797 void *value, size_t size)
798{
799 struct inode *inode = entry->d_inode;
800 struct fuse_conn *fc = get_fuse_conn(inode);
801 struct fuse_req *req;
802 struct fuse_getxattr_in inarg;
803 struct fuse_getxattr_out outarg;
804 ssize_t ret;
805
806 if (fc->no_getxattr)
807 return -EOPNOTSUPP;
808
809 req = fuse_get_request(fc);
810 if (!req)
7c352bdf 811 return -EINTR;
92a8780e
MS
812
813 memset(&inarg, 0, sizeof(inarg));
814 inarg.size = size;
815 req->in.h.opcode = FUSE_GETXATTR;
816 req->in.h.nodeid = get_node_id(inode);
817 req->inode = inode;
818 req->in.numargs = 2;
819 req->in.args[0].size = sizeof(inarg);
820 req->in.args[0].value = &inarg;
821 req->in.args[1].size = strlen(name) + 1;
822 req->in.args[1].value = name;
823 /* This is really two different operations rolled into one */
824 req->out.numargs = 1;
825 if (size) {
826 req->out.argvar = 1;
827 req->out.args[0].size = size;
828 req->out.args[0].value = value;
829 } else {
830 req->out.args[0].size = sizeof(outarg);
831 req->out.args[0].value = &outarg;
832 }
833 request_send(fc, req);
834 ret = req->out.h.error;
835 if (!ret)
836 ret = size ? req->out.args[0].size : outarg.size;
837 else {
838 if (ret == -ENOSYS) {
839 fc->no_getxattr = 1;
840 ret = -EOPNOTSUPP;
841 }
842 }
843 fuse_put_request(fc, req);
844 return ret;
845}
846
847static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
848{
849 struct inode *inode = entry->d_inode;
850 struct fuse_conn *fc = get_fuse_conn(inode);
851 struct fuse_req *req;
852 struct fuse_getxattr_in inarg;
853 struct fuse_getxattr_out outarg;
854 ssize_t ret;
855
856 if (fc->no_listxattr)
857 return -EOPNOTSUPP;
858
859 req = fuse_get_request(fc);
860 if (!req)
7c352bdf 861 return -EINTR;
92a8780e
MS
862
863 memset(&inarg, 0, sizeof(inarg));
864 inarg.size = size;
865 req->in.h.opcode = FUSE_LISTXATTR;
866 req->in.h.nodeid = get_node_id(inode);
867 req->inode = inode;
868 req->in.numargs = 1;
869 req->in.args[0].size = sizeof(inarg);
870 req->in.args[0].value = &inarg;
871 /* This is really two different operations rolled into one */
872 req->out.numargs = 1;
873 if (size) {
874 req->out.argvar = 1;
875 req->out.args[0].size = size;
876 req->out.args[0].value = list;
877 } else {
878 req->out.args[0].size = sizeof(outarg);
879 req->out.args[0].value = &outarg;
880 }
881 request_send(fc, req);
882 ret = req->out.h.error;
883 if (!ret)
884 ret = size ? req->out.args[0].size : outarg.size;
885 else {
886 if (ret == -ENOSYS) {
887 fc->no_listxattr = 1;
888 ret = -EOPNOTSUPP;
889 }
890 }
891 fuse_put_request(fc, req);
892 return ret;
893}
894
895static int fuse_removexattr(struct dentry *entry, const char *name)
896{
897 struct inode *inode = entry->d_inode;
898 struct fuse_conn *fc = get_fuse_conn(inode);
899 struct fuse_req *req;
900 int err;
901
902 if (fc->no_removexattr)
903 return -EOPNOTSUPP;
904
905 req = fuse_get_request(fc);
906 if (!req)
7c352bdf 907 return -EINTR;
92a8780e
MS
908
909 req->in.h.opcode = FUSE_REMOVEXATTR;
910 req->in.h.nodeid = get_node_id(inode);
911 req->inode = inode;
912 req->in.numargs = 1;
913 req->in.args[0].size = strlen(name) + 1;
914 req->in.args[0].value = name;
915 request_send(fc, req);
916 err = req->out.h.error;
917 fuse_put_request(fc, req);
918 if (err == -ENOSYS) {
919 fc->no_removexattr = 1;
920 err = -EOPNOTSUPP;
921 }
922 return err;
923}
924
e5e5558e
MS
925static struct inode_operations fuse_dir_inode_operations = {
926 .lookup = fuse_lookup,
9e6268db
MS
927 .mkdir = fuse_mkdir,
928 .symlink = fuse_symlink,
929 .unlink = fuse_unlink,
930 .rmdir = fuse_rmdir,
931 .rename = fuse_rename,
932 .link = fuse_link,
933 .setattr = fuse_setattr,
934 .create = fuse_create,
935 .mknod = fuse_mknod,
e5e5558e
MS
936 .permission = fuse_permission,
937 .getattr = fuse_getattr,
92a8780e
MS
938 .setxattr = fuse_setxattr,
939 .getxattr = fuse_getxattr,
940 .listxattr = fuse_listxattr,
941 .removexattr = fuse_removexattr,
e5e5558e
MS
942};
943
944static struct file_operations fuse_dir_operations = {
b6aeaded 945 .llseek = generic_file_llseek,
e5e5558e
MS
946 .read = generic_read_dir,
947 .readdir = fuse_readdir,
948 .open = fuse_dir_open,
949 .release = fuse_dir_release,
82547981 950 .fsync = fuse_dir_fsync,
e5e5558e
MS
951};
952
953static struct inode_operations fuse_common_inode_operations = {
9e6268db 954 .setattr = fuse_setattr,
e5e5558e
MS
955 .permission = fuse_permission,
956 .getattr = fuse_getattr,
92a8780e
MS
957 .setxattr = fuse_setxattr,
958 .getxattr = fuse_getxattr,
959 .listxattr = fuse_listxattr,
960 .removexattr = fuse_removexattr,
e5e5558e
MS
961};
962
963static struct inode_operations fuse_symlink_inode_operations = {
9e6268db 964 .setattr = fuse_setattr,
e5e5558e
MS
965 .follow_link = fuse_follow_link,
966 .put_link = fuse_put_link,
967 .readlink = generic_readlink,
968 .getattr = fuse_getattr,
92a8780e
MS
969 .setxattr = fuse_setxattr,
970 .getxattr = fuse_getxattr,
971 .listxattr = fuse_listxattr,
972 .removexattr = fuse_removexattr,
e5e5558e
MS
973};
974
975void fuse_init_common(struct inode *inode)
976{
977 inode->i_op = &fuse_common_inode_operations;
978}
979
980void fuse_init_dir(struct inode *inode)
981{
982 inode->i_op = &fuse_dir_inode_operations;
983 inode->i_fop = &fuse_dir_operations;
984}
985
986void fuse_init_symlink(struct inode *inode)
987{
988 inode->i_op = &fuse_symlink_inode_operations;
989}
This page took 0.078879 seconds and 5 git commands to generate.