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