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