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 strncpy(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#ifdef CONFIG_9P_FSCACHE
452 v9fs_cache_inode_put_cookie(inode);
453#endif
454
455 if (v9inode->writeback_fid) {
456 p9_client_clunk(v9inode->writeback_fid);
457 v9inode->writeback_fid = NULL;
458 }
459}
460
461static int v9fs_test_inode(struct inode *inode, void *data)
462{
463 int umode;
464 dev_t rdev;
465 struct v9fs_inode *v9inode = V9FS_I(inode);
466 struct p9_wstat *st = (struct p9_wstat *)data;
467 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
468
469 umode = p9mode2unixmode(v9ses, st, &rdev);
470
471 if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
472 return 0;
473
474
475 if (memcmp(&v9inode->qid.version,
476 &st->qid.version, sizeof(v9inode->qid.version)))
477 return 0;
478
479 if (v9inode->qid.type != st->qid.type)
480 return 0;
481 return 1;
482}
483
484static int v9fs_test_new_inode(struct inode *inode, void *data)
485{
486 return 0;
487}
488
489static int v9fs_set_inode(struct inode *inode, void *data)
490{
491 struct v9fs_inode *v9inode = V9FS_I(inode);
492 struct p9_wstat *st = (struct p9_wstat *)data;
493
494 memcpy(&v9inode->qid, &st->qid, sizeof(st->qid));
495 return 0;
496}
497
498static struct inode *v9fs_qid_iget(struct super_block *sb,
499 struct p9_qid *qid,
500 struct p9_wstat *st,
501 int new)
502{
503 dev_t rdev;
504 int retval;
505 umode_t umode;
506 unsigned long i_ino;
507 struct inode *inode;
508 struct v9fs_session_info *v9ses = sb->s_fs_info;
509 int (*test)(struct inode *, void *);
510
511 if (new)
512 test = v9fs_test_new_inode;
513 else
514 test = v9fs_test_inode;
515
516 i_ino = v9fs_qid2ino(qid);
517 inode = iget5_locked(sb, i_ino, test, v9fs_set_inode, st);
518 if (!inode)
519 return ERR_PTR(-ENOMEM);
520 if (!(inode->i_state & I_NEW))
521 return inode;
522
523
524
525
526
527 inode->i_ino = i_ino;
528 umode = p9mode2unixmode(v9ses, st, &rdev);
529 retval = v9fs_init_inode(v9ses, inode, umode, rdev);
530 if (retval)
531 goto error;
532
533 v9fs_stat2inode(st, inode, sb);
534#ifdef CONFIG_9P_FSCACHE
535 v9fs_cache_inode_get_cookie(inode);
536#endif
537 unlock_new_inode(inode);
538 return inode;
539error:
540 unlock_new_inode(inode);
541 iput(inode);
542 return ERR_PTR(retval);
543
544}
545
546struct inode *
547v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
548 struct super_block *sb, int new)
549{
550 struct p9_wstat *st;
551 struct inode *inode = NULL;
552
553 st = p9_client_stat(fid);
554 if (IS_ERR(st))
555 return ERR_CAST(st);
556
557 inode = v9fs_qid_iget(sb, &st->qid, st, new);
558 p9stat_free(st);
559 kfree(st);
560 return inode;
561}
562
563
564
565
566
567
568static int v9fs_at_to_dotl_flags(int flags)
569{
570 int rflags = 0;
571 if (flags & AT_REMOVEDIR)
572 rflags |= P9_DOTL_AT_REMOVEDIR;
573 return rflags;
574}
575
576
577
578
579
580
581
582
583
584static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
585{
586 struct inode *inode;
587 int retval = -EOPNOTSUPP;
588 struct p9_fid *v9fid, *dfid;
589 struct v9fs_session_info *v9ses;
590
591 p9_debug(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %x\n",
592 dir, dentry, flags);
593
594 v9ses = v9fs_inode2v9ses(dir);
595 inode = dentry->d_inode;
596 dfid = v9fs_fid_lookup(dentry->d_parent);
597 if (IS_ERR(dfid)) {
598 retval = PTR_ERR(dfid);
599 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", retval);
600 return retval;
601 }
602 if (v9fs_proto_dotl(v9ses))
603 retval = p9_client_unlinkat(dfid, dentry->d_name.name,
604 v9fs_at_to_dotl_flags(flags));
605 if (retval == -EOPNOTSUPP) {
606
607 v9fid = v9fs_fid_clone(dentry);
608 if (IS_ERR(v9fid))
609 return PTR_ERR(v9fid);
610 retval = p9_client_remove(v9fid);
611 }
612 if (!retval) {
613
614
615
616
617 if (flags & AT_REMOVEDIR) {
618 clear_nlink(inode);
619 drop_nlink(dir);
620 } else
621 drop_nlink(inode);
622
623 v9fs_invalidate_inode_attr(inode);
624 v9fs_invalidate_inode_attr(dir);
625 }
626 return retval;
627}
628
629
630
631
632
633
634
635
636
637
638
639static struct p9_fid *
640v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
641 struct dentry *dentry, char *extension, u32 perm, u8 mode)
642{
643 int err;
644 char *name;
645 struct p9_fid *dfid, *ofid, *fid;
646 struct inode *inode;
647
648 p9_debug(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
649
650 err = 0;
651 ofid = NULL;
652 fid = NULL;
653 name = (char *) dentry->d_name.name;
654 dfid = v9fs_fid_lookup(dentry->d_parent);
655 if (IS_ERR(dfid)) {
656 err = PTR_ERR(dfid);
657 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
658 return ERR_PTR(err);
659 }
660
661
662 ofid = p9_client_walk(dfid, 0, NULL, 1);
663 if (IS_ERR(ofid)) {
664 err = PTR_ERR(ofid);
665 p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
666 return ERR_PTR(err);
667 }
668
669 err = p9_client_fcreate(ofid, name, perm, mode, extension);
670 if (err < 0) {
671 p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
672 goto error;
673 }
674
675 if (!(perm & P9_DMLINK)) {
676
677 fid = p9_client_walk(dfid, 1, &name, 1);
678 if (IS_ERR(fid)) {
679 err = PTR_ERR(fid);
680 p9_debug(P9_DEBUG_VFS,
681 "p9_client_walk failed %d\n", err);
682 fid = NULL;
683 goto error;
684 }
685
686
687
688 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
689 if (IS_ERR(inode)) {
690 err = PTR_ERR(inode);
691 p9_debug(P9_DEBUG_VFS,
692 "inode creation failed %d\n", err);
693 goto error;
694 }
695 v9fs_fid_add(dentry, fid);
696 d_instantiate(dentry, inode);
697 }
698 return ofid;
699error:
700 if (ofid)
701 p9_client_clunk(ofid);
702
703 if (fid)
704 p9_client_clunk(fid);
705
706 return ERR_PTR(err);
707}
708
709
710
711
712
713
714
715
716
717
718
719
720
721static int
722v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
723 bool excl)
724{
725 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
726 u32 perm = unixmode2p9mode(v9ses, mode);
727 struct p9_fid *fid;
728
729
730 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_ORDWR);
731 if (IS_ERR(fid))
732 return PTR_ERR(fid);
733
734 v9fs_invalidate_inode_attr(dir);
735 p9_client_clunk(fid);
736
737 return 0;
738}
739
740
741
742
743
744
745
746
747
748static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
749{
750 int err;
751 u32 perm;
752 struct p9_fid *fid;
753 struct v9fs_session_info *v9ses;
754
755 p9_debug(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
756 err = 0;
757 v9ses = v9fs_inode2v9ses(dir);
758 perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
759 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD);
760 if (IS_ERR(fid)) {
761 err = PTR_ERR(fid);
762 fid = NULL;
763 } else {
764 inc_nlink(dir);
765 v9fs_invalidate_inode_attr(dir);
766 }
767
768 if (fid)
769 p9_client_clunk(fid);
770
771 return err;
772}
773
774
775
776
777
778
779
780
781
782struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
783 unsigned int flags)
784{
785 struct dentry *res;
786 struct super_block *sb;
787 struct v9fs_session_info *v9ses;
788 struct p9_fid *dfid, *fid;
789 struct inode *inode;
790 char *name;
791
792 p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p flags: %x\n",
793 dir, dentry->d_name.name, dentry, flags);
794
795 if (dentry->d_name.len > NAME_MAX)
796 return ERR_PTR(-ENAMETOOLONG);
797
798 sb = dir->i_sb;
799 v9ses = v9fs_inode2v9ses(dir);
800
801 dfid = v9fs_fid_lookup(dentry->d_parent);
802 if (IS_ERR(dfid))
803 return ERR_CAST(dfid);
804
805 name = (char *) dentry->d_name.name;
806 fid = p9_client_walk(dfid, 1, &name, 1);
807 if (IS_ERR(fid)) {
808 if (fid == ERR_PTR(-ENOENT)) {
809 d_add(dentry, NULL);
810 return NULL;
811 }
812 return ERR_CAST(fid);
813 }
814
815
816
817
818
819 if (v9ses->cache)
820 inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
821 else
822 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
823 if (IS_ERR(inode)) {
824 p9_client_clunk(fid);
825 return ERR_CAST(inode);
826 }
827
828
829
830
831
832
833
834 res = d_materialise_unique(dentry, inode);
835 if (!res)
836 v9fs_fid_add(dentry, fid);
837 else if (!IS_ERR(res))
838 v9fs_fid_add(res, fid);
839 else
840 p9_client_clunk(fid);
841 return res;
842}
843
844static int
845v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
846 struct file *file, unsigned flags, umode_t mode,
847 int *opened)
848{
849 int err;
850 u32 perm;
851 struct v9fs_inode *v9inode;
852 struct v9fs_session_info *v9ses;
853 struct p9_fid *fid, *inode_fid;
854 struct dentry *res = NULL;
855
856 if (d_unhashed(dentry)) {
857 res = v9fs_vfs_lookup(dir, dentry, 0);
858 if (IS_ERR(res))
859 return PTR_ERR(res);
860
861 if (res)
862 dentry = res;
863 }
864
865
866 if (!(flags & O_CREAT) || dentry->d_inode)
867 return finish_no_open(file, res);
868
869 err = 0;
870 fid = NULL;
871 v9ses = v9fs_inode2v9ses(dir);
872 perm = unixmode2p9mode(v9ses, mode);
873 fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
874 v9fs_uflags2omode(flags,
875 v9fs_proto_dotu(v9ses)));
876 if (IS_ERR(fid)) {
877 err = PTR_ERR(fid);
878 fid = NULL;
879 goto error;
880 }
881
882 v9fs_invalidate_inode_attr(dir);
883 v9inode = V9FS_I(dentry->d_inode);
884 mutex_lock(&v9inode->v_mutex);
885 if (v9ses->cache && !v9inode->writeback_fid &&
886 ((flags & O_ACCMODE) != O_RDONLY)) {
887
888
889
890
891
892
893
894 inode_fid = v9fs_writeback_fid(dentry);
895 if (IS_ERR(inode_fid)) {
896 err = PTR_ERR(inode_fid);
897 mutex_unlock(&v9inode->v_mutex);
898 goto error;
899 }
900 v9inode->writeback_fid = (void *) inode_fid;
901 }
902 mutex_unlock(&v9inode->v_mutex);
903 err = finish_open(file, dentry, generic_file_open, opened);
904 if (err)
905 goto error;
906
907 file->private_data = fid;
908#ifdef CONFIG_9P_FSCACHE
909 if (v9ses->cache)
910 v9fs_cache_inode_set_cookie(dentry->d_inode, file);
911#endif
912
913 *opened |= FILE_CREATED;
914out:
915 dput(res);
916 return err;
917
918error:
919 if (fid)
920 p9_client_clunk(fid);
921 goto out;
922}
923
924
925
926
927
928
929
930
931int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
932{
933 return v9fs_remove(i, d, 0);
934}
935
936
937
938
939
940
941
942
943int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
944{
945 return v9fs_remove(i, d, AT_REMOVEDIR);
946}
947
948
949
950
951
952
953
954
955
956
957int
958v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
959 struct inode *new_dir, struct dentry *new_dentry)
960{
961 int retval;
962 struct inode *old_inode;
963 struct inode *new_inode;
964 struct v9fs_session_info *v9ses;
965 struct p9_fid *oldfid;
966 struct p9_fid *olddirfid;
967 struct p9_fid *newdirfid;
968 struct p9_wstat wstat;
969
970 p9_debug(P9_DEBUG_VFS, "\n");
971 retval = 0;
972 old_inode = old_dentry->d_inode;
973 new_inode = new_dentry->d_inode;
974 v9ses = v9fs_inode2v9ses(old_inode);
975 oldfid = v9fs_fid_lookup(old_dentry);
976 if (IS_ERR(oldfid))
977 return PTR_ERR(oldfid);
978
979 olddirfid = v9fs_fid_clone(old_dentry->d_parent);
980 if (IS_ERR(olddirfid)) {
981 retval = PTR_ERR(olddirfid);
982 goto done;
983 }
984
985 newdirfid = v9fs_fid_clone(new_dentry->d_parent);
986 if (IS_ERR(newdirfid)) {
987 retval = PTR_ERR(newdirfid);
988 goto clunk_olddir;
989 }
990
991 down_write(&v9ses->rename_sem);
992 if (v9fs_proto_dotl(v9ses)) {
993 retval = p9_client_renameat(olddirfid, old_dentry->d_name.name,
994 newdirfid, new_dentry->d_name.name);
995 if (retval == -EOPNOTSUPP)
996 retval = p9_client_rename(oldfid, newdirfid,
997 new_dentry->d_name.name);
998 if (retval != -EOPNOTSUPP)
999 goto clunk_newdir;
1000 }
1001 if (old_dentry->d_parent != new_dentry->d_parent) {
1002
1003
1004
1005
1006 p9_debug(P9_DEBUG_ERROR, "old dir and new dir are different\n");
1007 retval = -EXDEV;
1008 goto clunk_newdir;
1009 }
1010 v9fs_blank_wstat(&wstat);
1011 wstat.muid = v9ses->uname;
1012 wstat.name = (char *) new_dentry->d_name.name;
1013 retval = p9_client_wstat(oldfid, &wstat);
1014
1015clunk_newdir:
1016 if (!retval) {
1017 if (new_inode) {
1018 if (S_ISDIR(new_inode->i_mode))
1019 clear_nlink(new_inode);
1020 else
1021 drop_nlink(new_inode);
1022 }
1023 if (S_ISDIR(old_inode->i_mode)) {
1024 if (!new_inode)
1025 inc_nlink(new_dir);
1026 drop_nlink(old_dir);
1027 }
1028 v9fs_invalidate_inode_attr(old_inode);
1029 v9fs_invalidate_inode_attr(old_dir);
1030 v9fs_invalidate_inode_attr(new_dir);
1031
1032
1033 d_move(old_dentry, new_dentry);
1034 }
1035 up_write(&v9ses->rename_sem);
1036 p9_client_clunk(newdirfid);
1037
1038clunk_olddir:
1039 p9_client_clunk(olddirfid);
1040
1041done:
1042 return retval;
1043}
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053static int
1054v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1055 struct kstat *stat)
1056{
1057 struct v9fs_session_info *v9ses;
1058 struct p9_fid *fid;
1059 struct p9_wstat *st;
1060
1061 p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
1062 v9ses = v9fs_dentry2v9ses(dentry);
1063 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
1064 generic_fillattr(dentry->d_inode, stat);
1065 return 0;
1066 }
1067 fid = v9fs_fid_lookup(dentry);
1068 if (IS_ERR(fid))
1069 return PTR_ERR(fid);
1070
1071 st = p9_client_stat(fid);
1072 if (IS_ERR(st))
1073 return PTR_ERR(st);
1074
1075 v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
1076 generic_fillattr(dentry->d_inode, stat);
1077
1078 p9stat_free(st);
1079 kfree(st);
1080 return 0;
1081}
1082
1083
1084
1085
1086
1087
1088
1089
1090static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
1091{
1092 int retval;
1093 struct v9fs_session_info *v9ses;
1094 struct p9_fid *fid;
1095 struct p9_wstat wstat;
1096
1097 p9_debug(P9_DEBUG_VFS, "\n");
1098 retval = inode_change_ok(dentry->d_inode, iattr);
1099 if (retval)
1100 return retval;
1101
1102 retval = -EPERM;
1103 v9ses = v9fs_dentry2v9ses(dentry);
1104 fid = v9fs_fid_lookup(dentry);
1105 if(IS_ERR(fid))
1106 return PTR_ERR(fid);
1107
1108 v9fs_blank_wstat(&wstat);
1109 if (iattr->ia_valid & ATTR_MODE)
1110 wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);
1111
1112 if (iattr->ia_valid & ATTR_MTIME)
1113 wstat.mtime = iattr->ia_mtime.tv_sec;
1114
1115 if (iattr->ia_valid & ATTR_ATIME)
1116 wstat.atime = iattr->ia_atime.tv_sec;
1117
1118 if (iattr->ia_valid & ATTR_SIZE)
1119 wstat.length = iattr->ia_size;
1120
1121 if (v9fs_proto_dotu(v9ses)) {
1122 if (iattr->ia_valid & ATTR_UID)
1123 wstat.n_uid = iattr->ia_uid;
1124
1125 if (iattr->ia_valid & ATTR_GID)
1126 wstat.n_gid = iattr->ia_gid;
1127 }
1128
1129
1130 if (S_ISREG(dentry->d_inode->i_mode))
1131 filemap_write_and_wait(dentry->d_inode->i_mapping);
1132
1133 retval = p9_client_wstat(fid, &wstat);
1134 if (retval < 0)
1135 return retval;
1136
1137 if ((iattr->ia_valid & ATTR_SIZE) &&
1138 iattr->ia_size != i_size_read(dentry->d_inode))
1139 truncate_setsize(dentry->d_inode, iattr->ia_size);
1140
1141 v9fs_invalidate_inode_attr(dentry->d_inode);
1142
1143 setattr_copy(dentry->d_inode, iattr);
1144 mark_inode_dirty(dentry->d_inode);
1145 return 0;
1146}
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156void
1157v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
1158 struct super_block *sb)
1159{
1160 umode_t mode;
1161 char ext[32];
1162 char tag_name[14];
1163 unsigned int i_nlink;
1164 struct v9fs_session_info *v9ses = sb->s_fs_info;
1165 struct v9fs_inode *v9inode = V9FS_I(inode);
1166
1167 set_nlink(inode, 1);
1168
1169 inode->i_atime.tv_sec = stat->atime;
1170 inode->i_mtime.tv_sec = stat->mtime;
1171 inode->i_ctime.tv_sec = stat->mtime;
1172
1173 inode->i_uid = v9ses->dfltuid;
1174 inode->i_gid = v9ses->dfltgid;
1175
1176 if (v9fs_proto_dotu(v9ses)) {
1177 inode->i_uid = stat->n_uid;
1178 inode->i_gid = stat->n_gid;
1179 }
1180 if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) {
1181 if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) {
1182
1183
1184
1185
1186
1187
1188
1189 strncpy(ext, stat->extension, sizeof(ext));
1190
1191 sscanf(ext, "%13s %u", tag_name, &i_nlink);
1192 if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
1193 set_nlink(inode, i_nlink);
1194 }
1195 }
1196 mode = p9mode2perm(v9ses, stat);
1197 mode |= inode->i_mode & ~S_IALLUGO;
1198 inode->i_mode = mode;
1199 i_size_write(inode, stat->length);
1200
1201
1202 inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
1203 v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
1204}
1205
1206
1207
1208
1209
1210
1211
1212
1213ino_t v9fs_qid2ino(struct p9_qid *qid)
1214{
1215 u64 path = qid->path + 2;
1216 ino_t i = 0;
1217
1218 if (sizeof(ino_t) == sizeof(path))
1219 memcpy(&i, &path, sizeof(ino_t));
1220 else
1221 i = (ino_t) (path ^ (path >> 32));
1222
1223 return i;
1224}
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
1235{
1236 int retval;
1237
1238 struct v9fs_session_info *v9ses;
1239 struct p9_fid *fid;
1240 struct p9_wstat *st;
1241
1242 p9_debug(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
1243 retval = -EPERM;
1244 v9ses = v9fs_dentry2v9ses(dentry);
1245 fid = v9fs_fid_lookup(dentry);
1246 if (IS_ERR(fid))
1247 return PTR_ERR(fid);
1248
1249 if (!v9fs_proto_dotu(v9ses))
1250 return -EBADF;
1251
1252 st = p9_client_stat(fid);
1253 if (IS_ERR(st))
1254 return PTR_ERR(st);
1255
1256 if (!(st->mode & P9_DMSYMLINK)) {
1257 retval = -EINVAL;
1258 goto done;
1259 }
1260
1261
1262 retval = min(strlen(st->extension)+1, (size_t)buflen);
1263 memcpy(buffer, st->extension, retval);
1264
1265 p9_debug(P9_DEBUG_VFS, "%s -> %s (%.*s)\n",
1266 dentry->d_name.name, st->extension, buflen, buffer);
1267
1268done:
1269 p9stat_free(st);
1270 kfree(st);
1271 return retval;
1272}
1273
1274
1275
1276
1277
1278
1279
1280
1281static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
1282{
1283 int len = 0;
1284 char *link = __getname();
1285
1286 p9_debug(P9_DEBUG_VFS, "%s\n", dentry->d_name.name);
1287
1288 if (!link)
1289 link = ERR_PTR(-ENOMEM);
1290 else {
1291 len = v9fs_readlink(dentry, link, PATH_MAX);
1292
1293 if (len < 0) {
1294 __putname(link);
1295 link = ERR_PTR(len);
1296 } else
1297 link[min(len, PATH_MAX-1)] = 0;
1298 }
1299 nd_set_link(nd, link);
1300
1301 return NULL;
1302}
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312void
1313v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
1314{
1315 char *s = nd_get_link(nd);
1316
1317 p9_debug(P9_DEBUG_VFS, " %s %s\n",
1318 dentry->d_name.name, IS_ERR(s) ? "<error>" : s);
1319 if (!IS_ERR(s))
1320 __putname(s);
1321}
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
1333 u32 perm, const char *extension)
1334{
1335 struct p9_fid *fid;
1336 struct v9fs_session_info *v9ses;
1337
1338 v9ses = v9fs_inode2v9ses(dir);
1339 if (!v9fs_proto_dotu(v9ses)) {
1340 p9_debug(P9_DEBUG_ERROR, "not extended\n");
1341 return -EPERM;
1342 }
1343
1344 fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
1345 P9_OREAD);
1346 if (IS_ERR(fid))
1347 return PTR_ERR(fid);
1348
1349 v9fs_invalidate_inode_attr(dir);
1350 p9_client_clunk(fid);
1351 return 0;
1352}
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364static int
1365v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1366{
1367 p9_debug(P9_DEBUG_VFS, " %lu,%s,%s\n",
1368 dir->i_ino, dentry->d_name.name, symname);
1369
1370 return v9fs_vfs_mkspecial(dir, dentry, P9_DMSYMLINK, symname);
1371}
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381static int
1382v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1383 struct dentry *dentry)
1384{
1385 int retval;
1386 char *name;
1387 struct p9_fid *oldfid;
1388
1389 p9_debug(P9_DEBUG_VFS, " %lu,%s,%s\n",
1390 dir->i_ino, dentry->d_name.name, old_dentry->d_name.name);
1391
1392 oldfid = v9fs_fid_clone(old_dentry);
1393 if (IS_ERR(oldfid))
1394 return PTR_ERR(oldfid);
1395
1396 name = __getname();
1397 if (unlikely(!name)) {
1398 retval = -ENOMEM;
1399 goto clunk_fid;
1400 }
1401
1402 sprintf(name, "%d\n", oldfid->fid);
1403 retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
1404 __putname(name);
1405 if (!retval) {
1406 v9fs_refresh_inode(oldfid, old_dentry->d_inode);
1407 v9fs_invalidate_inode_attr(dir);
1408 }
1409clunk_fid:
1410 p9_client_clunk(oldfid);
1411 return retval;
1412}
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423static int
1424v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
1425{
1426 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
1427 int retval;
1428 char *name;
1429 u32 perm;
1430
1431 p9_debug(P9_DEBUG_VFS, " %lu,%s mode: %hx MAJOR: %u MINOR: %u\n",
1432 dir->i_ino, dentry->d_name.name, mode,
1433 MAJOR(rdev), MINOR(rdev));
1434
1435 if (!new_valid_dev(rdev))
1436 return -EINVAL;
1437
1438 name = __getname();
1439 if (!name)
1440 return -ENOMEM;
1441
1442 if (S_ISBLK(mode))
1443 sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
1444 else if (S_ISCHR(mode))
1445 sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));
1446 else if (S_ISFIFO(mode))
1447 *name = 0;
1448 else if (S_ISSOCK(mode))
1449 *name = 0;
1450 else {
1451 __putname(name);
1452 return -EINVAL;
1453 }
1454
1455 perm = unixmode2p9mode(v9ses, mode);
1456 retval = v9fs_vfs_mkspecial(dir, dentry, perm, name);
1457 __putname(name);
1458
1459 return retval;
1460}
1461
1462int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
1463{
1464 int umode;
1465 dev_t rdev;
1466 loff_t i_size;
1467 struct p9_wstat *st;
1468 struct v9fs_session_info *v9ses;
1469
1470 v9ses = v9fs_inode2v9ses(inode);
1471 st = p9_client_stat(fid);
1472 if (IS_ERR(st))
1473 return PTR_ERR(st);
1474
1475
1476
1477 umode = p9mode2unixmode(v9ses, st, &rdev);
1478 if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
1479 goto out;
1480
1481 spin_lock(&inode->i_lock);
1482
1483
1484
1485
1486 i_size = inode->i_size;
1487 v9fs_stat2inode(st, inode, inode->i_sb);
1488 if (v9ses->cache)
1489 inode->i_size = i_size;
1490 spin_unlock(&inode->i_lock);
1491out:
1492 p9stat_free(st);
1493 kfree(st);
1494 return 0;
1495}
1496
1497static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1498 .create = v9fs_vfs_create,
1499 .lookup = v9fs_vfs_lookup,
1500 .atomic_open = v9fs_vfs_atomic_open,
1501 .symlink = v9fs_vfs_symlink,
1502 .link = v9fs_vfs_link,
1503 .unlink = v9fs_vfs_unlink,
1504 .mkdir = v9fs_vfs_mkdir,
1505 .rmdir = v9fs_vfs_rmdir,
1506 .mknod = v9fs_vfs_mknod,
1507 .rename = v9fs_vfs_rename,
1508 .getattr = v9fs_vfs_getattr,
1509 .setattr = v9fs_vfs_setattr,
1510};
1511
1512static const struct inode_operations v9fs_dir_inode_operations = {
1513 .create = v9fs_vfs_create,
1514 .lookup = v9fs_vfs_lookup,
1515 .atomic_open = v9fs_vfs_atomic_open,
1516 .unlink = v9fs_vfs_unlink,
1517 .mkdir = v9fs_vfs_mkdir,
1518 .rmdir = v9fs_vfs_rmdir,
1519 .mknod = v9fs_vfs_mknod,
1520 .rename = v9fs_vfs_rename,
1521 .getattr = v9fs_vfs_getattr,
1522 .setattr = v9fs_vfs_setattr,
1523};
1524
1525static const struct inode_operations v9fs_file_inode_operations = {
1526 .getattr = v9fs_vfs_getattr,
1527 .setattr = v9fs_vfs_setattr,
1528};
1529
1530static const struct inode_operations v9fs_symlink_inode_operations = {
1531 .readlink = generic_readlink,
1532 .follow_link = v9fs_vfs_follow_link,
1533 .put_link = v9fs_vfs_put_link,
1534 .getattr = v9fs_vfs_getattr,
1535 .setattr = v9fs_vfs_setattr,
1536};
1537
1538