fs/9p: rework qid2ino logic
[linux-block.git] / fs / 9p / vfs_inode.c
CommitLineData
1f327613 1// SPDX-License-Identifier: GPL-2.0-only
2bad8471 2/*
73c592b9 3 * This file contains vfs inode ops for the 9P2000 protocol.
2bad8471
EVH
4 *
5 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
6 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
2bad8471
EVH
7 */
8
5d385153
JP
9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
2bad8471
EVH
11#include <linux/module.h>
12#include <linux/errno.h>
13#include <linux/fs.h>
14#include <linux/file.h>
15#include <linux/pagemap.h>
16#include <linux/stat.h>
17#include <linux/string.h>
2bad8471 18#include <linux/namei.h>
e8edc6e0 19#include <linux/sched.h>
5a0e3ad6 20#include <linux/slab.h>
ebf46264 21#include <linux/xattr.h>
85ff872d 22#include <linux/posix_acl.h>
bd238fb4
LI
23#include <net/9p/9p.h>
24#include <net/9p/client.h>
2bad8471 25
2bad8471 26#include "v9fs.h"
2bad8471 27#include "v9fs_vfs.h"
2bad8471 28#include "fid.h"
60e78d2c 29#include "cache.h"
ebf46264 30#include "xattr.h"
85ff872d 31#include "acl.h"
2bad8471 32
754661f1 33static const struct inode_operations v9fs_dir_inode_operations;
9b6533c9 34static const struct inode_operations v9fs_dir_inode_operations_dotu;
754661f1
AV
35static const struct inode_operations v9fs_file_inode_operations;
36static const struct inode_operations v9fs_symlink_inode_operations;
f5fc6145 37
2bad8471
EVH
38/**
39 * unixmode2p9mode - convert unix mode bits to plan 9
40 * @v9ses: v9fs session information
41 * @mode: mode to convert
42 *
43 */
44
3eda0de6 45static u32 unixmode2p9mode(struct v9fs_session_info *v9ses, umode_t mode)
2bad8471
EVH
46{
47 int res;
6e195b0f 48
2bad8471
EVH
49 res = mode & 0777;
50 if (S_ISDIR(mode))
bd238fb4 51 res |= P9_DMDIR;
dd6102fb 52 if (v9fs_proto_dotu(v9ses)) {
2bad8471
EVH
53 if (v9ses->nodev == 0) {
54 if (S_ISSOCK(mode))
bd238fb4 55 res |= P9_DMSOCKET;
2bad8471 56 if (S_ISFIFO(mode))
bd238fb4 57 res |= P9_DMNAMEDPIPE;
2bad8471 58 if (S_ISBLK(mode))
bd238fb4 59 res |= P9_DMDEVICE;
2bad8471 60 if (S_ISCHR(mode))
bd238fb4 61 res |= P9_DMDEVICE;
2bad8471
EVH
62 }
63
64 if ((mode & S_ISUID) == S_ISUID)
bd238fb4 65 res |= P9_DMSETUID;
2bad8471 66 if ((mode & S_ISGID) == S_ISGID)
bd238fb4 67 res |= P9_DMSETGID;
d199d652
AL
68 if ((mode & S_ISVTX) == S_ISVTX)
69 res |= P9_DMSETVTX;
2bad8471 70 }
2bad8471
EVH
71 return res;
72}
73
df345c67
AK
74/**
75 * p9mode2perm- convert plan9 mode bits to unix permission bits
76 * @v9ses: v9fs session information
77 * @stat: p9_wstat from which mode need to be derived
78 *
79 */
80static int p9mode2perm(struct v9fs_session_info *v9ses,
81 struct p9_wstat *stat)
82{
83 int res;
84 int mode = stat->mode;
85
86 res = mode & S_IALLUGO;
87 if (v9fs_proto_dotu(v9ses)) {
88 if ((mode & P9_DMSETUID) == P9_DMSETUID)
89 res |= S_ISUID;
90
91 if ((mode & P9_DMSETGID) == P9_DMSETGID)
92 res |= S_ISGID;
93
94 if ((mode & P9_DMSETVTX) == P9_DMSETVTX)
95 res |= S_ISVTX;
96 }
97 return res;
98}
99
2bad8471
EVH
100/**
101 * p9mode2unixmode- convert plan9 mode bits to unix mode bits
102 * @v9ses: v9fs session information
45089142
AK
103 * @stat: p9_wstat from which mode need to be derived
104 * @rdev: major number, minor number in case of device files.
2bad8471
EVH
105 *
106 */
3eda0de6
AV
107static umode_t p9mode2unixmode(struct v9fs_session_info *v9ses,
108 struct p9_wstat *stat, dev_t *rdev)
2bad8471 109{
05f975cd 110 int res, r;
3eda0de6 111 u32 mode = stat->mode;
2bad8471 112
45089142 113 *rdev = 0;
df345c67 114 res = p9mode2perm(v9ses, stat);
2bad8471 115
bd238fb4 116 if ((mode & P9_DMDIR) == P9_DMDIR)
2bad8471 117 res |= S_IFDIR;
dd6102fb 118 else if ((mode & P9_DMSYMLINK) && (v9fs_proto_dotu(v9ses)))
2bad8471 119 res |= S_IFLNK;
dd6102fb 120 else if ((mode & P9_DMSOCKET) && (v9fs_proto_dotu(v9ses))
2bad8471
EVH
121 && (v9ses->nodev == 0))
122 res |= S_IFSOCK;
dd6102fb 123 else if ((mode & P9_DMNAMEDPIPE) && (v9fs_proto_dotu(v9ses))
2bad8471
EVH
124 && (v9ses->nodev == 0))
125 res |= S_IFIFO;
dd6102fb 126 else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses))
45089142 127 && (v9ses->nodev == 0)) {
05f975cd 128 char type = 0;
45089142
AK
129 int major = -1, minor = -1;
130
05f975cd
DM
131 r = sscanf(stat->extension, "%c %i %i", &type, &major, &minor);
132 if (r != 3) {
133 p9_debug(P9_DEBUG_ERROR,
134 "invalid device string, umode will be bogus: %s\n",
135 stat->extension);
136 return res;
137 }
45089142
AK
138 switch (type) {
139 case 'c':
140 res |= S_IFCHR;
141 break;
142 case 'b':
143 res |= S_IFBLK;
144 break;
145 default:
5d385153
JP
146 p9_debug(P9_DEBUG_ERROR, "Unknown special type %c %s\n",
147 type, stat->extension);
51958817 148 }
45089142
AK
149 *rdev = MKDEV(major, minor);
150 } else
2bad8471
EVH
151 res |= S_IFREG;
152
2bad8471
EVH
153 return res;
154}
155
ee443996
EVH
156/**
157 * v9fs_uflags2omode- convert posix open flags to plan 9 mode bits
158 * @uflags: flags to convert
2e4bef41 159 * @extended: if .u extensions are active
ee443996
EVH
160 */
161
2e4bef41 162int v9fs_uflags2omode(int uflags, int extended)
6a3124a3
LI
163{
164 int ret;
165
6a3124a3
LI
166 switch (uflags&3) {
167 default:
168 case O_RDONLY:
bd238fb4 169 ret = P9_OREAD;
6a3124a3
LI
170 break;
171
172 case O_WRONLY:
bd238fb4 173 ret = P9_OWRITE;
6a3124a3
LI
174 break;
175
176 case O_RDWR:
bd238fb4 177 ret = P9_ORDWR;
6a3124a3
LI
178 break;
179 }
180
2e4bef41
EVH
181 if (extended) {
182 if (uflags & O_EXCL)
183 ret |= P9_OEXCL;
184
185 if (uflags & O_APPEND)
186 ret |= P9_OAPPEND;
187 }
6a3124a3
LI
188
189 return ret;
190}
191
2bad8471 192/**
531b1094 193 * v9fs_blank_wstat - helper function to setup a 9P stat structure
531b1094 194 * @wstat: structure to initialize
2bad8471
EVH
195 *
196 */
197
7a4439c4 198void
bd238fb4 199v9fs_blank_wstat(struct p9_wstat *wstat)
2bad8471 200{
531b1094
LI
201 wstat->type = ~0;
202 wstat->dev = ~0;
203 wstat->qid.type = ~0;
204 wstat->qid.version = ~0;
205 *((long long *)&wstat->qid.path) = ~0;
206 wstat->mode = ~0;
207 wstat->atime = ~0;
208 wstat->mtime = ~0;
209 wstat->length = ~0;
210 wstat->name = NULL;
211 wstat->uid = NULL;
212 wstat->gid = NULL;
213 wstat->muid = NULL;
447c5094
EB
214 wstat->n_uid = INVALID_UID;
215 wstat->n_gid = INVALID_GID;
216 wstat->n_muid = INVALID_UID;
531b1094 217 wstat->extension = NULL;
2bad8471
EVH
218}
219
60e78d2c
AK
220/**
221 * v9fs_alloc_inode - helper function to allocate an inode
bc868036 222 * @sb: The superblock to allocate the inode from
60e78d2c 223 */
60e78d2c
AK
224struct inode *v9fs_alloc_inode(struct super_block *sb)
225{
a78ce05d 226 struct v9fs_inode *v9inode;
6e195b0f 227
fd60b288 228 v9inode = alloc_inode_sb(sb, v9fs_inode_cache, GFP_KERNEL);
a78ce05d 229 if (!v9inode)
60e78d2c 230 return NULL;
b3cbea03 231 v9inode->cache_validity = 0;
5a7e0a8c 232 mutex_init(&v9inode->v_mutex);
874c8ca1 233 return &v9inode->netfs.inode;
60e78d2c
AK
234}
235
236/**
5e8a0770 237 * v9fs_free_inode - destroy an inode
bc868036 238 * @inode: The inode to be freed
60e78d2c
AK
239 */
240
5e8a0770 241void v9fs_free_inode(struct inode *inode)
60e78d2c 242{
a78ce05d 243 kmem_cache_free(v9fs_inode_cache, V9FS_I(inode));
60e78d2c 244}
fa0d7e3d 245
bc899ee1
DH
246/*
247 * Set parameters for the netfs library
248 */
9546ac78 249void v9fs_set_netfs_context(struct inode *inode)
bc899ee1 250{
e81fb419 251 struct v9fs_inode *v9inode = V9FS_I(inode);
100ccd18 252 netfs_inode_init(&v9inode->netfs, &v9fs_req_ops, true);
bc899ee1
DH
253}
254
5ffc0cb3 255int v9fs_init_inode(struct v9fs_session_info *v9ses,
3eda0de6 256 struct inode *inode, umode_t mode, dev_t rdev)
2bad8471 257{
5ffc0cb3 258 int err = 0;
2bb54115 259
f2d40141 260 inode_init_owner(&nop_mnt_idmap, inode, NULL, mode);
2bb54115 261 inode->i_blocks = 0;
45089142 262 inode->i_rdev = rdev;
d0242a3a 263 simple_inode_init_ts(inode);
2bb54115 264 inode->i_mapping->a_ops = &v9fs_addr_operations;
987a6485 265 inode->i_private = NULL;
2bb54115
AK
266
267 switch (mode & S_IFMT) {
268 case S_IFIFO:
269 case S_IFBLK:
270 case S_IFCHR:
271 case S_IFSOCK:
4b43516a
MK
272 if (v9fs_proto_dotl(v9ses)) {
273 inode->i_op = &v9fs_file_inode_operations_dotl;
4b43516a
MK
274 } else if (v9fs_proto_dotu(v9ses)) {
275 inode->i_op = &v9fs_file_inode_operations;
4b43516a 276 } else {
5d385153
JP
277 p9_debug(P9_DEBUG_ERROR,
278 "special files without extended mode\n");
2bb54115
AK
279 err = -EINVAL;
280 goto error;
2bad8471 281 }
2bb54115
AK
282 init_special_inode(inode, inode->i_mode, inode->i_rdev);
283 break;
284 case S_IFREG:
9b6533c9
SK
285 if (v9fs_proto_dotl(v9ses)) {
286 inode->i_op = &v9fs_file_inode_operations_dotl;
d9bc0d11 287 inode->i_fop = &v9fs_file_operations_dotl;
9b6533c9
SK
288 } else {
289 inode->i_op = &v9fs_file_inode_operations;
d9bc0d11 290 inode->i_fop = &v9fs_file_operations;
9b6533c9
SK
291 }
292
2bb54115
AK
293 break;
294 case S_IFLNK:
9b6533c9 295 if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) {
5d385153
JP
296 p9_debug(P9_DEBUG_ERROR,
297 "extended modes used with legacy protocol\n");
2bb54115
AK
298 err = -EINVAL;
299 goto error;
300 }
9b6533c9
SK
301
302 if (v9fs_proto_dotl(v9ses))
303 inode->i_op = &v9fs_symlink_inode_operations_dotl;
304 else
305 inode->i_op = &v9fs_symlink_inode_operations;
306
2bb54115
AK
307 break;
308 case S_IFDIR:
309 inc_nlink(inode);
9b6533c9
SK
310 if (v9fs_proto_dotl(v9ses))
311 inode->i_op = &v9fs_dir_inode_operations_dotl;
312 else if (v9fs_proto_dotu(v9ses))
313 inode->i_op = &v9fs_dir_inode_operations_dotu;
2bb54115
AK
314 else
315 inode->i_op = &v9fs_dir_inode_operations;
9b6533c9
SK
316
317 if (v9fs_proto_dotl(v9ses))
318 inode->i_fop = &v9fs_dir_operations_dotl;
319 else
320 inode->i_fop = &v9fs_dir_operations;
321
2bb54115
AK
322 break;
323 default:
609eac1c 324 p9_debug(P9_DEBUG_ERROR, "BAD mode 0x%hx S_IFMT 0x%x\n",
5d385153 325 mode, mode & S_IFMT);
2bb54115
AK
326 err = -EINVAL;
327 goto error;
2bad8471 328 }
5ffc0cb3
AK
329error:
330 return err;
2bb54115 331
5ffc0cb3 332}
2bb54115 333
60e78d2c 334/**
bc868036 335 * v9fs_evict_inode - Remove an inode from the inode cache
60e78d2c
AK
336 * @inode: inode to release
337 *
338 */
b57922d9 339void v9fs_evict_inode(struct inode *inode)
60e78d2c 340{
4eb31178
EVH
341 struct v9fs_inode __maybe_unused *v9inode = V9FS_I(inode);
342 __le32 __maybe_unused version;
6b39f6d2 343
4ad78628 344 truncate_inode_pages_final(&inode->i_data);
4eb31178 345
93c84614 346 version = cpu_to_le32(v9inode->qid.version);
c9c4ff12 347 netfs_clear_inode_writeback(inode, &version);
4eb31178 348
dbd5768f 349 clear_inode(inode);
4ad78628 350 filemap_fdatawrite(&inode->i_data);
60e78d2c 351
4eb31178 352#ifdef CONFIG_9P_FSCACHE
24e42e32 353 fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false);
4eb31178 354#endif
60e78d2c
AK
355}
356
fd2421f5
AK
357static int v9fs_test_inode(struct inode *inode, void *data)
358{
359 int umode;
45089142 360 dev_t rdev;
fd2421f5
AK
361 struct v9fs_inode *v9inode = V9FS_I(inode);
362 struct p9_wstat *st = (struct p9_wstat *)data;
363 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
364
45089142 365 umode = p9mode2unixmode(v9ses, st, &rdev);
fd2421f5 366 /* don't match inode of different type */
6e3e2c43 367 if (inode_wrong_type(inode, umode))
fd2421f5
AK
368 return 0;
369
370 /* compare qid details */
371 if (memcmp(&v9inode->qid.version,
372 &st->qid.version, sizeof(v9inode->qid.version)))
373 return 0;
374
375 if (v9inode->qid.type != st->qid.type)
376 return 0;
8ee03163
TT
377
378 if (v9inode->qid.path != st->qid.path)
379 return 0;
fd2421f5
AK
380 return 1;
381}
382
ed80fcfa
AK
383static int v9fs_test_new_inode(struct inode *inode, void *data)
384{
385 return 0;
386}
387
fd2421f5
AK
388static int v9fs_set_inode(struct inode *inode, void *data)
389{
390 struct v9fs_inode *v9inode = V9FS_I(inode);
391 struct p9_wstat *st = (struct p9_wstat *)data;
392
393 memcpy(&v9inode->qid, &st->qid, sizeof(st->qid));
394 return 0;
395}
396
5ffc0cb3
AK
397static struct inode *v9fs_qid_iget(struct super_block *sb,
398 struct p9_qid *qid,
ed80fcfa
AK
399 struct p9_wstat *st,
400 int new)
6a3124a3 401{
45089142 402 dev_t rdev;
3eda0de6
AV
403 int retval;
404 umode_t umode;
5ffc0cb3
AK
405 struct inode *inode;
406 struct v9fs_session_info *v9ses = sb->s_fs_info;
6e195b0f 407 int (*test)(struct inode *inode, void *data);
ed80fcfa
AK
408
409 if (new)
410 test = v9fs_test_new_inode;
411 else
412 test = v9fs_test_inode;
2bad8471 413
b91a2669 414 inode = iget5_locked(sb, QID2INO(qid), test, v9fs_set_inode, st);
5ffc0cb3
AK
415 if (!inode)
416 return ERR_PTR(-ENOMEM);
417 if (!(inode->i_state & I_NEW))
418 return inode;
419 /*
420 * initialize the inode with the stat info
421 * FIXME!! we may need support for stale inodes
422 * later.
423 */
b91a2669 424 inode->i_ino = QID2INO(qid);
45089142
AK
425 umode = p9mode2unixmode(v9ses, st, &rdev);
426 retval = v9fs_init_inode(v9ses, inode, umode, rdev);
5ffc0cb3 427 if (retval)
6a3124a3 428 goto error;
60e78d2c 429
5e3cc1ee 430 v9fs_stat2inode(st, inode, sb, 0);
9546ac78 431 v9fs_set_netfs_context(inode);
5ffc0cb3 432 v9fs_cache_inode_get_cookie(inode);
5ffc0cb3
AK
433 unlock_new_inode(inode);
434 return inode;
6a3124a3 435error:
0a73d0a2 436 iget_failed(inode);
5ffc0cb3
AK
437 return ERR_PTR(retval);
438
439}
440
441struct inode *
a78ce05d 442v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
ed80fcfa 443 struct super_block *sb, int new)
5ffc0cb3
AK
444{
445 struct p9_wstat *st;
446 struct inode *inode = NULL;
447
448 st = p9_client_stat(fid);
449 if (IS_ERR(st))
450 return ERR_CAST(st);
451
ed80fcfa 452 inode = v9fs_qid_iget(sb, &st->qid, st, new);
02bc3567 453 p9stat_free(st);
bd238fb4 454 kfree(st);
5ffc0cb3 455 return inode;
2bad8471
EVH
456}
457
f88657ce
AK
458/**
459 * v9fs_at_to_dotl_flags- convert Linux specific AT flags to
460 * plan 9 AT flag.
461 * @flags: flags to convert
462 */
463static int v9fs_at_to_dotl_flags(int flags)
464{
465 int rflags = 0;
6e195b0f 466
f88657ce
AK
467 if (flags & AT_REMOVEDIR)
468 rflags |= P9_DOTL_AT_REMOVEDIR;
6e195b0f 469
f88657ce
AK
470 return rflags;
471}
472
ac89b2ef
EG
473/**
474 * v9fs_dec_count - helper functon to drop i_nlink.
475 *
476 * If a directory had nlink <= 2 (including . and ..), then we should not drop
477 * the link count, which indicates the underlying exported fs doesn't maintain
478 * nlink accurately. e.g.
479 * - overlayfs sets nlink to 1 for merged dir
480 * - ext4 (with dir_nlink feature enabled) sets nlink to 1 if a dir has more
481 * than EXT4_LINK_MAX (65000) links.
482 *
483 * @inode: inode whose nlink is being dropped
484 */
485static void v9fs_dec_count(struct inode *inode)
486{
487 if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2)
488 drop_nlink(inode);
489}
490
2bad8471
EVH
491/**
492 * v9fs_remove - helper function to remove files and directories
73c592b9 493 * @dir: directory inode that is being deleted
48e370ff 494 * @dentry: dentry that is being deleted
fd2916bd 495 * @flags: removing a directory
2bad8471
EVH
496 *
497 */
498
48e370ff 499static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
2bad8471 500{
48e370ff
AK
501 struct inode *inode;
502 int retval = -EOPNOTSUPP;
503 struct p9_fid *v9fid, *dfid;
504 struct v9fs_session_info *v9ses;
2bad8471 505
5d385153
JP
506 p9_debug(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %x\n",
507 dir, dentry, flags);
2bad8471 508
48e370ff 509 v9ses = v9fs_inode2v9ses(dir);
2b0143b5 510 inode = d_inode(dentry);
77d5a6b7 511 dfid = v9fs_parent_fid(dentry);
48e370ff
AK
512 if (IS_ERR(dfid)) {
513 retval = PTR_ERR(dfid);
5d385153 514 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", retval);
48e370ff
AK
515 return retval;
516 }
517 if (v9fs_proto_dotl(v9ses))
f88657ce
AK
518 retval = p9_client_unlinkat(dfid, dentry->d_name.name,
519 v9fs_at_to_dotl_flags(flags));
b48dbb99 520 p9_fid_put(dfid);
48e370ff
AK
521 if (retval == -EOPNOTSUPP) {
522 /* Try the one based on path */
523 v9fid = v9fs_fid_clone(dentry);
524 if (IS_ERR(v9fid))
525 return PTR_ERR(v9fid);
526 retval = p9_client_remove(v9fid);
527 }
b271ec47
AK
528 if (!retval) {
529 /*
530 * directories on unlink should have zero
531 * link count
532 */
48e370ff
AK
533 if (flags & AT_REMOVEDIR) {
534 clear_nlink(inode);
ac89b2ef 535 v9fs_dec_count(dir);
b271ec47 536 } else
ac89b2ef 537 v9fs_dec_count(inode);
d28c61f0 538
48e370ff 539 v9fs_invalidate_inode_attr(inode);
d28c61f0 540 v9fs_invalidate_inode_attr(dir);
154372e6
EVH
541
542 /* invalidate all fids associated with dentry */
543 /* NOTE: This will not include open fids */
544 dentry->d_op->d_release(dentry);
b271ec47 545 }
d994f405 546 return retval;
2bad8471
EVH
547}
548
549/**
bd238fb4 550 * v9fs_create - Create a file
ee443996
EVH
551 * @v9ses: session information
552 * @dir: directory that dentry is being created in
bd238fb4 553 * @dentry: dentry that is being created
0e15597e 554 * @extension: 9p2000.u extension string to support devices, etc.
bd238fb4
LI
555 * @perm: create permissions
556 * @mode: open mode
2bad8471
EVH
557 *
558 */
bd238fb4
LI
559static struct p9_fid *
560v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
561 struct dentry *dentry, char *extension, u32 perm, u8 mode)
2bad8471 562{
6a3124a3 563 int err;
7880b43b 564 const unsigned char *name;
6636b6dc 565 struct p9_fid *dfid, *ofid = NULL, *fid = NULL;
6a3124a3 566 struct inode *inode;
6a3124a3 567
4b8e9923 568 p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry);
51a87c55 569
7880b43b 570 name = dentry->d_name.name;
77d5a6b7 571 dfid = v9fs_parent_fid(dentry);
ba17674f 572 if (IS_ERR(dfid)) {
da977b2c 573 err = PTR_ERR(dfid);
5d385153 574 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
6d27e64d 575 return ERR_PTR(err);
da977b2c 576 }
6a3124a3 577
bd238fb4 578 /* clone a fid to use for creation */
7d50a29f 579 ofid = clone_fid(dfid);
bd238fb4
LI
580 if (IS_ERR(ofid)) {
581 err = PTR_ERR(ofid);
5d385153 582 p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
dafbe689 583 goto error;
bd238fb4 584 }
6a3124a3 585
bd238fb4 586 err = p9_client_fcreate(ofid, name, perm, mode, extension);
51a87c55 587 if (err < 0) {
5d385153 588 p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
6a3124a3 589 goto error;
6d27e64d 590 }
6a3124a3 591
b6054793
AK
592 if (!(perm & P9_DMLINK)) {
593 /* now walk from the parent so we can get unopened fid */
594 fid = p9_client_walk(dfid, 1, &name, 1);
595 if (IS_ERR(fid)) {
596 err = PTR_ERR(fid);
597 p9_debug(P9_DEBUG_VFS,
598 "p9_client_walk failed %d\n", err);
b6054793
AK
599 goto error;
600 }
601 /*
602 * instantiate inode and assign the unopened fid to the dentry
603 */
604 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
605 if (IS_ERR(inode)) {
606 err = PTR_ERR(inode);
607 p9_debug(P9_DEBUG_VFS,
608 "inode creation failed %d\n", err);
609 goto error;
610 }
dafbe689 611 v9fs_fid_add(dentry, &fid);
b6054793 612 d_instantiate(dentry, inode);
6a3124a3 613 }
b48dbb99 614 p9_fid_put(dfid);
bd238fb4 615 return ofid;
bd238fb4 616error:
dafbe689
DM
617 p9_fid_put(dfid);
618 p9_fid_put(ofid);
619 p9_fid_put(fid);
bd238fb4
LI
620 return ERR_PTR(err);
621}
622
623/**
e43ae79c 624 * v9fs_vfs_create - VFS hook to create a regular file
6c960e68 625 * @idmap: idmap of the mount
bc868036
DH
626 * @dir: The parent directory
627 * @dentry: The name of file to be created
628 * @mode: The UNIX file mode to set
629 * @excl: True if the file must not yet exist
e43ae79c
MS
630 *
631 * open(.., O_CREAT) is handled in v9fs_vfs_atomic_open(). This is only called
632 * for mknod(2).
633 *
bd238fb4 634 */
6a3124a3 635
bd238fb4 636static int
6c960e68 637v9fs_vfs_create(struct mnt_idmap *idmap, struct inode *dir,
549c7297 638 struct dentry *dentry, umode_t mode, bool excl)
bd238fb4 639{
e43ae79c
MS
640 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
641 u32 perm = unixmode2p9mode(v9ses, mode);
642 struct p9_fid *fid;
bd238fb4 643
e43ae79c
MS
644 /* P9_OEXCL? */
645 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_ORDWR);
646 if (IS_ERR(fid))
647 return PTR_ERR(fid);
bd238fb4 648
d28c61f0 649 v9fs_invalidate_inode_attr(dir);
b48dbb99 650 p9_fid_put(fid);
6a3124a3
LI
651
652 return 0;
2bad8471
EVH
653}
654
655/**
656 * v9fs_vfs_mkdir - VFS mkdir hook to create a directory
c54bd91e 657 * @idmap: idmap of the mount
ee443996 658 * @dir: inode that is being unlinked
2bad8471
EVH
659 * @dentry: dentry that is being unlinked
660 * @mode: mode for new directory
661 *
662 */
663
c54bd91e 664static int v9fs_vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
549c7297 665 struct dentry *dentry, umode_t mode)
2bad8471 666{
6a3124a3 667 int err;
bd238fb4 668 u32 perm;
bd238fb4 669 struct p9_fid *fid;
d28c61f0 670 struct v9fs_session_info *v9ses;
6a3124a3 671
4b8e9923 672 p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry);
bd238fb4 673 err = 0;
6a3124a3 674 v9ses = v9fs_inode2v9ses(dir);
6a3124a3 675 perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
bd238fb4
LI
676 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD);
677 if (IS_ERR(fid)) {
678 err = PTR_ERR(fid);
679 fid = NULL;
d28c61f0 680 } else {
b271ec47 681 inc_nlink(dir);
d28c61f0
AK
682 v9fs_invalidate_inode_attr(dir);
683 }
6a3124a3 684
bd238fb4 685 if (fid)
b48dbb99 686 p9_fid_put(fid);
6a3124a3 687
6a3124a3 688 return err;
2bad8471
EVH
689}
690
691/**
692 * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode
693 * @dir: inode that is being walked from
694 * @dentry: dentry that is being walked to?
fd2916bd 695 * @flags: lookup flags (unused)
2bad8471
EVH
696 *
697 */
698
53c06f4e 699struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
00cd8dd3 700 unsigned int flags)
2bad8471 701{
73f50717 702 struct dentry *res;
2bad8471 703 struct v9fs_session_info *v9ses;
bd238fb4 704 struct p9_fid *dfid, *fid;
2bad8471 705 struct inode *inode;
7880b43b 706 const unsigned char *name;
2bad8471 707
4b8e9923
AV
708 p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%pd) %p flags: %x\n",
709 dir, dentry, dentry, flags);
2bad8471 710
11e9b49b
SK
711 if (dentry->d_name.len > NAME_MAX)
712 return ERR_PTR(-ENAMETOOLONG);
713
2bad8471 714 v9ses = v9fs_inode2v9ses(dir);
a534c8d1 715 /* We can walk d_parent because we hold the dir->i_mutex */
77d5a6b7 716 dfid = v9fs_parent_fid(dentry);
bd238fb4 717 if (IS_ERR(dfid))
e231c2ee 718 return ERR_CAST(dfid);
bd238fb4 719
73f50717
AK
720 /*
721 * Make sure we don't use a wrong inode due to parallel
722 * unlink. For cached mode create calls request for new
723 * inode. But with cache disabled, lookup should do this.
724 */
500e2ab6
AV
725 name = dentry->d_name.name;
726 fid = p9_client_walk(dfid, 1, &name, 1);
b48dbb99 727 p9_fid_put(dfid);
500e2ab6
AV
728 if (fid == ERR_PTR(-ENOENT))
729 inode = NULL;
730 else if (IS_ERR(fid))
731 inode = ERR_CAST(fid);
4eb31178 732 else if (v9ses->cache & (CACHE_META|CACHE_LOOSE))
73f50717
AK
733 inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
734 else
735 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
73f50717
AK
736 /*
737 * If we had a rename on the server and a parallel lookup
738 * for the new name, then make sure we instantiate with
739 * the new name. ie look up for a/b, while on server somebody
740 * moved b under k and client parallely did a lookup for
741 * k/b.
742 */
41d28bca 743 res = d_splice_alias(inode, dentry);
500e2ab6
AV
744 if (!IS_ERR(fid)) {
745 if (!res)
dafbe689 746 v9fs_fid_add(dentry, &fid);
500e2ab6 747 else if (!IS_ERR(res))
dafbe689 748 v9fs_fid_add(res, &fid);
500e2ab6 749 else
b48dbb99 750 p9_fid_put(fid);
500e2ab6 751 }
7b5be621 752 return res;
2bad8471
EVH
753}
754
d9585277 755static int
e43ae79c 756v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
6e195b0f 757 struct file *file, unsigned int flags, umode_t mode)
e43ae79c
MS
758{
759 int err;
760 u32 perm;
4eb31178 761 struct v9fs_inode __maybe_unused *v9inode;
e43ae79c 762 struct v9fs_session_info *v9ses;
1543b4c5 763 struct p9_fid *fid;
e43ae79c 764 struct dentry *res = NULL;
987a6485 765 struct inode *inode;
1543b4c5 766 int p9_omode;
e43ae79c 767
00699ad8 768 if (d_in_lookup(dentry)) {
00cd8dd3 769 res = v9fs_vfs_lookup(dir, dentry, 0);
e43ae79c 770 if (IS_ERR(res))
d9585277 771 return PTR_ERR(res);
e43ae79c
MS
772
773 if (res)
774 dentry = res;
775 }
776
777 /* Only creates */
2b0143b5 778 if (!(flags & O_CREAT) || d_really_is_positive(dentry))
e45198a6 779 return finish_no_open(file, res);
e43ae79c 780
e43ae79c
MS
781 v9ses = v9fs_inode2v9ses(dir);
782 perm = unixmode2p9mode(v9ses, mode);
1543b4c5
EVH
783 p9_omode = v9fs_uflags2omode(flags, v9fs_proto_dotu(v9ses));
784
4eb31178 785 if ((v9ses->cache & CACHE_WRITEBACK) && (p9_omode & P9_OWRITE)) {
21e26d5e 786 p9_omode = (p9_omode & ~P9_OWRITE) | P9_ORDWR;
1543b4c5
EVH
787 p9_debug(P9_DEBUG_CACHE,
788 "write-only file with writeback enabled, creating w/ O_RDWR\n");
789 }
790 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, p9_omode);
e43ae79c
MS
791 if (IS_ERR(fid)) {
792 err = PTR_ERR(fid);
e43ae79c
MS
793 goto error;
794 }
795
796 v9fs_invalidate_inode_attr(dir);
987a6485
GK
797 inode = d_inode(dentry);
798 v9inode = V9FS_I(inode);
be12af3e 799 err = finish_open(file, dentry, generic_file_open);
30d90494 800 if (err)
e43ae79c 801 goto error;
e43ae79c 802
30d90494 803 file->private_data = fid;
4eb31178
EVH
804#ifdef CONFIG_9P_FSCACHE
805 if (v9ses->cache & CACHE_FSCACHE)
24e42e32
DH
806 fscache_use_cookie(v9fs_inode_cookie(v9inode),
807 file->f_mode & FMODE_WRITE);
4eb31178 808#endif
1543b4c5
EVH
809
810 v9fs_fid_add_modes(fid, v9ses->flags, v9ses->cache, file->f_flags);
dafbe689 811 v9fs_open_fid_add(inode, &fid);
e43ae79c 812
73a09dd9 813 file->f_mode |= FMODE_CREATED;
e43ae79c
MS
814out:
815 dput(res);
d9585277 816 return err;
e43ae79c
MS
817
818error:
dafbe689 819 p9_fid_put(fid);
e43ae79c
MS
820 goto out;
821}
822
2bad8471
EVH
823/**
824 * v9fs_vfs_unlink - VFS unlink hook to delete an inode
825 * @i: inode that is being unlinked
73c592b9 826 * @d: dentry that is being unlinked
2bad8471
EVH
827 *
828 */
829
53c06f4e 830int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
2bad8471
EVH
831{
832 return v9fs_remove(i, d, 0);
833}
834
835/**
836 * v9fs_vfs_rmdir - VFS unlink hook to delete a directory
837 * @i: inode that is being unlinked
73c592b9 838 * @d: dentry that is being unlinked
2bad8471
EVH
839 *
840 */
841
53c06f4e 842int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
2bad8471 843{
48e370ff 844 return v9fs_remove(i, d, AT_REMOVEDIR);
2bad8471
EVH
845}
846
847/**
848 * v9fs_vfs_rename - VFS hook to rename an inode
e18275ae 849 * @idmap: The idmap of the mount
2bad8471
EVH
850 * @old_dir: old dir inode
851 * @old_dentry: old dentry
852 * @new_dir: new dir inode
853 * @new_dentry: new dentry
bc868036 854 * @flags: RENAME_* flags
2bad8471
EVH
855 *
856 */
857
53c06f4e 858int
e18275ae 859v9fs_vfs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
549c7297
CB
860 struct dentry *old_dentry, struct inode *new_dir,
861 struct dentry *new_dentry, unsigned int flags)
2bad8471 862{
d28c61f0 863 int retval;
bd238fb4 864 struct inode *old_inode;
b271ec47 865 struct inode *new_inode;
bd238fb4 866 struct v9fs_session_info *v9ses;
dafbe689
DM
867 struct p9_fid *oldfid = NULL, *dfid = NULL;
868 struct p9_fid *olddirfid = NULL;
869 struct p9_fid *newdirfid = NULL;
bd238fb4 870 struct p9_wstat wstat;
2bad8471 871
1cd66c93
MS
872 if (flags)
873 return -EINVAL;
874
5d385153 875 p9_debug(P9_DEBUG_VFS, "\n");
2b0143b5
DH
876 old_inode = d_inode(old_dentry);
877 new_inode = d_inode(new_dentry);
bd238fb4
LI
878 v9ses = v9fs_inode2v9ses(old_inode);
879 oldfid = v9fs_fid_lookup(old_dentry);
ba17674f 880 if (IS_ERR(oldfid))
da977b2c
EVH
881 return PTR_ERR(oldfid);
882
6636b6dc
JW
883 dfid = v9fs_parent_fid(old_dentry);
884 olddirfid = clone_fid(dfid);
dafbe689
DM
885 p9_fid_put(dfid);
886 dfid = NULL;
6636b6dc 887
ba17674f 888 if (IS_ERR(olddirfid)) {
da977b2c 889 retval = PTR_ERR(olddirfid);
dafbe689 890 goto error;
da977b2c
EVH
891 }
892
6636b6dc
JW
893 dfid = v9fs_parent_fid(new_dentry);
894 newdirfid = clone_fid(dfid);
b48dbb99 895 p9_fid_put(dfid);
dafbe689 896 dfid = NULL;
6636b6dc 897
ba17674f 898 if (IS_ERR(newdirfid)) {
da977b2c 899 retval = PTR_ERR(newdirfid);
dafbe689 900 goto error;
2bad8471
EVH
901 }
902
a534c8d1 903 down_write(&v9ses->rename_sem);
4681dbda 904 if (v9fs_proto_dotl(v9ses)) {
9e8fb38e
AK
905 retval = p9_client_renameat(olddirfid, old_dentry->d_name.name,
906 newdirfid, new_dentry->d_name.name);
907 if (retval == -EOPNOTSUPP)
908 retval = p9_client_rename(oldfid, newdirfid,
909 new_dentry->d_name.name);
910 if (retval != -EOPNOTSUPP)
dafbe689 911 goto error_locked;
4681dbda 912 }
a534c8d1
AK
913 if (old_dentry->d_parent != new_dentry->d_parent) {
914 /*
915 * 9P .u can only handle file rename in the same directory
916 */
4681dbda 917
5d385153 918 p9_debug(P9_DEBUG_ERROR, "old dir and new dir are different\n");
621997cd 919 retval = -EXDEV;
dafbe689 920 goto error_locked;
2bad8471 921 }
531b1094 922 v9fs_blank_wstat(&wstat);
ba17674f 923 wstat.muid = v9ses->uname;
7880b43b 924 wstat.name = new_dentry->d_name.name;
bd238fb4 925 retval = p9_client_wstat(oldfid, &wstat);
2bad8471 926
dafbe689 927error_locked:
b271ec47
AK
928 if (!retval) {
929 if (new_inode) {
930 if (S_ISDIR(new_inode->i_mode))
931 clear_nlink(new_inode);
932 else
ac89b2ef 933 v9fs_dec_count(new_inode);
b271ec47
AK
934 }
935 if (S_ISDIR(old_inode->i_mode)) {
936 if (!new_inode)
937 inc_nlink(new_dir);
ac89b2ef 938 v9fs_dec_count(old_dir);
b271ec47 939 }
3bc86de3 940 v9fs_invalidate_inode_attr(old_inode);
d28c61f0
AK
941 v9fs_invalidate_inode_attr(old_dir);
942 v9fs_invalidate_inode_attr(new_dir);
3bc86de3 943
a534c8d1
AK
944 /* successful rename */
945 d_move(old_dentry, new_dentry);
b271ec47 946 }
a534c8d1 947 up_write(&v9ses->rename_sem);
2bad8471 948
dafbe689
DM
949error:
950 p9_fid_put(newdirfid);
b48dbb99 951 p9_fid_put(olddirfid);
b48dbb99 952 p9_fid_put(oldfid);
2bad8471
EVH
953 return retval;
954}
955
956/**
943ffb58 957 * v9fs_vfs_getattr - retrieve file metadata
b74d24f7 958 * @idmap: idmap of the mount
a528d35e 959 * @path: Object to query
ee443996 960 * @stat: metadata structure to populate
a528d35e
DH
961 * @request_mask: Mask of STATX_xxx flags indicating the caller's interests
962 * @flags: AT_STATX_xxx setting
2bad8471
EVH
963 *
964 */
965
966static int
b74d24f7 967v9fs_vfs_getattr(struct mnt_idmap *idmap, const struct path *path,
549c7297 968 struct kstat *stat, u32 request_mask, unsigned int flags)
2bad8471 969{
a528d35e 970 struct dentry *dentry = path->dentry;
d9bc0d11 971 struct inode *inode = d_inode(dentry);
bd238fb4
LI
972 struct v9fs_session_info *v9ses;
973 struct p9_fid *fid;
51a87c55 974 struct p9_wstat *st;
bd238fb4 975
5d385153 976 p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
42869c8a 977 v9ses = v9fs_dentry2v9ses(dentry);
4eb31178 978 if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) {
0d72b928 979 generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
a1211908 980 return 0;
4eb31178 981 } else if (v9ses->cache & CACHE_WRITEBACK) {
d9bc0d11
EVH
982 if (S_ISREG(inode->i_mode)) {
983 int retval = filemap_fdatawrite(inode->i_mapping);
984
985 if (retval)
986 p9_debug(P9_DEBUG_ERROR,
987 "flushing writeback during getattr returned %d\n", retval);
988 }
a1211908 989 }
bd238fb4
LI
990 fid = v9fs_fid_lookup(dentry);
991 if (IS_ERR(fid))
da977b2c 992 return PTR_ERR(fid);
2bad8471 993
bd238fb4 994 st = p9_client_stat(fid);
b48dbb99 995 p9_fid_put(fid);
bd238fb4
LI
996 if (IS_ERR(st))
997 return PTR_ERR(st);
2bad8471 998
5e3cc1ee 999 v9fs_stat2inode(st, d_inode(dentry), dentry->d_sb, 0);
0d72b928 1000 generic_fillattr(&nop_mnt_idmap, request_mask, d_inode(dentry), stat);
2bad8471 1001
62b2be59 1002 p9stat_free(st);
bd238fb4
LI
1003 kfree(st);
1004 return 0;
2bad8471
EVH
1005}
1006
1007/**
1008 * v9fs_vfs_setattr - set file metadata
c1632a0f 1009 * @idmap: idmap of the mount
2bad8471
EVH
1010 * @dentry: file whose metadata to set
1011 * @iattr: metadata assignment structure
1012 *
1013 */
1014
c1632a0f 1015static int v9fs_vfs_setattr(struct mnt_idmap *idmap,
549c7297 1016 struct dentry *dentry, struct iattr *iattr)
2bad8471 1017{
6636b6dc 1018 int retval, use_dentry = 0;
24e42e32 1019 struct inode *inode = d_inode(dentry);
bd238fb4 1020 struct v9fs_session_info *v9ses;
66246641 1021 struct p9_fid *fid = NULL;
bd238fb4 1022 struct p9_wstat wstat;
2bad8471 1023
5d385153 1024 p9_debug(P9_DEBUG_VFS, "\n");
c1632a0f 1025 retval = setattr_prepare(&nop_mnt_idmap, dentry, iattr);
059c138b
AK
1026 if (retval)
1027 return retval;
1028
42869c8a 1029 v9ses = v9fs_dentry2v9ses(dentry);
66246641
JW
1030 if (iattr->ia_valid & ATTR_FILE) {
1031 fid = iattr->ia_file->private_data;
1032 WARN_ON(!fid);
1033 }
6636b6dc 1034 if (!fid) {
66246641 1035 fid = v9fs_fid_lookup(dentry);
6636b6dc
JW
1036 use_dentry = 1;
1037 }
6e195b0f 1038 if (IS_ERR(fid))
da977b2c 1039 return PTR_ERR(fid);
2bad8471 1040
531b1094 1041 v9fs_blank_wstat(&wstat);
2bad8471 1042 if (iattr->ia_valid & ATTR_MODE)
531b1094 1043 wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);
2bad8471
EVH
1044
1045 if (iattr->ia_valid & ATTR_MTIME)
531b1094 1046 wstat.mtime = iattr->ia_mtime.tv_sec;
2bad8471
EVH
1047
1048 if (iattr->ia_valid & ATTR_ATIME)
531b1094 1049 wstat.atime = iattr->ia_atime.tv_sec;
2bad8471
EVH
1050
1051 if (iattr->ia_valid & ATTR_SIZE)
531b1094 1052 wstat.length = iattr->ia_size;
2bad8471 1053
dd6102fb 1054 if (v9fs_proto_dotu(v9ses)) {
531b1094
LI
1055 if (iattr->ia_valid & ATTR_UID)
1056 wstat.n_uid = iattr->ia_uid;
2bad8471 1057
531b1094
LI
1058 if (iattr->ia_valid & ATTR_GID)
1059 wstat.n_gid = iattr->ia_gid;
2bad8471 1060 }
059c138b 1061
3dc5436a 1062 /* Write all dirty data */
d9bc0d11
EVH
1063 if (d_is_reg(dentry)) {
1064 retval = filemap_fdatawrite(inode->i_mapping);
1065 if (retval)
1066 p9_debug(P9_DEBUG_ERROR,
1067 "flushing writeback during setattr returned %d\n", retval);
1068 }
3dc5436a 1069
f10fc50f 1070 retval = p9_client_wstat(fid, &wstat);
6636b6dc
JW
1071
1072 if (use_dentry)
b48dbb99 1073 p9_fid_put(fid);
6636b6dc 1074
f10fc50f
AK
1075 if (retval < 0)
1076 return retval;
059c138b
AK
1077
1078 if ((iattr->ia_valid & ATTR_SIZE) &&
d9bc0d11 1079 iattr->ia_size != i_size_read(inode)) {
24e42e32 1080 truncate_setsize(inode, iattr->ia_size);
80105ed2 1081 netfs_resize_file(netfs_inode(inode), iattr->ia_size, true);
1543b4c5 1082
4eb31178
EVH
1083#ifdef CONFIG_9P_FSCACHE
1084 if (v9ses->cache & CACHE_FSCACHE) {
1085 struct v9fs_inode *v9inode = V9FS_I(inode);
1086
d9bc0d11 1087 fscache_resize_cookie(v9fs_inode_cookie(v9inode), iattr->ia_size);
4eb31178
EVH
1088 }
1089#endif
24e42e32 1090 }
059c138b 1091
24e42e32 1092 v9fs_invalidate_inode_attr(inode);
2bad8471 1093
c1632a0f 1094 setattr_copy(&nop_mnt_idmap, inode, iattr);
24e42e32 1095 mark_inode_dirty(inode);
1025774c 1096 return 0;
2bad8471
EVH
1097}
1098
1099/**
531b1094
LI
1100 * v9fs_stat2inode - populate an inode structure with mistat info
1101 * @stat: Plan 9 metadata (mistat) structure
2bad8471
EVH
1102 * @inode: inode to populate
1103 * @sb: superblock of filesystem
5e3cc1ee 1104 * @flags: control flags (e.g. V9FS_STAT2INODE_KEEP_ISIZE)
2bad8471
EVH
1105 *
1106 */
1107
1108void
51a87c55 1109v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
5e3cc1ee 1110 struct super_block *sb, unsigned int flags)
2bad8471 1111{
3eda0de6 1112 umode_t mode;
2bad8471 1113 struct v9fs_session_info *v9ses = sb->s_fs_info;
b3cbea03 1114 struct v9fs_inode *v9inode = V9FS_I(inode);
2bad8471 1115
bfe86848 1116 set_nlink(inode, 1);
2bad8471 1117
d0242a3a
JL
1118 inode_set_atime(inode, stat->atime, 0);
1119 inode_set_mtime(inode, stat->mtime, 0);
4f871800 1120 inode_set_ctime(inode, stat->mtime, 0);
2bad8471 1121
bd32b82d
LI
1122 inode->i_uid = v9ses->dfltuid;
1123 inode->i_gid = v9ses->dfltgid;
2bad8471 1124
dd6102fb 1125 if (v9fs_proto_dotu(v9ses)) {
531b1094
LI
1126 inode->i_uid = stat->n_uid;
1127 inode->i_gid = stat->n_gid;
2bad8471 1128 }
5717144a 1129 if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) {
9652c732
AV
1130 if (v9fs_proto_dotu(v9ses)) {
1131 unsigned int i_nlink;
5717144a 1132 /*
9652c732
AV
1133 * Hadlink support got added later to the .u extension.
1134 * So there can be a server out there that doesn't
1135 * support this even with .u extension. That would
1136 * just leave us with stat->extension being an empty
1137 * string, though.
5717144a 1138 */
5717144a 1139 /* HARDLINKCOUNT %u */
9652c732
AV
1140 if (sscanf(stat->extension,
1141 " HARDLINKCOUNT %u", &i_nlink) == 1)
bfe86848 1142 set_nlink(inode, i_nlink);
5717144a
AK
1143 }
1144 }
df345c67 1145 mode = p9mode2perm(v9ses, stat);
45089142
AK
1146 mode |= inode->i_mode & ~S_IALLUGO;
1147 inode->i_mode = mode;
2bad8471 1148
80105ed2 1149 v9inode->netfs.remote_i_size = stat->length;
5e3cc1ee
HT
1150 if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE))
1151 v9fs_i_size_write(inode, stat->length);
bd238fb4 1152 /* not real number of blocks, but 512 byte ones ... */
5e3cc1ee 1153 inode->i_blocks = (stat->length + 512 - 1) >> 9;
b3cbea03 1154 v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
2bad8471
EVH
1155}
1156
2bad8471 1157/**
6b255391 1158 * v9fs_vfs_get_link - follow a symlink path
2bad8471 1159 * @dentry: dentry for symlink
6b255391 1160 * @inode: inode for symlink
fceef393 1161 * @done: delayed call for when we are done with the return value
2bad8471
EVH
1162 */
1163
6b255391 1164static const char *v9fs_vfs_get_link(struct dentry *dentry,
fceef393
AV
1165 struct inode *inode,
1166 struct delayed_call *done)
2bad8471 1167{
6b255391
AV
1168 struct v9fs_session_info *v9ses;
1169 struct p9_fid *fid;
51a87c55 1170 struct p9_wstat *st;
680baacb 1171 char *res;
2bad8471 1172
6b255391
AV
1173 if (!dentry)
1174 return ERR_PTR(-ECHILD);
1175
1176 v9ses = v9fs_dentry2v9ses(dentry);
e5690f26
DM
1177 if (!v9fs_proto_dotu(v9ses))
1178 return ERR_PTR(-EBADF);
1179
90e4fc88 1180 p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
e5690f26 1181 fid = v9fs_fid_lookup(dentry);
90e4fc88 1182
ba17674f 1183 if (IS_ERR(fid))
90e4fc88 1184 return ERR_CAST(fid);
2bad8471 1185
bd238fb4 1186 st = p9_client_stat(fid);
b48dbb99 1187 p9_fid_put(fid);
bd238fb4 1188 if (IS_ERR(st))
90e4fc88 1189 return ERR_CAST(st);
2bad8471 1190
bd238fb4 1191 if (!(st->mode & P9_DMSYMLINK)) {
90e4fc88
AV
1192 p9stat_free(st);
1193 kfree(st);
1194 return ERR_PTR(-EINVAL);
2bad8471 1195 }
680baacb 1196 res = st->extension;
90e4fc88 1197 st->extension = NULL;
680baacb
AV
1198 if (strlen(res) >= PATH_MAX)
1199 res[PATH_MAX - 1] = '\0';
1200
62b2be59 1201 p9stat_free(st);
bd238fb4 1202 kfree(st);
fceef393
AV
1203 set_delayed_call(done, kfree_link, res);
1204 return res;
2bad8471
EVH
1205}
1206
ee443996
EVH
1207/**
1208 * v9fs_vfs_mkspecial - create a special file
1209 * @dir: inode to create special file in
1210 * @dentry: dentry to create
fd2916bd 1211 * @perm: mode to create special file
ee443996
EVH
1212 * @extension: 9p2000.u format extension string representing special file
1213 *
1214 */
1215
531b1094 1216static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
c2837de7 1217 u32 perm, const char *extension)
2bad8471 1218{
bd238fb4 1219 struct p9_fid *fid;
d28c61f0 1220 struct v9fs_session_info *v9ses;
2bad8471 1221
6a3124a3 1222 v9ses = v9fs_inode2v9ses(dir);
dd6102fb 1223 if (!v9fs_proto_dotu(v9ses)) {
5d385153 1224 p9_debug(P9_DEBUG_ERROR, "not extended\n");
6a3124a3 1225 return -EPERM;
2bad8471
EVH
1226 }
1227
bd238fb4
LI
1228 fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
1229 P9_OREAD);
1230 if (IS_ERR(fid))
1231 return PTR_ERR(fid);
da977b2c 1232
d28c61f0 1233 v9fs_invalidate_inode_attr(dir);
b48dbb99 1234 p9_fid_put(fid);
6a3124a3 1235 return 0;
531b1094
LI
1236}
1237
1238/**
1239 * v9fs_vfs_symlink - helper function to create symlinks
7a77db95 1240 * @idmap: idmap of the mount
531b1094
LI
1241 * @dir: directory inode containing symlink
1242 * @dentry: dentry for symlink
1243 * @symname: symlink data
1244 *
ee443996 1245 * See Also: 9P2000.u RFC for more information
531b1094
LI
1246 *
1247 */
1248
1249static int
7a77db95 1250v9fs_vfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
549c7297 1251 struct dentry *dentry, const char *symname)
531b1094 1252{
4b8e9923
AV
1253 p9_debug(P9_DEBUG_VFS, " %lu,%pd,%s\n",
1254 dir->i_ino, dentry, symname);
531b1094 1255
c2837de7 1256 return v9fs_vfs_mkspecial(dir, dentry, P9_DMSYMLINK, symname);
531b1094
LI
1257}
1258
b46c267e
AV
1259#define U32_MAX_DIGITS 10
1260
531b1094
LI
1261/**
1262 * v9fs_vfs_link - create a hardlink
1263 * @old_dentry: dentry for file to link to
1264 * @dir: inode destination for new link
1265 * @dentry: dentry for link
1266 *
1267 */
1268
531b1094
LI
1269static int
1270v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1271 struct dentry *dentry)
1272{
1273 int retval;
b46c267e 1274 char name[1 + U32_MAX_DIGITS + 2]; /* sign + number + \n + \0 */
d28c61f0 1275 struct p9_fid *oldfid;
531b1094 1276
4b8e9923
AV
1277 p9_debug(P9_DEBUG_VFS, " %lu,%pd,%pd\n",
1278 dir->i_ino, dentry, old_dentry);
531b1094 1279
da977b2c 1280 oldfid = v9fs_fid_clone(old_dentry);
ba17674f 1281 if (IS_ERR(oldfid))
da977b2c 1282 return PTR_ERR(oldfid);
531b1094 1283
16cce6d2 1284 sprintf(name, "%d\n", oldfid->fid);
bd238fb4 1285 retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
c06c066a 1286 if (!retval) {
2b0143b5 1287 v9fs_refresh_inode(oldfid, d_inode(old_dentry));
d28c61f0 1288 v9fs_invalidate_inode_attr(dir);
c06c066a 1289 }
b48dbb99 1290 p9_fid_put(oldfid);
2bad8471
EVH
1291 return retval;
1292}
1293
1294/**
1295 * v9fs_vfs_mknod - create a special file
5ebb29be 1296 * @idmap: idmap of the mount
2bad8471
EVH
1297 * @dir: inode destination for new link
1298 * @dentry: dentry for file
1299 * @mode: mode for creation
ee443996 1300 * @rdev: device associated with special file
2bad8471
EVH
1301 *
1302 */
1303
1304static int
5ebb29be 1305v9fs_vfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
549c7297 1306 struct dentry *dentry, umode_t mode, dev_t rdev)
2bad8471 1307{
c2837de7 1308 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
531b1094 1309 int retval;
b46c267e 1310 char name[2 + U32_MAX_DIGITS + 1 + U32_MAX_DIGITS + 1];
c2837de7 1311 u32 perm;
2bad8471 1312
6e195b0f 1313 p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %x MAJOR: %u MINOR: %u\n",
4b8e9923 1314 dir->i_ino, dentry, mode,
5d385153 1315 MAJOR(rdev), MINOR(rdev));
2bad8471 1316
2bad8471
EVH
1317 /* build extension */
1318 if (S_ISBLK(mode))
531b1094 1319 sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
2bad8471 1320 else if (S_ISCHR(mode))
531b1094 1321 sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));
b46c267e 1322 else
75cc5c9b 1323 *name = 0;
2bad8471 1324
c2837de7
AV
1325 perm = unixmode2p9mode(v9ses, mode);
1326 retval = v9fs_vfs_mkspecial(dir, dentry, perm, name);
2bad8471
EVH
1327
1328 return retval;
1329}
1330
b3cbea03
AK
1331int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
1332{
45089142
AK
1333 int umode;
1334 dev_t rdev;
b3cbea03
AK
1335 struct p9_wstat *st;
1336 struct v9fs_session_info *v9ses;
5e3cc1ee 1337 unsigned int flags;
b3cbea03
AK
1338
1339 v9ses = v9fs_inode2v9ses(inode);
1340 st = p9_client_stat(fid);
1341 if (IS_ERR(st))
1342 return PTR_ERR(st);
45089142
AK
1343 /*
1344 * Don't update inode if the file type is different
1345 */
1346 umode = p9mode2unixmode(v9ses, st, &rdev);
6e3e2c43 1347 if (inode_wrong_type(inode, umode))
45089142 1348 goto out;
b3cbea03 1349
b3cbea03
AK
1350 /*
1351 * We don't want to refresh inode->i_size,
1352 * because we may have cached data
1353 */
4eb31178 1354 flags = (v9ses->cache & CACHE_LOOSE) ?
5e3cc1ee
HT
1355 V9FS_STAT2INODE_KEEP_ISIZE : 0;
1356 v9fs_stat2inode(st, inode, inode->i_sb, flags);
45089142 1357out:
b3cbea03
AK
1358 p9stat_free(st);
1359 kfree(st);
1360 return 0;
1361}
1362
9b6533c9
SK
1363static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1364 .create = v9fs_vfs_create,
1365 .lookup = v9fs_vfs_lookup,
e43ae79c 1366 .atomic_open = v9fs_vfs_atomic_open,
9b6533c9 1367 .symlink = v9fs_vfs_symlink,
50cc42ff 1368 .link = v9fs_vfs_link,
9b6533c9
SK
1369 .unlink = v9fs_vfs_unlink,
1370 .mkdir = v9fs_vfs_mkdir,
1371 .rmdir = v9fs_vfs_rmdir,
1d76e313 1372 .mknod = v9fs_vfs_mknod,
9b6533c9
SK
1373 .rename = v9fs_vfs_rename,
1374 .getattr = v9fs_vfs_getattr,
1375 .setattr = v9fs_vfs_setattr,
1376};
1377
754661f1 1378static const struct inode_operations v9fs_dir_inode_operations = {
b501611a
EVH
1379 .create = v9fs_vfs_create,
1380 .lookup = v9fs_vfs_lookup,
e43ae79c 1381 .atomic_open = v9fs_vfs_atomic_open,
b501611a
EVH
1382 .unlink = v9fs_vfs_unlink,
1383 .mkdir = v9fs_vfs_mkdir,
1384 .rmdir = v9fs_vfs_rmdir,
1385 .mknod = v9fs_vfs_mknod,
1386 .rename = v9fs_vfs_rename,
1387 .getattr = v9fs_vfs_getattr,
1388 .setattr = v9fs_vfs_setattr,
1389};
1390
754661f1 1391static const struct inode_operations v9fs_file_inode_operations = {
2bad8471
EVH
1392 .getattr = v9fs_vfs_getattr,
1393 .setattr = v9fs_vfs_setattr,
1394};
1395
754661f1 1396static const struct inode_operations v9fs_symlink_inode_operations = {
6b255391 1397 .get_link = v9fs_vfs_get_link,
2bad8471
EVH
1398 .getattr = v9fs_vfs_getattr,
1399 .setattr = v9fs_vfs_setattr,
1400};
9b6533c9 1401