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