blob: ffce168296bd3b5679ea2661099863862c2cfd0d [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * linux/fs/9p/vfs_inode.c
4 *
5 * This file contains vfs inode ops for the 9P2000 protocol.
6 *
7 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
8 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
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 * unixmode2p9mode - convert unix mode bits to plan 9
44 * @v9ses: v9fs session information
45 * @mode: mode to convert
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 * p9mode2perm- convert plan9 mode bits to unix permission bits
79 * @v9ses: v9fs session information
80 * @stat: p9_wstat from which mode need to be derived
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 & 0777; /* S_IRWXUGO */
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 * p9mode2unixmode- convert plan9 mode bits to unix mode bits
105 * @v9ses: v9fs session information
106 * @stat: p9_wstat from which mode need to be derived
107 * @rdev: major number, minor number in case of device files.
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 * v9fs_uflags2omode- convert posix open flags to plan 9 mode bits
156 * @uflags: flags to convert
157 * @extended: if .u extensions are active
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 (uflags & O_TRUNC)
181 ret |= P9_OTRUNC;
182
183 if (extended) {
184 if (uflags & O_EXCL)
185 ret |= P9_OEXCL;
186
187 if (uflags & O_APPEND)
188 ret |= P9_OAPPEND;
189 }
190
191 return ret;
192}
193
194/**
195 * v9fs_blank_wstat - helper function to setup a 9P stat structure
196 * @wstat: structure to initialize
197 *
198 */
199
200void
201v9fs_blank_wstat(struct p9_wstat *wstat)
202{
203 wstat->type = ~0;
204 wstat->dev = ~0;
205 wstat->qid.type = ~0;
206 wstat->qid.version = ~0;
207 *((long long *)&wstat->qid.path) = ~0;
208 wstat->mode = ~0;
209 wstat->atime = ~0;
210 wstat->mtime = ~0;
211 wstat->length = ~0;
212 wstat->name = NULL;
213 wstat->uid = NULL;
214 wstat->gid = NULL;
215 wstat->muid = NULL;
216 wstat->n_uid = INVALID_UID;
217 wstat->n_gid = INVALID_GID;
218 wstat->n_muid = INVALID_UID;
219 wstat->extension = NULL;
220}
221
222/**
223 * v9fs_alloc_inode - helper function to allocate an inode
224 *
225 */
226struct inode *v9fs_alloc_inode(struct super_block *sb)
227{
228 struct v9fs_inode *v9inode;
229 v9inode = (struct v9fs_inode *)kmem_cache_alloc(v9fs_inode_cache,
230 GFP_KERNEL);
231 if (!v9inode)
232 return NULL;
233#ifdef CONFIG_9P_FSCACHE
234 v9inode->fscache = NULL;
235 mutex_init(&v9inode->fscache_lock);
236#endif
237 v9inode->writeback_fid = NULL;
238 v9inode->cache_validity = 0;
239 mutex_init(&v9inode->v_mutex);
240 return &v9inode->vfs_inode;
241}
242
243/**
244 * v9fs_free_inode - destroy an inode
245 *
246 */
247
248void v9fs_free_inode(struct inode *inode)
249{
250 kmem_cache_free(v9fs_inode_cache, V9FS_I(inode));
251}
252
253int v9fs_init_inode(struct v9fs_session_info *v9ses,
254 struct inode *inode, umode_t mode, dev_t rdev)
255{
256 int err = 0;
257
258 inode_init_owner(inode, NULL, mode);
259 inode->i_blocks = 0;
260 inode->i_rdev = rdev;
261 inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
262 inode->i_mapping->a_ops = &v9fs_addr_operations;
263
264 switch (mode & S_IFMT) {
265 case S_IFIFO:
266 case S_IFBLK:
267 case S_IFCHR:
268 case S_IFSOCK:
269 if (v9fs_proto_dotl(v9ses)) {
270 inode->i_op = &v9fs_file_inode_operations_dotl;
271 } else if (v9fs_proto_dotu(v9ses)) {
272 inode->i_op = &v9fs_file_inode_operations;
273 } else {
274 p9_debug(P9_DEBUG_ERROR,
275 "special files without extended mode\n");
276 err = -EINVAL;
277 goto error;
278 }
279 init_special_inode(inode, inode->i_mode, inode->i_rdev);
280 break;
281 case S_IFREG:
282 if (v9fs_proto_dotl(v9ses)) {
283 inode->i_op = &v9fs_file_inode_operations_dotl;
284 if (v9ses->cache == CACHE_LOOSE ||
285 v9ses->cache == CACHE_FSCACHE)
286 inode->i_fop =
287 &v9fs_cached_file_operations_dotl;
288 else if (v9ses->cache == CACHE_MMAP)
289 inode->i_fop = &v9fs_mmap_file_operations_dotl;
290 else
291 inode->i_fop = &v9fs_file_operations_dotl;
292 } else {
293 inode->i_op = &v9fs_file_inode_operations;
294 if (v9ses->cache == CACHE_LOOSE ||
295 v9ses->cache == CACHE_FSCACHE)
296 inode->i_fop =
297 &v9fs_cached_file_operations;
298 else if (v9ses->cache == CACHE_MMAP)
299 inode->i_fop = &v9fs_mmap_file_operations;
300 else
301 inode->i_fop = &v9fs_file_operations;
302 }
303
304 break;
305 case S_IFLNK:
306 if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) {
307 p9_debug(P9_DEBUG_ERROR,
308 "extended modes used with legacy protocol\n");
309 err = -EINVAL;
310 goto error;
311 }
312
313 if (v9fs_proto_dotl(v9ses))
314 inode->i_op = &v9fs_symlink_inode_operations_dotl;
315 else
316 inode->i_op = &v9fs_symlink_inode_operations;
317
318 break;
319 case S_IFDIR:
320 inc_nlink(inode);
321 if (v9fs_proto_dotl(v9ses))
322 inode->i_op = &v9fs_dir_inode_operations_dotl;
323 else if (v9fs_proto_dotu(v9ses))
324 inode->i_op = &v9fs_dir_inode_operations_dotu;
325 else
326 inode->i_op = &v9fs_dir_inode_operations;
327
328 if (v9fs_proto_dotl(v9ses))
329 inode->i_fop = &v9fs_dir_operations_dotl;
330 else
331 inode->i_fop = &v9fs_dir_operations;
332
333 break;
334 default:
335 p9_debug(P9_DEBUG_ERROR, "BAD mode 0x%hx S_IFMT 0x%x\n",
336 mode, mode & S_IFMT);
337 err = -EINVAL;
338 goto error;
339 }
340error:
341 return err;
342
343}
344
345/**
346 * v9fs_get_inode - helper function to setup an inode
347 * @sb: superblock
348 * @mode: mode to setup inode with
349 *
350 */
351
352struct inode *v9fs_get_inode(struct super_block *sb, umode_t mode, dev_t rdev)
353{
354 int err;
355 struct inode *inode;
356 struct v9fs_session_info *v9ses = sb->s_fs_info;
357
358 p9_debug(P9_DEBUG_VFS, "super block: %p mode: %ho\n", sb, mode);
359
360 inode = new_inode(sb);
361 if (!inode) {
362 pr_warn("%s (%d): Problem allocating inode\n",
363 __func__, task_pid_nr(current));
364 return ERR_PTR(-ENOMEM);
365 }
366 err = v9fs_init_inode(v9ses, inode, mode, rdev);
367 if (err) {
368 iput(inode);
369 return ERR_PTR(err);
370 }
371 return inode;
372}
373
374/*
375static struct v9fs_fid*
376v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
377{
378 int err;
379 int nfid;
380 struct v9fs_fid *ret;
381 struct v9fs_fcall *fcall;
382
383 nfid = v9fs_get_idpool(&v9ses->fidpool);
384 if (nfid < 0) {
385 eprintk(KERN_WARNING, "no free fids available\n");
386 return ERR_PTR(-ENOSPC);
387 }
388
389 err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name,
390 &fcall);
391
392 if (err < 0) {
393 if (fcall && fcall->id == RWALK)
394 goto clunk_fid;
395
396 PRINT_FCALL_ERROR("walk error", fcall);
397 v9fs_put_idpool(nfid, &v9ses->fidpool);
398 goto error;
399 }
400
401 kfree(fcall);
402 fcall = NULL;
403 ret = v9fs_fid_create(v9ses, nfid);
404 if (!ret) {
405 err = -ENOMEM;
406 goto clunk_fid;
407 }
408
409 err = v9fs_fid_insert(ret, dentry);
410 if (err < 0) {
411 v9fs_fid_destroy(ret);
412 goto clunk_fid;
413 }
414
415 return ret;
416
417clunk_fid:
418 v9fs_t_clunk(v9ses, nfid);
419
420error:
421 kfree(fcall);
422 return ERR_PTR(err);
423}
424*/
425
426
427/**
428 * v9fs_clear_inode - release an inode
429 * @inode: inode to release
430 *
431 */
432void v9fs_evict_inode(struct inode *inode)
433{
434 struct v9fs_inode *v9inode = V9FS_I(inode);
435
436 truncate_inode_pages_final(&inode->i_data);
437 clear_inode(inode);
438 filemap_fdatawrite(&inode->i_data);
439
440 v9fs_cache_inode_put_cookie(inode);
441 /* clunk the fid stashed in writeback_fid */
442 if (v9inode->writeback_fid) {
443 p9_client_clunk(v9inode->writeback_fid);
444 v9inode->writeback_fid = NULL;
445 }
446}
447
448static int v9fs_test_inode(struct inode *inode, void *data)
449{
450 int umode;
451 dev_t rdev;
452 struct v9fs_inode *v9inode = V9FS_I(inode);
453 struct p9_wstat *st = (struct p9_wstat *)data;
454 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
455
456 umode = p9mode2unixmode(v9ses, st, &rdev);
457 /* don't match inode of different type */
458 if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
459 return 0;
460
461 /* compare qid details */
462 if (memcmp(&v9inode->qid.version,
463 &st->qid.version, sizeof(v9inode->qid.version)))
464 return 0;
465
466 if (v9inode->qid.type != st->qid.type)
467 return 0;
468
469 if (v9inode->qid.path != st->qid.path)
470 return 0;
471 return 1;
472}
473
474static int v9fs_test_new_inode(struct inode *inode, void *data)
475{
476 return 0;
477}
478
479static int v9fs_set_inode(struct inode *inode, void *data)
480{
481 struct v9fs_inode *v9inode = V9FS_I(inode);
482 struct p9_wstat *st = (struct p9_wstat *)data;
483
484 memcpy(&v9inode->qid, &st->qid, sizeof(st->qid));
485 return 0;
486}
487
488static struct inode *v9fs_qid_iget(struct super_block *sb,
489 struct p9_qid *qid,
490 struct p9_wstat *st,
491 int new)
492{
493 dev_t rdev;
494 int retval;
495 umode_t umode;
496 unsigned long i_ino;
497 struct inode *inode;
498 struct v9fs_session_info *v9ses = sb->s_fs_info;
499 int (*test)(struct inode *, void *);
500
501 if (new)
502 test = v9fs_test_new_inode;
503 else
504 test = v9fs_test_inode;
505
506 i_ino = v9fs_qid2ino(qid);
507 inode = iget5_locked(sb, i_ino, test, v9fs_set_inode, st);
508 if (!inode)
509 return ERR_PTR(-ENOMEM);
510 if (!(inode->i_state & I_NEW))
511 return inode;
512 /*
513 * initialize the inode with the stat info
514 * FIXME!! we may need support for stale inodes
515 * later.
516 */
517 inode->i_ino = i_ino;
518 umode = p9mode2unixmode(v9ses, st, &rdev);
519 retval = v9fs_init_inode(v9ses, inode, umode, rdev);
520 if (retval)
521 goto error;
522
523 v9fs_stat2inode(st, inode, sb, 0);
524 v9fs_cache_inode_get_cookie(inode);
525 unlock_new_inode(inode);
526 return inode;
527error:
528 iget_failed(inode);
529 return ERR_PTR(retval);
530
531}
532
533struct inode *
534v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
535 struct super_block *sb, int new)
536{
537 struct p9_wstat *st;
538 struct inode *inode = NULL;
539
540 st = p9_client_stat(fid);
541 if (IS_ERR(st))
542 return ERR_CAST(st);
543
544 inode = v9fs_qid_iget(sb, &st->qid, st, new);
545 p9stat_free(st);
546 kfree(st);
547 return inode;
548}
549
550/**
551 * v9fs_at_to_dotl_flags- convert Linux specific AT flags to
552 * plan 9 AT flag.
553 * @flags: flags to convert
554 */
555static int v9fs_at_to_dotl_flags(int flags)
556{
557 int rflags = 0;
558 if (flags & AT_REMOVEDIR)
559 rflags |= P9_DOTL_AT_REMOVEDIR;
560 return rflags;
561}
562
563/**
564 * v9fs_dec_count - helper functon to drop i_nlink.
565 *
566 * If a directory had nlink <= 2 (including . and ..), then we should not drop
567 * the link count, which indicates the underlying exported fs doesn't maintain
568 * nlink accurately. e.g.
569 * - overlayfs sets nlink to 1 for merged dir
570 * - ext4 (with dir_nlink feature enabled) sets nlink to 1 if a dir has more
571 * than EXT4_LINK_MAX (65000) links.
572 *
573 * @inode: inode whose nlink is being dropped
574 */
575static void v9fs_dec_count(struct inode *inode)
576{
577 if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2)
578 drop_nlink(inode);
579}
580
581/**
582 * v9fs_remove - helper function to remove files and directories
583 * @dir: directory inode that is being deleted
584 * @dentry: dentry that is being deleted
585 * @flags: removing a directory
586 *
587 */
588
589static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
590{
591 struct inode *inode;
592 int retval = -EOPNOTSUPP;
593 struct p9_fid *v9fid, *dfid;
594 struct v9fs_session_info *v9ses;
595
596 p9_debug(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %x\n",
597 dir, dentry, flags);
598
599 v9ses = v9fs_inode2v9ses(dir);
600 inode = d_inode(dentry);
601 dfid = v9fs_parent_fid(dentry);
602 if (IS_ERR(dfid)) {
603 retval = PTR_ERR(dfid);
604 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", retval);
605 return retval;
606 }
607 if (v9fs_proto_dotl(v9ses))
608 retval = p9_client_unlinkat(dfid, dentry->d_name.name,
609 v9fs_at_to_dotl_flags(flags));
610 if (retval == -EOPNOTSUPP) {
611 /* Try the one based on path */
612 v9fid = v9fs_fid_clone(dentry);
613 if (IS_ERR(v9fid))
614 return PTR_ERR(v9fid);
615 retval = p9_client_remove(v9fid);
616 }
617 if (!retval) {
618 /*
619 * directories on unlink should have zero
620 * link count
621 */
622 if (flags & AT_REMOVEDIR) {
623 clear_nlink(inode);
624 v9fs_dec_count(dir);
625 } else
626 v9fs_dec_count(inode);
627
628 v9fs_invalidate_inode_attr(inode);
629 v9fs_invalidate_inode_attr(dir);
630 }
631 return retval;
632}
633
634/**
635 * v9fs_create - Create a file
636 * @v9ses: session information
637 * @dir: directory that dentry is being created in
638 * @dentry: dentry that is being created
639 * @extension: 9p2000.u extension string to support devices, etc.
640 * @perm: create permissions
641 * @mode: open mode
642 *
643 */
644static struct p9_fid *
645v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
646 struct dentry *dentry, char *extension, u32 perm, u8 mode)
647{
648 int err;
649 const unsigned char *name;
650 struct p9_fid *dfid, *ofid, *fid;
651 struct inode *inode;
652
653 p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry);
654
655 err = 0;
656 ofid = NULL;
657 fid = NULL;
658 name = dentry->d_name.name;
659 dfid = v9fs_parent_fid(dentry);
660 if (IS_ERR(dfid)) {
661 err = PTR_ERR(dfid);
662 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
663 return ERR_PTR(err);
664 }
665
666 /* clone a fid to use for creation */
667 ofid = clone_fid(dfid);
668 if (IS_ERR(ofid)) {
669 err = PTR_ERR(ofid);
670 p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
671 return ERR_PTR(err);
672 }
673
674 err = p9_client_fcreate(ofid, name, perm, mode, extension);
675 if (err < 0) {
676 p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
677 goto error;
678 }
679
680 if (!(perm & P9_DMLINK)) {
681 /* now walk from the parent so we can get unopened fid */
682 fid = p9_client_walk(dfid, 1, &name, 1);
683 if (IS_ERR(fid)) {
684 err = PTR_ERR(fid);
685 p9_debug(P9_DEBUG_VFS,
686 "p9_client_walk failed %d\n", err);
687 fid = NULL;
688 goto error;
689 }
690 /*
691 * instantiate inode and assign the unopened fid to the dentry
692 */
693 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
694 if (IS_ERR(inode)) {
695 err = PTR_ERR(inode);
696 p9_debug(P9_DEBUG_VFS,
697 "inode creation failed %d\n", err);
698 goto error;
699 }
700 v9fs_fid_add(dentry, fid);
701 d_instantiate(dentry, inode);
702 }
703 return ofid;
704error:
705 if (ofid)
706 p9_client_clunk(ofid);
707
708 if (fid)
709 p9_client_clunk(fid);
710
711 return ERR_PTR(err);
712}
713
714/**
715 * v9fs_vfs_create - VFS hook to create a regular file
716 *
717 * open(.., O_CREAT) is handled in v9fs_vfs_atomic_open(). This is only called
718 * for mknod(2).
719 *
720 * @dir: directory inode that is being created
721 * @dentry: dentry that is being deleted
722 * @mode: create permissions
723 *
724 */
725
726static int
727v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
728 bool excl)
729{
730 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
731 u32 perm = unixmode2p9mode(v9ses, mode);
732 struct p9_fid *fid;
733
734 /* P9_OEXCL? */
735 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_ORDWR);
736 if (IS_ERR(fid))
737 return PTR_ERR(fid);
738
739 v9fs_invalidate_inode_attr(dir);
740 p9_client_clunk(fid);
741
742 return 0;
743}
744
745/**
746 * v9fs_vfs_mkdir - VFS mkdir hook to create a directory
747 * @dir: inode that is being unlinked
748 * @dentry: dentry that is being unlinked
749 * @mode: mode for new directory
750 *
751 */
752
753static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
754{
755 int err;
756 u32 perm;
757 struct p9_fid *fid;
758 struct v9fs_session_info *v9ses;
759
760 p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry);
761 err = 0;
762 v9ses = v9fs_inode2v9ses(dir);
763 perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
764 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD);
765 if (IS_ERR(fid)) {
766 err = PTR_ERR(fid);
767 fid = NULL;
768 } else {
769 inc_nlink(dir);
770 v9fs_invalidate_inode_attr(dir);
771 }
772
773 if (fid)
774 p9_client_clunk(fid);
775
776 return err;
777}
778
779/**
780 * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode
781 * @dir: inode that is being walked from
782 * @dentry: dentry that is being walked to?
783 * @flags: lookup flags (unused)
784 *
785 */
786
787struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
788 unsigned int flags)
789{
790 struct dentry *res;
791 struct v9fs_session_info *v9ses;
792 struct p9_fid *dfid, *fid;
793 struct inode *inode;
794 const unsigned char *name;
795
796 p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%pd) %p flags: %x\n",
797 dir, dentry, dentry, flags);
798
799 if (dentry->d_name.len > NAME_MAX)
800 return ERR_PTR(-ENAMETOOLONG);
801
802 v9ses = v9fs_inode2v9ses(dir);
803 /* We can walk d_parent because we hold the dir->i_mutex */
804 dfid = v9fs_parent_fid(dentry);
805 if (IS_ERR(dfid))
806 return ERR_CAST(dfid);
807
808 /*
809 * Make sure we don't use a wrong inode due to parallel
810 * unlink. For cached mode create calls request for new
811 * inode. But with cache disabled, lookup should do this.
812 */
813 name = dentry->d_name.name;
814 fid = p9_client_walk(dfid, 1, &name, 1);
815 if (fid == ERR_PTR(-ENOENT))
816 inode = NULL;
817 else if (IS_ERR(fid))
818 inode = ERR_CAST(fid);
819 else 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 /*
824 * If we had a rename on the server and a parallel lookup
825 * for the new name, then make sure we instantiate with
826 * the new name. ie look up for a/b, while on server somebody
827 * moved b under k and client parallely did a lookup for
828 * k/b.
829 */
830 res = d_splice_alias(inode, dentry);
831 if (!IS_ERR(fid)) {
832 if (!res)
833 v9fs_fid_add(dentry, fid);
834 else if (!IS_ERR(res))
835 v9fs_fid_add(res, fid);
836 else
837 p9_client_clunk(fid);
838 }
839 return res;
840}
841
842static int
843v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
844 struct file *file, unsigned flags, umode_t mode)
845{
846 int err;
847 u32 perm;
848 struct v9fs_inode *v9inode;
849 struct v9fs_session_info *v9ses;
850 struct p9_fid *fid, *inode_fid;
851 struct dentry *res = NULL;
852
853 if (d_in_lookup(dentry)) {
854 res = v9fs_vfs_lookup(dir, dentry, 0);
855 if (IS_ERR(res))
856 return PTR_ERR(res);
857
858 if (res)
859 dentry = res;
860 }
861
862 /* Only creates */
863 if (!(flags & O_CREAT) || d_really_is_positive(dentry))
864 return finish_no_open(file, res);
865
866 err = 0;
867
868 v9ses = v9fs_inode2v9ses(dir);
869 perm = unixmode2p9mode(v9ses, mode);
870 fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
871 v9fs_uflags2omode(flags,
872 v9fs_proto_dotu(v9ses)));
873 if (IS_ERR(fid)) {
874 err = PTR_ERR(fid);
875 fid = NULL;
876 goto error;
877 }
878
879 v9fs_invalidate_inode_attr(dir);
880 v9inode = V9FS_I(d_inode(dentry));
881 mutex_lock(&v9inode->v_mutex);
882 if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) &&
883 !v9inode->writeback_fid &&
884 ((flags & O_ACCMODE) != O_RDONLY)) {
885 /*
886 * clone a fid and add it to writeback_fid
887 * we do it during open time instead of
888 * page dirty time via write_begin/page_mkwrite
889 * because we want write after unlink usecase
890 * to work.
891 */
892 inode_fid = v9fs_writeback_fid(dentry);
893 if (IS_ERR(inode_fid)) {
894 err = PTR_ERR(inode_fid);
895 mutex_unlock(&v9inode->v_mutex);
896 goto error;
897 }
898 v9inode->writeback_fid = (void *) inode_fid;
899 }
900 mutex_unlock(&v9inode->v_mutex);
901 err = finish_open(file, dentry, generic_file_open);
902 if (err)
903 goto error;
904
905 file->private_data = fid;
906 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
907 v9fs_cache_inode_set_cookie(d_inode(dentry), file);
908
909 file->f_mode |= FMODE_CREATED;
910out:
911 dput(res);
912 return err;
913
914error:
915 if (fid)
916 p9_client_clunk(fid);
917 goto out;
918}
919
920/**
921 * v9fs_vfs_unlink - VFS unlink hook to delete an inode
922 * @i: inode that is being unlinked
923 * @d: dentry that is being unlinked
924 *
925 */
926
927int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
928{
929 return v9fs_remove(i, d, 0);
930}
931
932/**
933 * v9fs_vfs_rmdir - VFS unlink hook to delete a directory
934 * @i: inode that is being unlinked
935 * @d: dentry that is being unlinked
936 *
937 */
938
939int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
940{
941 return v9fs_remove(i, d, AT_REMOVEDIR);
942}
943
944/**
945 * v9fs_vfs_rename - VFS hook to rename an inode
946 * @old_dir: old dir inode
947 * @old_dentry: old dentry
948 * @new_dir: new dir inode
949 * @new_dentry: new dentry
950 *
951 */
952
953int
954v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
955 struct inode *new_dir, struct dentry *new_dentry,
956 unsigned int flags)
957{
958 int retval;
959 struct inode *old_inode;
960 struct inode *new_inode;
961 struct v9fs_session_info *v9ses;
962 struct p9_fid *oldfid;
963 struct p9_fid *olddirfid;
964 struct p9_fid *newdirfid;
965 struct p9_wstat wstat;
966
967 if (flags)
968 return -EINVAL;
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 = clone_fid(v9fs_parent_fid(old_dentry));
980 if (IS_ERR(olddirfid)) {
981 retval = PTR_ERR(olddirfid);
982 goto done;
983 }
984
985 newdirfid = clone_fid(v9fs_parent_fid(new_dentry));
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 * 9P .u can only handle file rename in the same directory
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 = 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 v9fs_dec_count(new_inode);
1022 }
1023 if (S_ISDIR(old_inode->i_mode)) {
1024 if (!new_inode)
1025 inc_nlink(new_dir);
1026 v9fs_dec_count(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 /* successful rename */
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 * v9fs_vfs_getattr - retrieve file metadata
1047 * @path: Object to query
1048 * @stat: metadata structure to populate
1049 * @request_mask: Mask of STATX_xxx flags indicating the caller's interests
1050 * @flags: AT_STATX_xxx setting
1051 *
1052 */
1053
1054static int
1055v9fs_vfs_getattr(const struct path *path, struct kstat *stat,
1056 u32 request_mask, unsigned int flags)
1057{
1058 struct dentry *dentry = path->dentry;
1059 struct v9fs_session_info *v9ses;
1060 struct p9_fid *fid;
1061 struct p9_wstat *st;
1062
1063 p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
1064 v9ses = v9fs_dentry2v9ses(dentry);
1065 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
1066 generic_fillattr(d_inode(dentry), stat);
1067 return 0;
1068 }
1069 fid = v9fs_fid_lookup(dentry);
1070 if (IS_ERR(fid))
1071 return PTR_ERR(fid);
1072
1073 st = p9_client_stat(fid);
1074 if (IS_ERR(st))
1075 return PTR_ERR(st);
1076
1077 v9fs_stat2inode(st, d_inode(dentry), dentry->d_sb, 0);
1078 generic_fillattr(d_inode(dentry), stat);
1079
1080 p9stat_free(st);
1081 kfree(st);
1082 return 0;
1083}
1084
1085/**
1086 * v9fs_vfs_setattr - set file metadata
1087 * @dentry: file whose metadata to set
1088 * @iattr: metadata assignment structure
1089 *
1090 */
1091
1092static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
1093{
1094 int retval;
1095 struct v9fs_session_info *v9ses;
1096 struct p9_fid *fid;
1097 struct p9_wstat wstat;
1098
1099 p9_debug(P9_DEBUG_VFS, "\n");
1100 retval = setattr_prepare(dentry, iattr);
1101 if (retval)
1102 return retval;
1103
1104 retval = -EPERM;
1105 v9ses = v9fs_dentry2v9ses(dentry);
1106 fid = v9fs_fid_lookup(dentry);
1107 if(IS_ERR(fid))
1108 return PTR_ERR(fid);
1109
1110 v9fs_blank_wstat(&wstat);
1111 if (iattr->ia_valid & ATTR_MODE)
1112 wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);
1113
1114 if (iattr->ia_valid & ATTR_MTIME)
1115 wstat.mtime = iattr->ia_mtime.tv_sec;
1116
1117 if (iattr->ia_valid & ATTR_ATIME)
1118 wstat.atime = iattr->ia_atime.tv_sec;
1119
1120 if (iattr->ia_valid & ATTR_SIZE)
1121 wstat.length = iattr->ia_size;
1122
1123 if (v9fs_proto_dotu(v9ses)) {
1124 if (iattr->ia_valid & ATTR_UID)
1125 wstat.n_uid = iattr->ia_uid;
1126
1127 if (iattr->ia_valid & ATTR_GID)
1128 wstat.n_gid = iattr->ia_gid;
1129 }
1130
1131 /* Write all dirty data */
1132 if (d_is_reg(dentry))
1133 filemap_write_and_wait(d_inode(dentry)->i_mapping);
1134
1135 retval = p9_client_wstat(fid, &wstat);
1136 if (retval < 0)
1137 return retval;
1138
1139 if ((iattr->ia_valid & ATTR_SIZE) &&
1140 iattr->ia_size != i_size_read(d_inode(dentry)))
1141 truncate_setsize(d_inode(dentry), iattr->ia_size);
1142
1143 v9fs_invalidate_inode_attr(d_inode(dentry));
1144
1145 setattr_copy(d_inode(dentry), iattr);
1146 mark_inode_dirty(d_inode(dentry));
1147 return 0;
1148}
1149
1150/**
1151 * v9fs_stat2inode - populate an inode structure with mistat info
1152 * @stat: Plan 9 metadata (mistat) structure
1153 * @inode: inode to populate
1154 * @sb: superblock of filesystem
1155 * @flags: control flags (e.g. V9FS_STAT2INODE_KEEP_ISIZE)
1156 *
1157 */
1158
1159void
1160v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
1161 struct super_block *sb, unsigned int flags)
1162{
1163 umode_t mode;
1164 char ext[32];
1165 char tag_name[14];
1166 unsigned int i_nlink;
1167 struct v9fs_session_info *v9ses = sb->s_fs_info;
1168 struct v9fs_inode *v9inode = V9FS_I(inode);
1169
1170 set_nlink(inode, 1);
1171
1172 inode->i_atime.tv_sec = stat->atime;
1173 inode->i_mtime.tv_sec = stat->mtime;
1174 inode->i_ctime.tv_sec = stat->mtime;
1175
1176 inode->i_uid = v9ses->dfltuid;
1177 inode->i_gid = v9ses->dfltgid;
1178
1179 if (v9fs_proto_dotu(v9ses)) {
1180 inode->i_uid = stat->n_uid;
1181 inode->i_gid = stat->n_gid;
1182 }
1183 if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) {
1184 if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) {
1185 /*
1186 * Hadlink support got added later to
1187 * to the .u extension. So there can be
1188 * server out there that doesn't support
1189 * this even with .u extension. So check
1190 * for non NULL stat->extension
1191 */
1192 strlcpy(ext, stat->extension, sizeof(ext));
1193 /* HARDLINKCOUNT %u */
1194 sscanf(ext, "%13s %u", tag_name, &i_nlink);
1195 if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
1196 set_nlink(inode, i_nlink);
1197 }
1198 }
1199 mode = p9mode2perm(v9ses, stat);
1200 mode |= inode->i_mode & ~S_IALLUGO;
1201 inode->i_mode = mode;
1202
1203 if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE))
1204 v9fs_i_size_write(inode, stat->length);
1205 /* not real number of blocks, but 512 byte ones ... */
1206 inode->i_blocks = (stat->length + 512 - 1) >> 9;
1207 v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
1208}
1209
1210/**
1211 * v9fs_qid2ino - convert qid into inode number
1212 * @qid: qid to hash
1213 *
1214 * BUG: potential for inode number collisions?
1215 */
1216
1217ino_t v9fs_qid2ino(struct p9_qid *qid)
1218{
1219 u64 path = qid->path + 2;
1220 ino_t i = 0;
1221
1222 if (sizeof(ino_t) == sizeof(path))
1223 memcpy(&i, &path, sizeof(ino_t));
1224 else
1225 i = (ino_t) (path ^ (path >> 32));
1226
1227 return i;
1228}
1229
1230/**
1231 * v9fs_vfs_get_link - follow a symlink path
1232 * @dentry: dentry for symlink
1233 * @inode: inode for symlink
1234 * @done: delayed call for when we are done with the return value
1235 */
1236
1237static const char *v9fs_vfs_get_link(struct dentry *dentry,
1238 struct inode *inode,
1239 struct delayed_call *done)
1240{
1241 struct v9fs_session_info *v9ses;
1242 struct p9_fid *fid;
1243 struct p9_wstat *st;
1244 char *res;
1245
1246 if (!dentry)
1247 return ERR_PTR(-ECHILD);
1248
1249 v9ses = v9fs_dentry2v9ses(dentry);
1250 fid = v9fs_fid_lookup(dentry);
1251 p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
1252
1253 if (IS_ERR(fid))
1254 return ERR_CAST(fid);
1255
1256 if (!v9fs_proto_dotu(v9ses))
1257 return ERR_PTR(-EBADF);
1258
1259 st = p9_client_stat(fid);
1260 if (IS_ERR(st))
1261 return ERR_CAST(st);
1262
1263 if (!(st->mode & P9_DMSYMLINK)) {
1264 p9stat_free(st);
1265 kfree(st);
1266 return ERR_PTR(-EINVAL);
1267 }
1268 res = st->extension;
1269 st->extension = NULL;
1270 if (strlen(res) >= PATH_MAX)
1271 res[PATH_MAX - 1] = '\0';
1272
1273 p9stat_free(st);
1274 kfree(st);
1275 set_delayed_call(done, kfree_link, res);
1276 return res;
1277}
1278
1279/**
1280 * v9fs_vfs_mkspecial - create a special file
1281 * @dir: inode to create special file in
1282 * @dentry: dentry to create
1283 * @perm: mode to create special file
1284 * @extension: 9p2000.u format extension string representing special file
1285 *
1286 */
1287
1288static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
1289 u32 perm, const char *extension)
1290{
1291 struct p9_fid *fid;
1292 struct v9fs_session_info *v9ses;
1293
1294 v9ses = v9fs_inode2v9ses(dir);
1295 if (!v9fs_proto_dotu(v9ses)) {
1296 p9_debug(P9_DEBUG_ERROR, "not extended\n");
1297 return -EPERM;
1298 }
1299
1300 fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
1301 P9_OREAD);
1302 if (IS_ERR(fid))
1303 return PTR_ERR(fid);
1304
1305 v9fs_invalidate_inode_attr(dir);
1306 p9_client_clunk(fid);
1307 return 0;
1308}
1309
1310/**
1311 * v9fs_vfs_symlink - helper function to create symlinks
1312 * @dir: directory inode containing symlink
1313 * @dentry: dentry for symlink
1314 * @symname: symlink data
1315 *
1316 * See Also: 9P2000.u RFC for more information
1317 *
1318 */
1319
1320static int
1321v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1322{
1323 p9_debug(P9_DEBUG_VFS, " %lu,%pd,%s\n",
1324 dir->i_ino, dentry, symname);
1325
1326 return v9fs_vfs_mkspecial(dir, dentry, P9_DMSYMLINK, symname);
1327}
1328
1329#define U32_MAX_DIGITS 10
1330
1331/**
1332 * v9fs_vfs_link - create a hardlink
1333 * @old_dentry: dentry for file to link to
1334 * @dir: inode destination for new link
1335 * @dentry: dentry for link
1336 *
1337 */
1338
1339static int
1340v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1341 struct dentry *dentry)
1342{
1343 int retval;
1344 char name[1 + U32_MAX_DIGITS + 2]; /* sign + number + \n + \0 */
1345 struct p9_fid *oldfid;
1346
1347 p9_debug(P9_DEBUG_VFS, " %lu,%pd,%pd\n",
1348 dir->i_ino, dentry, old_dentry);
1349
1350 oldfid = v9fs_fid_clone(old_dentry);
1351 if (IS_ERR(oldfid))
1352 return PTR_ERR(oldfid);
1353
1354 sprintf(name, "%d\n", oldfid->fid);
1355 retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
1356 if (!retval) {
1357 v9fs_refresh_inode(oldfid, d_inode(old_dentry));
1358 v9fs_invalidate_inode_attr(dir);
1359 }
1360 p9_client_clunk(oldfid);
1361 return retval;
1362}
1363
1364/**
1365 * v9fs_vfs_mknod - create a special file
1366 * @dir: inode destination for new link
1367 * @dentry: dentry for file
1368 * @mode: mode for creation
1369 * @rdev: device associated with special file
1370 *
1371 */
1372
1373static int
1374v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
1375{
1376 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
1377 int retval;
1378 char name[2 + U32_MAX_DIGITS + 1 + U32_MAX_DIGITS + 1];
1379 u32 perm;
1380
1381 p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %hx MAJOR: %u MINOR: %u\n",
1382 dir->i_ino, dentry, mode,
1383 MAJOR(rdev), MINOR(rdev));
1384
1385 /* build extension */
1386 if (S_ISBLK(mode))
1387 sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
1388 else if (S_ISCHR(mode))
1389 sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));
1390 else
1391 *name = 0;
1392
1393 perm = unixmode2p9mode(v9ses, mode);
1394 retval = v9fs_vfs_mkspecial(dir, dentry, perm, name);
1395
1396 return retval;
1397}
1398
1399int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
1400{
1401 int umode;
1402 dev_t rdev;
1403 struct p9_wstat *st;
1404 struct v9fs_session_info *v9ses;
1405 unsigned int flags;
1406
1407 v9ses = v9fs_inode2v9ses(inode);
1408 st = p9_client_stat(fid);
1409 if (IS_ERR(st))
1410 return PTR_ERR(st);
1411 /*
1412 * Don't update inode if the file type is different
1413 */
1414 umode = p9mode2unixmode(v9ses, st, &rdev);
1415 if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
1416 goto out;
1417
1418 /*
1419 * We don't want to refresh inode->i_size,
1420 * because we may have cached data
1421 */
1422 flags = (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) ?
1423 V9FS_STAT2INODE_KEEP_ISIZE : 0;
1424 v9fs_stat2inode(st, inode, inode->i_sb, flags);
1425out:
1426 p9stat_free(st);
1427 kfree(st);
1428 return 0;
1429}
1430
1431static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1432 .create = v9fs_vfs_create,
1433 .lookup = v9fs_vfs_lookup,
1434 .atomic_open = v9fs_vfs_atomic_open,
1435 .symlink = v9fs_vfs_symlink,
1436 .link = v9fs_vfs_link,
1437 .unlink = v9fs_vfs_unlink,
1438 .mkdir = v9fs_vfs_mkdir,
1439 .rmdir = v9fs_vfs_rmdir,
1440 .mknod = v9fs_vfs_mknod,
1441 .rename = v9fs_vfs_rename,
1442 .getattr = v9fs_vfs_getattr,
1443 .setattr = v9fs_vfs_setattr,
1444};
1445
1446static const struct inode_operations v9fs_dir_inode_operations = {
1447 .create = v9fs_vfs_create,
1448 .lookup = v9fs_vfs_lookup,
1449 .atomic_open = v9fs_vfs_atomic_open,
1450 .unlink = v9fs_vfs_unlink,
1451 .mkdir = v9fs_vfs_mkdir,
1452 .rmdir = v9fs_vfs_rmdir,
1453 .mknod = v9fs_vfs_mknod,
1454 .rename = v9fs_vfs_rename,
1455 .getattr = v9fs_vfs_getattr,
1456 .setattr = v9fs_vfs_setattr,
1457};
1458
1459static const struct inode_operations v9fs_file_inode_operations = {
1460 .getattr = v9fs_vfs_getattr,
1461 .setattr = v9fs_vfs_setattr,
1462};
1463
1464static const struct inode_operations v9fs_symlink_inode_operations = {
1465 .get_link = v9fs_vfs_get_link,
1466 .getattr = v9fs_vfs_getattr,
1467 .setattr = v9fs_vfs_setattr,
1468};
1469