/[fuse_dbi]/fuse/trunk/kernel/dir.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /fuse/trunk/kernel/dir.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (hide annotations)
Wed Aug 4 11:40:49 2004 UTC (19 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 28678 byte(s)
copy CVS to trunk

1 dpavlin 4 /*
2     FUSE: Filesystem in Userspace
3     Copyright (C) 2001-2004 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/slab.h>
13     #include <linux/file.h>
14    
15     static struct inode_operations fuse_dir_inode_operations;
16     static struct inode_operations fuse_file_inode_operations;
17     static struct inode_operations fuse_symlink_inode_operations;
18    
19     static struct file_operations fuse_dir_operations;
20    
21     static struct dentry_operations fuse_dentry_operations;
22    
23     #ifndef KERNEL_2_6
24     #define new_decode_dev(x) (x)
25     #define new_encode_dev(x) (x)
26     #endif
27    
28     static void change_attributes(struct inode *inode, struct fuse_attr *attr)
29     {
30     if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size) {
31     #ifdef KERNEL_2_6
32     invalidate_inode_pages(inode->i_mapping);
33     #else
34     invalidate_inode_pages(inode);
35     #endif
36     }
37    
38     inode->i_mode = (inode->i_mode & S_IFMT) + (attr->mode & 07777);
39     inode->i_nlink = attr->nlink;
40     inode->i_uid = attr->uid;
41     inode->i_gid = attr->gid;
42     i_size_write(inode, attr->size);
43     inode->i_blksize = PAGE_CACHE_SIZE;
44     inode->i_blocks = attr->blocks;
45     #ifdef KERNEL_2_6
46     inode->i_atime.tv_sec = attr->atime;
47     inode->i_atime.tv_nsec = attr->atimensec;
48     inode->i_mtime.tv_sec = attr->mtime;
49     inode->i_mtime.tv_nsec = attr->mtimensec;
50     inode->i_ctime.tv_sec = attr->ctime;
51     inode->i_ctime.tv_nsec = attr->ctimensec;
52     #else
53     inode->i_atime = attr->atime;
54     inode->i_mtime = attr->mtime;
55     inode->i_ctime = attr->ctime;
56     #endif
57     }
58    
59     static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
60     {
61     inode->i_mode = attr->mode & S_IFMT;
62     i_size_write(inode, attr->size);
63     if (S_ISREG(inode->i_mode)) {
64     inode->i_op = &fuse_file_inode_operations;
65     fuse_init_file_inode(inode);
66     }
67     else if (S_ISDIR(inode->i_mode)) {
68     inode->i_op = &fuse_dir_inode_operations;
69     inode->i_fop = &fuse_dir_operations;
70     }
71     else if (S_ISLNK(inode->i_mode)) {
72     inode->i_op = &fuse_symlink_inode_operations;
73     }
74     else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
75     S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)){
76     inode->i_op = &fuse_file_inode_operations;
77     init_special_inode(inode, inode->i_mode,
78     new_decode_dev(attr->rdev));
79     } else
80     printk("fuse_init_inode: bad file type: %o\n", inode->i_mode);
81     }
82    
83     struct inode *fuse_iget(struct super_block *sb, ino_t ino, int generation,
84     struct fuse_attr *attr, int version)
85     {
86     struct inode *inode;
87    
88     inode = iget(sb, ino);
89     if (inode) {
90     if (!INO_FI(inode)) {
91     struct fuse_inode *fi = fuse_inode_alloc();
92     if (!fi) {
93     iput(inode);
94     inode = NULL;
95     goto out;
96     }
97     INO_FI(inode) = fi;
98     inode->i_generation = generation;
99     fuse_init_inode(inode, attr);
100     } else if (inode->i_generation != generation)
101     printk("fuse_iget: bad generation for ino %lu\n", ino);
102    
103     change_attributes(inode, attr);
104     inode->i_version = version;
105     }
106     out:
107    
108     return inode;
109     }
110    
111     static int fuse_send_lookup(struct fuse_conn *fc, struct fuse_req *req,
112     struct inode *dir, struct dentry *entry,
113     struct fuse_entry_out *outarg, int *version)
114     {
115     req->in.h.opcode = FUSE_LOOKUP;
116     req->in.h.ino = dir->i_ino;
117     req->in.numargs = 1;
118     req->in.args[0].size = entry->d_name.len + 1;
119     req->in.args[0].value = entry->d_name.name;
120     req->out.numargs = 1;
121     req->out.args[0].size = sizeof(struct fuse_entry_out);
122     req->out.args[0].value = outarg;
123     request_send(fc, req);
124     *version = req->out.h.unique;
125     return req->out.h.error;
126     }
127    
128     static int fuse_do_lookup(struct inode *dir, struct dentry *entry,
129     struct fuse_entry_out *outarg, int *version)
130     {
131     struct fuse_conn *fc = INO_FC(dir);
132     struct fuse_req *req;
133     int err;
134    
135     if (entry->d_name.len > FUSE_NAME_MAX)
136     return -ENAMETOOLONG;
137     req = fuse_get_request(fc);
138     if (!req)
139     return -ERESTARTSYS;
140    
141     err = fuse_send_lookup(fc, req, dir, entry, outarg, version);
142     fuse_put_request(fc, req);
143     return err;
144     }
145    
146     static inline unsigned long time_to_jiffies(unsigned long sec,
147     unsigned long nsec)
148     {
149     /* prevent wrapping of jiffies */
150     if (sec + 1 >= LONG_MAX / HZ)
151     return 0;
152    
153     return jiffies + sec * HZ + nsec / (1000000000 / HZ);
154     }
155    
156     static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
157     struct inode **inodep)
158     {
159     struct fuse_conn *fc = INO_FC(dir);
160     int err;
161     struct fuse_entry_out outarg;
162     int version;
163     struct inode *inode = NULL;
164     struct fuse_req *req;
165    
166     if (entry->d_name.len > FUSE_NAME_MAX)
167     return -ENAMETOOLONG;
168     req = fuse_get_request(fc);
169     if (!req)
170     return -ERESTARTSYS;
171    
172     err = fuse_send_lookup(fc, req, dir, entry, &outarg, &version);
173     if (!err) {
174     inode = fuse_iget(dir->i_sb, outarg.ino, outarg.generation,
175     &outarg.attr, version);
176     if (!inode) {
177     fuse_send_forget(fc, req, outarg.ino, version);
178     return -ENOMEM;
179     }
180     }
181     fuse_put_request(fc, req);
182     if (err && err != -ENOENT)
183     return err;
184    
185     if (inode) {
186     struct fuse_inode *fi = INO_FI(inode);
187     entry->d_time = time_to_jiffies(outarg.entry_valid,
188     outarg.entry_valid_nsec);
189     fi->i_time = time_to_jiffies(outarg.attr_valid,
190     outarg.attr_valid_nsec);
191     }
192    
193     entry->d_op = &fuse_dentry_operations;
194     *inodep = inode;
195     return 0;
196     }
197    
198     static void fuse_invalidate_attr(struct inode *inode)
199     {
200     struct fuse_inode *fi = INO_FI(inode);
201     fi->i_time = jiffies - 1;
202     }
203    
204     static int lookup_new_entry(struct fuse_conn *fc, struct fuse_req *req,
205     struct inode *dir, struct dentry *entry,
206     struct fuse_entry_out *outarg, int version,
207     int mode)
208     {
209     struct inode *inode;
210     struct fuse_inode *fi;
211     inode = fuse_iget(dir->i_sb, outarg->ino, outarg->generation,
212     &outarg->attr, version);
213     if (!inode) {
214     fuse_send_forget(fc, req, outarg->ino, version);
215     return -ENOMEM;
216     }
217     fuse_put_request(fc, req);
218    
219     /* Don't allow userspace to do really stupid things... */
220     if ((inode->i_mode ^ mode) & S_IFMT) {
221     iput(inode);
222     printk("fuse_mknod: inode has wrong type\n");
223     return -EINVAL;
224     }
225    
226     entry->d_time = time_to_jiffies(outarg->entry_valid,
227     outarg->entry_valid_nsec);
228    
229     fi = INO_FI(inode);
230     fi->i_time = time_to_jiffies(outarg->attr_valid,
231     outarg->attr_valid_nsec);
232    
233     d_instantiate(entry, inode);
234     fuse_invalidate_attr(dir);
235     return 0;
236     }
237    
238    
239     static int _fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
240     dev_t rdev)
241     {
242     struct fuse_conn *fc = INO_FC(dir);
243     struct fuse_req *req = fuse_get_request(fc);
244     struct fuse_mknod_in inarg;
245     struct fuse_entry_out outarg;
246     int err;
247    
248     if (!req)
249     return -ERESTARTSYS;
250    
251     memset(&inarg, 0, sizeof(inarg));
252     inarg.mode = mode;
253     inarg.rdev = new_encode_dev(rdev);
254     req->in.h.opcode = FUSE_MKNOD;
255     req->in.h.ino = dir->i_ino;
256     req->in.numargs = 2;
257     req->in.args[0].size = sizeof(inarg);
258     req->in.args[0].value = &inarg;
259     req->in.args[1].size = entry->d_name.len + 1;
260     req->in.args[1].value = entry->d_name.name;
261     req->out.numargs = 1;
262     req->out.args[0].size = sizeof(outarg);
263     req->out.args[0].value = &outarg;
264     request_send(fc, req);
265     err = req->out.h.error;
266     if (!err)
267     err = lookup_new_entry(fc, req, dir, entry, &outarg,
268     req->out.h.unique, mode);
269     else
270     fuse_put_request(fc, req);
271     return err;
272     }
273    
274     static int _fuse_create(struct inode *dir, struct dentry *entry, int mode)
275     {
276     return _fuse_mknod(dir, entry, mode, 0);
277     }
278    
279    
280     static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
281     {
282     struct fuse_conn *fc = INO_FC(dir);
283     struct fuse_req *req = fuse_get_request(fc);
284     struct fuse_mkdir_in inarg;
285     struct fuse_entry_out outarg;
286     int err;
287    
288     if (!req)
289     return -ERESTARTSYS;
290    
291     memset(&inarg, 0, sizeof(inarg));
292     inarg.mode = mode;
293     req->in.h.opcode = FUSE_MKDIR;
294     req->in.h.ino = dir->i_ino;
295     req->in.numargs = 2;
296     req->in.args[0].size = sizeof(inarg);
297     req->in.args[0].value = &inarg;
298     req->in.args[1].size = entry->d_name.len + 1;
299     req->in.args[1].value = entry->d_name.name;
300     req->out.numargs = 1;
301     req->out.args[0].size = sizeof(outarg);
302     req->out.args[0].value = &outarg;
303     request_send(fc, req);
304     err = req->out.h.error;
305     if (!err)
306     err = lookup_new_entry(fc, req, dir, entry, &outarg,
307     req->out.h.unique, S_IFDIR);
308     else
309     fuse_put_request(fc, req);
310     return err;
311     }
312    
313     static int fuse_symlink(struct inode *dir, struct dentry *entry,
314     const char *link)
315     {
316     struct fuse_conn *fc = INO_FC(dir);
317     struct fuse_req *req;
318     struct fuse_entry_out outarg;
319     unsigned int len = strlen(link) + 1;
320     int err;
321    
322     if (len > FUSE_SYMLINK_MAX)
323     return -ENAMETOOLONG;
324    
325     req = fuse_get_request(fc);
326     if (!req)
327     return -ERESTARTSYS;
328    
329     req->in.h.opcode = FUSE_SYMLINK;
330     req->in.h.ino = dir->i_ino;
331     req->in.numargs = 2;
332     req->in.args[0].size = entry->d_name.len + 1;
333     req->in.args[0].value = entry->d_name.name;
334     req->in.args[1].size = len;
335     req->in.args[1].value = link;
336     req->out.numargs = 1;
337     req->out.args[0].size = sizeof(outarg);
338     req->out.args[0].value = &outarg;
339     request_send(fc, req);
340     err = req->out.h.error;
341     if (!err)
342     err = lookup_new_entry(fc, req, dir, entry, &outarg,
343     req->out.h.unique, S_IFLNK);
344     else
345     fuse_put_request(fc, req);
346     return err;
347     }
348    
349     static int fuse_unlink(struct inode *dir, struct dentry *entry)
350     {
351     struct fuse_conn *fc = INO_FC(dir);
352     struct fuse_req *req = fuse_get_request(fc);
353     int err;
354    
355     if (!req)
356     return -ERESTARTSYS;
357    
358     req->in.h.opcode = FUSE_UNLINK;
359     req->in.h.ino = dir->i_ino;
360     req->in.numargs = 1;
361     req->in.args[0].size = entry->d_name.len + 1;
362     req->in.args[0].value = entry->d_name.name;
363     request_send(fc, req);
364     err = req->out.h.error;
365     if (!err) {
366     struct inode *inode = entry->d_inode;
367    
368     /* Set nlink to zero so the inode can be cleared, if
369     the inode does have more links this will be
370     discovered at the next lookup/getattr */
371     inode->i_nlink = 0;
372     fuse_invalidate_attr(inode);
373     fuse_invalidate_attr(dir);
374     }
375     fuse_put_request(fc, req);
376     return err;
377     }
378    
379     static int fuse_rmdir(struct inode *dir, struct dentry *entry)
380     {
381     struct fuse_conn *fc = INO_FC(dir);
382     struct fuse_req *req = fuse_get_request(fc);
383     int err;
384    
385     if (!req)
386     return -ERESTARTSYS;
387    
388     req->in.h.opcode = FUSE_RMDIR;
389     req->in.h.ino = dir->i_ino;
390     req->in.numargs = 1;
391     req->in.args[0].size = entry->d_name.len + 1;
392     req->in.args[0].value = entry->d_name.name;
393     request_send(fc, req);
394     err = req->out.h.error;
395     if (!err) {
396     entry->d_inode->i_nlink = 0;
397     fuse_invalidate_attr(dir);
398     }
399     fuse_put_request(fc, req);
400     return err;
401     }
402    
403     static int fuse_rename(struct inode *olddir, struct dentry *oldent,
404     struct inode *newdir, struct dentry *newent)
405     {
406     struct fuse_conn *fc = INO_FC(olddir);
407     struct fuse_req *req = fuse_get_request(fc);
408     struct fuse_rename_in inarg;
409     int err;
410    
411     if (!req)
412     return -ERESTARTSYS;
413    
414     memset(&inarg, 0, sizeof(inarg));
415     inarg.newdir = newdir->i_ino;
416     req->in.h.opcode = FUSE_RENAME;
417     req->in.h.ino = olddir->i_ino;
418     req->in.numargs = 3;
419     req->in.args[0].size = sizeof(inarg);
420     req->in.args[0].value = &inarg;
421     req->in.args[1].size = oldent->d_name.len + 1;
422     req->in.args[1].value = oldent->d_name.name;
423     req->in.args[2].size = newent->d_name.len + 1;
424     req->in.args[2].value = newent->d_name.name;
425     request_send(fc, req);
426     err = req->out.h.error;
427     fuse_put_request(fc, req);
428     if (!err) {
429     fuse_invalidate_attr(olddir);
430     if (olddir != newdir)
431     fuse_invalidate_attr(newdir);
432     }
433     return err;
434     }
435    
436     static int fuse_link(struct dentry *entry, struct inode *newdir,
437     struct dentry *newent)
438     {
439     struct inode *inode = entry->d_inode;
440     struct fuse_conn *fc = INO_FC(inode);
441     struct fuse_req *req = fuse_get_request(fc);
442     struct fuse_link_in inarg;
443     struct fuse_entry_out outarg;
444     int err;
445    
446     if (!req)
447     return -ERESTARTSYS;
448    
449     memset(&inarg, 0, sizeof(inarg));
450     inarg.newdir = newdir->i_ino;
451     req->in.h.opcode = FUSE_LINK;
452     req->in.h.ino = inode->i_ino;
453     req->in.numargs = 2;
454     req->in.args[0].size = sizeof(inarg);
455     req->in.args[0].value = &inarg;
456     req->in.args[1].size = newent->d_name.len + 1;
457     req->in.args[1].value = newent->d_name.name;
458     req->out.numargs = 1;
459     req->out.args[0].size = sizeof(outarg);
460     req->out.args[0].value = &outarg;
461     request_send(fc, req);
462     err = req->out.h.error;
463     if (!err) {
464     /* Invalidate old entry, so attributes are refreshed */
465     d_invalidate(entry);
466     err = lookup_new_entry(fc, req, newdir, newent, &outarg,
467     req->out.h.unique, inode->i_mode);
468     } else
469     fuse_put_request(fc, req);
470     return err;
471     }
472    
473     int fuse_do_getattr(struct inode *inode)
474     {
475     struct fuse_inode *fi = INO_FI(inode);
476     struct fuse_conn *fc = INO_FC(inode);
477     struct fuse_req *req = fuse_get_request(fc);
478     struct fuse_attr_out arg;
479     int err;
480    
481     if (!req)
482     return -ERESTARTSYS;
483    
484     req->in.h.opcode = FUSE_GETATTR;
485     req->in.h.ino = inode->i_ino;
486     req->out.numargs = 1;
487     req->out.args[0].size = sizeof(arg);
488     req->out.args[0].value = &arg;
489     request_send(fc, req);
490     err = req->out.h.error;
491     if (!err) {
492     change_attributes(inode, &arg.attr);
493     fi->i_time = time_to_jiffies(arg.attr_valid,
494     arg.attr_valid_nsec);
495     }
496     fuse_put_request(fc, req);
497     return err;
498     }
499    
500     static int fuse_revalidate(struct dentry *entry)
501     {
502     struct inode *inode = entry->d_inode;
503     struct fuse_inode *fi = INO_FI(inode);
504     struct fuse_conn *fc = INO_FC(inode);
505    
506     if (inode->i_ino == FUSE_ROOT_INO) {
507     if (!(fc->flags & FUSE_ALLOW_OTHER) &&
508     current->fsuid != fc->uid)
509     return -EACCES;
510     } else if (!fi->i_time || time_before_eq(jiffies, fi->i_time))
511     return 0;
512    
513     return fuse_do_getattr(inode);
514     }
515    
516     static int _fuse_permission(struct inode *inode, int mask)
517     {
518     struct fuse_conn *fc = INO_FC(inode);
519    
520     if (!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->uid)
521     return -EACCES;
522     else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
523     int err = vfs_permission(inode, mask);
524    
525     /* If permission is denied, try to refresh file
526     attributes. This is also needed, because the root
527     node will at first have no permissions */
528    
529     if (err == -EACCES) {
530     err = fuse_do_getattr(inode);
531     if (!err)
532     err = vfs_permission(inode, mask);
533     }
534    
535     /* FIXME: Need some mechanism to revoke permissions:
536     currently if the filesystem suddenly changes the
537     file mode, we will not be informed abot that, and
538     continue to allow access to the file/directory.
539    
540     This is actually not so grave, since the user can
541     simply keep access to the file/directory anyway by
542     keeping it open... */
543    
544     return err;
545     } else
546     return 0;
547     }
548    
549     static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
550     void *dstbuf, filldir_t filldir)
551     {
552     while (nbytes >= FUSE_NAME_OFFSET) {
553     struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
554     size_t reclen = FUSE_DIRENT_SIZE(dirent);
555     int over;
556     if (dirent->namelen > NAME_MAX) {
557     printk("fuse_readdir: name too long\n");
558     return -EPROTO;
559     }
560     if (reclen > nbytes)
561     break;
562    
563     over = filldir(dstbuf, dirent->name, dirent->namelen,
564     file->f_pos, dirent->ino, dirent->type);
565     if (over)
566     break;
567    
568     buf += reclen;
569     file->f_pos += reclen;
570     nbytes -= reclen;
571     }
572    
573     return 0;
574     }
575    
576     static int fuse_checkdir(struct file *cfile, struct file *file)
577     {
578     struct inode *inode;
579     if (!cfile) {
580     printk("fuse_getdir: invalid file\n");
581     return -EPROTO;
582     }
583     inode = cfile->f_dentry->d_inode;
584     if (!S_ISREG(inode->i_mode)) {
585     printk("fuse_getdir: not a regular file\n");
586     fput(cfile);
587     return -EPROTO;
588     }
589    
590     file->private_data = cfile;
591     return 0;
592     }
593    
594     static int fuse_getdir(struct file *file)
595     {
596     struct inode *inode = file->f_dentry->d_inode;
597     struct fuse_conn *fc = INO_FC(inode);
598     struct fuse_req *req = fuse_get_request(fc);
599     struct fuse_getdir_out_i outarg;
600     int err;
601    
602     if (!req)
603     return -ERESTARTSYS;
604    
605     req->in.h.opcode = FUSE_GETDIR;
606     req->in.h.ino = inode->i_ino;
607     req->out.numargs = 1;
608     req->out.args[0].size = sizeof(struct fuse_getdir_out);
609     req->out.args[0].value = &outarg;
610     request_send(fc, req);
611     err = req->out.h.error;
612     if (!err)
613     err = fuse_checkdir(outarg.file, file);
614     fuse_put_request(fc, req);
615     return err;
616     }
617    
618     #define DIR_BUFSIZE 2048
619     static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
620     {
621     struct file *cfile = file->private_data;
622     char *buf;
623     int ret;
624    
625     if (!cfile) {
626     ret = fuse_getdir(file);
627     if (ret)
628     return ret;
629    
630     cfile = file->private_data;
631     }
632    
633     buf = kmalloc(DIR_BUFSIZE, GFP_KERNEL);
634     if (!buf)
635     return -ENOMEM;
636    
637     ret = kernel_read(cfile, file->f_pos, buf, DIR_BUFSIZE);
638     if (ret < 0)
639     printk("fuse_readdir: failed to read container file\n");
640     else
641     ret = parse_dirfile(buf, ret, file, dstbuf, filldir);
642    
643     kfree(buf);
644     return ret;
645     }
646    
647     static char *read_link(struct dentry *dentry)
648     {
649     struct inode *inode = dentry->d_inode;
650     struct fuse_conn *fc = INO_FC(inode);
651     struct fuse_req *req = fuse_get_request(fc);
652     char *link;
653    
654     if (!req)
655     return ERR_PTR(-ERESTARTSYS);
656    
657     link = (char *) __get_free_page(GFP_KERNEL);
658     if (!link) {
659     link = ERR_PTR(-ENOMEM);
660     goto out;
661     }
662     req->in.h.opcode = FUSE_READLINK;
663     req->in.h.ino = inode->i_ino;
664     req->out.argvar = 1;
665     req->out.numargs = 1;
666     req->out.args[0].size = PAGE_SIZE - 1;
667     req->out.args[0].value = link;
668     request_send(fc, req);
669     if (req->out.h.error) {
670     free_page((unsigned long) link);
671     link = ERR_PTR(req->out.h.error);
672     } else
673     link[req->out.args[0].size] = '\0';
674     out:
675     fuse_put_request(fc, req);
676     return link;
677     }
678    
679     static void free_link(char *link)
680     {
681     if (!IS_ERR(link))
682     free_page((unsigned long) link);
683     }
684    
685     static int fuse_readlink(struct dentry *dentry, char *buffer, int buflen)
686     {
687     int ret;
688     char *link;
689    
690     link = read_link(dentry);
691     ret = vfs_readlink(dentry, buffer, buflen, link);
692     free_link(link);
693     return ret;
694     }
695    
696     static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
697     {
698     int ret;
699     char *link;
700    
701     link = read_link(dentry);
702     ret = vfs_follow_link(nd, link);
703     free_link(link);
704     return ret;
705     }
706    
707     static int fuse_dir_open(struct inode *inode, struct file *file)
708     {
709     file->private_data = NULL;
710     return 0;
711     }
712    
713     static int fuse_dir_release(struct inode *inode, struct file *file)
714     {
715     struct file *cfile = file->private_data;
716    
717     if (cfile)
718     fput(cfile);
719    
720     return 0;
721     }
722    
723     static unsigned int iattr_to_fattr(struct iattr *iattr,
724     struct fuse_attr *fattr)
725     {
726     unsigned int ivalid = iattr->ia_valid;
727     unsigned int fvalid = 0;
728    
729     memset(fattr, 0, sizeof(*fattr));
730    
731     if (ivalid & ATTR_MODE)
732     fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode;
733     if (ivalid & ATTR_UID)
734     fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid;
735     if (ivalid & ATTR_GID)
736     fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid;
737     if (ivalid & ATTR_SIZE)
738     fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size;
739     /* You can only _set_ these together (they may change by themselves) */
740     if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
741     fvalid |= FATTR_ATIME | FATTR_MTIME;
742     #ifdef KERNEL_2_6
743     fattr->atime = iattr->ia_atime.tv_sec;
744     fattr->mtime = iattr->ia_mtime.tv_sec;
745     #else
746     fattr->atime = iattr->ia_atime;
747     fattr->mtime = iattr->ia_mtime;
748     #endif
749     }
750    
751     return fvalid;
752     }
753    
754     static int fuse_setattr(struct dentry *entry, struct iattr *attr)
755     {
756     struct inode *inode = entry->d_inode;
757     struct fuse_conn *fc = INO_FC(inode);
758     struct fuse_inode *fi = INO_FI(inode);
759     struct fuse_req *req;
760     struct fuse_setattr_in inarg;
761     struct fuse_attr_out outarg;
762     int err;
763     int is_truncate = 0;
764    
765     if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
766     err = inode_change_ok(inode, attr);
767     if (err)
768     return err;
769     }
770    
771     if (attr->ia_valid & ATTR_SIZE) {
772     unsigned long limit;
773     is_truncate = 1;
774    
775     limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
776     if (limit != RLIM_INFINITY && attr->ia_size > limit) {
777     send_sig(SIGXFSZ, current, 0);
778     return -EFBIG;
779     }
780     //fuse_sync_inode(inode);
781     }
782    
783     req = fuse_get_request(fc);
784     if (!req)
785     return -ERESTARTSYS;
786    
787     if (is_truncate)
788     down_write(&fi->write_sem);
789    
790     memset(&inarg, 0, sizeof(inarg));
791     inarg.valid = iattr_to_fattr(attr, &inarg.attr);
792     req->in.h.opcode = FUSE_SETATTR;
793     req->in.h.ino = inode->i_ino;
794     req->in.numargs = 1;
795     req->in.args[0].size = sizeof(inarg);
796     req->in.args[0].value = &inarg;
797     req->out.numargs = 1;
798     req->out.args[0].size = sizeof(outarg);
799     req->out.args[0].value = &outarg;
800     request_send(fc, req);
801     err = req->out.h.error;
802     fuse_put_request(fc, req);
803    
804     if (!err) {
805     if (is_truncate) {
806     loff_t origsize = i_size_read(inode);
807     i_size_write(inode, outarg.attr.size);
808     up_write(&fi->write_sem);
809     if (origsize > outarg.attr.size)
810     vmtruncate(inode, outarg.attr.size);
811     }
812     change_attributes(inode, &outarg.attr);
813     fi->i_time = time_to_jiffies(outarg.attr_valid,
814     outarg.attr_valid_nsec);
815     } else if (is_truncate)
816     up_write(&fi->write_sem);
817    
818     return err;
819     }
820    
821     static int _fuse_dentry_revalidate(struct dentry *entry)
822     {
823     if (!entry->d_inode)
824     return 0;
825     else if (entry->d_time && time_after(jiffies, entry->d_time)) {
826     struct inode *inode = entry->d_inode;
827     struct fuse_inode *fi = INO_FI(inode);
828     struct fuse_entry_out outarg;
829     int version;
830     int ret;
831    
832     ret = fuse_do_lookup(entry->d_parent->d_inode, entry, &outarg,
833     &version);
834     if (ret)
835     return 0;
836    
837     if (outarg.ino != inode->i_ino)
838     return 0;
839    
840     change_attributes(inode, &outarg.attr);
841     inode->i_version = version;
842     entry->d_time = time_to_jiffies(outarg.entry_valid,
843     outarg.entry_valid_nsec);
844     fi->i_time = time_to_jiffies(outarg.attr_valid,
845     outarg.attr_valid_nsec);
846     }
847     return 1;
848     }
849    
850     #ifdef KERNEL_2_6
851    
852     #define fuse_mknod _fuse_mknod
853    
854     static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
855     struct kstat *stat)
856     {
857     struct inode *inode = entry->d_inode;
858     int err = fuse_revalidate(entry);
859     if (!err)
860     generic_fillattr(inode, stat);
861    
862     return err;
863     }
864    
865     static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
866     struct nameidata *nd)
867     {
868     struct inode *inode;
869     int err = fuse_lookup_iget(dir, entry, &inode);
870     if (err)
871     return ERR_PTR(err);
872     return d_splice_alias(inode, entry);
873     }
874    
875     static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
876     struct nameidata *nd)
877     {
878     return _fuse_create(dir, entry, mode);
879     }
880    
881     static int fuse_permission(struct inode *inode, int mask,
882     struct nameidata *nd)
883     {
884     return _fuse_permission(inode, mask);
885     }
886    
887     static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
888     {
889     return _fuse_dentry_revalidate(entry);
890     }
891    
892     #else /* KERNEL_2_6 */
893    
894     #define fuse_create _fuse_create
895     #define fuse_permission _fuse_permission
896    
897     static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry)
898     {
899     struct inode *inode;
900     struct dentry *alias;
901    
902     int err = fuse_lookup_iget(dir, entry, &inode);
903     if (err)
904     return ERR_PTR(err);
905    
906     if (inode && S_ISDIR(inode->i_mode) &&
907     (alias = d_find_alias(inode)) != NULL) {
908     dput(alias);
909     iput(inode);
910     printk("fuse: cannot assign an existing directory\n");
911     return ERR_PTR(-EPROTO);
912     }
913    
914     d_add(entry, inode);
915     return NULL;
916     }
917    
918     static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
919     int rdev)
920     {
921     return _fuse_mknod(dir, entry, mode, rdev);
922     }
923    
924     static int fuse_dentry_revalidate(struct dentry *entry, int flags)
925     {
926     return _fuse_dentry_revalidate(entry);
927     }
928     #endif /* KERNEL_2_6 */
929    
930     #ifdef HAVE_KERNEL_XATTR
931    
932     #ifdef KERNEL_2_6
933     static int fuse_setxattr(struct dentry *entry, const char *name,
934     const void *value, size_t size, int flags)
935     #else
936     static int fuse_setxattr(struct dentry *entry, const char *name,
937     void *value, size_t size, int flags)
938     #endif
939     {
940     struct inode *inode = entry->d_inode;
941     struct fuse_conn *fc = INO_FC(inode);
942     struct fuse_req *req;
943     struct fuse_setxattr_in inarg;
944     int err;
945    
946     if (size > FUSE_XATTR_SIZE_MAX)
947     return -E2BIG;
948    
949     if (fc->no_setxattr)
950     return -EOPNOTSUPP;
951    
952     req = fuse_get_request(fc);
953     if (!req)
954     return -ERESTARTSYS;
955    
956     memset(&inarg, 0, sizeof(inarg));
957     inarg.size = size;
958     inarg.flags = flags;
959     req->in.h.opcode = FUSE_SETXATTR;
960     req->in.h.ino = inode->i_ino;
961     req->in.numargs = 3;
962     req->in.args[0].size = sizeof(inarg);
963     req->in.args[0].value = &inarg;
964     req->in.args[1].size = strlen(name) + 1;
965     req->in.args[1].value = name;
966     req->in.args[2].size = size;
967     req->in.args[2].value = value;
968     request_send(fc, req);
969     err = req->out.h.error;
970     if (err == -ENOSYS) {
971     fc->no_setxattr = 1;
972     err = -EOPNOTSUPP;
973     }
974     fuse_put_request(fc, req);
975     return err;
976     }
977    
978     static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
979     void *value, size_t size)
980     {
981     struct inode *inode = entry->d_inode;
982     struct fuse_conn *fc = INO_FC(inode);
983     struct fuse_req *req;
984     struct fuse_getxattr_in inarg;
985     struct fuse_getxattr_out outarg;
986     ssize_t ret;
987    
988     if (fc->no_getxattr)
989     return -EOPNOTSUPP;
990    
991     req = fuse_get_request(fc);
992     if (!req)
993     return -ERESTARTSYS;
994    
995     memset(&inarg, 0, sizeof(inarg));
996     inarg.size = size;
997     req->in.h.opcode = FUSE_GETXATTR;
998     req->in.h.ino = inode->i_ino;
999     req->in.numargs = 2;
1000     req->in.args[0].size = sizeof(inarg);
1001     req->in.args[0].value = &inarg;
1002     req->in.args[1].size = strlen(name) + 1;
1003     req->in.args[1].value = name;
1004     /* This is really two different operations rolled into one */
1005     req->out.numargs = 1;
1006     if (size) {
1007     req->out.argvar = 1;
1008     req->out.args[0].size = size;
1009     req->out.args[0].value = value;
1010     } else {
1011     req->out.args[0].size = sizeof(outarg);
1012     req->out.args[0].value = &outarg;
1013     }
1014     request_send(fc, req);
1015     ret = req->out.h.error;
1016     if (!ret)
1017     ret = size ? req->out.args[0].size : outarg.size;
1018     else {
1019     if (ret == -ENOSYS) {
1020     fc->no_getxattr = 1;
1021     ret = -EOPNOTSUPP;
1022     }
1023     }
1024     fuse_put_request(fc, req);
1025     return ret;
1026     }
1027    
1028     static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
1029     {
1030     struct inode *inode = entry->d_inode;
1031     struct fuse_conn *fc = INO_FC(inode);
1032     struct fuse_req *req;
1033     struct fuse_getxattr_in inarg;
1034     struct fuse_getxattr_out outarg;
1035     ssize_t ret;
1036    
1037     if (fc->no_listxattr)
1038     return -EOPNOTSUPP;
1039    
1040     req = fuse_get_request(fc);
1041     if (!req)
1042     return -ERESTARTSYS;
1043    
1044     memset(&inarg, 0, sizeof(inarg));
1045     inarg.size = size;
1046     req->in.h.opcode = FUSE_LISTXATTR;
1047     req->in.h.ino = inode->i_ino;
1048     req->in.numargs = 1;
1049     req->in.args[0].size = sizeof(inarg);
1050     req->in.args[0].value = &inarg;
1051     /* This is really two different operations rolled into one */
1052     req->out.numargs = 1;
1053     if (size) {
1054     req->out.argvar = 1;
1055     req->out.args[0].size = size;
1056     req->out.args[0].value = list;
1057     } else {
1058     req->out.args[0].size = sizeof(outarg);
1059     req->out.args[0].value = &outarg;
1060     }
1061     request_send(fc, req);
1062     ret = req->out.h.error;
1063     if (!ret)
1064     ret = size ? req->out.args[0].size : outarg.size;
1065     else {
1066     if (ret == -ENOSYS) {
1067     fc->no_listxattr = 1;
1068     ret = -EOPNOTSUPP;
1069     }
1070     }
1071     fuse_put_request(fc, req);
1072     return ret;
1073     }
1074    
1075     static int fuse_removexattr(struct dentry *entry, const char *name)
1076     {
1077     struct inode *inode = entry->d_inode;
1078     struct fuse_conn *fc = INO_FC(inode);
1079     struct fuse_req *req;
1080     int err;
1081    
1082     if (fc->no_removexattr)
1083     return -EOPNOTSUPP;
1084    
1085     req = fuse_get_request(fc);
1086     if (!req)
1087     return -ERESTARTSYS;
1088    
1089     req->in.h.opcode = FUSE_REMOVEXATTR;
1090     req->in.h.ino = inode->i_ino;
1091     req->in.numargs = 1;
1092     req->in.args[0].size = strlen(name) + 1;
1093     req->in.args[0].value = name;
1094     request_send(fc, req);
1095     err = req->out.h.error;
1096     if (err == -ENOSYS) {
1097     fc->no_removexattr = 1;
1098     err = -EOPNOTSUPP;
1099     }
1100     fuse_put_request(fc, req);
1101     return err;
1102     }
1103    
1104     #endif
1105    
1106     static struct inode_operations fuse_dir_inode_operations =
1107     {
1108     .lookup = fuse_lookup,
1109     .create = fuse_create,
1110     .mknod = fuse_mknod,
1111     .mkdir = fuse_mkdir,
1112     .symlink = fuse_symlink,
1113     .unlink = fuse_unlink,
1114     .rmdir = fuse_rmdir,
1115     .rename = fuse_rename,
1116     .link = fuse_link,
1117     .setattr = fuse_setattr,
1118     .permission = fuse_permission,
1119     #ifdef KERNEL_2_6
1120     .getattr = fuse_getattr,
1121     #else
1122     .revalidate = fuse_revalidate,
1123     #endif
1124     #ifdef HAVE_KERNEL_XATTR
1125     .setxattr = fuse_setxattr,
1126     .getxattr = fuse_getxattr,
1127     .listxattr = fuse_listxattr,
1128     .removexattr = fuse_removexattr,
1129     #endif
1130     };
1131    
1132     static struct file_operations fuse_dir_operations = {
1133     .read = generic_read_dir,
1134     .readdir = fuse_readdir,
1135     .open = fuse_dir_open,
1136     .release = fuse_dir_release,
1137     };
1138    
1139     static struct inode_operations fuse_file_inode_operations = {
1140     .setattr = fuse_setattr,
1141     .permission = fuse_permission,
1142     #ifdef KERNEL_2_6
1143     .getattr = fuse_getattr,
1144     #else
1145     .revalidate = fuse_revalidate,
1146     #endif
1147     #ifdef HAVE_KERNEL_XATTR
1148     .setxattr = fuse_setxattr,
1149     .getxattr = fuse_getxattr,
1150     .listxattr = fuse_listxattr,
1151     .removexattr = fuse_removexattr,
1152     #endif
1153     };
1154    
1155     static struct inode_operations fuse_symlink_inode_operations =
1156     {
1157     .setattr = fuse_setattr,
1158     .readlink = fuse_readlink,
1159     .follow_link = fuse_follow_link,
1160     #ifdef KERNEL_2_6
1161     .getattr = fuse_getattr,
1162     #else
1163     .revalidate = fuse_revalidate,
1164     #endif
1165     #ifdef HAVE_KERNEL_XATTR
1166     .setxattr = fuse_setxattr,
1167     .getxattr = fuse_getxattr,
1168     .listxattr = fuse_listxattr,
1169     .removexattr = fuse_removexattr,
1170     #endif
1171     };
1172    
1173     static struct dentry_operations fuse_dentry_operations = {
1174     .d_revalidate = fuse_dentry_revalidate,
1175     };
1176    
1177     /*
1178     * Local Variables:
1179     * indent-tabs-mode: t
1180     * c-basic-offset: 8
1181     * End:
1182     */

  ViewVC Help
Powered by ViewVC 1.1.26