1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
27
28#include <linux/module.h>
29#include <linux/errno.h>
30#include <linux/fs.h>
31#include <linux/file.h>
32#include <linux/pagemap.h>
33#include <linux/stat.h>
34#include <linux/string.h>
35#include <linux/inet.h>
36#include <linux/namei.h>
37#include <linux/idr.h>
38#include <linux/sched.h>
39#include <linux/slab.h>
40#include <linux/xattr.h>
41#include <linux/posix_acl.h>
42#include <net/9p/9p.h>
43#include <net/9p/client.h>
44
45#include "v9fs.h"
46#include "v9fs_vfs.h"
47#include "fid.h"
48#include "cache.h"
49#include "xattr.h"
50#include "acl.h"
51
52static const struct inode_operations v9fs_dir_inode_operations;
53static const struct inode_operations v9fs_dir_inode_operations_dotu;
54static const struct inode_operations v9fs_file_inode_operations;
55static const struct inode_operations v9fs_symlink_inode_operations;
56
57
58
59
60
61
62
63
64static u32 unixmode2p9mode(struct v9fs_session_info *v9ses, umode_t mode)
65{
66 int res;
67 res = mode & 0777;
68 if (S_ISDIR(mode))
69 res |= P9_DMDIR;
70 if (v9fs_proto_dotu(v9ses)) {
71 if (v9ses->nodev == 0) {
72 if (S_ISSOCK(mode))
73 res |= P9_DMSOCKET;
74 if (S_ISFIFO(mode))
75 res |= P9_DMNAMEDPIPE;
76 if (S_ISBLK(mode))
77 res |= P9_DMDEVICE;
78 if (S_ISCHR(mode))
79 res |= P9_DMDEVICE;
80 }
81
82 if ((mode & S_ISUID) == S_ISUID)
83 res |= P9_DMSETUID;
84 if ((mode & S_ISGID) == S_ISGID)
85 res |= P9_DMSETGID;
86 if ((mode & S_ISVTX) == S_ISVTX)
87 res |= P9_DMSETVTX;
88 }
89 return res;
90}
91
92
93
94
95
96
97
98static int p9mode2perm(struct v9fs_session_info *v9ses,
99 struct p9_wstat *stat)
100{
101 int res;
102 int mode = stat->mode;
103
104 res = mode & S_IALLUGO;
105 if (v9fs_proto_dotu(v9ses)) {
106 if ((mode & P9_DMSETUID) == P9_DMSETUID)
107 res |= S_ISUID;
108
109 if ((mode & P9_DMSETGID) == P9_DMSETGID)
110 res |= S_ISGID;
111
112 if ((mode & P9_DMSETVTX) == P9_DMSETVTX)
113 res |= S_ISVTX;
114 }
115 return res;
116}
117
118
119
120
121
122
123
124
125static umode_t p9mode2unixmode(struct v9fs_session_info *v9ses,
126 struct p9_wstat *stat, dev_t *rdev)
127{
128 int res;
129 u32 mode = stat->mode;
130
131 *rdev = 0;
132 res = p9mode2perm(v9ses, stat);
133
134 if ((mode & P9_DMDIR) == P9_DMDIR)
135 res |= S_IFDIR;
136 else if ((mode & P9_DMSYMLINK) && (v9fs_proto_dotu(v9ses)))
137 res |= S_IFLNK;
138 else if ((mode & P9_DMSOCKET) && (v9fs_proto_dotu(v9ses))
139 && (v9ses->nodev == 0))
140 res |= S_IFSOCK;
141 else if ((mode & P9_DMNAMEDPIPE) && (v9fs_proto_dotu(v9ses))
142 && (v9ses->nodev == 0))
143 res |= S_IFIFO;
144 else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses))
145 && (v9ses->nodev == 0)) {
146 char type = 0, ext[32];
147 int major = -1, minor = -1;
148
149 strlcpy(ext, stat->extension, sizeof(ext));
150 sscanf(ext, "%c %u %u", &type, &major, &minor);
151 switch (type) {
152 case 'c':
153 res |= S_IFCHR;
154 break;
155 case 'b':
156 res |= S_IFBLK;
157 break;
158 default:
159 p9_debug(P9_DEBUG_ERROR, "Unknown special type %c %s\n",
160 type, stat->extension);
161 };
162 *rdev = MKDEV(major, minor);
163 } else
164 res |= S_IFREG;
165
166 return res;
167}
168
169
170
171
172
173
174
175int v9fs_uflags2omode(int uflags, int extended)
176{
177 int ret;
178
179 ret = 0;
180 switch (uflags&3) {
181 default:
182 case O_RDONLY:
183 ret = P9_OREAD;
184 break;
185
186 case O_WRONLY:
187 ret = P9_OWRITE;
188 break;
189
190 case O_RDWR:
191 ret = P9_ORDWR;
192 break;
193 }
194
195 if (extended) {
196 if (uflags & O_EXCL)
197 ret |= P9_OEXCL;
198
199 if (uflags & O_APPEND)
200 ret |= P9_OAPPEND;
201 }
202
203 return ret;
204}
205
206
207
208
209
210
211
212void
213v9fs_blank_wstat(struct p9_wstat *wstat)
214{
215 wstat->type = ~0;
216 wstat->dev = ~0;
217 wstat->qid.type = ~0;
218 wstat->qid.version = ~0;
219 *((long long *)&wstat->qid.path) = ~0;
220 wstat->mode = ~0;
221 wstat->atime = ~0;
222 wstat->mtime = ~0;
223 wstat->length = ~0;
224 wstat->name = NULL;
225 wstat->uid = NULL;
226 wstat->gid = NULL;
227 wstat->muid = NULL;
228 wstat->n_uid = INVALID_UID;
229 wstat->n_gid = INVALID_GID;
230 wstat->n_muid = INVALID_UID;
231 wstat->extension = NULL;
232}
233
234
235
236
237
238struct inode *v9fs_alloc_inode(struct super_block *sb)
239{
240 struct v9fs_inode *v9inode;
241 v9inode = (struct v9fs_inode *)kmem_cache_alloc(v9fs_inode_cache,
242 GFP_KERNEL);
243 if (!v9inode)
244 return NULL;
245#ifdef CONFIG_9P_FSCACHE
246 v9inode->fscache = NULL;
247 spin_lock_init(&v9inode->fscache_lock);
248#endif
249 v9inode->writeback_fid = NULL;
250 v9inode->cache_validity = 0;
251 mutex_init(&v9inode->v_mutex);
252 return &v9inode->vfs_inode;
253}
254
255
256
257
258
259
260static void v9fs_i_callback(struct rcu_head *head)
261{
262 struct inode *inode = container_of(head, struct inode, i_rcu);
263 kmem_cache_free(v9fs_inode_cache, V9FS_I(inode));
264}
265
266void v9fs_destroy_inode(struct inode *inode)
267{
268 call_rcu(&inode->i_rcu, v9fs_i_callback);
269}
270
271int v9fs_init_inode(struct v9fs_session_info *v9ses,
272 struct inode *inode, umode_t mode, dev_t rdev)
273{
274 int err = 0;
275
276 inode_init_owner(inode, NULL, mode);
277 inode->i_blocks = 0;
278 inode->i_rdev = rdev;
279 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
280 inode->i_mapping->a_ops = &v9fs_addr_operations;
281
282 switch (mode & S_IFMT) {
283 case S_IFIFO:
284 case S_IFBLK:
285 case S_IFCHR:
286 case S_IFSOCK:
287 if (v9fs_proto_dotl(v9ses)) {
288 inode->i_op = &v9fs_file_inode_operations_dotl;
289 } else if (v9fs_proto_dotu(v9ses)) {
290 inode->i_op = &v9fs_file_inode_operations;
291 } else {
292 p9_debug(P9_DEBUG_ERROR,
293 "special files without extended mode\n");
294 err = -EINVAL;
295 goto error;
296 }
297 init_special_inode(inode, inode->i_mode, inode->i_rdev);
298 break;
299 case S_IFREG:
300 if (v9fs_proto_dotl(v9ses)) {
301 inode->i_op = &v9fs_file_inode_operations_dotl;
302 if (v9ses->cache)
303 inode->i_fop =
304 &v9fs_cached_file_operations_dotl;
305 else
306 inode->i_fop = &v9fs_file_operations_dotl;
307 } else {
308 inode->i_op = &v9fs_file_inode_operations;
309 if (v9ses->cache)
310 inode->i_fop = &v9fs_cached_file_operations;
311 else
312 inode->i_fop = &v9fs_file_operations;
313 }
314
315 break;
316 case S_IFLNK:
317 if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) {
318 p9_debug(P9_DEBUG_ERROR,
319 "extended modes used with legacy protocol\n");
320 err = -EINVAL;
321 goto error;
322 }
323
324 if (v9fs_proto_dotl(v9ses))
325 inode->i_op = &v9fs_symlink_inode_operations_dotl;
326 else
327 inode->i_op = &v9fs_symlink_inode_operations;
328
329 break;
330 case S_IFDIR:
331 inc_nlink(inode);
332 if (v9fs_proto_dotl(v9ses))
333 inode->i_op = &v9fs_dir_inode_operations_dotl;
334 else if (v9fs_proto_dotu(v9ses))
335 inode->i_op = &v9fs_dir_inode_operations_dotu;
336 else
337 inode->i_op = &v9fs_dir_inode_operations;
338
339 if (v9fs_proto_dotl(v9ses))
340 inode->i_fop = &v9fs_dir_operations_dotl;
341 else
342 inode->i_fop = &v9fs_dir_operations;
343
344 break;
345 default:
346 p9_debug(P9_DEBUG_ERROR, "BAD mode 0x%hx S_IFMT 0x%x\n",
347 mode, mode & S_IFMT);
348 err = -EINVAL;
349 goto error;
350 }
351error:
352 return err;
353
354}
355
356
357
358
359
360
361
362
363struct inode *v9fs_get_inode(struct super_block *sb, umode_t mode, dev_t rdev)
364{
365 int err;
366 struct inode *inode;
367 struct v9fs_session_info *v9ses = sb->s_fs_info;
368
369 p9_debug(P9_DEBUG_VFS, "super block: %p mode: %ho\n", sb, mode);
370
371 inode = new_inode(sb);
372 if (!inode) {
373 pr_warn("%s (%d): Problem allocating inode\n",
374 __func__, task_pid_nr(current));
375 return ERR_PTR(-ENOMEM);
376 }
377 err = v9fs_init_inode(v9ses, inode, mode, rdev);
378 if (err) {
379 iput(inode);
380 return ERR_PTR(err);
381 }
382 return inode;
383}
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443void v9fs_evict_inode(struct inode *inode)
444{
445 struct v9fs_inode *v9inode = V9FS_I(inode);
446
447 truncate_inode_pages(inode->i_mapping, 0);
448 clear_inode(inode);
449 filemap_fdatawrite(inode->i_mapping);
450
451 v9fs_cache_inode_put_cookie(inode);
452
453 if (v9inode->writeback_fid) {
454 p9_client_clunk(v9inode->writeback_fid);
455 v9inode->writeback_fid = NULL;
456 }
457}
458
459static int v9fs_test_inode(struct inode *inode, void *data)
460{
461 int umode;
462 dev_t rdev;
463 struct v9fs_inode *v9inode = V9FS_I(inode);
464 struct p9_wstat *st = (struct p9_wstat *)data;
465 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
466
467 umode = p9mode2unixmode(v9ses, st, &rdev);
468
469 if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
470 return 0;
471
472
473 if (memcmp(&v9inode->qid.version,
474 &st->qid.version, sizeof(v9inode->qid.version)))
475 return 0;
476
477 if (v9inode->qid.type != st->qid.type)
478 return 0;
479 return 1;
480}
481
482static int v9fs_test_new_inode(struct inode *inode, void *data)
483{
484 return 0;
485}
486
487static int v9fs_set_inode(struct inode *inode, void *data)
488{
489 struct v9fs_inode *v9inode = V9FS_I(inode);
490 struct p9_wstat *st = (struct p9_wstat *)data;
491
492 memcpy(&v9inode->qid, &st->qid, sizeof(st->qid));
493 return 0;
494}
495
496static struct inode *v9fs_qid_iget(struct super_block *sb,
497 struct p9_qid *qid,
498 struct p9_wstat *st,
499 int new)
500{
501 dev_t rdev;
502 int retval;
503 umode_t umode;
504 unsigned long i_ino;
505 struct inode *inode;
506 struct v9fs_session_info *v9ses = sb->s_fs_info;
507 int (*test)(struct inode *, void *);
508
509 if (new)
510 test = v9fs_test_new_inode;
511 else
512 test = v9fs_test_inode;
513
514 i_ino = v9fs_qid2ino(qid);
515 inode = iget5_locked(sb, i_ino, test, v9fs_set_inode, st);
516 if (!inode)
517 return ERR_PTR(-ENOMEM);
518 if (!(inode->i_state & I_NEW))
519 return inode;
520
521
522
523
524
525 inode->i_ino = i_ino;
526 umode = p9mode2unixmode(v9ses, st, &rdev);
527 retval = v9fs_init_inode(v9ses, inode, umode, rdev);
528 if (retval)
529 goto error;
530
531 v9fs_stat2inode(st, inode, sb);
532 v9fs_cache_inode_get_cookie(inode);
533 unlock_new_inode(inode);
534 return inode;
535error:
536 unlock_new_inode(inode);
537 iput(inode);
538 return ERR_PTR(retval);
539
540}
541
542struct inode *
543v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
544 struct super_block *sb, int new)
545{
546 struct p9_wstat *st;
547 struct inode *inode = NULL;
548
549 st = p9_client_stat(fid);
550 if (IS_ERR(st))
551 return ERR_CAST(st);
552
553 inode = v9fs_qid_iget(sb, &st->qid, st, new);
554 p9stat_free(st);
555 kfree(st);
556 return inode;
557}
558
559
560
561
562
563
564static int v9fs_at_to_dotl_flags(int flags)
565{
566 int rflags = 0;
567 if (flags & AT_REMOVEDIR)
568 rflags |= P9_DOTL_AT_REMOVEDIR;
569 return rflags;
570}
571
572
573
574
575
576
577
578
579
580static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
581{
582 struct inode *inode;
583 int retval = -EOPNOTSUPP;
584 struct p9_fid *v9fid, *dfid;
585 struct v9fs_session_info *v9ses;
586
587 p9_debug(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %x\n",
588 dir, dentry, flags);
589
590 v9ses = v9fs_inode2v9ses(dir);
591 inode = dentry->d_inode;
592 dfid = v9fs_fid_lookup(dentry->d_parent);
593 if (IS_ERR(dfid)) {
594 retval = PTR_ERR(dfid);
595 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", retval);
596 return retval;
597 }
598 if (v9fs_proto_dotl(v9ses))
599 retval = p9_client_unlinkat(dfid, dentry->d_name.name,
600 v9fs_at_to_dotl_flags(flags));
601 if (retval == -EOPNOTSUPP) {
602
603 v9fid = v9fs_fid_clone(dentry);
604 if (IS_ERR(v9fid))
605 return PTR_ERR(v9fid);
606 retval = p9_client_remove(v9fid);
607 }
608 if (!retval) {
609
610
611
612
613 if (flags & AT_REMOVEDIR) {
614 clear_nlink(inode);
615 drop_nlink(dir);
616 } else
617 drop_nlink(inode);
618
619 v9fs_invalidate_inode_attr(inode);
620 v9fs_invalidate_inode_attr(dir);
621 }
622 return retval;
623}
624
625
626
627
628
629
630
631
632
633
634
635static struct p9_fid *
636v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
637 struct dentry *dentry, char *extension, u32 perm, u8 mode)
638{
639 int err;
640 char *name;
641 struct p9_fid *dfid, *ofid, *fid;
642 struct inode *inode;
643
644 p9_debug(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
645
646 err = 0;
647 ofid = NULL;
648 fid = NULL;
649 name = (char *) dentry->d_name.name;
650 dfid = v9fs_fid_lookup(dentry->d_parent);
651 if (IS_ERR(dfid)) {
652 err = PTR_ERR(dfid);
653 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
654 return ERR_PTR(err);
655 }
656
657
658 ofid = p9_client_walk(dfid, 0, NULL, 1);
659 if (IS_ERR(ofid)) {
660 err = PTR_ERR(ofid);
661 p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
662 return ERR_PTR(err);
663 }
664
665 err = p9_client_fcreate(ofid, name, perm, mode, extension);
666 if (err < 0) {
667 p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
668 goto error;
669 }
670
671 if (!(perm & P9_DMLINK)) {
672
673 fid = p9_client_walk(dfid, 1, &name, 1);
674 if (IS_ERR(fid)) {
675 err = PTR_ERR(fid);
676 p9_debug(P9_DEBUG_VFS,
677 "p9_client_walk failed %d\n", err);
678 fid = NULL;
679 goto error;
680 }
681
682
683
684 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
685 if (IS_ERR(inode)) {
686 err = PTR_ERR(inode);
687 p9_debug(P9_DEBUG_VFS,
688 "inode creation failed %d\n", err);
689 goto error;
690 }
691 v9fs_fid_add(dentry, fid);
692 d_instantiate(dentry, inode);
693 }
694 return ofid;
695error:
696 if (ofid)
697 p9_client_clunk(ofid);
698
699 if (fid)
700 p9_client_clunk(fid);
701
702 return ERR_PTR(err);
703}
704
705
706
707
708
709
710
711
712
713
714
715
716
717static int
718v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
719 bool excl)
720{
721 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
722 u32 perm = unixmode2p9mode(v9ses, mode);
723 struct p9_fid *fid;
724
725
726 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_ORDWR);
727 if (IS_ERR(fid))
728 return PTR_ERR(fid);
729
730 v9fs_invalidate_inode_attr(dir);
731 p9_client_clunk(fid);
732
733 return 0;
734}
735
736
737
738
739
740
741
742
743
744static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
745{
746 int err;
747 u32 perm;
748 struct p9_fid *fid;
749 struct v9fs_session_info *v9ses;
750
751 p9_debug(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
752 err = 0;
753 v9ses = v9fs_inode2v9ses(dir);
754 perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
755 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD);
756 if (IS_ERR(fid)) {
757 err = PTR_ERR(fid);
758 fid = NULL;
759 } else {
760 inc_nlink(dir);
761 v9fs_invalidate_inode_attr(dir);
762 }
763
764 if (fid)
765 p9_client_clunk(fid);
766
767 return err;
768}
769
770
771
772
773
774
775
776
777
778struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
779 unsigned int flags)
780{
781 struct dentry *res;
782 struct super_block *sb;
783 struct v9fs_session_info *v9ses;
784 struct p9_fid *dfid, *fid;
785 struct inode *inode;
786 char *name;
787
788 p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p flags: %x\n",
789 dir, dentry->d_name.name, dentry, flags);
790
791 if (dentry->d_name.len > NAME_MAX)
792 return ERR_PTR(-ENAMETOOLONG);
793
794 sb = dir->i_sb;
795 v9ses = v9fs_inode2v9ses(dir);
796
797 dfid = v9fs_fid_lookup(dentry->d_parent);
798 if (IS_ERR(dfid))
799 return ERR_CAST(dfid);
800
801 name = (char *) dentry->d_name.name;
802 fid = p9_client_walk(dfid, 1, &name, 1);
803 if (IS_ERR(fid)) {
804 if (fid == ERR_PTR(-ENOENT)) {
805 d_add(dentry, NULL);
806 return NULL;
807 }
808 return ERR_CAST(fid);
809 }
810
811
812
813
814
815 if (v9ses->cache)
816 inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
817 else
818 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
819 if (IS_ERR(inode)) {
820 p9_client_clunk(fid);
821 return ERR_CAST(inode);
822 }
823
824
825
826
827
828
829
830 res = d_materialise_unique(dentry, inode);
831 if (!res)
832 v9fs_fid_add(dentry, fid);
833 else if (!IS_ERR(res))
834 v9fs_fid_add(res, fid);
835 else
836 p9_client_clunk(fid);
837 return res;
838}
839
840static int
841v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
842 struct file *file, unsigned flags, umode_t mode,
843 int *opened)
844{
845 int err;
846 u32 perm;
847 struct v9fs_inode *v9inode;
848 struct v9fs_session_info *v9ses;
849 struct p9_fid *fid, *inode_fid;
850 struct dentry *res = NULL;
851
852 if (d_unhashed(dentry)) {
853 res = v9fs_vfs_lookup(dir, dentry, 0);
854 if (IS_ERR(res))
855 return PTR_ERR(res);
856
857 if (res)
858 dentry = res;
859 }
860
861
862 if (!(flags & O_CREAT) || dentry->d_inode)
863 return finish_no_open(file, res);
864
865 err = 0;
866 fid = NULL;
867 v9ses = v9fs_inode2v9ses(dir);
868 perm = unixmode2p9mode(v9ses, mode);
869 fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
870 v9fs_uflags2omode(flags,
871 v9fs_proto_dotu(v9ses)));
872 if (IS_ERR(fid)) {
873 err = PTR_ERR(fid);
874 fid = NULL;
875 goto error;
876 }
877
878 v9fs_invalidate_inode_attr(dir);
879 v9inode = V9FS_I(dentry->d_inode);
880 mutex_lock(&v9inode->v_mutex);
881 if (v9ses->cache && !v9inode->writeback_fid &&
882 ((flags & O_ACCMODE) != O_RDONLY)) {
883
884
885
886
887
888
889
890 inode_fid = v9fs_writeback_fid(dentry);
891 if (IS_ERR(inode_fid)) {
892 err = PTR_ERR(inode_fid);
893 mutex_unlock(&v9inode->v_mutex);
894 goto error;
895 }
896 v9inode->writeback_fid = (void *) inode_fid;
897 }
898 mutex_unlock(&v9inode->v_mutex);
899 err = finish_open(file, dentry, generic_file_open, opened);
900 if (err)
901 goto error;
902
903 file->private_data = fid;
904 if (v9ses->cache)
905 v9fs_cache_inode_set_cookie(dentry->d_inode, file);
906
907 *opened |= FILE_CREATED;
908out:
909 dput(res);
910 return err;
911
912error:
913 if (fid)
914 p9_client_clunk(fid);
915 goto out;
916}
917
918
919
920
921
922
923
924
925int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
926{
927 return v9fs_remove(i, d, 0);
928}
929
930
931
932
933
934
935
936
937int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
938{
939 return v9fs_remove(i, d, AT_REMOVEDIR);
940}
941
942
943
944
945
946
947
948
949
950
951int
952v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
953 struct inode *new_dir, struct dentry *new_dentry)
954{
955 int retval;
956 struct inode *old_inode;
957 struct inode *new_inode;
958 struct v9fs_session_info *v9ses;
959 struct p9_fid *oldfid;
960 struct p9_fid *olddirfid;
961 struct p9_fid *newdirfid;
962 struct p9_wstat wstat;
963
964 p9_debug(P9_DEBUG_VFS, "\n");
965 retval = 0;
966 old_inode = old_dentry->d_inode;
967 new_inode = new_dentry->d_inode;
968 v9ses = v9fs_inode2v9ses(old_inode);
969 oldfid = v9fs_fid_lookup(old_dentry);
970 if (IS_ERR(oldfid))
971 return PTR_ERR(oldfid);
972
973 olddirfid = v9fs_fid_clone(old_dentry->d_parent);
974 if (IS_ERR(olddirfid)) {
975 retval = PTR_ERR(olddirfid);
976 goto done;
977 }
978
979 newdirfid = v9fs_fid_clone(new_dentry->d_parent);
980 if (IS_ERR(newdirfid)) {
981 retval = PTR_ERR(newdirfid);
982 goto clunk_olddir;
983 }
984
985 down_write(&v9ses->rename_sem);
986 if (v9fs_proto_dotl(v9ses)) {
987 retval = p9_client_renameat(olddirfid, old_dentry->d_name.name,
988 newdirfid, new_dentry->d_name.name);
989 if (retval == -EOPNOTSUPP)
990 retval = p9_client_rename(oldfid, newdirfid,
991 new_dentry->d_name.name);
992 if (retval != -EOPNOTSUPP)
993 goto clunk_newdir;
994 }
995 if (old_dentry->d_parent != new_dentry->d_parent) {
996
997
998
999
1000 p9_debug(P9_DEBUG_ERROR, "old dir and new dir are different\n");
1001 retval = -EXDEV;
1002 goto clunk_newdir;
1003 }
1004 v9fs_blank_wstat(&wstat);
1005 wstat.muid = v9ses->uname;
1006 wstat.name = (char *) new_dentry->d_name.name;
1007 retval = p9_client_wstat(oldfid, &wstat);
1008
1009clunk_newdir:
1010 if (!retval) {
1011 if (new_inode) {
1012 if (S_ISDIR(new_inode->i_mode))
1013 clear_nlink(new_inode);
1014 else
1015 drop_nlink(new_inode);
1016 }
1017 if (S_ISDIR(old_inode->i_mode)) {
1018 if (!new_inode)
1019 inc_nlink(new_dir);
1020 drop_nlink(old_dir);
1021 }
1022 v9fs_invalidate_inode_attr(old_inode);
1023 v9fs_invalidate_inode_attr(old_dir);
1024 v9fs_invalidate_inode_attr(new_dir);
1025
1026
1027 d_move(old_dentry, new_dentry);
1028 }
1029 up_write(&v9ses->rename_sem);
1030 p9_client_clunk(newdirfid);
1031
1032clunk_olddir:
1033 p9_client_clunk(olddirfid);
1034
1035done:
1036 return retval;
1037}
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047static int
1048v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1049 struct kstat *stat)
1050{
1051 struct v9fs_session_info *v9ses;
1052 struct p9_fid *fid;
1053 struct p9_wstat *st;
1054
1055 p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
1056 v9ses = v9fs_dentry2v9ses(dentry);
1057 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
1058 generic_fillattr(dentry->d_inode, stat);
1059 return 0;
1060 }
1061 fid = v9fs_fid_lookup(dentry);
1062 if (IS_ERR(fid))
1063 return PTR_ERR(fid);
1064
1065 st = p9_client_stat(fid);
1066 if (IS_ERR(st))
1067 return PTR_ERR(st);
1068
1069 v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
1070 generic_fillattr(dentry->d_inode, stat);
1071
1072 p9stat_free(st);
1073 kfree(st);
1074 return 0;
1075}
1076
1077
1078
1079
1080
1081
1082
1083
1084static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
1085{
1086 int retval;
1087 struct v9fs_session_info *v9ses;
1088 struct p9_fid *fid;
1089 struct p9_wstat wstat;
1090
1091 p9_debug(P9_DEBUG_VFS, "\n");
1092 retval = inode_change_ok(dentry->d_inode, iattr);
1093 if (retval)
1094 return retval;
1095
1096 retval = -EPERM;
1097 v9ses = v9fs_dentry2v9ses(dentry);
1098 fid = v9fs_fid_lookup(dentry);
1099 if(IS_ERR(fid))
1100 return PTR_ERR(fid);
1101
1102 v9fs_blank_wstat(&wstat);
1103 if (iattr->ia_valid & ATTR_MODE)
1104 wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);
1105
1106 if (iattr->ia_valid & ATTR_MTIME)
1107 wstat.mtime = iattr->ia_mtime.tv_sec;
1108
1109 if (iattr->ia_valid & ATTR_ATIME)
1110 wstat.atime = iattr->ia_atime.tv_sec;
1111
1112 if (iattr->ia_valid & ATTR_SIZE)
1113 wstat.length = iattr->ia_size;
1114
1115 if (v9fs_proto_dotu(v9ses)) {
1116 if (iattr->ia_valid & ATTR_UID)
1117 wstat.n_uid = iattr->ia_uid;
1118
1119 if (iattr->ia_valid & ATTR_GID)
1120 wstat.n_gid = iattr->ia_gid;
1121 }
1122
1123
1124 if (S_ISREG(dentry->d_inode->i_mode))
1125 filemap_write_and_wait(dentry->d_inode->i_mapping);
1126
1127 retval = p9_client_wstat(fid, &wstat);
1128 if (retval < 0)
1129 return retval;
1130
1131 if ((iattr->ia_valid & ATTR_SIZE) &&
1132 iattr->ia_size != i_size_read(dentry->d_inode))
1133 truncate_setsize(dentry->d_inode, iattr->ia_size);
1134
1135 v9fs_invalidate_inode_attr(dentry->d_inode);
1136
1137 setattr_copy(dentry->d_inode, iattr);
1138 mark_inode_dirty(dentry->d_inode);
1139 return 0;
1140}
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150void
1151v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
1152 struct super_block *sb)
1153{
1154 umode_t mode;
1155 char ext[32];
1156 char tag_name[14];
1157 unsigned int i_nlink;
1158 struct v9fs_session_info *v9ses = sb->s_fs_info;
1159 struct v9fs_inode *v9inode = V9FS_I(inode);
1160
1161 set_nlink(inode, 1);
1162
1163 inode->i_atime.tv_sec = stat->atime;
1164 inode->i_mtime.tv_sec = stat->mtime;
1165 inode->i_ctime.tv_sec = stat->mtime;
1166
1167 inode->i_uid = v9ses->dfltuid;
1168 inode->i_gid = v9ses->dfltgid;
1169
1170 if (v9fs_proto_dotu(v9ses)) {
1171 inode->i_uid = stat->n_uid;
1172 inode->i_gid = stat->n_gid;
1173 }
1174 if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) {
1175 if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) {
1176
1177
1178
1179
1180
1181
1182
1183 strlcpy(ext, stat->extension, sizeof(ext));
1184
1185 sscanf(ext, "%13s %u", tag_name, &i_nlink);
1186 if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
1187 set_nlink(inode, i_nlink);
1188 }
1189 }
1190 mode = p9mode2perm(v9ses, stat);
1191 mode |= inode->i_mode & ~S_IALLUGO;
1192 inode->i_mode = mode;
1193 i_size_write(inode, stat->length);
1194
1195
1196 inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
1197 v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
1198}
1199
1200
1201
1202
1203
1204
1205
1206
1207ino_t v9fs_qid2ino(struct p9_qid *qid)
1208{
1209 u64 path = qid->path + 2;
1210 ino_t i = 0;
1211
1212 if (sizeof(ino_t) == sizeof(path))
1213 memcpy(&i, &path, sizeof(ino_t));
1214 else
1215 i = (ino_t) (path ^ (path >> 32));
1216
1217 return i;
1218}
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
1229{
1230 int retval;
1231
1232 struct v9fs_session_info *v9ses;
1233 struct p9_fid *fid;
1234 struct p9_wstat *st;
1235
1236 p9_debug(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
1237 retval = -EPERM;
1238 v9ses = v9fs_dentry2v9ses(dentry);
1239 fid = v9fs_fid_lookup(dentry);
1240 if (IS_ERR(fid))
1241 return PTR_ERR(fid);
1242
1243 if (!v9fs_proto_dotu(v9ses))
1244 return -EBADF;
1245
1246 st = p9_client_stat(fid);
1247 if (IS_ERR(st))
1248 return PTR_ERR(st);
1249
1250 if (!(st->mode & P9_DMSYMLINK)) {
1251 retval = -EINVAL;
1252 goto done;
1253 }
1254
1255
1256 retval = min(strlen(st->extension)+1, (size_t)buflen);
1257 memcpy(buffer, st->extension, retval);
1258
1259 p9_debug(P9_DEBUG_VFS, "%s -> %s (%.*s)\n",
1260 dentry->d_name.name, st->extension, buflen, buffer);
1261
1262done:
1263 p9stat_free(st);
1264 kfree(st);
1265 return retval;
1266}
1267
1268
1269
1270
1271
1272
1273
1274
1275static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
1276{
1277 int len = 0;
1278 char *link = __getname();
1279
1280 p9_debug(P9_DEBUG_VFS, "%s\n", dentry->d_name.name);
1281
1282 if (!link)
1283 link = ERR_PTR(-ENOMEM);
1284 else {
1285 len = v9fs_readlink(dentry, link, PATH_MAX);
1286
1287 if (len < 0) {
1288 __putname(link);
1289 link = ERR_PTR(len);
1290 } else
1291 link[min(len, PATH_MAX-1)] = 0;
1292 }
1293 nd_set_link(nd, link);
1294
1295 return NULL;
1296}
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306void
1307v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
1308{
1309 char *s = nd_get_link(nd);
1310
1311 p9_debug(P9_DEBUG_VFS, " %s %s\n",
1312 dentry->d_name.name, IS_ERR(s) ? "<error>" : s);
1313 if (!IS_ERR(s))
1314 __putname(s);
1315}
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
1327 u32 perm, const char *extension)
1328{
1329 struct p9_fid *fid;
1330 struct v9fs_session_info *v9ses;
1331
1332 v9ses = v9fs_inode2v9ses(dir);
1333 if (!v9fs_proto_dotu(v9ses)) {
1334 p9_debug(P9_DEBUG_ERROR, "not extended\n");
1335 return -EPERM;
1336 }
1337
1338 fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
1339 P9_OREAD);
1340 if (IS_ERR(fid))
1341 return PTR_ERR(fid);
1342
1343 v9fs_invalidate_inode_attr(dir);
1344 p9_client_clunk(fid);
1345 return 0;
1346}
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358static int
1359v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1360{
1361 p9_debug(P9_DEBUG_VFS, " %lu,%s,%s\n",
1362 dir->i_ino, dentry->d_name.name, symname);
1363
1364 return v9fs_vfs_mkspecial(dir, dentry, P9_DMSYMLINK, symname);
1365}
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375static int
1376v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1377 struct dentry *dentry)
1378{
1379 int retval;
1380 char *name;
1381 struct p9_fid *oldfid;
1382
1383 p9_debug(P9_DEBUG_VFS, " %lu,%s,%s\n",
1384 dir->i_ino, dentry->d_name.name, old_dentry->d_name.name);
1385
1386 oldfid = v9fs_fid_clone(old_dentry);
1387 if (IS_ERR(oldfid))
1388 return PTR_ERR(oldfid);
1389
1390 name = __getname();
1391 if (unlikely(!name)) {
1392 retval = -ENOMEM;
1393 goto clunk_fid;
1394 }
1395
1396 sprintf(name, "%d\n", oldfid->fid);
1397 retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
1398 __putname(name);
1399 if (!retval) {
1400 v9fs_refresh_inode(oldfid, old_dentry->d_inode);
1401 v9fs_invalidate_inode_attr(dir);
1402 }
1403clunk_fid:
1404 p9_client_clunk(oldfid);
1405 return retval;
1406}
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417static int
1418v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
1419{
1420 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
1421 int retval;
1422 char *name;
1423 u32 perm;
1424
1425 p9_debug(P9_DEBUG_VFS, " %lu,%s mode: %hx MAJOR: %u MINOR: %u\n",
1426 dir->i_ino, dentry->d_name.name, mode,
1427 MAJOR(rdev), MINOR(rdev));
1428
1429 if (!new_valid_dev(rdev))
1430 return -EINVAL;
1431
1432 name = __getname();
1433 if (!name)
1434 return -ENOMEM;
1435
1436 if (S_ISBLK(mode))
1437 sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
1438 else if (S_ISCHR(mode))
1439 sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));
1440 else if (S_ISFIFO(mode))
1441 *name = 0;
1442 else if (S_ISSOCK(mode))
1443 *name = 0;
1444 else {
1445 __putname(name);
1446 return -EINVAL;
1447 }
1448
1449 perm = unixmode2p9mode(v9ses, mode);
1450 retval = v9fs_vfs_mkspecial(dir, dentry, perm, name);
1451 __putname(name);
1452
1453 return retval;
1454}
1455
1456int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
1457{
1458 int umode;
1459 dev_t rdev;
1460 loff_t i_size;
1461 struct p9_wstat *st;
1462 struct v9fs_session_info *v9ses;
1463
1464 v9ses = v9fs_inode2v9ses(inode);
1465 st = p9_client_stat(fid);
1466 if (IS_ERR(st))
1467 return PTR_ERR(st);
1468
1469
1470
1471 umode = p9mode2unixmode(v9ses, st, &rdev);
1472 if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
1473 goto out;
1474
1475 spin_lock(&inode->i_lock);
1476
1477
1478
1479
1480 i_size = inode->i_size;
1481 v9fs_stat2inode(st, inode, inode->i_sb);
1482 if (v9ses->cache)
1483 inode->i_size = i_size;
1484 spin_unlock(&inode->i_lock);
1485out:
1486 p9stat_free(st);
1487 kfree(st);
1488 return 0;
1489}
1490
1491static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1492 .create = v9fs_vfs_create,
1493 .lookup = v9fs_vfs_lookup,
1494 .atomic_open = v9fs_vfs_atomic_open,
1495 .symlink = v9fs_vfs_symlink,
1496 .link = v9fs_vfs_link,
1497 .unlink = v9fs_vfs_unlink,
1498 .mkdir = v9fs_vfs_mkdir,
1499 .rmdir = v9fs_vfs_rmdir,
1500 .mknod = v9fs_vfs_mknod,
1501 .rename = v9fs_vfs_rename,
1502 .getattr = v9fs_vfs_getattr,
1503 .setattr = v9fs_vfs_setattr,
1504};
1505
1506static const struct inode_operations v9fs_dir_inode_operations = {
1507 .create = v9fs_vfs_create,
1508 .lookup = v9fs_vfs_lookup,
1509 .atomic_open = v9fs_vfs_atomic_open,
1510 .unlink = v9fs_vfs_unlink,
1511 .mkdir = v9fs_vfs_mkdir,
1512 .rmdir = v9fs_vfs_rmdir,
1513 .mknod = v9fs_vfs_mknod,
1514 .rename = v9fs_vfs_rename,
1515 .getattr = v9fs_vfs_getattr,
1516 .setattr = v9fs_vfs_setattr,
1517};
1518
1519static const struct inode_operations v9fs_file_inode_operations = {
1520 .getattr = v9fs_vfs_getattr,
1521 .setattr = v9fs_vfs_setattr,
1522};
1523
1524static const struct inode_operations v9fs_symlink_inode_operations = {
1525 .readlink = generic_readlink,
1526 .follow_link = v9fs_vfs_follow_link,
1527 .put_link = v9fs_vfs_put_link,
1528 .getattr = v9fs_vfs_getattr,
1529 .setattr = v9fs_vfs_setattr,
1530};
1531
1532