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 spin_lock_init(&v9inode->fscache_lock);
248#endif
249 v9inode->writeback_fid = NULL;
250 v9inode->cache_validity = 0;
251 mutex_init(&v9inode->v_mutex);
252 return &v9inode->vfs_inode;
253}
254
255
256
257
258
259
260static void v9fs_i_callback(struct rcu_head *head)
261{
262 struct inode *inode = container_of(head, struct inode, i_rcu);
263 kmem_cache_free(v9fs_inode_cache, V9FS_I(inode));
264}
265
266void v9fs_destroy_inode(struct inode *inode)
267{
268 call_rcu(&inode->i_rcu, v9fs_i_callback);
269}
270
271int v9fs_init_inode(struct v9fs_session_info *v9ses,
272 struct inode *inode, umode_t mode, dev_t rdev)
273{
274 int err = 0;
275
276 inode_init_owner(inode, NULL, mode);
277 inode->i_blocks = 0;
278 inode->i_rdev = rdev;
279 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
280 inode->i_mapping->a_ops = &v9fs_addr_operations;
281
282 switch (mode & S_IFMT) {
283 case S_IFIFO:
284 case S_IFBLK:
285 case S_IFCHR:
286 case S_IFSOCK:
287 if (v9fs_proto_dotl(v9ses)) {
288 inode->i_op = &v9fs_file_inode_operations_dotl;
289 } else if (v9fs_proto_dotu(v9ses)) {
290 inode->i_op = &v9fs_file_inode_operations;
291 } else {
292 p9_debug(P9_DEBUG_ERROR,
293 "special files without extended mode\n");
294 err = -EINVAL;
295 goto error;
296 }
297 init_special_inode(inode, inode->i_mode, inode->i_rdev);
298 break;
299 case S_IFREG:
300 if (v9fs_proto_dotl(v9ses)) {
301 inode->i_op = &v9fs_file_inode_operations_dotl;
302 if (v9ses->cache == 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_mapping);
455 clear_inode(inode);
456 filemap_fdatawrite(inode->i_mapping);
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 return 1;
487}
488
489static int v9fs_test_new_inode(struct inode *inode, void *data)
490{
491 return 0;
492}
493
494static int v9fs_set_inode(struct inode *inode, void *data)
495{
496 struct v9fs_inode *v9inode = V9FS_I(inode);
497 struct p9_wstat *st = (struct p9_wstat *)data;
498
499 memcpy(&v9inode->qid, &st->qid, sizeof(st->qid));
500 return 0;
501}
502
503static struct inode *v9fs_qid_iget(struct super_block *sb,
504 struct p9_qid *qid,
505 struct p9_wstat *st,
506 int new)
507{
508 dev_t rdev;
509 int retval;
510 umode_t umode;
511 unsigned long i_ino;
512 struct inode *inode;
513 struct v9fs_session_info *v9ses = sb->s_fs_info;
514 int (*test)(struct inode *, void *);
515
516 if (new)
517 test = v9fs_test_new_inode;
518 else
519 test = v9fs_test_inode;
520
521 i_ino = v9fs_qid2ino(qid);
522 inode = iget5_locked(sb, i_ino, test, v9fs_set_inode, st);
523 if (!inode)
524 return ERR_PTR(-ENOMEM);
525 if (!(inode->i_state & I_NEW))
526 return inode;
527
528
529
530
531
532 inode->i_ino = i_ino;
533 umode = p9mode2unixmode(v9ses, st, &rdev);
534 retval = v9fs_init_inode(v9ses, inode, umode, rdev);
535 if (retval)
536 goto error;
537
538 v9fs_stat2inode(st, inode, sb);
539 v9fs_cache_inode_get_cookie(inode);
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 = d_inode(dentry);
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 %pd\n", dentry);
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 v9fs_fid_add(dentry, fid);
699 d_instantiate(dentry, inode);
700 }
701 return ofid;
702error:
703 if (ofid)
704 p9_client_clunk(ofid);
705
706 if (fid)
707 p9_client_clunk(fid);
708
709 return ERR_PTR(err);
710}
711
712
713
714
715
716
717
718
719
720
721
722
723
724static int
725v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
726 bool excl)
727{
728 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
729 u32 perm = unixmode2p9mode(v9ses, mode);
730 struct p9_fid *fid;
731
732
733 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_ORDWR);
734 if (IS_ERR(fid))
735 return PTR_ERR(fid);
736
737 v9fs_invalidate_inode_attr(dir);
738 p9_client_clunk(fid);
739
740 return 0;
741}
742
743
744
745
746
747
748
749
750
751static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
752{
753 int err;
754 u32 perm;
755 struct p9_fid *fid;
756 struct v9fs_session_info *v9ses;
757
758 p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry);
759 err = 0;
760 v9ses = v9fs_inode2v9ses(dir);
761 perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
762 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD);
763 if (IS_ERR(fid)) {
764 err = PTR_ERR(fid);
765 fid = NULL;
766 } else {
767 inc_nlink(dir);
768 v9fs_invalidate_inode_attr(dir);
769 }
770
771 if (fid)
772 p9_client_clunk(fid);
773
774 return err;
775}
776
777
778
779
780
781
782
783
784
785struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
786 unsigned int flags)
787{
788 struct dentry *res;
789 struct v9fs_session_info *v9ses;
790 struct p9_fid *dfid, *fid;
791 struct inode *inode;
792 char *name;
793
794 p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%pd) %p flags: %x\n",
795 dir, dentry, dentry, flags);
796
797 if (dentry->d_name.len > NAME_MAX)
798 return ERR_PTR(-ENAMETOOLONG);
799
800 v9ses = v9fs_inode2v9ses(dir);
801
802 dfid = v9fs_fid_lookup(dentry->d_parent);
803 if (IS_ERR(dfid))
804 return ERR_CAST(dfid);
805
806 name = (char *) dentry->d_name.name;
807 fid = p9_client_walk(dfid, 1, &name, 1);
808 if (IS_ERR(fid)) {
809 if (fid == ERR_PTR(-ENOENT)) {
810 d_add(dentry, NULL);
811 return NULL;
812 }
813 return ERR_CAST(fid);
814 }
815
816
817
818
819
820 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
821 inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
822 else
823 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
824 if (IS_ERR(inode)) {
825 p9_client_clunk(fid);
826 return ERR_CAST(inode);
827 }
828
829
830
831
832
833
834
835 res = d_splice_alias(inode, dentry);
836 if (!res)
837 v9fs_fid_add(dentry, fid);
838 else if (!IS_ERR(res))
839 v9fs_fid_add(res, fid);
840 else
841 p9_client_clunk(fid);
842 return res;
843}
844
845static int
846v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
847 struct file *file, unsigned flags, umode_t mode,
848 int *opened)
849{
850 int err;
851 u32 perm;
852 struct v9fs_inode *v9inode;
853 struct v9fs_session_info *v9ses;
854 struct p9_fid *fid, *inode_fid;
855 struct dentry *res = NULL;
856
857 if (d_unhashed(dentry)) {
858 res = v9fs_vfs_lookup(dir, dentry, 0);
859 if (IS_ERR(res))
860 return PTR_ERR(res);
861
862 if (res)
863 dentry = res;
864 }
865
866
867 if (!(flags & O_CREAT) || d_really_is_positive(dentry))
868 return finish_no_open(file, res);
869
870 err = 0;
871
872 v9ses = v9fs_inode2v9ses(dir);
873 perm = unixmode2p9mode(v9ses, mode);
874 fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
875 v9fs_uflags2omode(flags,
876 v9fs_proto_dotu(v9ses)));
877 if (IS_ERR(fid)) {
878 err = PTR_ERR(fid);
879 fid = NULL;
880 goto error;
881 }
882
883 v9fs_invalidate_inode_attr(dir);
884 v9inode = V9FS_I(d_inode(dentry));
885 mutex_lock(&v9inode->v_mutex);
886 if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) &&
887 !v9inode->writeback_fid &&
888 ((flags & O_ACCMODE) != O_RDONLY)) {
889
890
891
892
893
894
895
896 inode_fid = v9fs_writeback_fid(dentry);
897 if (IS_ERR(inode_fid)) {
898 err = PTR_ERR(inode_fid);
899 mutex_unlock(&v9inode->v_mutex);
900 goto error;
901 }
902 v9inode->writeback_fid = (void *) inode_fid;
903 }
904 mutex_unlock(&v9inode->v_mutex);
905 err = finish_open(file, dentry, generic_file_open, opened);
906 if (err)
907 goto error;
908
909 file->private_data = fid;
910 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
911 v9fs_cache_inode_set_cookie(d_inode(dentry), file);
912
913 *opened |= FILE_CREATED;
914out:
915 dput(res);
916 return err;
917
918error:
919 if (fid)
920 p9_client_clunk(fid);
921 goto out;
922}
923
924
925
926
927
928
929
930
931int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
932{
933 return v9fs_remove(i, d, 0);
934}
935
936
937
938
939
940
941
942
943int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
944{
945 return v9fs_remove(i, d, AT_REMOVEDIR);
946}
947
948
949
950
951
952
953
954
955
956
957int
958v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
959 struct inode *new_dir, struct dentry *new_dentry)
960{
961 int retval;
962 struct inode *old_inode;
963 struct inode *new_inode;
964 struct v9fs_session_info *v9ses;
965 struct p9_fid *oldfid;
966 struct p9_fid *olddirfid;
967 struct p9_fid *newdirfid;
968 struct p9_wstat wstat;
969
970 p9_debug(P9_DEBUG_VFS, "\n");
971 retval = 0;
972 old_inode = d_inode(old_dentry);
973 new_inode = d_inode(new_dentry);
974 v9ses = v9fs_inode2v9ses(old_inode);
975 oldfid = v9fs_fid_lookup(old_dentry);
976 if (IS_ERR(oldfid))
977 return PTR_ERR(oldfid);
978
979 olddirfid = v9fs_fid_clone(old_dentry->d_parent);
980 if (IS_ERR(olddirfid)) {
981 retval = PTR_ERR(olddirfid);
982 goto done;
983 }
984
985 newdirfid = v9fs_fid_clone(new_dentry->d_parent);
986 if (IS_ERR(newdirfid)) {
987 retval = PTR_ERR(newdirfid);
988 goto clunk_olddir;
989 }
990
991 down_write(&v9ses->rename_sem);
992 if (v9fs_proto_dotl(v9ses)) {
993 retval = p9_client_renameat(olddirfid, old_dentry->d_name.name,
994 newdirfid, new_dentry->d_name.name);
995 if (retval == -EOPNOTSUPP)
996 retval = p9_client_rename(oldfid, newdirfid,
997 new_dentry->d_name.name);
998 if (retval != -EOPNOTSUPP)
999 goto clunk_newdir;
1000 }
1001 if (old_dentry->d_parent != new_dentry->d_parent) {
1002
1003
1004
1005
1006 p9_debug(P9_DEBUG_ERROR, "old dir and new dir are different\n");
1007 retval = -EXDEV;
1008 goto clunk_newdir;
1009 }
1010 v9fs_blank_wstat(&wstat);
1011 wstat.muid = v9ses->uname;
1012 wstat.name = (char *) new_dentry->d_name.name;
1013 retval = p9_client_wstat(oldfid, &wstat);
1014
1015clunk_newdir:
1016 if (!retval) {
1017 if (new_inode) {
1018 if (S_ISDIR(new_inode->i_mode))
1019 clear_nlink(new_inode);
1020 else
1021 drop_nlink(new_inode);
1022 }
1023 if (S_ISDIR(old_inode->i_mode)) {
1024 if (!new_inode)
1025 inc_nlink(new_dir);
1026 drop_nlink(old_dir);
1027 }
1028 v9fs_invalidate_inode_attr(old_inode);
1029 v9fs_invalidate_inode_attr(old_dir);
1030 v9fs_invalidate_inode_attr(new_dir);
1031
1032
1033 d_move(old_dentry, new_dentry);
1034 }
1035 up_write(&v9ses->rename_sem);
1036 p9_client_clunk(newdirfid);
1037
1038clunk_olddir:
1039 p9_client_clunk(olddirfid);
1040
1041done:
1042 return retval;
1043}
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053static int
1054v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1055 struct kstat *stat)
1056{
1057 struct v9fs_session_info *v9ses;
1058 struct p9_fid *fid;
1059 struct p9_wstat *st;
1060
1061 p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
1062 v9ses = v9fs_dentry2v9ses(dentry);
1063 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
1064 generic_fillattr(d_inode(dentry), stat);
1065 return 0;
1066 }
1067 fid = v9fs_fid_lookup(dentry);
1068 if (IS_ERR(fid))
1069 return PTR_ERR(fid);
1070
1071 st = p9_client_stat(fid);
1072 if (IS_ERR(st))
1073 return PTR_ERR(st);
1074
1075 v9fs_stat2inode(st, d_inode(dentry), d_inode(dentry)->i_sb);
1076 generic_fillattr(d_inode(dentry), stat);
1077
1078 p9stat_free(st);
1079 kfree(st);
1080 return 0;
1081}
1082
1083
1084
1085
1086
1087
1088
1089
1090static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
1091{
1092 int retval;
1093 struct v9fs_session_info *v9ses;
1094 struct p9_fid *fid;
1095 struct p9_wstat wstat;
1096
1097 p9_debug(P9_DEBUG_VFS, "\n");
1098 retval = inode_change_ok(d_inode(dentry), iattr);
1099 if (retval)
1100 return retval;
1101
1102 retval = -EPERM;
1103 v9ses = v9fs_dentry2v9ses(dentry);
1104 fid = v9fs_fid_lookup(dentry);
1105 if(IS_ERR(fid))
1106 return PTR_ERR(fid);
1107
1108 v9fs_blank_wstat(&wstat);
1109 if (iattr->ia_valid & ATTR_MODE)
1110 wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);
1111
1112 if (iattr->ia_valid & ATTR_MTIME)
1113 wstat.mtime = iattr->ia_mtime.tv_sec;
1114
1115 if (iattr->ia_valid & ATTR_ATIME)
1116 wstat.atime = iattr->ia_atime.tv_sec;
1117
1118 if (iattr->ia_valid & ATTR_SIZE)
1119 wstat.length = iattr->ia_size;
1120
1121 if (v9fs_proto_dotu(v9ses)) {
1122 if (iattr->ia_valid & ATTR_UID)
1123 wstat.n_uid = iattr->ia_uid;
1124
1125 if (iattr->ia_valid & ATTR_GID)
1126 wstat.n_gid = iattr->ia_gid;
1127 }
1128
1129
1130 if (d_is_reg(dentry))
1131 filemap_write_and_wait(d_inode(dentry)->i_mapping);
1132
1133 retval = p9_client_wstat(fid, &wstat);
1134 if (retval < 0)
1135 return retval;
1136
1137 if ((iattr->ia_valid & ATTR_SIZE) &&
1138 iattr->ia_size != i_size_read(d_inode(dentry)))
1139 truncate_setsize(d_inode(dentry), iattr->ia_size);
1140
1141 v9fs_invalidate_inode_attr(d_inode(dentry));
1142
1143 setattr_copy(d_inode(dentry), iattr);
1144 mark_inode_dirty(d_inode(dentry));
1145 return 0;
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)
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 i_size_write(inode, stat->length);
1200
1201
1202 inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
1203 v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
1204}
1205
1206
1207
1208
1209
1210
1211
1212
1213ino_t v9fs_qid2ino(struct p9_qid *qid)
1214{
1215 u64 path = qid->path + 2;
1216 ino_t i = 0;
1217
1218 if (sizeof(ino_t) == sizeof(path))
1219 memcpy(&i, &path, sizeof(ino_t));
1220 else
1221 i = (ino_t) (path ^ (path >> 32));
1222
1223 return i;
1224}
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
1235{
1236 int retval;
1237
1238 struct v9fs_session_info *v9ses;
1239 struct p9_fid *fid;
1240 struct p9_wstat *st;
1241
1242 p9_debug(P9_DEBUG_VFS, " %pd\n", dentry);
1243 retval = -EPERM;
1244 v9ses = v9fs_dentry2v9ses(dentry);
1245 fid = v9fs_fid_lookup(dentry);
1246 if (IS_ERR(fid))
1247 return PTR_ERR(fid);
1248
1249 if (!v9fs_proto_dotu(v9ses))
1250 return -EBADF;
1251
1252 st = p9_client_stat(fid);
1253 if (IS_ERR(st))
1254 return PTR_ERR(st);
1255
1256 if (!(st->mode & P9_DMSYMLINK)) {
1257 retval = -EINVAL;
1258 goto done;
1259 }
1260
1261
1262 retval = min(strlen(st->extension)+1, (size_t)buflen);
1263 memcpy(buffer, st->extension, retval);
1264
1265 p9_debug(P9_DEBUG_VFS, "%pd -> %s (%.*s)\n",
1266 dentry, st->extension, buflen, buffer);
1267
1268done:
1269 p9stat_free(st);
1270 kfree(st);
1271 return retval;
1272}
1273
1274
1275
1276
1277
1278
1279
1280
1281static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
1282{
1283 int len = 0;
1284 char *link = __getname();
1285
1286 p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
1287
1288 if (!link)
1289 link = ERR_PTR(-ENOMEM);
1290 else {
1291 len = v9fs_readlink(dentry, link, PATH_MAX);
1292
1293 if (len < 0) {
1294 __putname(link);
1295 link = ERR_PTR(len);
1296 } else
1297 link[min(len, PATH_MAX-1)] = 0;
1298 }
1299 nd_set_link(nd, link);
1300
1301 return NULL;
1302}
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312void
1313v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
1314{
1315 char *s = nd_get_link(nd);
1316
1317 p9_debug(P9_DEBUG_VFS, " %pd %s\n",
1318 dentry, IS_ERR(s) ? "<error>" : s);
1319 if (!IS_ERR(s))
1320 __putname(s);
1321}
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
1333 u32 perm, const char *extension)
1334{
1335 struct p9_fid *fid;
1336 struct v9fs_session_info *v9ses;
1337
1338 v9ses = v9fs_inode2v9ses(dir);
1339 if (!v9fs_proto_dotu(v9ses)) {
1340 p9_debug(P9_DEBUG_ERROR, "not extended\n");
1341 return -EPERM;
1342 }
1343
1344 fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
1345 P9_OREAD);
1346 if (IS_ERR(fid))
1347 return PTR_ERR(fid);
1348
1349 v9fs_invalidate_inode_attr(dir);
1350 p9_client_clunk(fid);
1351 return 0;
1352}
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364static int
1365v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1366{
1367 p9_debug(P9_DEBUG_VFS, " %lu,%pd,%s\n",
1368 dir->i_ino, dentry, symname);
1369
1370 return v9fs_vfs_mkspecial(dir, dentry, P9_DMSYMLINK, symname);
1371}
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381static int
1382v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1383 struct dentry *dentry)
1384{
1385 int retval;
1386 char *name;
1387 struct p9_fid *oldfid;
1388
1389 p9_debug(P9_DEBUG_VFS, " %lu,%pd,%pd\n",
1390 dir->i_ino, dentry, old_dentry);
1391
1392 oldfid = v9fs_fid_clone(old_dentry);
1393 if (IS_ERR(oldfid))
1394 return PTR_ERR(oldfid);
1395
1396 name = __getname();
1397 if (unlikely(!name)) {
1398 retval = -ENOMEM;
1399 goto clunk_fid;
1400 }
1401
1402 sprintf(name, "%d\n", oldfid->fid);
1403 retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
1404 __putname(name);
1405 if (!retval) {
1406 v9fs_refresh_inode(oldfid, d_inode(old_dentry));
1407 v9fs_invalidate_inode_attr(dir);
1408 }
1409clunk_fid:
1410 p9_client_clunk(oldfid);
1411 return retval;
1412}
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423static int
1424v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
1425{
1426 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
1427 int retval;
1428 char *name;
1429 u32 perm;
1430
1431 p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %hx MAJOR: %u MINOR: %u\n",
1432 dir->i_ino, dentry, mode,
1433 MAJOR(rdev), MINOR(rdev));
1434
1435 if (!new_valid_dev(rdev))
1436 return -EINVAL;
1437
1438 name = __getname();
1439 if (!name)
1440 return -ENOMEM;
1441
1442 if (S_ISBLK(mode))
1443 sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
1444 else if (S_ISCHR(mode))
1445 sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));
1446 else if (S_ISFIFO(mode))
1447 *name = 0;
1448 else if (S_ISSOCK(mode))
1449 *name = 0;
1450 else {
1451 __putname(name);
1452 return -EINVAL;
1453 }
1454
1455 perm = unixmode2p9mode(v9ses, mode);
1456 retval = v9fs_vfs_mkspecial(dir, dentry, perm, name);
1457 __putname(name);
1458
1459 return retval;
1460}
1461
1462int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
1463{
1464 int umode;
1465 dev_t rdev;
1466 loff_t i_size;
1467 struct p9_wstat *st;
1468 struct v9fs_session_info *v9ses;
1469
1470 v9ses = v9fs_inode2v9ses(inode);
1471 st = p9_client_stat(fid);
1472 if (IS_ERR(st))
1473 return PTR_ERR(st);
1474
1475
1476
1477 umode = p9mode2unixmode(v9ses, st, &rdev);
1478 if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
1479 goto out;
1480
1481 spin_lock(&inode->i_lock);
1482
1483
1484
1485
1486 i_size = inode->i_size;
1487 v9fs_stat2inode(st, inode, inode->i_sb);
1488 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
1489 inode->i_size = i_size;
1490 spin_unlock(&inode->i_lock);
1491out:
1492 p9stat_free(st);
1493 kfree(st);
1494 return 0;
1495}
1496
1497static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1498 .create = v9fs_vfs_create,
1499 .lookup = v9fs_vfs_lookup,
1500 .atomic_open = v9fs_vfs_atomic_open,
1501 .symlink = v9fs_vfs_symlink,
1502 .link = v9fs_vfs_link,
1503 .unlink = v9fs_vfs_unlink,
1504 .mkdir = v9fs_vfs_mkdir,
1505 .rmdir = v9fs_vfs_rmdir,
1506 .mknod = v9fs_vfs_mknod,
1507 .rename = v9fs_vfs_rename,
1508 .getattr = v9fs_vfs_getattr,
1509 .setattr = v9fs_vfs_setattr,
1510};
1511
1512static const struct inode_operations v9fs_dir_inode_operations = {
1513 .create = v9fs_vfs_create,
1514 .lookup = v9fs_vfs_lookup,
1515 .atomic_open = v9fs_vfs_atomic_open,
1516 .unlink = v9fs_vfs_unlink,
1517 .mkdir = v9fs_vfs_mkdir,
1518 .rmdir = v9fs_vfs_rmdir,
1519 .mknod = v9fs_vfs_mknod,
1520 .rename = v9fs_vfs_rename,
1521 .getattr = v9fs_vfs_getattr,
1522 .setattr = v9fs_vfs_setattr,
1523};
1524
1525static const struct inode_operations v9fs_file_inode_operations = {
1526 .getattr = v9fs_vfs_getattr,
1527 .setattr = v9fs_vfs_setattr,
1528};
1529
1530static const struct inode_operations v9fs_symlink_inode_operations = {
1531 .readlink = generic_readlink,
1532 .follow_link = v9fs_vfs_follow_link,
1533 .put_link = v9fs_vfs_put_link,
1534 .getattr = v9fs_vfs_getattr,
1535 .setattr = v9fs_vfs_setattr,
1536};
1537
1538