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