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_final(inode->i_mapping);
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 int err;
1058 struct v9fs_session_info *v9ses;
1059 struct p9_fid *fid;
1060 struct p9_wstat *st;
1061
1062 p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
1063 err = -EPERM;
1064 v9ses = v9fs_dentry2v9ses(dentry);
1065 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
1066 generic_fillattr(dentry->d_inode, stat);
1067 return 0;
1068 }
1069 fid = v9fs_fid_lookup(dentry);
1070 if (IS_ERR(fid))
1071 return PTR_ERR(fid);
1072
1073 st = p9_client_stat(fid);
1074 if (IS_ERR(st))
1075 return PTR_ERR(st);
1076
1077 v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
1078 generic_fillattr(dentry->d_inode, stat);
1079
1080 p9stat_free(st);
1081 kfree(st);
1082 return 0;
1083}
1084
1085
1086
1087
1088
1089
1090
1091
1092static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
1093{
1094 int retval;
1095 struct v9fs_session_info *v9ses;
1096 struct p9_fid *fid;
1097 struct p9_wstat wstat;
1098
1099 p9_debug(P9_DEBUG_VFS, "\n");
1100 retval = inode_change_ok(dentry->d_inode, iattr);
1101 if (retval)
1102 return retval;
1103
1104 retval = -EPERM;
1105 v9ses = v9fs_dentry2v9ses(dentry);
1106 fid = v9fs_fid_lookup(dentry);
1107 if(IS_ERR(fid))
1108 return PTR_ERR(fid);
1109
1110 v9fs_blank_wstat(&wstat);
1111 if (iattr->ia_valid & ATTR_MODE)
1112 wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);
1113
1114 if (iattr->ia_valid & ATTR_MTIME)
1115 wstat.mtime = iattr->ia_mtime.tv_sec;
1116
1117 if (iattr->ia_valid & ATTR_ATIME)
1118 wstat.atime = iattr->ia_atime.tv_sec;
1119
1120 if (iattr->ia_valid & ATTR_SIZE)
1121 wstat.length = iattr->ia_size;
1122
1123 if (v9fs_proto_dotu(v9ses)) {
1124 if (iattr->ia_valid & ATTR_UID)
1125 wstat.n_uid = iattr->ia_uid;
1126
1127 if (iattr->ia_valid & ATTR_GID)
1128 wstat.n_gid = iattr->ia_gid;
1129 }
1130
1131
1132 if (S_ISREG(dentry->d_inode->i_mode))
1133 filemap_write_and_wait(dentry->d_inode->i_mapping);
1134
1135 retval = p9_client_wstat(fid, &wstat);
1136 if (retval < 0)
1137 return retval;
1138
1139 if ((iattr->ia_valid & ATTR_SIZE) &&
1140 iattr->ia_size != i_size_read(dentry->d_inode))
1141 truncate_setsize(dentry->d_inode, iattr->ia_size);
1142
1143 v9fs_invalidate_inode_attr(dentry->d_inode);
1144
1145 setattr_copy(dentry->d_inode, iattr);
1146 mark_inode_dirty(dentry->d_inode);
1147 return 0;
1148}
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158void
1159v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
1160 struct super_block *sb)
1161{
1162 umode_t mode;
1163 char ext[32];
1164 char tag_name[14];
1165 unsigned int i_nlink;
1166 struct v9fs_session_info *v9ses = sb->s_fs_info;
1167 struct v9fs_inode *v9inode = V9FS_I(inode);
1168
1169 set_nlink(inode, 1);
1170
1171 inode->i_atime.tv_sec = stat->atime;
1172 inode->i_mtime.tv_sec = stat->mtime;
1173 inode->i_ctime.tv_sec = stat->mtime;
1174
1175 inode->i_uid = v9ses->dfltuid;
1176 inode->i_gid = v9ses->dfltgid;
1177
1178 if (v9fs_proto_dotu(v9ses)) {
1179 inode->i_uid = stat->n_uid;
1180 inode->i_gid = stat->n_gid;
1181 }
1182 if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) {
1183 if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) {
1184
1185
1186
1187
1188
1189
1190
1191 strncpy(ext, stat->extension, sizeof(ext));
1192
1193 sscanf(ext, "%13s %u", tag_name, &i_nlink);
1194 if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
1195 set_nlink(inode, i_nlink);
1196 }
1197 }
1198 mode = p9mode2perm(v9ses, stat);
1199 mode |= inode->i_mode & ~S_IALLUGO;
1200 inode->i_mode = mode;
1201 i_size_write(inode, stat->length);
1202
1203
1204 inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
1205 v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
1206}
1207
1208
1209
1210
1211
1212
1213
1214
1215ino_t v9fs_qid2ino(struct p9_qid *qid)
1216{
1217 u64 path = qid->path + 2;
1218 ino_t i = 0;
1219
1220 if (sizeof(ino_t) == sizeof(path))
1221 memcpy(&i, &path, sizeof(ino_t));
1222 else
1223 i = (ino_t) (path ^ (path >> 32));
1224
1225 return i;
1226}
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
1237{
1238 int retval;
1239
1240 struct v9fs_session_info *v9ses;
1241 struct p9_fid *fid;
1242 struct p9_wstat *st;
1243
1244 p9_debug(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
1245 retval = -EPERM;
1246 v9ses = v9fs_dentry2v9ses(dentry);
1247 fid = v9fs_fid_lookup(dentry);
1248 if (IS_ERR(fid))
1249 return PTR_ERR(fid);
1250
1251 if (!v9fs_proto_dotu(v9ses))
1252 return -EBADF;
1253
1254 st = p9_client_stat(fid);
1255 if (IS_ERR(st))
1256 return PTR_ERR(st);
1257
1258 if (!(st->mode & P9_DMSYMLINK)) {
1259 retval = -EINVAL;
1260 goto done;
1261 }
1262
1263
1264 retval = min(strlen(st->extension)+1, (size_t)buflen);
1265 memcpy(buffer, st->extension, retval);
1266
1267 p9_debug(P9_DEBUG_VFS, "%s -> %s (%.*s)\n",
1268 dentry->d_name.name, st->extension, buflen, buffer);
1269
1270done:
1271 p9stat_free(st);
1272 kfree(st);
1273 return retval;
1274}
1275
1276
1277
1278
1279
1280
1281
1282
1283static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
1284{
1285 int len = 0;
1286 char *link = __getname();
1287
1288 p9_debug(P9_DEBUG_VFS, "%s\n", dentry->d_name.name);
1289
1290 if (!link)
1291 link = ERR_PTR(-ENOMEM);
1292 else {
1293 len = v9fs_readlink(dentry, link, PATH_MAX);
1294
1295 if (len < 0) {
1296 __putname(link);
1297 link = ERR_PTR(len);
1298 } else
1299 link[min(len, PATH_MAX-1)] = 0;
1300 }
1301 nd_set_link(nd, link);
1302
1303 return NULL;
1304}
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314void
1315v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
1316{
1317 char *s = nd_get_link(nd);
1318
1319 p9_debug(P9_DEBUG_VFS, " %s %s\n",
1320 dentry->d_name.name, IS_ERR(s) ? "<error>" : s);
1321 if (!IS_ERR(s))
1322 __putname(s);
1323}
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
1335 u32 perm, const char *extension)
1336{
1337 struct p9_fid *fid;
1338 struct v9fs_session_info *v9ses;
1339
1340 v9ses = v9fs_inode2v9ses(dir);
1341 if (!v9fs_proto_dotu(v9ses)) {
1342 p9_debug(P9_DEBUG_ERROR, "not extended\n");
1343 return -EPERM;
1344 }
1345
1346 fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
1347 P9_OREAD);
1348 if (IS_ERR(fid))
1349 return PTR_ERR(fid);
1350
1351 v9fs_invalidate_inode_attr(dir);
1352 p9_client_clunk(fid);
1353 return 0;
1354}
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366static int
1367v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1368{
1369 p9_debug(P9_DEBUG_VFS, " %lu,%s,%s\n",
1370 dir->i_ino, dentry->d_name.name, symname);
1371
1372 return v9fs_vfs_mkspecial(dir, dentry, P9_DMSYMLINK, symname);
1373}
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383static int
1384v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1385 struct dentry *dentry)
1386{
1387 int retval;
1388 char *name;
1389 struct p9_fid *oldfid;
1390
1391 p9_debug(P9_DEBUG_VFS, " %lu,%s,%s\n",
1392 dir->i_ino, dentry->d_name.name, old_dentry->d_name.name);
1393
1394 oldfid = v9fs_fid_clone(old_dentry);
1395 if (IS_ERR(oldfid))
1396 return PTR_ERR(oldfid);
1397
1398 name = __getname();
1399 if (unlikely(!name)) {
1400 retval = -ENOMEM;
1401 goto clunk_fid;
1402 }
1403
1404 sprintf(name, "%d\n", oldfid->fid);
1405 retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
1406 __putname(name);
1407 if (!retval) {
1408 v9fs_refresh_inode(oldfid, old_dentry->d_inode);
1409 v9fs_invalidate_inode_attr(dir);
1410 }
1411clunk_fid:
1412 p9_client_clunk(oldfid);
1413 return retval;
1414}
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425static int
1426v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
1427{
1428 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
1429 int retval;
1430 char *name;
1431 u32 perm;
1432
1433 p9_debug(P9_DEBUG_VFS, " %lu,%s mode: %hx MAJOR: %u MINOR: %u\n",
1434 dir->i_ino, dentry->d_name.name, mode,
1435 MAJOR(rdev), MINOR(rdev));
1436
1437 if (!new_valid_dev(rdev))
1438 return -EINVAL;
1439
1440 name = __getname();
1441 if (!name)
1442 return -ENOMEM;
1443
1444 if (S_ISBLK(mode))
1445 sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
1446 else if (S_ISCHR(mode))
1447 sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));
1448 else if (S_ISFIFO(mode))
1449 *name = 0;
1450 else if (S_ISSOCK(mode))
1451 *name = 0;
1452 else {
1453 __putname(name);
1454 return -EINVAL;
1455 }
1456
1457 perm = unixmode2p9mode(v9ses, mode);
1458 retval = v9fs_vfs_mkspecial(dir, dentry, perm, name);
1459 __putname(name);
1460
1461 return retval;
1462}
1463
1464int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
1465{
1466 int umode;
1467 dev_t rdev;
1468 loff_t i_size;
1469 struct p9_wstat *st;
1470 struct v9fs_session_info *v9ses;
1471
1472 v9ses = v9fs_inode2v9ses(inode);
1473 st = p9_client_stat(fid);
1474 if (IS_ERR(st))
1475 return PTR_ERR(st);
1476
1477
1478
1479 umode = p9mode2unixmode(v9ses, st, &rdev);
1480 if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
1481 goto out;
1482
1483 spin_lock(&inode->i_lock);
1484
1485
1486
1487
1488 i_size = inode->i_size;
1489 v9fs_stat2inode(st, inode, inode->i_sb);
1490 if (v9ses->cache)
1491 inode->i_size = i_size;
1492 spin_unlock(&inode->i_lock);
1493out:
1494 p9stat_free(st);
1495 kfree(st);
1496 return 0;
1497}
1498
1499static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1500 .create = v9fs_vfs_create,
1501 .lookup = v9fs_vfs_lookup,
1502 .atomic_open = v9fs_vfs_atomic_open,
1503 .symlink = v9fs_vfs_symlink,
1504 .link = v9fs_vfs_link,
1505 .unlink = v9fs_vfs_unlink,
1506 .mkdir = v9fs_vfs_mkdir,
1507 .rmdir = v9fs_vfs_rmdir,
1508 .mknod = v9fs_vfs_mknod,
1509 .rename = v9fs_vfs_rename,
1510 .getattr = v9fs_vfs_getattr,
1511 .setattr = v9fs_vfs_setattr,
1512};
1513
1514static const struct inode_operations v9fs_dir_inode_operations = {
1515 .create = v9fs_vfs_create,
1516 .lookup = v9fs_vfs_lookup,
1517 .atomic_open = v9fs_vfs_atomic_open,
1518 .unlink = v9fs_vfs_unlink,
1519 .mkdir = v9fs_vfs_mkdir,
1520 .rmdir = v9fs_vfs_rmdir,
1521 .mknod = v9fs_vfs_mknod,
1522 .rename = v9fs_vfs_rename,
1523 .getattr = v9fs_vfs_getattr,
1524 .setattr = v9fs_vfs_setattr,
1525};
1526
1527static const struct inode_operations v9fs_file_inode_operations = {
1528 .getattr = v9fs_vfs_getattr,
1529 .setattr = v9fs_vfs_setattr,
1530};
1531
1532static const struct inode_operations v9fs_symlink_inode_operations = {
1533 .readlink = generic_readlink,
1534 .follow_link = v9fs_vfs_follow_link,
1535 .put_link = v9fs_vfs_put_link,
1536 .getattr = v9fs_vfs_getattr,
1537 .setattr = v9fs_vfs_setattr,
1538};
1539
1540