1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * This file contains vfs inode ops for the 9P2000.L protocol. 4 * 5 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 6 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 7 */ 8 9 #include <linux/module.h> 10 #include <linux/errno.h> 11 #include <linux/fs.h> 12 #include <linux/file.h> 13 #include <linux/pagemap.h> 14 #include <linux/stat.h> 15 #include <linux/string.h> 16 #include <linux/namei.h> 17 #include <linux/sched.h> 18 #include <linux/slab.h> 19 #include <linux/xattr.h> 20 #include <linux/posix_acl.h> 21 #include <net/9p/9p.h> 22 #include <net/9p/client.h> 23 24 #include "v9fs.h" 25 #include "v9fs_vfs.h" 26 #include "fid.h" 27 #include "cache.h" 28 #include "xattr.h" 29 #include "acl.h" 30 31 static int 32 v9fs_vfs_mknod_dotl(struct mnt_idmap *idmap, struct inode *dir, 33 struct dentry *dentry, umode_t omode, dev_t rdev); 34 35 /** 36 * v9fs_get_fsgid_for_create - Helper function to get the gid for a new object 37 * @dir_inode: The directory inode 38 * 39 * Helper function to get the gid for creating a 40 * new file system object. This checks the S_ISGID to determine the owning 41 * group of the new file system object. 42 */ 43 44 static kgid_t v9fs_get_fsgid_for_create(struct inode *dir_inode) 45 { 46 BUG_ON(dir_inode == NULL); 47 48 if (dir_inode->i_mode & S_ISGID) { 49 /* set_gid bit is set.*/ 50 return dir_inode->i_gid; 51 } 52 return current_fsgid(); 53 } 54 55 56 57 struct inode * 58 v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid, bool new) 59 { 60 int retval; 61 struct inode *inode; 62 struct p9_stat_dotl *st; 63 struct v9fs_session_info *v9ses = sb->s_fs_info; 64 65 inode = iget_locked(sb, QID2INO(&fid->qid)); 66 if (unlikely(!inode)) 67 return ERR_PTR(-ENOMEM); 68 if (!(inode->i_state & I_NEW)) { 69 if (!new) { 70 goto done; 71 } else { /* deal with race condition in inode number reuse */ 72 p9_debug(P9_DEBUG_ERROR, "WARNING: Inode collision %lx\n", 73 inode->i_ino); 74 iput(inode); 75 remove_inode_hash(inode); 76 inode = iget_locked(sb, QID2INO(&fid->qid)); 77 WARN_ON(!(inode->i_state & I_NEW)); 78 } 79 } 80 81 /* 82 * initialize the inode with the stat info 83 * FIXME!! we may need support for stale inodes 84 * later. 85 */ 86 st = p9_client_getattr_dotl(fid, P9_STATS_BASIC | P9_STATS_GEN); 87 if (IS_ERR(st)) { 88 retval = PTR_ERR(st); 89 goto error; 90 } 91 92 retval = v9fs_init_inode(v9ses, inode, &fid->qid, 93 st->st_mode, new_decode_dev(st->st_rdev)); 94 v9fs_stat2inode_dotl(st, inode, 0); 95 kfree(st); 96 if (retval) 97 goto error; 98 99 v9fs_set_netfs_context(inode); 100 v9fs_cache_inode_get_cookie(inode); 101 retval = v9fs_get_acl(inode, fid); 102 if (retval) 103 goto error; 104 105 unlock_new_inode(inode); 106 done: 107 return inode; 108 error: 109 iget_failed(inode); 110 return ERR_PTR(retval); 111 } 112 113 struct dotl_openflag_map { 114 int open_flag; 115 int dotl_flag; 116 }; 117 118 static int v9fs_mapped_dotl_flags(int flags) 119 { 120 int i; 121 int rflags = 0; 122 struct dotl_openflag_map dotl_oflag_map[] = { 123 { O_CREAT, P9_DOTL_CREATE }, 124 { O_EXCL, P9_DOTL_EXCL }, 125 { O_NOCTTY, P9_DOTL_NOCTTY }, 126 { O_APPEND, P9_DOTL_APPEND }, 127 { O_NONBLOCK, P9_DOTL_NONBLOCK }, 128 { O_DSYNC, P9_DOTL_DSYNC }, 129 { FASYNC, P9_DOTL_FASYNC }, 130 { O_DIRECT, P9_DOTL_DIRECT }, 131 { O_LARGEFILE, P9_DOTL_LARGEFILE }, 132 { O_DIRECTORY, P9_DOTL_DIRECTORY }, 133 { O_NOFOLLOW, P9_DOTL_NOFOLLOW }, 134 { O_NOATIME, P9_DOTL_NOATIME }, 135 { O_CLOEXEC, P9_DOTL_CLOEXEC }, 136 { O_SYNC, P9_DOTL_SYNC}, 137 }; 138 for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) { 139 if (flags & dotl_oflag_map[i].open_flag) 140 rflags |= dotl_oflag_map[i].dotl_flag; 141 } 142 return rflags; 143 } 144 145 /** 146 * v9fs_open_to_dotl_flags- convert Linux specific open flags to 147 * plan 9 open flag. 148 * @flags: flags to convert 149 */ 150 int v9fs_open_to_dotl_flags(int flags) 151 { 152 int rflags = 0; 153 154 /* 155 * We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY 156 * and P9_DOTL_NOACCESS 157 */ 158 rflags |= flags & O_ACCMODE; 159 rflags |= v9fs_mapped_dotl_flags(flags); 160 161 return rflags; 162 } 163 164 /** 165 * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol. 166 * @idmap: The user namespace of the mount 167 * @dir: directory inode that is being created 168 * @dentry: dentry that is being deleted 169 * @omode: create permissions 170 * @excl: True if the file must not yet exist 171 * 172 */ 173 static int 174 v9fs_vfs_create_dotl(struct mnt_idmap *idmap, struct inode *dir, 175 struct dentry *dentry, umode_t omode, bool excl) 176 { 177 return v9fs_vfs_mknod_dotl(idmap, dir, dentry, omode, 0); 178 } 179 180 static int 181 v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, 182 struct file *file, unsigned int flags, umode_t omode) 183 { 184 int err = 0; 185 kgid_t gid; 186 umode_t mode; 187 int p9_omode = v9fs_open_to_dotl_flags(flags); 188 const unsigned char *name = NULL; 189 struct p9_qid qid; 190 struct inode *inode; 191 struct p9_fid *fid = NULL; 192 struct p9_fid *dfid = NULL, *ofid = NULL; 193 struct v9fs_session_info *v9ses; 194 struct posix_acl *pacl = NULL, *dacl = NULL; 195 struct dentry *res = NULL; 196 197 if (d_in_lookup(dentry)) { 198 res = v9fs_vfs_lookup(dir, dentry, 0); 199 if (IS_ERR(res)) 200 return PTR_ERR(res); 201 202 if (res) 203 dentry = res; 204 } 205 206 /* Only creates */ 207 if (!(flags & O_CREAT) || d_really_is_positive(dentry)) 208 return finish_no_open(file, res); 209 210 v9ses = v9fs_inode2v9ses(dir); 211 212 name = dentry->d_name.name; 213 p9_debug(P9_DEBUG_VFS, "name:%s flags:0x%x mode:0x%x\n", 214 name, flags, omode); 215 216 dfid = v9fs_parent_fid(dentry); 217 if (IS_ERR(dfid)) { 218 err = PTR_ERR(dfid); 219 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 220 goto out; 221 } 222 223 /* clone a fid to use for creation */ 224 ofid = clone_fid(dfid); 225 if (IS_ERR(ofid)) { 226 err = PTR_ERR(ofid); 227 p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); 228 goto out; 229 } 230 231 gid = v9fs_get_fsgid_for_create(dir); 232 233 mode = omode; 234 /* Update mode based on ACL value */ 235 err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); 236 if (err) { 237 p9_debug(P9_DEBUG_VFS, "Failed to get acl values in create %d\n", 238 err); 239 goto out; 240 } 241 242 if ((v9ses->cache & CACHE_WRITEBACK) && (p9_omode & P9_OWRITE)) { 243 p9_omode = (p9_omode & ~P9_OWRITE) | P9_ORDWR; 244 p9_debug(P9_DEBUG_CACHE, 245 "write-only file with writeback enabled, creating w/ O_RDWR\n"); 246 } 247 err = p9_client_create_dotl(ofid, name, p9_omode, mode, gid, &qid); 248 if (err < 0) { 249 p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in create %d\n", 250 err); 251 goto out; 252 } 253 v9fs_invalidate_inode_attr(dir); 254 255 /* instantiate inode and assign the unopened fid to the dentry */ 256 fid = p9_client_walk(dfid, 1, &name, 1); 257 if (IS_ERR(fid)) { 258 err = PTR_ERR(fid); 259 p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); 260 goto out; 261 } 262 inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true); 263 if (IS_ERR(inode)) { 264 err = PTR_ERR(inode); 265 p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err); 266 goto out; 267 } 268 /* Now set the ACL based on the default value */ 269 v9fs_set_create_acl(inode, fid, dacl, pacl); 270 271 v9fs_fid_add(dentry, &fid); 272 d_instantiate(dentry, inode); 273 274 /* Since we are opening a file, assign the open fid to the file */ 275 err = finish_open(file, dentry, generic_file_open); 276 if (err) 277 goto out; 278 file->private_data = ofid; 279 #ifdef CONFIG_9P_FSCACHE 280 if (v9ses->cache & CACHE_FSCACHE) { 281 struct v9fs_inode *v9inode = V9FS_I(inode); 282 fscache_use_cookie(v9fs_inode_cookie(v9inode), 283 file->f_mode & FMODE_WRITE); 284 } 285 #endif 286 v9fs_fid_add_modes(ofid, v9ses->flags, v9ses->cache, flags); 287 v9fs_open_fid_add(inode, &ofid); 288 file->f_mode |= FMODE_CREATED; 289 out: 290 p9_fid_put(dfid); 291 p9_fid_put(ofid); 292 p9_fid_put(fid); 293 v9fs_put_acl(dacl, pacl); 294 dput(res); 295 return err; 296 } 297 298 /** 299 * v9fs_vfs_mkdir_dotl - VFS mkdir hook to create a directory 300 * @idmap: The idmap of the mount 301 * @dir: inode that is being unlinked 302 * @dentry: dentry that is being unlinked 303 * @omode: mode for new directory 304 * 305 */ 306 307 static int v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap, 308 struct inode *dir, struct dentry *dentry, 309 umode_t omode) 310 { 311 int err; 312 struct p9_fid *fid = NULL, *dfid = NULL; 313 kgid_t gid; 314 const unsigned char *name; 315 umode_t mode; 316 struct inode *inode; 317 struct p9_qid qid; 318 struct posix_acl *dacl = NULL, *pacl = NULL; 319 320 p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry); 321 322 omode |= S_IFDIR; 323 if (dir->i_mode & S_ISGID) 324 omode |= S_ISGID; 325 326 dfid = v9fs_parent_fid(dentry); 327 if (IS_ERR(dfid)) { 328 err = PTR_ERR(dfid); 329 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 330 goto error; 331 } 332 333 gid = v9fs_get_fsgid_for_create(dir); 334 mode = omode; 335 /* Update mode based on ACL value */ 336 err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); 337 if (err) { 338 p9_debug(P9_DEBUG_VFS, "Failed to get acl values in mkdir %d\n", 339 err); 340 goto error; 341 } 342 name = dentry->d_name.name; 343 err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid); 344 if (err < 0) 345 goto error; 346 fid = p9_client_walk(dfid, 1, &name, 1); 347 if (IS_ERR(fid)) { 348 err = PTR_ERR(fid); 349 p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", 350 err); 351 goto error; 352 } 353 354 /* instantiate inode and assign the unopened fid to the dentry */ 355 inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true); 356 if (IS_ERR(inode)) { 357 err = PTR_ERR(inode); 358 p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", 359 err); 360 goto error; 361 } 362 v9fs_fid_add(dentry, &fid); 363 v9fs_set_create_acl(inode, fid, dacl, pacl); 364 d_instantiate(dentry, inode); 365 err = 0; 366 inc_nlink(dir); 367 v9fs_invalidate_inode_attr(dir); 368 error: 369 p9_fid_put(fid); 370 v9fs_put_acl(dacl, pacl); 371 p9_fid_put(dfid); 372 return err; 373 } 374 375 static int 376 v9fs_vfs_getattr_dotl(struct mnt_idmap *idmap, 377 const struct path *path, struct kstat *stat, 378 u32 request_mask, unsigned int flags) 379 { 380 struct dentry *dentry = path->dentry; 381 struct v9fs_session_info *v9ses; 382 struct p9_fid *fid; 383 struct inode *inode = d_inode(dentry); 384 struct p9_stat_dotl *st; 385 386 p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry); 387 v9ses = v9fs_dentry2v9ses(dentry); 388 if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) { 389 generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat); 390 return 0; 391 } else if (v9ses->cache) { 392 if (S_ISREG(inode->i_mode)) { 393 int retval = filemap_fdatawrite(inode->i_mapping); 394 395 if (retval) 396 p9_debug(P9_DEBUG_ERROR, 397 "flushing writeback during getattr returned %d\n", retval); 398 } 399 } 400 fid = v9fs_fid_lookup(dentry); 401 if (IS_ERR(fid)) 402 return PTR_ERR(fid); 403 404 /* Ask for all the fields in stat structure. Server will return 405 * whatever it supports 406 */ 407 408 st = p9_client_getattr_dotl(fid, P9_STATS_ALL); 409 p9_fid_put(fid); 410 if (IS_ERR(st)) 411 return PTR_ERR(st); 412 413 v9fs_stat2inode_dotl(st, d_inode(dentry), 0); 414 generic_fillattr(&nop_mnt_idmap, request_mask, d_inode(dentry), stat); 415 /* Change block size to what the server returned */ 416 stat->blksize = st->st_blksize; 417 418 kfree(st); 419 return 0; 420 } 421 422 /* 423 * Attribute flags. 424 */ 425 #define P9_ATTR_MODE (1 << 0) 426 #define P9_ATTR_UID (1 << 1) 427 #define P9_ATTR_GID (1 << 2) 428 #define P9_ATTR_SIZE (1 << 3) 429 #define P9_ATTR_ATIME (1 << 4) 430 #define P9_ATTR_MTIME (1 << 5) 431 #define P9_ATTR_CTIME (1 << 6) 432 #define P9_ATTR_ATIME_SET (1 << 7) 433 #define P9_ATTR_MTIME_SET (1 << 8) 434 435 struct dotl_iattr_map { 436 int iattr_valid; 437 int p9_iattr_valid; 438 }; 439 440 static int v9fs_mapped_iattr_valid(int iattr_valid) 441 { 442 int i; 443 int p9_iattr_valid = 0; 444 struct dotl_iattr_map dotl_iattr_map[] = { 445 { ATTR_MODE, P9_ATTR_MODE }, 446 { ATTR_UID, P9_ATTR_UID }, 447 { ATTR_GID, P9_ATTR_GID }, 448 { ATTR_SIZE, P9_ATTR_SIZE }, 449 { ATTR_ATIME, P9_ATTR_ATIME }, 450 { ATTR_MTIME, P9_ATTR_MTIME }, 451 { ATTR_CTIME, P9_ATTR_CTIME }, 452 { ATTR_ATIME_SET, P9_ATTR_ATIME_SET }, 453 { ATTR_MTIME_SET, P9_ATTR_MTIME_SET }, 454 }; 455 for (i = 0; i < ARRAY_SIZE(dotl_iattr_map); i++) { 456 if (iattr_valid & dotl_iattr_map[i].iattr_valid) 457 p9_iattr_valid |= dotl_iattr_map[i].p9_iattr_valid; 458 } 459 return p9_iattr_valid; 460 } 461 462 /** 463 * v9fs_vfs_setattr_dotl - set file metadata 464 * @idmap: idmap of the mount 465 * @dentry: file whose metadata to set 466 * @iattr: metadata assignment structure 467 * 468 */ 469 470 int v9fs_vfs_setattr_dotl(struct mnt_idmap *idmap, 471 struct dentry *dentry, struct iattr *iattr) 472 { 473 int retval, use_dentry = 0; 474 struct inode *inode = d_inode(dentry); 475 struct v9fs_session_info __maybe_unused *v9ses; 476 struct p9_fid *fid = NULL; 477 struct p9_iattr_dotl p9attr = { 478 .uid = INVALID_UID, 479 .gid = INVALID_GID, 480 }; 481 482 p9_debug(P9_DEBUG_VFS, "\n"); 483 484 retval = setattr_prepare(&nop_mnt_idmap, dentry, iattr); 485 if (retval) 486 return retval; 487 488 v9ses = v9fs_dentry2v9ses(dentry); 489 490 p9attr.valid = v9fs_mapped_iattr_valid(iattr->ia_valid); 491 if (iattr->ia_valid & ATTR_MODE) 492 p9attr.mode = iattr->ia_mode; 493 if (iattr->ia_valid & ATTR_UID) 494 p9attr.uid = iattr->ia_uid; 495 if (iattr->ia_valid & ATTR_GID) 496 p9attr.gid = iattr->ia_gid; 497 if (iattr->ia_valid & ATTR_SIZE) 498 p9attr.size = iattr->ia_size; 499 if (iattr->ia_valid & ATTR_ATIME_SET) { 500 p9attr.atime_sec = iattr->ia_atime.tv_sec; 501 p9attr.atime_nsec = iattr->ia_atime.tv_nsec; 502 } 503 if (iattr->ia_valid & ATTR_MTIME_SET) { 504 p9attr.mtime_sec = iattr->ia_mtime.tv_sec; 505 p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec; 506 } 507 508 if (iattr->ia_valid & ATTR_FILE) { 509 fid = iattr->ia_file->private_data; 510 WARN_ON(!fid); 511 } 512 if (!fid) { 513 fid = v9fs_fid_lookup(dentry); 514 use_dentry = 1; 515 } 516 if (IS_ERR(fid)) 517 return PTR_ERR(fid); 518 519 /* Write all dirty data */ 520 if (S_ISREG(inode->i_mode)) { 521 retval = filemap_fdatawrite(inode->i_mapping); 522 if (retval < 0) 523 p9_debug(P9_DEBUG_ERROR, 524 "Flushing file prior to setattr failed: %d\n", retval); 525 } 526 527 retval = p9_client_setattr(fid, &p9attr); 528 if (retval < 0) { 529 if (use_dentry) 530 p9_fid_put(fid); 531 return retval; 532 } 533 534 if ((iattr->ia_valid & ATTR_SIZE) && iattr->ia_size != 535 i_size_read(inode)) { 536 truncate_setsize(inode, iattr->ia_size); 537 netfs_resize_file(netfs_inode(inode), iattr->ia_size, true); 538 539 #ifdef CONFIG_9P_FSCACHE 540 if (v9ses->cache & CACHE_FSCACHE) 541 fscache_resize_cookie(v9fs_inode_cookie(V9FS_I(inode)), 542 iattr->ia_size); 543 #endif 544 } 545 546 v9fs_invalidate_inode_attr(inode); 547 setattr_copy(&nop_mnt_idmap, inode, iattr); 548 mark_inode_dirty(inode); 549 if (iattr->ia_valid & ATTR_MODE) { 550 /* We also want to update ACL when we update mode bits */ 551 retval = v9fs_acl_chmod(inode, fid); 552 if (retval < 0) { 553 if (use_dentry) 554 p9_fid_put(fid); 555 return retval; 556 } 557 } 558 if (use_dentry) 559 p9_fid_put(fid); 560 561 return 0; 562 } 563 564 /** 565 * v9fs_stat2inode_dotl - populate an inode structure with stat info 566 * @stat: stat structure 567 * @inode: inode to populate 568 * @flags: ctrl flags (e.g. V9FS_STAT2INODE_KEEP_ISIZE) 569 * 570 */ 571 572 void 573 v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode, 574 unsigned int flags) 575 { 576 umode_t mode; 577 struct v9fs_inode *v9inode = V9FS_I(inode); 578 579 if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { 580 inode_set_atime(inode, stat->st_atime_sec, 581 stat->st_atime_nsec); 582 inode_set_mtime(inode, stat->st_mtime_sec, 583 stat->st_mtime_nsec); 584 inode_set_ctime(inode, stat->st_ctime_sec, 585 stat->st_ctime_nsec); 586 inode->i_uid = stat->st_uid; 587 inode->i_gid = stat->st_gid; 588 set_nlink(inode, stat->st_nlink); 589 590 mode = stat->st_mode & S_IALLUGO; 591 mode |= inode->i_mode & ~S_IALLUGO; 592 inode->i_mode = mode; 593 594 v9inode->netfs.remote_i_size = stat->st_size; 595 if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE)) 596 v9fs_i_size_write(inode, stat->st_size); 597 inode->i_blocks = stat->st_blocks; 598 } else { 599 if (stat->st_result_mask & P9_STATS_ATIME) { 600 inode_set_atime(inode, stat->st_atime_sec, 601 stat->st_atime_nsec); 602 } 603 if (stat->st_result_mask & P9_STATS_MTIME) { 604 inode_set_mtime(inode, stat->st_mtime_sec, 605 stat->st_mtime_nsec); 606 } 607 if (stat->st_result_mask & P9_STATS_CTIME) { 608 inode_set_ctime(inode, stat->st_ctime_sec, 609 stat->st_ctime_nsec); 610 } 611 if (stat->st_result_mask & P9_STATS_UID) 612 inode->i_uid = stat->st_uid; 613 if (stat->st_result_mask & P9_STATS_GID) 614 inode->i_gid = stat->st_gid; 615 if (stat->st_result_mask & P9_STATS_NLINK) 616 set_nlink(inode, stat->st_nlink); 617 if (stat->st_result_mask & P9_STATS_MODE) { 618 mode = stat->st_mode & S_IALLUGO; 619 mode |= inode->i_mode & ~S_IALLUGO; 620 inode->i_mode = mode; 621 } 622 if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE) && 623 stat->st_result_mask & P9_STATS_SIZE) { 624 v9inode->netfs.remote_i_size = stat->st_size; 625 v9fs_i_size_write(inode, stat->st_size); 626 } 627 if (stat->st_result_mask & P9_STATS_BLOCKS) 628 inode->i_blocks = stat->st_blocks; 629 } 630 if (stat->st_result_mask & P9_STATS_GEN) 631 inode->i_generation = stat->st_gen; 632 633 /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION 634 * because the inode structure does not have fields for them. 635 */ 636 v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR; 637 } 638 639 static int 640 v9fs_vfs_symlink_dotl(struct mnt_idmap *idmap, struct inode *dir, 641 struct dentry *dentry, const char *symname) 642 { 643 int err; 644 kgid_t gid; 645 const unsigned char *name; 646 struct p9_qid qid; 647 struct p9_fid *dfid; 648 struct p9_fid *fid = NULL; 649 650 name = dentry->d_name.name; 651 p9_debug(P9_DEBUG_VFS, "%lu,%s,%s\n", dir->i_ino, name, symname); 652 653 dfid = v9fs_parent_fid(dentry); 654 if (IS_ERR(dfid)) { 655 err = PTR_ERR(dfid); 656 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 657 return err; 658 } 659 660 gid = v9fs_get_fsgid_for_create(dir); 661 662 /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */ 663 err = p9_client_symlink(dfid, name, symname, gid, &qid); 664 665 if (err < 0) { 666 p9_debug(P9_DEBUG_VFS, "p9_client_symlink failed %d\n", err); 667 goto error; 668 } 669 670 v9fs_invalidate_inode_attr(dir); 671 672 error: 673 p9_fid_put(fid); 674 p9_fid_put(dfid); 675 return err; 676 } 677 678 /** 679 * v9fs_vfs_link_dotl - create a hardlink for dotl 680 * @old_dentry: dentry for file to link to 681 * @dir: inode destination for new link 682 * @dentry: dentry for link 683 * 684 */ 685 686 static int 687 v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir, 688 struct dentry *dentry) 689 { 690 int err; 691 struct p9_fid *dfid, *oldfid; 692 struct v9fs_session_info *v9ses; 693 694 p9_debug(P9_DEBUG_VFS, "dir ino: %lu, old_name: %pd, new_name: %pd\n", 695 dir->i_ino, old_dentry, dentry); 696 697 v9ses = v9fs_inode2v9ses(dir); 698 dfid = v9fs_parent_fid(dentry); 699 if (IS_ERR(dfid)) 700 return PTR_ERR(dfid); 701 702 oldfid = v9fs_fid_lookup(old_dentry); 703 if (IS_ERR(oldfid)) { 704 p9_fid_put(dfid); 705 return PTR_ERR(oldfid); 706 } 707 708 err = p9_client_link(dfid, oldfid, dentry->d_name.name); 709 710 p9_fid_put(dfid); 711 p9_fid_put(oldfid); 712 if (err < 0) { 713 p9_debug(P9_DEBUG_VFS, "p9_client_link failed %d\n", err); 714 return err; 715 } 716 717 v9fs_invalidate_inode_attr(dir); 718 if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) { 719 /* Get the latest stat info from server. */ 720 struct p9_fid *fid; 721 722 fid = v9fs_fid_lookup(old_dentry); 723 if (IS_ERR(fid)) 724 return PTR_ERR(fid); 725 726 v9fs_refresh_inode_dotl(fid, d_inode(old_dentry)); 727 p9_fid_put(fid); 728 } 729 ihold(d_inode(old_dentry)); 730 d_instantiate(dentry, d_inode(old_dentry)); 731 732 return err; 733 } 734 735 /** 736 * v9fs_vfs_mknod_dotl - create a special file 737 * @idmap: The idmap of the mount 738 * @dir: inode destination for new link 739 * @dentry: dentry for file 740 * @omode: mode for creation 741 * @rdev: device associated with special file 742 * 743 */ 744 static int 745 v9fs_vfs_mknod_dotl(struct mnt_idmap *idmap, struct inode *dir, 746 struct dentry *dentry, umode_t omode, dev_t rdev) 747 { 748 int err; 749 kgid_t gid; 750 const unsigned char *name; 751 umode_t mode; 752 struct p9_fid *fid = NULL, *dfid = NULL; 753 struct inode *inode; 754 struct p9_qid qid; 755 struct posix_acl *dacl = NULL, *pacl = NULL; 756 757 p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %x MAJOR: %u MINOR: %u\n", 758 dir->i_ino, dentry, omode, 759 MAJOR(rdev), MINOR(rdev)); 760 761 dfid = v9fs_parent_fid(dentry); 762 if (IS_ERR(dfid)) { 763 err = PTR_ERR(dfid); 764 p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 765 goto error; 766 } 767 768 gid = v9fs_get_fsgid_for_create(dir); 769 mode = omode; 770 /* Update mode based on ACL value */ 771 err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); 772 if (err) { 773 p9_debug(P9_DEBUG_VFS, "Failed to get acl values in mknod %d\n", 774 err); 775 goto error; 776 } 777 name = dentry->d_name.name; 778 779 err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid); 780 if (err < 0) 781 goto error; 782 783 v9fs_invalidate_inode_attr(dir); 784 fid = p9_client_walk(dfid, 1, &name, 1); 785 if (IS_ERR(fid)) { 786 err = PTR_ERR(fid); 787 p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", 788 err); 789 goto error; 790 } 791 inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true); 792 if (IS_ERR(inode)) { 793 err = PTR_ERR(inode); 794 p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", 795 err); 796 goto error; 797 } 798 v9fs_set_create_acl(inode, fid, dacl, pacl); 799 v9fs_fid_add(dentry, &fid); 800 d_instantiate(dentry, inode); 801 err = 0; 802 error: 803 p9_fid_put(fid); 804 v9fs_put_acl(dacl, pacl); 805 p9_fid_put(dfid); 806 807 return err; 808 } 809 810 /** 811 * v9fs_vfs_get_link_dotl - follow a symlink path 812 * @dentry: dentry for symlink 813 * @inode: inode for symlink 814 * @done: destructor for return value 815 */ 816 817 static const char * 818 v9fs_vfs_get_link_dotl(struct dentry *dentry, 819 struct inode *inode, 820 struct delayed_call *done) 821 { 822 struct p9_fid *fid; 823 char *target; 824 int retval; 825 826 if (!dentry) 827 return ERR_PTR(-ECHILD); 828 829 p9_debug(P9_DEBUG_VFS, "%pd\n", dentry); 830 831 fid = v9fs_fid_lookup(dentry); 832 if (IS_ERR(fid)) 833 return ERR_CAST(fid); 834 retval = p9_client_readlink(fid, &target); 835 p9_fid_put(fid); 836 if (retval) 837 return ERR_PTR(retval); 838 set_delayed_call(done, kfree_link, target); 839 return target; 840 } 841 842 int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode) 843 { 844 struct p9_stat_dotl *st; 845 struct v9fs_session_info *v9ses; 846 unsigned int flags; 847 848 v9ses = v9fs_inode2v9ses(inode); 849 st = p9_client_getattr_dotl(fid, P9_STATS_ALL); 850 if (IS_ERR(st)) 851 return PTR_ERR(st); 852 /* 853 * Don't update inode if the file type is different 854 */ 855 if (inode_wrong_type(inode, st->st_mode)) 856 goto out; 857 858 /* 859 * We don't want to refresh inode->i_size, 860 * because we may have cached data 861 */ 862 flags = (v9ses->cache & CACHE_LOOSE) ? 863 V9FS_STAT2INODE_KEEP_ISIZE : 0; 864 v9fs_stat2inode_dotl(st, inode, flags); 865 out: 866 kfree(st); 867 return 0; 868 } 869 870 const struct inode_operations v9fs_dir_inode_operations_dotl = { 871 .create = v9fs_vfs_create_dotl, 872 .atomic_open = v9fs_vfs_atomic_open_dotl, 873 .lookup = v9fs_vfs_lookup, 874 .link = v9fs_vfs_link_dotl, 875 .symlink = v9fs_vfs_symlink_dotl, 876 .unlink = v9fs_vfs_unlink, 877 .mkdir = v9fs_vfs_mkdir_dotl, 878 .rmdir = v9fs_vfs_rmdir, 879 .mknod = v9fs_vfs_mknod_dotl, 880 .rename = v9fs_vfs_rename, 881 .getattr = v9fs_vfs_getattr_dotl, 882 .setattr = v9fs_vfs_setattr_dotl, 883 .listxattr = v9fs_listxattr, 884 .get_inode_acl = v9fs_iop_get_inode_acl, 885 .get_acl = v9fs_iop_get_acl, 886 .set_acl = v9fs_iop_set_acl, 887 }; 888 889 const struct inode_operations v9fs_file_inode_operations_dotl = { 890 .getattr = v9fs_vfs_getattr_dotl, 891 .setattr = v9fs_vfs_setattr_dotl, 892 .listxattr = v9fs_listxattr, 893 .get_inode_acl = v9fs_iop_get_inode_acl, 894 .get_acl = v9fs_iop_get_acl, 895 .set_acl = v9fs_iop_set_acl, 896 }; 897 898 const struct inode_operations v9fs_symlink_inode_operations_dotl = { 899 .get_link = v9fs_vfs_get_link_dotl, 900 .getattr = v9fs_vfs_getattr_dotl, 901 .setattr = v9fs_vfs_setattr_dotl, 902 .listxattr = v9fs_listxattr, 903 }; 904
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.