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