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
589static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
590{
591 struct inode *inode;
592 int retval = -EOPNOTSUPP;
593 struct p9_fid *v9fid, *dfid;
594 struct v9fs_session_info *v9ses;
595
596 p9_debug(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %x\n",
597 dir, dentry, flags);
598
599 v9ses = v9fs_inode2v9ses(dir);
600 inode = d_inode(dentry);
601 dfid = v9fs_parent_fid(dentry);
602 if (IS_ERR(dfid)) {
603 retval = PTR_ERR(dfid);
604 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", retval);
605 return retval;
606 }
607 if (v9fs_proto_dotl(v9ses))
608 retval = p9_client_unlinkat(dfid, dentry->d_name.name,
609 v9fs_at_to_dotl_flags(flags));
610 if (retval == -EOPNOTSUPP) {
611
612 v9fid = v9fs_fid_clone(dentry);
613 if (IS_ERR(v9fid))
614 return PTR_ERR(v9fid);
615 retval = p9_client_remove(v9fid);
616 }
617 if (!retval) {
618
619
620
621
622 if (flags & AT_REMOVEDIR) {
623 clear_nlink(inode);
624 drop_nlink(dir);
625 } else
626 drop_nlink(inode);
627
628 v9fs_invalidate_inode_attr(inode);
629 v9fs_invalidate_inode_attr(dir);
630 }
631 return retval;
632}
633
634
635
636
637
638
639
640
641
642
643
644static struct p9_fid *
645v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
646 struct dentry *dentry, char *extension, u32 perm, u8 mode)
647{
648 int err;
649 const unsigned char *name;
650 struct p9_fid *dfid, *ofid, *fid;
651 struct inode *inode;
652
653 p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry);
654
655 err = 0;
656 ofid = NULL;
657 fid = NULL;
658 name = dentry->d_name.name;
659 dfid = v9fs_parent_fid(dentry);
660 if (IS_ERR(dfid)) {
661 err = PTR_ERR(dfid);
662 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
663 return ERR_PTR(err);
664 }
665
666
667 ofid = clone_fid(dfid);
668 if (IS_ERR(ofid)) {
669 err = PTR_ERR(ofid);
670 p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
671 return ERR_PTR(err);
672 }
673
674 err = p9_client_fcreate(ofid, name, perm, mode, extension);
675 if (err < 0) {
676 p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
677 goto error;
678 }
679
680 if (!(perm & P9_DMLINK)) {
681
682 fid = p9_client_walk(dfid, 1, &name, 1);
683 if (IS_ERR(fid)) {
684 err = PTR_ERR(fid);
685 p9_debug(P9_DEBUG_VFS,
686 "p9_client_walk failed %d\n", err);
687 fid = NULL;
688 goto error;
689 }
690
691
692
693 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
694 if (IS_ERR(inode)) {
695 err = PTR_ERR(inode);
696 p9_debug(P9_DEBUG_VFS,
697 "inode creation failed %d\n", err);
698 goto error;
699 }
700 v9fs_fid_add(dentry, fid);
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 %pd\n", dentry);
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 v9fs_session_info *v9ses;
792 struct p9_fid *dfid, *fid;
793 struct inode *inode;
794 const unsigned char *name;
795
796 p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%pd) %p flags: %x\n",
797 dir, dentry, dentry, flags);
798
799 if (dentry->d_name.len > NAME_MAX)
800 return ERR_PTR(-ENAMETOOLONG);
801
802 v9ses = v9fs_inode2v9ses(dir);
803
804 dfid = v9fs_parent_fid(dentry);
805 if (IS_ERR(dfid))
806 return ERR_CAST(dfid);
807
808 name = dentry->d_name.name;
809 fid = p9_client_walk(dfid, 1, &name, 1);
810 if (IS_ERR(fid)) {
811 if (fid == ERR_PTR(-ENOENT)) {
812 d_add(dentry, NULL);
813 return NULL;
814 }
815 return ERR_CAST(fid);
816 }
817
818
819
820
821
822 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
823 inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
824 else
825 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
826 if (IS_ERR(inode)) {
827 p9_client_clunk(fid);
828 return ERR_CAST(inode);
829 }
830
831
832
833
834
835
836
837 res = d_splice_alias(inode, dentry);
838 if (!res)
839 v9fs_fid_add(dentry, fid);
840 else if (!IS_ERR(res))
841 v9fs_fid_add(res, fid);
842 else
843 p9_client_clunk(fid);
844 return res;
845}
846
847static int
848v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
849 struct file *file, unsigned flags, umode_t mode,
850 int *opened)
851{
852 int err;
853 u32 perm;
854 struct v9fs_inode *v9inode;
855 struct v9fs_session_info *v9ses;
856 struct p9_fid *fid, *inode_fid;
857 struct dentry *res = NULL;
858
859 if (d_in_lookup(dentry)) {
860 res = v9fs_vfs_lookup(dir, dentry, 0);
861 if (IS_ERR(res))
862 return PTR_ERR(res);
863
864 if (res)
865 dentry = res;
866 }
867
868
869 if (!(flags & O_CREAT) || d_really_is_positive(dentry))
870 return finish_no_open(file, res);
871
872 err = 0;
873
874 v9ses = v9fs_inode2v9ses(dir);
875 perm = unixmode2p9mode(v9ses, mode);
876 fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
877 v9fs_uflags2omode(flags,
878 v9fs_proto_dotu(v9ses)));
879 if (IS_ERR(fid)) {
880 err = PTR_ERR(fid);
881 fid = NULL;
882 goto error;
883 }
884
885 v9fs_invalidate_inode_attr(dir);
886 v9inode = V9FS_I(d_inode(dentry));
887 mutex_lock(&v9inode->v_mutex);
888 if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) &&
889 !v9inode->writeback_fid &&
890 ((flags & O_ACCMODE) != O_RDONLY)) {
891
892
893
894
895
896
897
898 inode_fid = v9fs_writeback_fid(dentry);
899 if (IS_ERR(inode_fid)) {
900 err = PTR_ERR(inode_fid);
901 mutex_unlock(&v9inode->v_mutex);
902 goto error;
903 }
904 v9inode->writeback_fid = (void *) inode_fid;
905 }
906 mutex_unlock(&v9inode->v_mutex);
907 err = finish_open(file, dentry, generic_file_open, opened);
908 if (err)
909 goto error;
910
911 file->private_data = fid;
912 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
913 v9fs_cache_inode_set_cookie(d_inode(dentry), file);
914
915 *opened |= FILE_CREATED;
916out:
917 dput(res);
918 return err;
919
920error:
921 if (fid)
922 p9_client_clunk(fid);
923 goto out;
924}
925
926
927
928
929
930
931
932
933int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
934{
935 return v9fs_remove(i, d, 0);
936}
937
938
939
940
941
942
943
944
945int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
946{
947 return v9fs_remove(i, d, AT_REMOVEDIR);
948}
949
950
951
952
953
954
955
956
957
958
959int
960v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
961 struct inode *new_dir, struct dentry *new_dentry,
962 unsigned int flags)
963{
964 int retval;
965 struct inode *old_inode;
966 struct inode *new_inode;
967 struct v9fs_session_info *v9ses;
968 struct p9_fid *oldfid;
969 struct p9_fid *olddirfid;
970 struct p9_fid *newdirfid;
971 struct p9_wstat wstat;
972
973 if (flags)
974 return -EINVAL;
975
976 p9_debug(P9_DEBUG_VFS, "\n");
977 retval = 0;
978 old_inode = d_inode(old_dentry);
979 new_inode = d_inode(new_dentry);
980 v9ses = v9fs_inode2v9ses(old_inode);
981 oldfid = v9fs_fid_lookup(old_dentry);
982 if (IS_ERR(oldfid))
983 return PTR_ERR(oldfid);
984
985 olddirfid = clone_fid(v9fs_parent_fid(old_dentry));
986 if (IS_ERR(olddirfid)) {
987 retval = PTR_ERR(olddirfid);
988 goto done;
989 }
990
991 newdirfid = clone_fid(v9fs_parent_fid(new_dentry));
992 if (IS_ERR(newdirfid)) {
993 retval = PTR_ERR(newdirfid);
994 goto clunk_olddir;
995 }
996
997 down_write(&v9ses->rename_sem);
998 if (v9fs_proto_dotl(v9ses)) {
999 retval = p9_client_renameat(olddirfid, old_dentry->d_name.name,
1000 newdirfid, new_dentry->d_name.name);
1001 if (retval == -EOPNOTSUPP)
1002 retval = p9_client_rename(oldfid, newdirfid,
1003 new_dentry->d_name.name);
1004 if (retval != -EOPNOTSUPP)
1005 goto clunk_newdir;
1006 }
1007 if (old_dentry->d_parent != new_dentry->d_parent) {
1008
1009
1010
1011
1012 p9_debug(P9_DEBUG_ERROR, "old dir and new dir are different\n");
1013 retval = -EXDEV;
1014 goto clunk_newdir;
1015 }
1016 v9fs_blank_wstat(&wstat);
1017 wstat.muid = v9ses->uname;
1018 wstat.name = new_dentry->d_name.name;
1019 retval = p9_client_wstat(oldfid, &wstat);
1020
1021clunk_newdir:
1022 if (!retval) {
1023 if (new_inode) {
1024 if (S_ISDIR(new_inode->i_mode))
1025 clear_nlink(new_inode);
1026 else
1027 drop_nlink(new_inode);
1028 }
1029 if (S_ISDIR(old_inode->i_mode)) {
1030 if (!new_inode)
1031 inc_nlink(new_dir);
1032 drop_nlink(old_dir);
1033 }
1034 v9fs_invalidate_inode_attr(old_inode);
1035 v9fs_invalidate_inode_attr(old_dir);
1036 v9fs_invalidate_inode_attr(new_dir);
1037
1038
1039 d_move(old_dentry, new_dentry);
1040 }
1041 up_write(&v9ses->rename_sem);
1042 p9_client_clunk(newdirfid);
1043
1044clunk_olddir:
1045 p9_client_clunk(olddirfid);
1046
1047done:
1048 return retval;
1049}
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060static int
1061v9fs_vfs_getattr(const struct path *path, struct kstat *stat,
1062 u32 request_mask, unsigned int flags)
1063{
1064 struct dentry *dentry = path->dentry;
1065 struct v9fs_session_info *v9ses;
1066 struct p9_fid *fid;
1067 struct p9_wstat *st;
1068
1069 p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
1070 v9ses = v9fs_dentry2v9ses(dentry);
1071 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
1072 generic_fillattr(d_inode(dentry), stat);
1073 return 0;
1074 }
1075 fid = v9fs_fid_lookup(dentry);
1076 if (IS_ERR(fid))
1077 return PTR_ERR(fid);
1078
1079 st = p9_client_stat(fid);
1080 if (IS_ERR(st))
1081 return PTR_ERR(st);
1082
1083 v9fs_stat2inode(st, d_inode(dentry), dentry->d_sb);
1084 generic_fillattr(d_inode(dentry), stat);
1085
1086 p9stat_free(st);
1087 kfree(st);
1088 return 0;
1089}
1090
1091
1092
1093
1094
1095
1096
1097
1098static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
1099{
1100 int retval;
1101 struct v9fs_session_info *v9ses;
1102 struct p9_fid *fid;
1103 struct p9_wstat wstat;
1104
1105 p9_debug(P9_DEBUG_VFS, "\n");
1106 retval = setattr_prepare(dentry, iattr);
1107 if (retval)
1108 return retval;
1109
1110 retval = -EPERM;
1111 v9ses = v9fs_dentry2v9ses(dentry);
1112 fid = v9fs_fid_lookup(dentry);
1113 if(IS_ERR(fid))
1114 return PTR_ERR(fid);
1115
1116 v9fs_blank_wstat(&wstat);
1117 if (iattr->ia_valid & ATTR_MODE)
1118 wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);
1119
1120 if (iattr->ia_valid & ATTR_MTIME)
1121 wstat.mtime = iattr->ia_mtime.tv_sec;
1122
1123 if (iattr->ia_valid & ATTR_ATIME)
1124 wstat.atime = iattr->ia_atime.tv_sec;
1125
1126 if (iattr->ia_valid & ATTR_SIZE)
1127 wstat.length = iattr->ia_size;
1128
1129 if (v9fs_proto_dotu(v9ses)) {
1130 if (iattr->ia_valid & ATTR_UID)
1131 wstat.n_uid = iattr->ia_uid;
1132
1133 if (iattr->ia_valid & ATTR_GID)
1134 wstat.n_gid = iattr->ia_gid;
1135 }
1136
1137
1138 if (d_is_reg(dentry))
1139 filemap_write_and_wait(d_inode(dentry)->i_mapping);
1140
1141 retval = p9_client_wstat(fid, &wstat);
1142 if (retval < 0)
1143 return retval;
1144
1145 if ((iattr->ia_valid & ATTR_SIZE) &&
1146 iattr->ia_size != i_size_read(d_inode(dentry)))
1147 truncate_setsize(d_inode(dentry), iattr->ia_size);
1148
1149 v9fs_invalidate_inode_attr(d_inode(dentry));
1150
1151 setattr_copy(d_inode(dentry), iattr);
1152 mark_inode_dirty(d_inode(dentry));
1153 return 0;
1154}
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164void
1165v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
1166 struct super_block *sb)
1167{
1168 umode_t mode;
1169 char ext[32];
1170 char tag_name[14];
1171 unsigned int i_nlink;
1172 struct v9fs_session_info *v9ses = sb->s_fs_info;
1173 struct v9fs_inode *v9inode = V9FS_I(inode);
1174
1175 set_nlink(inode, 1);
1176
1177 inode->i_atime.tv_sec = stat->atime;
1178 inode->i_mtime.tv_sec = stat->mtime;
1179 inode->i_ctime.tv_sec = stat->mtime;
1180
1181 inode->i_uid = v9ses->dfltuid;
1182 inode->i_gid = v9ses->dfltgid;
1183
1184 if (v9fs_proto_dotu(v9ses)) {
1185 inode->i_uid = stat->n_uid;
1186 inode->i_gid = stat->n_gid;
1187 }
1188 if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) {
1189 if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) {
1190
1191
1192
1193
1194
1195
1196
1197 strlcpy(ext, stat->extension, sizeof(ext));
1198
1199 sscanf(ext, "%13s %u", tag_name, &i_nlink);
1200 if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
1201 set_nlink(inode, i_nlink);
1202 }
1203 }
1204 mode = p9mode2perm(v9ses, stat);
1205 mode |= inode->i_mode & ~S_IALLUGO;
1206 inode->i_mode = mode;
1207 i_size_write(inode, stat->length);
1208
1209
1210 inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
1211 v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
1212}
1213
1214
1215
1216
1217
1218
1219
1220
1221ino_t v9fs_qid2ino(struct p9_qid *qid)
1222{
1223 u64 path = qid->path + 2;
1224 ino_t i = 0;
1225
1226 if (sizeof(ino_t) == sizeof(path))
1227 memcpy(&i, &path, sizeof(ino_t));
1228 else
1229 i = (ino_t) (path ^ (path >> 32));
1230
1231 return i;
1232}
1233
1234
1235
1236
1237
1238
1239
1240
1241static const char *v9fs_vfs_get_link(struct dentry *dentry,
1242 struct inode *inode,
1243 struct delayed_call *done)
1244{
1245 struct v9fs_session_info *v9ses;
1246 struct p9_fid *fid;
1247 struct p9_wstat *st;
1248 char *res;
1249
1250 if (!dentry)
1251 return ERR_PTR(-ECHILD);
1252
1253 v9ses = v9fs_dentry2v9ses(dentry);
1254 fid = v9fs_fid_lookup(dentry);
1255 p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
1256
1257 if (IS_ERR(fid))
1258 return ERR_CAST(fid);
1259
1260 if (!v9fs_proto_dotu(v9ses))
1261 return ERR_PTR(-EBADF);
1262
1263 st = p9_client_stat(fid);
1264 if (IS_ERR(st))
1265 return ERR_CAST(st);
1266
1267 if (!(st->mode & P9_DMSYMLINK)) {
1268 p9stat_free(st);
1269 kfree(st);
1270 return ERR_PTR(-EINVAL);
1271 }
1272 res = st->extension;
1273 st->extension = NULL;
1274 if (strlen(res) >= PATH_MAX)
1275 res[PATH_MAX - 1] = '\0';
1276
1277 p9stat_free(st);
1278 kfree(st);
1279 set_delayed_call(done, kfree_link, res);
1280 return res;
1281}
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
1293 u32 perm, const char *extension)
1294{
1295 struct p9_fid *fid;
1296 struct v9fs_session_info *v9ses;
1297
1298 v9ses = v9fs_inode2v9ses(dir);
1299 if (!v9fs_proto_dotu(v9ses)) {
1300 p9_debug(P9_DEBUG_ERROR, "not extended\n");
1301 return -EPERM;
1302 }
1303
1304 fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
1305 P9_OREAD);
1306 if (IS_ERR(fid))
1307 return PTR_ERR(fid);
1308
1309 v9fs_invalidate_inode_attr(dir);
1310 p9_client_clunk(fid);
1311 return 0;
1312}
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324static int
1325v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1326{
1327 p9_debug(P9_DEBUG_VFS, " %lu,%pd,%s\n",
1328 dir->i_ino, dentry, symname);
1329
1330 return v9fs_vfs_mkspecial(dir, dentry, P9_DMSYMLINK, symname);
1331}
1332
1333#define U32_MAX_DIGITS 10
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343static int
1344v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1345 struct dentry *dentry)
1346{
1347 int retval;
1348 char name[1 + U32_MAX_DIGITS + 2];
1349 struct p9_fid *oldfid;
1350
1351 p9_debug(P9_DEBUG_VFS, " %lu,%pd,%pd\n",
1352 dir->i_ino, dentry, old_dentry);
1353
1354 oldfid = v9fs_fid_clone(old_dentry);
1355 if (IS_ERR(oldfid))
1356 return PTR_ERR(oldfid);
1357
1358 sprintf(name, "%d\n", oldfid->fid);
1359 retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
1360 if (!retval) {
1361 v9fs_refresh_inode(oldfid, d_inode(old_dentry));
1362 v9fs_invalidate_inode_attr(dir);
1363 }
1364 p9_client_clunk(oldfid);
1365 return retval;
1366}
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377static int
1378v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
1379{
1380 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
1381 int retval;
1382 char name[2 + U32_MAX_DIGITS + 1 + U32_MAX_DIGITS + 1];
1383 u32 perm;
1384
1385 p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %hx MAJOR: %u MINOR: %u\n",
1386 dir->i_ino, dentry, mode,
1387 MAJOR(rdev), MINOR(rdev));
1388
1389
1390 if (S_ISBLK(mode))
1391 sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
1392 else if (S_ISCHR(mode))
1393 sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));
1394 else
1395 *name = 0;
1396
1397 perm = unixmode2p9mode(v9ses, mode);
1398 retval = v9fs_vfs_mkspecial(dir, dentry, perm, name);
1399
1400 return retval;
1401}
1402
1403int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
1404{
1405 int umode;
1406 dev_t rdev;
1407 loff_t i_size;
1408 struct p9_wstat *st;
1409 struct v9fs_session_info *v9ses;
1410
1411 v9ses = v9fs_inode2v9ses(inode);
1412 st = p9_client_stat(fid);
1413 if (IS_ERR(st))
1414 return PTR_ERR(st);
1415
1416
1417
1418 umode = p9mode2unixmode(v9ses, st, &rdev);
1419 if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
1420 goto out;
1421
1422 spin_lock(&inode->i_lock);
1423
1424
1425
1426
1427 i_size = inode->i_size;
1428 v9fs_stat2inode(st, inode, inode->i_sb);
1429 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
1430 inode->i_size = i_size;
1431 spin_unlock(&inode->i_lock);
1432out:
1433 p9stat_free(st);
1434 kfree(st);
1435 return 0;
1436}
1437
1438static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1439 .create = v9fs_vfs_create,
1440 .lookup = v9fs_vfs_lookup,
1441 .atomic_open = v9fs_vfs_atomic_open,
1442 .symlink = v9fs_vfs_symlink,
1443 .link = v9fs_vfs_link,
1444 .unlink = v9fs_vfs_unlink,
1445 .mkdir = v9fs_vfs_mkdir,
1446 .rmdir = v9fs_vfs_rmdir,
1447 .mknod = v9fs_vfs_mknod,
1448 .rename = v9fs_vfs_rename,
1449 .getattr = v9fs_vfs_getattr,
1450 .setattr = v9fs_vfs_setattr,
1451};
1452
1453static const struct inode_operations v9fs_dir_inode_operations = {
1454 .create = v9fs_vfs_create,
1455 .lookup = v9fs_vfs_lookup,
1456 .atomic_open = v9fs_vfs_atomic_open,
1457 .unlink = v9fs_vfs_unlink,
1458 .mkdir = v9fs_vfs_mkdir,
1459 .rmdir = v9fs_vfs_rmdir,
1460 .mknod = v9fs_vfs_mknod,
1461 .rename = v9fs_vfs_rename,
1462 .getattr = v9fs_vfs_getattr,
1463 .setattr = v9fs_vfs_setattr,
1464};
1465
1466static const struct inode_operations v9fs_file_inode_operations = {
1467 .getattr = v9fs_vfs_getattr,
1468 .setattr = v9fs_vfs_setattr,
1469};
1470
1471static const struct inode_operations v9fs_symlink_inode_operations = {
1472 .get_link = v9fs_vfs_get_link,
1473 .getattr = v9fs_vfs_getattr,
1474 .setattr = v9fs_vfs_setattr,
1475};
1476
1477