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