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.
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>
17 static inline unsigned long time_to_jiffies(unsigned long sec
,
20 struct timespec ts
= {sec
, nsec
};
21 return jiffies
+ timespec_to_jiffies(&ts
);
24 static void fuse_lookup_init(struct fuse_req
*req
, struct inode
*dir
,
26 struct fuse_entry_out
*outarg
)
28 req
->in
.h
.opcode
= FUSE_LOOKUP
;
29 req
->in
.h
.nodeid
= get_node_id(dir
);
32 req
->in
.args
[0].size
= entry
->d_name
.len
+ 1;
33 req
->in
.args
[0].value
= entry
->d_name
.name
;
35 req
->out
.args
[0].size
= sizeof(struct fuse_entry_out
);
36 req
->out
.args
[0].value
= outarg
;
39 static int fuse_dentry_revalidate(struct dentry
*entry
, struct nameidata
*nd
)
41 if (!entry
->d_inode
|| is_bad_inode(entry
->d_inode
))
43 else if (time_after(jiffies
, entry
->d_time
)) {
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
);
53 fuse_lookup_init(req
, entry
->d_parent
->d_inode
, entry
, &outarg
);
54 request_send_nonint(fc
, req
);
55 err
= req
->out
.h
.error
;
57 if (outarg
.nodeid
!= get_node_id(inode
)) {
58 fuse_send_forget(fc
, req
, outarg
.nodeid
, 1);
63 fuse_put_request(fc
, req
);
64 if (err
|| (outarg
.attr
.mode
^ inode
->i_mode
) & S_IFMT
)
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
);
76 static struct dentry_operations fuse_dentry_operations
= {
77 .d_revalidate
= fuse_dentry_revalidate
,
80 static int fuse_lookup_iget(struct inode
*dir
, struct dentry
*entry
,
81 struct inode
**inodep
)
84 struct fuse_entry_out outarg
;
85 struct inode
*inode
= NULL
;
86 struct fuse_conn
*fc
= get_fuse_conn(dir
);
89 if (entry
->d_name
.len
> FUSE_NAME_MAX
)
92 req
= fuse_get_request(fc
);
94 return -ERESTARTNOINTR
;
96 fuse_lookup_init(req
, dir
, entry
, &outarg
);
97 request_send(fc
, req
);
98 err
= req
->out
.h
.error
;
100 inode
= fuse_iget(dir
->i_sb
, outarg
.nodeid
, outarg
.generation
,
103 fuse_send_forget(fc
, req
, outarg
.nodeid
, 1);
107 fuse_put_request(fc
, req
);
108 if (err
&& err
!= -ENOENT
)
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
);
119 entry
->d_op
= &fuse_dentry_operations
;
124 void fuse_invalidate_attr(struct inode
*inode
)
126 get_fuse_inode(inode
)->i_time
= jiffies
- 1;
129 static void fuse_invalidate_entry(struct dentry
*entry
)
132 entry
->d_time
= jiffies
- 1;
135 static int create_new_entry(struct fuse_conn
*fc
, struct fuse_req
*req
,
136 struct inode
*dir
, struct dentry
*entry
,
139 struct fuse_entry_out outarg
;
141 struct fuse_inode
*fi
;
144 req
->in
.h
.nodeid
= get_node_id(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
;
152 fuse_put_request(fc
, req
);
155 inode
= fuse_iget(dir
->i_sb
, outarg
.nodeid
, outarg
.generation
,
158 fuse_send_forget(fc
, req
, outarg
.nodeid
, 1);
161 fuse_put_request(fc
, req
);
163 /* Don't allow userspace to do really stupid things... */
164 if ((inode
->i_mode
^ mode
) & S_IFMT
) {
169 entry
->d_time
= time_to_jiffies(outarg
.entry_valid
,
170 outarg
.entry_valid_nsec
);
172 fi
= get_fuse_inode(inode
);
173 fi
->i_time
= time_to_jiffies(outarg
.attr_valid
,
174 outarg
.attr_valid_nsec
);
176 d_instantiate(entry
, inode
);
177 fuse_invalidate_attr(dir
);
181 static int fuse_mknod(struct inode
*dir
, struct dentry
*entry
, int mode
,
184 struct fuse_mknod_in inarg
;
185 struct fuse_conn
*fc
= get_fuse_conn(dir
);
186 struct fuse_req
*req
= fuse_get_request(fc
);
188 return -ERESTARTNOINTR
;
190 memset(&inarg
, 0, sizeof(inarg
));
192 inarg
.rdev
= new_encode_dev(rdev
);
193 req
->in
.h
.opcode
= FUSE_MKNOD
;
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
);
202 static int fuse_create(struct inode
*dir
, struct dentry
*entry
, int mode
,
203 struct nameidata
*nd
)
205 return fuse_mknod(dir
, entry
, mode
, 0);
208 static int fuse_mkdir(struct inode
*dir
, struct dentry
*entry
, int mode
)
210 struct fuse_mkdir_in inarg
;
211 struct fuse_conn
*fc
= get_fuse_conn(dir
);
212 struct fuse_req
*req
= fuse_get_request(fc
);
214 return -ERESTARTNOINTR
;
216 memset(&inarg
, 0, sizeof(inarg
));
218 req
->in
.h
.opcode
= FUSE_MKDIR
;
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
);
227 static int fuse_symlink(struct inode
*dir
, struct dentry
*entry
,
230 struct fuse_conn
*fc
= get_fuse_conn(dir
);
231 unsigned len
= strlen(link
) + 1;
232 struct fuse_req
*req
;
234 if (len
> FUSE_SYMLINK_MAX
)
235 return -ENAMETOOLONG
;
237 req
= fuse_get_request(fc
);
239 return -ERESTARTNOINTR
;
241 req
->in
.h
.opcode
= FUSE_SYMLINK
;
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
);
250 static int fuse_unlink(struct inode
*dir
, struct dentry
*entry
)
253 struct fuse_conn
*fc
= get_fuse_conn(dir
);
254 struct fuse_req
*req
= fuse_get_request(fc
);
256 return -ERESTARTNOINTR
;
258 req
->in
.h
.opcode
= FUSE_UNLINK
;
259 req
->in
.h
.nodeid
= get_node_id(dir
);
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
);
268 struct inode
*inode
= entry
->d_inode
;
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 */
274 fuse_invalidate_attr(inode
);
275 fuse_invalidate_attr(dir
);
276 } else if (err
== -EINTR
)
277 fuse_invalidate_entry(entry
);
281 static int fuse_rmdir(struct inode
*dir
, struct dentry
*entry
)
284 struct fuse_conn
*fc
= get_fuse_conn(dir
);
285 struct fuse_req
*req
= fuse_get_request(fc
);
287 return -ERESTARTNOINTR
;
289 req
->in
.h
.opcode
= FUSE_RMDIR
;
290 req
->in
.h
.nodeid
= get_node_id(dir
);
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
);
299 entry
->d_inode
->i_nlink
= 0;
300 fuse_invalidate_attr(dir
);
301 } else if (err
== -EINTR
)
302 fuse_invalidate_entry(entry
);
306 static int fuse_rename(struct inode
*olddir
, struct dentry
*oldent
,
307 struct inode
*newdir
, struct dentry
*newent
)
310 struct fuse_rename_in inarg
;
311 struct fuse_conn
*fc
= get_fuse_conn(olddir
);
312 struct fuse_req
*req
= fuse_get_request(fc
);
314 return -ERESTARTNOINTR
;
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
);
321 req
->inode2
= newdir
;
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
);
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
);
344 fuse_invalidate_entry(newent
);
350 static int fuse_link(struct dentry
*entry
, struct inode
*newdir
,
351 struct dentry
*newent
)
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
);
359 return -ERESTARTNOINTR
;
361 memset(&inarg
, 0, sizeof(inarg
));
362 inarg
.oldnodeid
= get_node_id(inode
);
363 req
->in
.h
.opcode
= FUSE_LINK
;
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,
377 if (!err
|| err
== -EINTR
)
378 fuse_invalidate_attr(inode
);
382 int fuse_do_getattr(struct inode
*inode
)
385 struct fuse_attr_out arg
;
386 struct fuse_conn
*fc
= get_fuse_conn(inode
);
387 struct fuse_req
*req
= fuse_get_request(fc
);
389 return -ERESTARTNOINTR
;
391 req
->in
.h
.opcode
= FUSE_GETATTR
;
392 req
->in
.h
.nodeid
= get_node_id(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
);
401 if ((inode
->i_mode
^ arg
.attr
.mode
) & S_IFMT
) {
402 make_bad_inode(inode
);
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
);
415 * Calling into a user-controlled filesystem gives the filesystem
416 * daemon ptrace-like capabilities over the requester process. This
417 * means, that the filesystem daemon is able to record the exact
418 * filesystem operations performed, and can also control the behavior
419 * of the requester process in otherwise impossible ways. For example
420 * it can delay the operation for arbitrary length of time allowing
421 * DoS against the requester.
423 * For this reason only those processes can call into the filesystem,
424 * for which the owner of the mount has ptrace privilege. This
425 * excludes processes started by other users, suid or sgid processes.
427 static int fuse_allow_task(struct fuse_conn
*fc
, struct task_struct
*task
)
429 if (fc
->flags
& FUSE_ALLOW_OTHER
)
432 if (task
->euid
== fc
->user_id
&&
433 task
->suid
== fc
->user_id
&&
434 task
->uid
== fc
->user_id
&&
435 task
->egid
== fc
->group_id
&&
436 task
->sgid
== fc
->group_id
&&
437 task
->gid
== fc
->group_id
)
443 static int fuse_revalidate(struct dentry
*entry
)
445 struct inode
*inode
= entry
->d_inode
;
446 struct fuse_inode
*fi
= get_fuse_inode(inode
);
447 struct fuse_conn
*fc
= get_fuse_conn(inode
);
449 if (!fuse_allow_task(fc
, current
))
451 if (get_node_id(inode
) != FUSE_ROOT_ID
&&
452 time_before_eq(jiffies
, fi
->i_time
))
455 return fuse_do_getattr(inode
);
458 static int fuse_permission(struct inode
*inode
, int mask
, struct nameidata
*nd
)
460 struct fuse_conn
*fc
= get_fuse_conn(inode
);
462 if (!fuse_allow_task(fc
, current
))
464 else if (fc
->flags
& FUSE_DEFAULT_PERMISSIONS
) {
465 int err
= generic_permission(inode
, mask
, NULL
);
467 /* If permission is denied, try to refresh file
468 attributes. This is also needed, because the root
469 node will at first have no permissions */
470 if (err
== -EACCES
) {
471 err
= fuse_do_getattr(inode
);
473 err
= generic_permission(inode
, mask
, NULL
);
476 /* FIXME: Need some mechanism to revoke permissions:
477 currently if the filesystem suddenly changes the
478 file mode, we will not be informed about it, and
479 continue to allow access to the file/directory.
481 This is actually not so grave, since the user can
482 simply keep access to the file/directory anyway by
483 keeping it open... */
487 int mode
= inode
->i_mode
;
488 if ((mask
& MAY_WRITE
) && IS_RDONLY(inode
) &&
489 (S_ISREG(mode
) || S_ISDIR(mode
) || S_ISLNK(mode
)))
491 if ((mask
& MAY_EXEC
) && !S_ISDIR(mode
) && !(mode
& S_IXUGO
))
497 static int parse_dirfile(char *buf
, size_t nbytes
, struct file
*file
,
498 void *dstbuf
, filldir_t filldir
)
500 while (nbytes
>= FUSE_NAME_OFFSET
) {
501 struct fuse_dirent
*dirent
= (struct fuse_dirent
*) buf
;
502 size_t reclen
= FUSE_DIRENT_SIZE(dirent
);
504 if (!dirent
->namelen
|| dirent
->namelen
> FUSE_NAME_MAX
)
509 over
= filldir(dstbuf
, dirent
->name
, dirent
->namelen
,
510 file
->f_pos
, dirent
->ino
, dirent
->type
);
516 file
->f_pos
= dirent
->off
;
522 static inline size_t fuse_send_readdir(struct fuse_req
*req
, struct file
*file
,
523 struct inode
*inode
, loff_t pos
,
526 return fuse_send_read_common(req
, file
, inode
, pos
, count
, 1);
529 static int fuse_readdir(struct file
*file
, void *dstbuf
, filldir_t filldir
)
534 struct inode
*inode
= file
->f_dentry
->d_inode
;
535 struct fuse_conn
*fc
= get_fuse_conn(inode
);
536 struct fuse_req
*req
= fuse_get_request_nonint(fc
);
540 page
= alloc_page(GFP_KERNEL
);
542 fuse_put_request(fc
, req
);
546 req
->pages
[0] = page
;
547 nbytes
= fuse_send_readdir(req
, file
, inode
, file
->f_pos
, PAGE_SIZE
);
548 err
= req
->out
.h
.error
;
549 fuse_put_request(fc
, req
);
551 err
= parse_dirfile(page_address(page
), nbytes
, file
, dstbuf
,
555 fuse_invalidate_attr(inode
); /* atime changed */
559 static char *read_link(struct dentry
*dentry
)
561 struct inode
*inode
= dentry
->d_inode
;
562 struct fuse_conn
*fc
= get_fuse_conn(inode
);
563 struct fuse_req
*req
= fuse_get_request(fc
);
567 return ERR_PTR(-ERESTARTNOINTR
);
569 link
= (char *) __get_free_page(GFP_KERNEL
);
571 link
= ERR_PTR(-ENOMEM
);
574 req
->in
.h
.opcode
= FUSE_READLINK
;
575 req
->in
.h
.nodeid
= get_node_id(inode
);
578 req
->out
.numargs
= 1;
579 req
->out
.args
[0].size
= PAGE_SIZE
- 1;
580 req
->out
.args
[0].value
= link
;
581 request_send(fc
, req
);
582 if (req
->out
.h
.error
) {
583 free_page((unsigned long) link
);
584 link
= ERR_PTR(req
->out
.h
.error
);
586 link
[req
->out
.args
[0].size
] = '\0';
588 fuse_put_request(fc
, req
);
589 fuse_invalidate_attr(inode
); /* atime changed */
593 static void free_link(char *link
)
596 free_page((unsigned long) link
);
599 static void *fuse_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
601 nd_set_link(nd
, read_link(dentry
));
605 static void fuse_put_link(struct dentry
*dentry
, struct nameidata
*nd
, void *c
)
607 free_link(nd_get_link(nd
));
610 static int fuse_dir_open(struct inode
*inode
, struct file
*file
)
612 return fuse_open_common(inode
, file
, 1);
615 static int fuse_dir_release(struct inode
*inode
, struct file
*file
)
617 return fuse_release_common(inode
, file
, 1);
620 static unsigned iattr_to_fattr(struct iattr
*iattr
, struct fuse_attr
*fattr
)
622 unsigned ivalid
= iattr
->ia_valid
;
625 memset(fattr
, 0, sizeof(*fattr
));
627 if (ivalid
& ATTR_MODE
)
628 fvalid
|= FATTR_MODE
, fattr
->mode
= iattr
->ia_mode
;
629 if (ivalid
& ATTR_UID
)
630 fvalid
|= FATTR_UID
, fattr
->uid
= iattr
->ia_uid
;
631 if (ivalid
& ATTR_GID
)
632 fvalid
|= FATTR_GID
, fattr
->gid
= iattr
->ia_gid
;
633 if (ivalid
& ATTR_SIZE
)
634 fvalid
|= FATTR_SIZE
, fattr
->size
= iattr
->ia_size
;
635 /* You can only _set_ these together (they may change by themselves) */
636 if ((ivalid
& (ATTR_ATIME
| ATTR_MTIME
)) == (ATTR_ATIME
| ATTR_MTIME
)) {
637 fvalid
|= FATTR_ATIME
| FATTR_MTIME
;
638 fattr
->atime
= iattr
->ia_atime
.tv_sec
;
639 fattr
->mtime
= iattr
->ia_mtime
.tv_sec
;
645 static int fuse_setattr(struct dentry
*entry
, struct iattr
*attr
)
647 struct inode
*inode
= entry
->d_inode
;
648 struct fuse_conn
*fc
= get_fuse_conn(inode
);
649 struct fuse_inode
*fi
= get_fuse_inode(inode
);
650 struct fuse_req
*req
;
651 struct fuse_setattr_in inarg
;
652 struct fuse_attr_out outarg
;
656 if (fc
->flags
& FUSE_DEFAULT_PERMISSIONS
) {
657 err
= inode_change_ok(inode
, attr
);
662 if (attr
->ia_valid
& ATTR_SIZE
) {
665 limit
= current
->signal
->rlim
[RLIMIT_FSIZE
].rlim_cur
;
666 if (limit
!= RLIM_INFINITY
&& attr
->ia_size
> (loff_t
) limit
) {
667 send_sig(SIGXFSZ
, current
, 0);
672 req
= fuse_get_request(fc
);
674 return -ERESTARTNOINTR
;
676 memset(&inarg
, 0, sizeof(inarg
));
677 inarg
.valid
= iattr_to_fattr(attr
, &inarg
.attr
);
678 req
->in
.h
.opcode
= FUSE_SETATTR
;
679 req
->in
.h
.nodeid
= get_node_id(inode
);
682 req
->in
.args
[0].size
= sizeof(inarg
);
683 req
->in
.args
[0].value
= &inarg
;
684 req
->out
.numargs
= 1;
685 req
->out
.args
[0].size
= sizeof(outarg
);
686 req
->out
.args
[0].value
= &outarg
;
687 request_send(fc
, req
);
688 err
= req
->out
.h
.error
;
689 fuse_put_request(fc
, req
);
691 if ((inode
->i_mode
^ outarg
.attr
.mode
) & S_IFMT
) {
692 make_bad_inode(inode
);
696 loff_t origsize
= i_size_read(inode
);
697 i_size_write(inode
, outarg
.attr
.size
);
698 if (origsize
> outarg
.attr
.size
)
699 vmtruncate(inode
, outarg
.attr
.size
);
701 fuse_change_attributes(inode
, &outarg
.attr
);
702 fi
->i_time
= time_to_jiffies(outarg
.attr_valid
,
703 outarg
.attr_valid_nsec
);
705 } else if (err
== -EINTR
)
706 fuse_invalidate_attr(inode
);
711 static int fuse_getattr(struct vfsmount
*mnt
, struct dentry
*entry
,
714 struct inode
*inode
= entry
->d_inode
;
715 int err
= fuse_revalidate(entry
);
717 generic_fillattr(inode
, stat
);
722 static struct dentry
*fuse_lookup(struct inode
*dir
, struct dentry
*entry
,
723 struct nameidata
*nd
)
726 int err
= fuse_lookup_iget(dir
, entry
, &inode
);
729 if (inode
&& S_ISDIR(inode
->i_mode
)) {
730 /* Don't allow creating an alias to a directory */
731 struct dentry
*alias
= d_find_alias(inode
);
732 if (alias
&& !(alias
->d_flags
& DCACHE_DISCONNECTED
)) {
735 return ERR_PTR(-EIO
);
738 return d_splice_alias(inode
, entry
);
741 static int fuse_setxattr(struct dentry
*entry
, const char *name
,
742 const void *value
, size_t size
, int flags
)
744 struct inode
*inode
= entry
->d_inode
;
745 struct fuse_conn
*fc
= get_fuse_conn(inode
);
746 struct fuse_req
*req
;
747 struct fuse_setxattr_in inarg
;
750 if (size
> FUSE_XATTR_SIZE_MAX
)
756 req
= fuse_get_request(fc
);
758 return -ERESTARTNOINTR
;
760 memset(&inarg
, 0, sizeof(inarg
));
763 req
->in
.h
.opcode
= FUSE_SETXATTR
;
764 req
->in
.h
.nodeid
= get_node_id(inode
);
767 req
->in
.args
[0].size
= sizeof(inarg
);
768 req
->in
.args
[0].value
= &inarg
;
769 req
->in
.args
[1].size
= strlen(name
) + 1;
770 req
->in
.args
[1].value
= name
;
771 req
->in
.args
[2].size
= size
;
772 req
->in
.args
[2].value
= value
;
773 request_send(fc
, req
);
774 err
= req
->out
.h
.error
;
775 fuse_put_request(fc
, req
);
776 if (err
== -ENOSYS
) {
783 static ssize_t
fuse_getxattr(struct dentry
*entry
, const char *name
,
784 void *value
, size_t size
)
786 struct inode
*inode
= entry
->d_inode
;
787 struct fuse_conn
*fc
= get_fuse_conn(inode
);
788 struct fuse_req
*req
;
789 struct fuse_getxattr_in inarg
;
790 struct fuse_getxattr_out outarg
;
796 req
= fuse_get_request(fc
);
798 return -ERESTARTNOINTR
;
800 memset(&inarg
, 0, sizeof(inarg
));
802 req
->in
.h
.opcode
= FUSE_GETXATTR
;
803 req
->in
.h
.nodeid
= get_node_id(inode
);
806 req
->in
.args
[0].size
= sizeof(inarg
);
807 req
->in
.args
[0].value
= &inarg
;
808 req
->in
.args
[1].size
= strlen(name
) + 1;
809 req
->in
.args
[1].value
= name
;
810 /* This is really two different operations rolled into one */
811 req
->out
.numargs
= 1;
814 req
->out
.args
[0].size
= size
;
815 req
->out
.args
[0].value
= value
;
817 req
->out
.args
[0].size
= sizeof(outarg
);
818 req
->out
.args
[0].value
= &outarg
;
820 request_send(fc
, req
);
821 ret
= req
->out
.h
.error
;
823 ret
= size
? req
->out
.args
[0].size
: outarg
.size
;
825 if (ret
== -ENOSYS
) {
830 fuse_put_request(fc
, req
);
834 static ssize_t
fuse_listxattr(struct dentry
*entry
, char *list
, size_t size
)
836 struct inode
*inode
= entry
->d_inode
;
837 struct fuse_conn
*fc
= get_fuse_conn(inode
);
838 struct fuse_req
*req
;
839 struct fuse_getxattr_in inarg
;
840 struct fuse_getxattr_out outarg
;
843 if (fc
->no_listxattr
)
846 req
= fuse_get_request(fc
);
848 return -ERESTARTNOINTR
;
850 memset(&inarg
, 0, sizeof(inarg
));
852 req
->in
.h
.opcode
= FUSE_LISTXATTR
;
853 req
->in
.h
.nodeid
= get_node_id(inode
);
856 req
->in
.args
[0].size
= sizeof(inarg
);
857 req
->in
.args
[0].value
= &inarg
;
858 /* This is really two different operations rolled into one */
859 req
->out
.numargs
= 1;
862 req
->out
.args
[0].size
= size
;
863 req
->out
.args
[0].value
= list
;
865 req
->out
.args
[0].size
= sizeof(outarg
);
866 req
->out
.args
[0].value
= &outarg
;
868 request_send(fc
, req
);
869 ret
= req
->out
.h
.error
;
871 ret
= size
? req
->out
.args
[0].size
: outarg
.size
;
873 if (ret
== -ENOSYS
) {
874 fc
->no_listxattr
= 1;
878 fuse_put_request(fc
, req
);
882 static int fuse_removexattr(struct dentry
*entry
, const char *name
)
884 struct inode
*inode
= entry
->d_inode
;
885 struct fuse_conn
*fc
= get_fuse_conn(inode
);
886 struct fuse_req
*req
;
889 if (fc
->no_removexattr
)
892 req
= fuse_get_request(fc
);
894 return -ERESTARTNOINTR
;
896 req
->in
.h
.opcode
= FUSE_REMOVEXATTR
;
897 req
->in
.h
.nodeid
= get_node_id(inode
);
900 req
->in
.args
[0].size
= strlen(name
) + 1;
901 req
->in
.args
[0].value
= name
;
902 request_send(fc
, req
);
903 err
= req
->out
.h
.error
;
904 fuse_put_request(fc
, req
);
905 if (err
== -ENOSYS
) {
906 fc
->no_removexattr
= 1;
912 static struct inode_operations fuse_dir_inode_operations
= {
913 .lookup
= fuse_lookup
,
915 .symlink
= fuse_symlink
,
916 .unlink
= fuse_unlink
,
918 .rename
= fuse_rename
,
920 .setattr
= fuse_setattr
,
921 .create
= fuse_create
,
923 .permission
= fuse_permission
,
924 .getattr
= fuse_getattr
,
925 .setxattr
= fuse_setxattr
,
926 .getxattr
= fuse_getxattr
,
927 .listxattr
= fuse_listxattr
,
928 .removexattr
= fuse_removexattr
,
931 static struct file_operations fuse_dir_operations
= {
932 .llseek
= generic_file_llseek
,
933 .read
= generic_read_dir
,
934 .readdir
= fuse_readdir
,
935 .open
= fuse_dir_open
,
936 .release
= fuse_dir_release
,
939 static struct inode_operations fuse_common_inode_operations
= {
940 .setattr
= fuse_setattr
,
941 .permission
= fuse_permission
,
942 .getattr
= fuse_getattr
,
943 .setxattr
= fuse_setxattr
,
944 .getxattr
= fuse_getxattr
,
945 .listxattr
= fuse_listxattr
,
946 .removexattr
= fuse_removexattr
,
949 static struct inode_operations fuse_symlink_inode_operations
= {
950 .setattr
= fuse_setattr
,
951 .follow_link
= fuse_follow_link
,
952 .put_link
= fuse_put_link
,
953 .readlink
= generic_readlink
,
954 .getattr
= fuse_getattr
,
955 .setxattr
= fuse_setxattr
,
956 .getxattr
= fuse_getxattr
,
957 .listxattr
= fuse_listxattr
,
958 .removexattr
= fuse_removexattr
,
961 void fuse_init_common(struct inode
*inode
)
963 inode
->i_op
= &fuse_common_inode_operations
;
966 void fuse_init_dir(struct inode
*inode
)
968 inode
->i_op
= &fuse_dir_inode_operations
;
969 inode
->i_fop
= &fuse_dir_operations
;
972 void fuse_init_symlink(struct inode
*inode
)
974 inode
->i_op
= &fuse_symlink_inode_operations
;