1 /* 2 * linux/fs/9p/vfs_inode.c 3 * 4 * This file contains vfs inode ops for the 9P2000 protocol. 5 * 6 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 7 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 11 * as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to: 20 * Free Software Foundation 21 * 51 Franklin Street, Fifth Floor 22 * Boston, MA 02111-1301 USA 23 * 24 */ 25 26 #include <linux/module.h> 27 #include <linux/errno.h> 28 #include <linux/fs.h> 29 #include <linux/file.h> 30 #include <linux/pagemap.h> 31 #include <linux/stat.h> 32 #include <linux/string.h> 33 #include <linux/inet.h> 34 #include <linux/namei.h> 35 #include <linux/idr.h> 36 #include <linux/sched.h> 37 #include <linux/slab.h> 38 #include <net/9p/9p.h> 39 #include <net/9p/client.h> 40 41 #include "v9fs.h" 42 #include "v9fs_vfs.h" 43 #include "fid.h" 44 #include "cache.h" 45 46 static const struct inode_operations v9fs_dir_inode_operations; 47 static const struct inode_operations v9fs_dir_inode_operations_dotu; 48 static const struct inode_operations v9fs_dir_inode_operations_dotl; 49 static const struct inode_operations v9fs_file_inode_operations; 50 static const struct inode_operations v9fs_file_inode_operations_dotl; 51 static const struct inode_operations v9fs_symlink_inode_operations; 52 static const struct inode_operations v9fs_symlink_inode_operations_dotl; 53 54 /** 55 * unixmode2p9mode - convert unix mode bits to plan 9 56 * @v9ses: v9fs session information 57 * @mode: mode to convert 58 * 59 */ 60 61 static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode) 62 { 63 int res; 64 res = mode & 0777; 65 if (S_ISDIR(mode)) 66 res |= P9_DMDIR; 67 if (v9fs_proto_dotu(v9ses)) { 68 if (S_ISLNK(mode)) 69 res |= P9_DMSYMLINK; 70 if (v9ses->nodev == 0) { 71 if (S_ISSOCK(mode)) 72 res |= P9_DMSOCKET; 73 if (S_ISFIFO(mode)) 74 res |= P9_DMNAMEDPIPE; 75 if (S_ISBLK(mode)) 76 res |= P9_DMDEVICE; 77 if (S_ISCHR(mode)) 78 res |= P9_DMDEVICE; 79 } 80 81 if ((mode & S_ISUID) == S_ISUID) 82 res |= P9_DMSETUID; 83 if ((mode & S_ISGID) == S_ISGID) 84 res |= P9_DMSETGID; 85 if ((mode & S_ISVTX) == S_ISVTX) 86 res |= P9_DMSETVTX; 87 if ((mode & P9_DMLINK)) 88 res |= P9_DMLINK; 89 } 90 91 return res; 92 } 93 94 /** 95 * p9mode2unixmode- convert plan9 mode bits to unix mode bits 96 * @v9ses: v9fs session information 97 * @mode: mode to convert 98 * 99 */ 100 101 static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode) 102 { 103 int res; 104 105 res = mode & 0777; 106 107 if ((mode & P9_DMDIR) == P9_DMDIR) 108 res |= S_IFDIR; 109 else if ((mode & P9_DMSYMLINK) && (v9fs_proto_dotu(v9ses))) 110 res |= S_IFLNK; 111 else if ((mode & P9_DMSOCKET) && (v9fs_proto_dotu(v9ses)) 112 && (v9ses->nodev == 0)) 113 res |= S_IFSOCK; 114 else if ((mode & P9_DMNAMEDPIPE) && (v9fs_proto_dotu(v9ses)) 115 && (v9ses->nodev == 0)) 116 res |= S_IFIFO; 117 else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses)) 118 && (v9ses->nodev == 0)) 119 res |= S_IFBLK; 120 else 121 res |= S_IFREG; 122 123 if (v9fs_proto_dotu(v9ses)) { 124 if ((mode & P9_DMSETUID) == P9_DMSETUID) 125 res |= S_ISUID; 126 127 if ((mode & P9_DMSETGID) == P9_DMSETGID) 128 res |= S_ISGID; 129 130 if ((mode & P9_DMSETVTX) == P9_DMSETVTX) 131 res |= S_ISVTX; 132 } 133 134 return res; 135 } 136 137 /** 138 * v9fs_uflags2omode- convert posix open flags to plan 9 mode bits 139 * @uflags: flags to convert 140 * @extended: if .u extensions are active 141 */ 142 143 int v9fs_uflags2omode(int uflags, int extended) 144 { 145 int ret; 146 147 ret = 0; 148 switch (uflags&3) { 149 default: 150 case O_RDONLY: 151 ret = P9_OREAD; 152 break; 153 154 case O_WRONLY: 155 ret = P9_OWRITE; 156 break; 157 158 case O_RDWR: 159 ret = P9_ORDWR; 160 break; 161 } 162 163 if (uflags & O_TRUNC) 164 ret |= P9_OTRUNC; 165 166 if (extended) { 167 if (uflags & O_EXCL) 168 ret |= P9_OEXCL; 169 170 if (uflags & O_APPEND) 171 ret |= P9_OAPPEND; 172 } 173 174 return ret; 175 } 176 177 /** 178 * v9fs_blank_wstat - helper function to setup a 9P stat structure 179 * @wstat: structure to initialize 180 * 181 */ 182 183 void 184 v9fs_blank_wstat(struct p9_wstat *wstat) 185 { 186 wstat->type = ~0; 187 wstat->dev = ~0; 188 wstat->qid.type = ~0; 189 wstat->qid.version = ~0; 190 *((long long *)&wstat->qid.path) = ~0; 191 wstat->mode = ~0; 192 wstat->atime = ~0; 193 wstat->mtime = ~0; 194 wstat->length = ~0; 195 wstat->name = NULL; 196 wstat->uid = NULL; 197 wstat->gid = NULL; 198 wstat->muid = NULL; 199 wstat->n_uid = ~0; 200 wstat->n_gid = ~0; 201 wstat->n_muid = ~0; 202 wstat->extension = NULL; 203 } 204 205 #ifdef CONFIG_9P_FSCACHE 206 /** 207 * v9fs_alloc_inode - helper function to allocate an inode 208 * This callback is executed before setting up the inode so that we 209 * can associate a vcookie with each inode. 210 * 211 */ 212 213 struct inode *v9fs_alloc_inode(struct super_block *sb) 214 { 215 struct v9fs_cookie *vcookie; 216 vcookie = (struct v9fs_cookie *)kmem_cache_alloc(vcookie_cache, 217 GFP_KERNEL); 218 if (!vcookie) 219 return NULL; 220 221 vcookie->fscache = NULL; 222 vcookie->qid = NULL; 223 spin_lock_init(&vcookie->lock); 224 return &vcookie->inode; 225 } 226 227 /** 228 * v9fs_destroy_inode - destroy an inode 229 * 230 */ 231 232 void v9fs_destroy_inode(struct inode *inode) 233 { 234 kmem_cache_free(vcookie_cache, v9fs_inode2cookie(inode)); 235 } 236 #endif 237 238 /** 239 * v9fs_get_inode - helper function to setup an inode 240 * @sb: superblock 241 * @mode: mode to setup inode with 242 * 243 */ 244 245 struct inode *v9fs_get_inode(struct super_block *sb, int mode) 246 { 247 int err; 248 struct inode *inode; 249 struct v9fs_session_info *v9ses = sb->s_fs_info; 250 251 P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); 252 253 inode = new_inode(sb); 254 if (!inode) { 255 P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n"); 256 return ERR_PTR(-ENOMEM); 257 } 258 259 inode_init_owner(inode, NULL, mode); 260 inode->i_blocks = 0; 261 inode->i_rdev = 0; 262 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 263 inode->i_mapping->a_ops = &v9fs_addr_operations; 264 265 switch (mode & S_IFMT) { 266 case S_IFIFO: 267 case S_IFBLK: 268 case S_IFCHR: 269 case S_IFSOCK: 270 if (!v9fs_proto_dotu(v9ses)) { 271 P9_DPRINTK(P9_DEBUG_ERROR, 272 "special files without extended mode\n"); 273 err = -EINVAL; 274 goto error; 275 } 276 init_special_inode(inode, inode->i_mode, inode->i_rdev); 277 break; 278 case S_IFREG: 279 if (v9fs_proto_dotl(v9ses)) { 280 inode->i_op = &v9fs_file_inode_operations_dotl; 281 inode->i_fop = &v9fs_file_operations_dotl; 282 } else { 283 inode->i_op = &v9fs_file_inode_operations; 284 inode->i_fop = &v9fs_file_operations; 285 } 286 287 break; 288 289 case S_IFLNK: 290 if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) { 291 P9_DPRINTK(P9_DEBUG_ERROR, "extended modes used with " 292 "legacy protocol.\n"); 293 err = -EINVAL; 294 goto error; 295 } 296 297 if (v9fs_proto_dotl(v9ses)) 298 inode->i_op = &v9fs_symlink_inode_operations_dotl; 299 else 300 inode->i_op = &v9fs_symlink_inode_operations; 301 302 break; 303 case S_IFDIR: 304 inc_nlink(inode); 305 if (v9fs_proto_dotl(v9ses)) 306 inode->i_op = &v9fs_dir_inode_operations_dotl; 307 else if (v9fs_proto_dotu(v9ses)) 308 inode->i_op = &v9fs_dir_inode_operations_dotu; 309 else 310 inode->i_op = &v9fs_dir_inode_operations; 311 312 if (v9fs_proto_dotl(v9ses)) 313 inode->i_fop = &v9fs_dir_operations_dotl; 314 else 315 inode->i_fop = &v9fs_dir_operations; 316 317 break; 318 default: 319 P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n", 320 mode, mode & S_IFMT); 321 err = -EINVAL; 322 goto error; 323 } 324 325 return inode; 326 327 error: 328 iput(inode); 329 return ERR_PTR(err); 330 } 331 332 /* 333 static struct v9fs_fid* 334 v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry) 335 { 336 int err; 337 int nfid; 338 struct v9fs_fid *ret; 339 struct v9fs_fcall *fcall; 340 341 nfid = v9fs_get_idpool(&v9ses->fidpool); 342 if (nfid < 0) { 343 eprintk(KERN_WARNING, "no free fids available\n"); 344 return ERR_PTR(-ENOSPC); 345 } 346 347 err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name, 348 &fcall); 349 350 if (err < 0) { 351 if (fcall && fcall->id == RWALK) 352 goto clunk_fid; 353 354 PRINT_FCALL_ERROR("walk error", fcall); 355 v9fs_put_idpool(nfid, &v9ses->fidpool); 356 goto error; 357 } 358 359 kfree(fcall); 360 fcall = NULL; 361 ret = v9fs_fid_create(v9ses, nfid); 362 if (!ret) { 363 err = -ENOMEM; 364 goto clunk_fid; 365 } 366 367 err = v9fs_fid_insert(ret, dentry); 368 if (err < 0) { 369 v9fs_fid_destroy(ret); 370 goto clunk_fid; 371 } 372 373 return ret; 374 375 clunk_fid: 376 v9fs_t_clunk(v9ses, nfid); 377 378 error: 379 kfree(fcall); 380 return ERR_PTR(err); 381 } 382 */ 383 384 385 /** 386 * v9fs_clear_inode - release an inode 387 * @inode: inode to release 388 * 389 */ 390 void v9fs_clear_inode(struct inode *inode) 391 { 392 filemap_fdatawrite(inode->i_mapping); 393 394 #ifdef CONFIG_9P_FSCACHE 395 v9fs_cache_inode_put_cookie(inode); 396 #endif 397 } 398 399 /** 400 * v9fs_inode_from_fid - populate an inode by issuing a attribute request 401 * @v9ses: session information 402 * @fid: fid to issue attribute request for 403 * @sb: superblock on which to create inode 404 * 405 */ 406 407 static struct inode * 408 v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, 409 struct super_block *sb) 410 { 411 int err, umode; 412 struct inode *ret; 413 struct p9_wstat *st; 414 415 ret = NULL; 416 st = p9_client_stat(fid); 417 if (IS_ERR(st)) 418 return ERR_CAST(st); 419 420 umode = p9mode2unixmode(v9ses, st->mode); 421 ret = v9fs_get_inode(sb, umode); 422 if (IS_ERR(ret)) { 423 err = PTR_ERR(ret); 424 goto error; 425 } 426 427 v9fs_stat2inode(st, ret, sb); 428 ret->i_ino = v9fs_qid2ino(&st->qid); 429 430 #ifdef CONFIG_9P_FSCACHE 431 v9fs_vcookie_set_qid(ret, &st->qid); 432 v9fs_cache_inode_get_cookie(ret); 433 #endif 434 p9stat_free(st); 435 kfree(st); 436 437 return ret; 438 439 error: 440 p9stat_free(st); 441 kfree(st); 442 return ERR_PTR(err); 443 } 444 445 /** 446 * v9fs_remove - helper function to remove files and directories 447 * @dir: directory inode that is being deleted 448 * @file: dentry that is being deleted 449 * @rmdir: removing a directory 450 * 451 */ 452 453 static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) 454 { 455 int retval; 456 struct inode *file_inode; 457 struct p9_fid *v9fid; 458 459 P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file, 460 rmdir); 461 462 file_inode = file->d_inode; 463 v9fid = v9fs_fid_clone(file); 464 if (IS_ERR(v9fid)) 465 return PTR_ERR(v9fid); 466 467 retval = p9_client_remove(v9fid); 468 if (!retval) 469 drop_nlink(file_inode); 470 return retval; 471 } 472 473 static int 474 v9fs_open_created(struct inode *inode, struct file *file) 475 { 476 return 0; 477 } 478 479 480 /** 481 * v9fs_create - Create a file 482 * @v9ses: session information 483 * @dir: directory that dentry is being created in 484 * @dentry: dentry that is being created 485 * @extension: 9p2000.u extension string to support devices, etc. 486 * @perm: create permissions 487 * @mode: open mode 488 * 489 */ 490 static struct p9_fid * 491 v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, 492 struct dentry *dentry, char *extension, u32 perm, u8 mode) 493 { 494 int err; 495 char *name; 496 struct p9_fid *dfid, *ofid, *fid; 497 struct inode *inode; 498 499 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); 500 501 err = 0; 502 ofid = NULL; 503 fid = NULL; 504 name = (char *) dentry->d_name.name; 505 dfid = v9fs_fid_lookup(dentry->d_parent); 506 if (IS_ERR(dfid)) { 507 err = PTR_ERR(dfid); 508 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 509 return ERR_PTR(err); 510 } 511 512 /* clone a fid to use for creation */ 513 ofid = p9_client_walk(dfid, 0, NULL, 1); 514 if (IS_ERR(ofid)) { 515 err = PTR_ERR(ofid); 516 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); 517 return ERR_PTR(err); 518 } 519 520 err = p9_client_fcreate(ofid, name, perm, mode, extension); 521 if (err < 0) { 522 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err); 523 goto error; 524 } 525 526 /* now walk from the parent so we can get unopened fid */ 527 fid = p9_client_walk(dfid, 1, &name, 1); 528 if (IS_ERR(fid)) { 529 err = PTR_ERR(fid); 530 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); 531 fid = NULL; 532 goto error; 533 } 534 535 /* instantiate inode and assign the unopened fid to the dentry */ 536 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 537 if (IS_ERR(inode)) { 538 err = PTR_ERR(inode); 539 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); 540 goto error; 541 } 542 543 if (v9ses->cache) 544 dentry->d_op = &v9fs_cached_dentry_operations; 545 else 546 dentry->d_op = &v9fs_dentry_operations; 547 548 d_instantiate(dentry, inode); 549 err = v9fs_fid_add(dentry, fid); 550 if (err < 0) 551 goto error; 552 553 return ofid; 554 555 error: 556 if (ofid) 557 p9_client_clunk(ofid); 558 559 if (fid) 560 p9_client_clunk(fid); 561 562 return ERR_PTR(err); 563 } 564 565 /** 566 * v9fs_vfs_create - VFS hook to create files 567 * @dir: directory inode that is being created 568 * @dentry: dentry that is being deleted 569 * @mode: create permissions 570 * @nd: path information 571 * 572 */ 573 574 static int 575 v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, 576 struct nameidata *nd) 577 { 578 int err; 579 u32 perm; 580 int flags; 581 struct v9fs_session_info *v9ses; 582 struct p9_fid *fid; 583 struct file *filp; 584 585 err = 0; 586 fid = NULL; 587 v9ses = v9fs_inode2v9ses(dir); 588 perm = unixmode2p9mode(v9ses, mode); 589 if (nd && nd->flags & LOOKUP_OPEN) 590 flags = nd->intent.open.flags - 1; 591 else 592 flags = O_RDWR; 593 594 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, 595 v9fs_uflags2omode(flags, 596 v9fs_proto_dotu(v9ses))); 597 if (IS_ERR(fid)) { 598 err = PTR_ERR(fid); 599 fid = NULL; 600 goto error; 601 } 602 603 /* if we are opening a file, assign the open fid to the file */ 604 if (nd && nd->flags & LOOKUP_OPEN) { 605 filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created); 606 if (IS_ERR(filp)) { 607 err = PTR_ERR(filp); 608 goto error; 609 } 610 611 filp->private_data = fid; 612 } else 613 p9_client_clunk(fid); 614 615 return 0; 616 617 error: 618 if (fid) 619 p9_client_clunk(fid); 620 621 return err; 622 } 623 624 /** 625 * v9fs_vfs_mkdir - VFS mkdir hook to create a directory 626 * @dir: inode that is being unlinked 627 * @dentry: dentry that is being unlinked 628 * @mode: mode for new directory 629 * 630 */ 631 632 static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 633 { 634 int err; 635 u32 perm; 636 struct v9fs_session_info *v9ses; 637 struct p9_fid *fid; 638 639 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); 640 err = 0; 641 v9ses = v9fs_inode2v9ses(dir); 642 perm = unixmode2p9mode(v9ses, mode | S_IFDIR); 643 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD); 644 if (IS_ERR(fid)) { 645 err = PTR_ERR(fid); 646 fid = NULL; 647 } 648 649 if (fid) 650 p9_client_clunk(fid); 651 652 return err; 653 } 654 655 /** 656 * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode 657 * @dir: inode that is being walked from 658 * @dentry: dentry that is being walked to? 659 * @nameidata: path data 660 * 661 */ 662 663 static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, 664 struct nameidata *nameidata) 665 { 666 struct super_block *sb; 667 struct v9fs_session_info *v9ses; 668 struct p9_fid *dfid, *fid; 669 struct inode *inode; 670 char *name; 671 int result = 0; 672 673 P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", 674 dir, dentry->d_name.name, dentry, nameidata); 675 676 if (dentry->d_name.len > NAME_MAX) 677 return ERR_PTR(-ENAMETOOLONG); 678 679 sb = dir->i_sb; 680 v9ses = v9fs_inode2v9ses(dir); 681 dfid = v9fs_fid_lookup(dentry->d_parent); 682 if (IS_ERR(dfid)) 683 return ERR_CAST(dfid); 684 685 name = (char *) dentry->d_name.name; 686 fid = p9_client_walk(dfid, 1, &name, 1); 687 if (IS_ERR(fid)) { 688 result = PTR_ERR(fid); 689 if (result == -ENOENT) { 690 inode = NULL; 691 goto inst_out; 692 } 693 694 return ERR_PTR(result); 695 } 696 697 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 698 if (IS_ERR(inode)) { 699 result = PTR_ERR(inode); 700 inode = NULL; 701 goto error; 702 } 703 704 result = v9fs_fid_add(dentry, fid); 705 if (result < 0) 706 goto error; 707 708 inst_out: 709 if (v9ses->cache) 710 dentry->d_op = &v9fs_cached_dentry_operations; 711 else 712 dentry->d_op = &v9fs_dentry_operations; 713 714 d_add(dentry, inode); 715 return NULL; 716 717 error: 718 p9_client_clunk(fid); 719 720 return ERR_PTR(result); 721 } 722 723 /** 724 * v9fs_vfs_unlink - VFS unlink hook to delete an inode 725 * @i: inode that is being unlinked 726 * @d: dentry that is being unlinked 727 * 728 */ 729 730 static int v9fs_vfs_unlink(struct inode *i, struct dentry *d) 731 { 732 return v9fs_remove(i, d, 0); 733 } 734 735 /** 736 * v9fs_vfs_rmdir - VFS unlink hook to delete a directory 737 * @i: inode that is being unlinked 738 * @d: dentry that is being unlinked 739 * 740 */ 741 742 static int v9fs_vfs_rmdir(struct inode *i, struct dentry *d) 743 { 744 return v9fs_remove(i, d, 1); 745 } 746 747 /** 748 * v9fs_vfs_rename - VFS hook to rename an inode 749 * @old_dir: old dir inode 750 * @old_dentry: old dentry 751 * @new_dir: new dir inode 752 * @new_dentry: new dentry 753 * 754 */ 755 756 static int 757 v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, 758 struct inode *new_dir, struct dentry *new_dentry) 759 { 760 struct inode *old_inode; 761 struct v9fs_session_info *v9ses; 762 struct p9_fid *oldfid; 763 struct p9_fid *olddirfid; 764 struct p9_fid *newdirfid; 765 struct p9_wstat wstat; 766 int retval; 767 768 P9_DPRINTK(P9_DEBUG_VFS, "\n"); 769 retval = 0; 770 old_inode = old_dentry->d_inode; 771 v9ses = v9fs_inode2v9ses(old_inode); 772 oldfid = v9fs_fid_lookup(old_dentry); 773 if (IS_ERR(oldfid)) 774 return PTR_ERR(oldfid); 775 776 olddirfid = v9fs_fid_clone(old_dentry->d_parent); 777 if (IS_ERR(olddirfid)) { 778 retval = PTR_ERR(olddirfid); 779 goto done; 780 } 781 782 newdirfid = v9fs_fid_clone(new_dentry->d_parent); 783 if (IS_ERR(newdirfid)) { 784 retval = PTR_ERR(newdirfid); 785 goto clunk_olddir; 786 } 787 788 if (v9fs_proto_dotl(v9ses)) { 789 retval = p9_client_rename(oldfid, newdirfid, 790 (char *) new_dentry->d_name.name); 791 if (retval != -ENOSYS) 792 goto clunk_newdir; 793 } 794 795 /* 9P can only handle file rename in the same directory */ 796 if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) { 797 P9_DPRINTK(P9_DEBUG_ERROR, 798 "old dir and new dir are different\n"); 799 retval = -EXDEV; 800 goto clunk_newdir; 801 } 802 803 v9fs_blank_wstat(&wstat); 804 wstat.muid = v9ses->uname; 805 wstat.name = (char *) new_dentry->d_name.name; 806 retval = p9_client_wstat(oldfid, &wstat); 807 808 clunk_newdir: 809 p9_client_clunk(newdirfid); 810 811 clunk_olddir: 812 p9_client_clunk(olddirfid); 813 814 done: 815 return retval; 816 } 817 818 /** 819 * v9fs_vfs_getattr - retrieve file metadata 820 * @mnt: mount information 821 * @dentry: file to get attributes on 822 * @stat: metadata structure to populate 823 * 824 */ 825 826 static int 827 v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 828 struct kstat *stat) 829 { 830 int err; 831 struct v9fs_session_info *v9ses; 832 struct p9_fid *fid; 833 struct p9_wstat *st; 834 835 P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); 836 err = -EPERM; 837 v9ses = v9fs_inode2v9ses(dentry->d_inode); 838 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) 839 return simple_getattr(mnt, dentry, stat); 840 841 fid = v9fs_fid_lookup(dentry); 842 if (IS_ERR(fid)) 843 return PTR_ERR(fid); 844 845 st = p9_client_stat(fid); 846 if (IS_ERR(st)) 847 return PTR_ERR(st); 848 849 v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); 850 generic_fillattr(dentry->d_inode, stat); 851 852 kfree(st); 853 return 0; 854 } 855 856 /** 857 * v9fs_vfs_setattr - set file metadata 858 * @dentry: file whose metadata to set 859 * @iattr: metadata assignment structure 860 * 861 */ 862 863 static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) 864 { 865 int retval; 866 struct v9fs_session_info *v9ses; 867 struct p9_fid *fid; 868 struct p9_wstat wstat; 869 870 P9_DPRINTK(P9_DEBUG_VFS, "\n"); 871 retval = -EPERM; 872 v9ses = v9fs_inode2v9ses(dentry->d_inode); 873 fid = v9fs_fid_lookup(dentry); 874 if(IS_ERR(fid)) 875 return PTR_ERR(fid); 876 877 v9fs_blank_wstat(&wstat); 878 if (iattr->ia_valid & ATTR_MODE) 879 wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode); 880 881 if (iattr->ia_valid & ATTR_MTIME) 882 wstat.mtime = iattr->ia_mtime.tv_sec; 883 884 if (iattr->ia_valid & ATTR_ATIME) 885 wstat.atime = iattr->ia_atime.tv_sec; 886 887 if (iattr->ia_valid & ATTR_SIZE) 888 wstat.length = iattr->ia_size; 889 890 if (v9fs_proto_dotu(v9ses)) { 891 if (iattr->ia_valid & ATTR_UID) 892 wstat.n_uid = iattr->ia_uid; 893 894 if (iattr->ia_valid & ATTR_GID) 895 wstat.n_gid = iattr->ia_gid; 896 } 897 898 retval = p9_client_wstat(fid, &wstat); 899 if (retval >= 0) 900 retval = inode_setattr(dentry->d_inode, iattr); 901 902 return retval; 903 } 904 905 /** 906 * v9fs_stat2inode - populate an inode structure with mistat info 907 * @stat: Plan 9 metadata (mistat) structure 908 * @inode: inode to populate 909 * @sb: superblock of filesystem 910 * 911 */ 912 913 void 914 v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, 915 struct super_block *sb) 916 { 917 char ext[32]; 918 char tag_name[14]; 919 unsigned int i_nlink; 920 struct v9fs_session_info *v9ses = sb->s_fs_info; 921 922 inode->i_nlink = 1; 923 924 inode->i_atime.tv_sec = stat->atime; 925 inode->i_mtime.tv_sec = stat->mtime; 926 inode->i_ctime.tv_sec = stat->mtime; 927 928 inode->i_uid = v9ses->dfltuid; 929 inode->i_gid = v9ses->dfltgid; 930 931 if (v9fs_proto_dotu(v9ses)) { 932 inode->i_uid = stat->n_uid; 933 inode->i_gid = stat->n_gid; 934 } 935 if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) { 936 if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) { 937 /* 938 * Hadlink support got added later to 939 * to the .u extension. So there can be 940 * server out there that doesn't support 941 * this even with .u extension. So check 942 * for non NULL stat->extension 943 */ 944 strncpy(ext, stat->extension, sizeof(ext)); 945 /* HARDLINKCOUNT %u */ 946 sscanf(ext, "%13s %u", tag_name, &i_nlink); 947 if (!strncmp(tag_name, "HARDLINKCOUNT", 13)) 948 inode->i_nlink = i_nlink; 949 } 950 } 951 inode->i_mode = p9mode2unixmode(v9ses, stat->mode); 952 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) { 953 char type = 0; 954 int major = -1; 955 int minor = -1; 956 957 strncpy(ext, stat->extension, sizeof(ext)); 958 sscanf(ext, "%c %u %u", &type, &major, &minor); 959 switch (type) { 960 case 'c': 961 inode->i_mode &= ~S_IFBLK; 962 inode->i_mode |= S_IFCHR; 963 break; 964 case 'b': 965 break; 966 default: 967 P9_DPRINTK(P9_DEBUG_ERROR, 968 "Unknown special type %c %s\n", type, 969 stat->extension); 970 }; 971 inode->i_rdev = MKDEV(major, minor); 972 init_special_inode(inode, inode->i_mode, inode->i_rdev); 973 } else 974 inode->i_rdev = 0; 975 976 i_size_write(inode, stat->length); 977 978 /* not real number of blocks, but 512 byte ones ... */ 979 inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9; 980 } 981 982 /** 983 * v9fs_qid2ino - convert qid into inode number 984 * @qid: qid to hash 985 * 986 * BUG: potential for inode number collisions? 987 */ 988 989 ino_t v9fs_qid2ino(struct p9_qid *qid) 990 { 991 u64 path = qid->path + 2; 992 ino_t i = 0; 993 994 if (sizeof(ino_t) == sizeof(path)) 995 memcpy(&i, &path, sizeof(ino_t)); 996 else 997 i = (ino_t) (path ^ (path >> 32)); 998 999 return i; 1000 } 1001 1002 /** 1003 * v9fs_readlink - read a symlink's location (internal version) 1004 * @dentry: dentry for symlink 1005 * @buffer: buffer to load symlink location into 1006 * @buflen: length of buffer 1007 * 1008 */ 1009 1010 static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) 1011 { 1012 int retval; 1013 1014 struct v9fs_session_info *v9ses; 1015 struct p9_fid *fid; 1016 struct p9_wstat *st; 1017 1018 P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name); 1019 retval = -EPERM; 1020 v9ses = v9fs_inode2v9ses(dentry->d_inode); 1021 fid = v9fs_fid_lookup(dentry); 1022 if (IS_ERR(fid)) 1023 return PTR_ERR(fid); 1024 1025 if (!v9fs_proto_dotu(v9ses)) 1026 return -EBADF; 1027 1028 st = p9_client_stat(fid); 1029 if (IS_ERR(st)) 1030 return PTR_ERR(st); 1031 1032 if (!(st->mode & P9_DMSYMLINK)) { 1033 retval = -EINVAL; 1034 goto done; 1035 } 1036 1037 /* copy extension buffer into buffer */ 1038 strncpy(buffer, st->extension, buflen); 1039 1040 P9_DPRINTK(P9_DEBUG_VFS, 1041 "%s -> %s (%s)\n", dentry->d_name.name, st->extension, buffer); 1042 1043 retval = strnlen(buffer, buflen); 1044 done: 1045 kfree(st); 1046 return retval; 1047 } 1048 1049 /** 1050 * v9fs_vfs_follow_link - follow a symlink path 1051 * @dentry: dentry for symlink 1052 * @nd: nameidata 1053 * 1054 */ 1055 1056 static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd) 1057 { 1058 int len = 0; 1059 char *link = __getname(); 1060 1061 P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name); 1062 1063 if (!link) 1064 link = ERR_PTR(-ENOMEM); 1065 else { 1066 len = v9fs_readlink(dentry, link, PATH_MAX); 1067 1068 if (len < 0) { 1069 __putname(link); 1070 link = ERR_PTR(len); 1071 } else 1072 link[min(len, PATH_MAX-1)] = 0; 1073 } 1074 nd_set_link(nd, link); 1075 1076 return NULL; 1077 } 1078 1079 /** 1080 * v9fs_vfs_put_link - release a symlink path 1081 * @dentry: dentry for symlink 1082 * @nd: nameidata 1083 * @p: unused 1084 * 1085 */ 1086 1087 static void 1088 v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) 1089 { 1090 char *s = nd_get_link(nd); 1091 1092 P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name, 1093 IS_ERR(s) ? "<error>" : s); 1094 if (!IS_ERR(s)) 1095 __putname(s); 1096 } 1097 1098 /** 1099 * v9fs_vfs_mkspecial - create a special file 1100 * @dir: inode to create special file in 1101 * @dentry: dentry to create 1102 * @mode: mode to create special file 1103 * @extension: 9p2000.u format extension string representing special file 1104 * 1105 */ 1106 1107 static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, 1108 int mode, const char *extension) 1109 { 1110 u32 perm; 1111 struct v9fs_session_info *v9ses; 1112 struct p9_fid *fid; 1113 1114 v9ses = v9fs_inode2v9ses(dir); 1115 if (!v9fs_proto_dotu(v9ses)) { 1116 P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n"); 1117 return -EPERM; 1118 } 1119 1120 perm = unixmode2p9mode(v9ses, mode); 1121 fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm, 1122 P9_OREAD); 1123 if (IS_ERR(fid)) 1124 return PTR_ERR(fid); 1125 1126 p9_client_clunk(fid); 1127 return 0; 1128 } 1129 1130 /** 1131 * v9fs_vfs_symlink - helper function to create symlinks 1132 * @dir: directory inode containing symlink 1133 * @dentry: dentry for symlink 1134 * @symname: symlink data 1135 * 1136 * See Also: 9P2000.u RFC for more information 1137 * 1138 */ 1139 1140 static int 1141 v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) 1142 { 1143 P9_DPRINTK(P9_DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, 1144 dentry->d_name.name, symname); 1145 1146 return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname); 1147 } 1148 1149 /** 1150 * v9fs_vfs_link - create a hardlink 1151 * @old_dentry: dentry for file to link to 1152 * @dir: inode destination for new link 1153 * @dentry: dentry for link 1154 * 1155 */ 1156 1157 static int 1158 v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, 1159 struct dentry *dentry) 1160 { 1161 int retval; 1162 struct p9_fid *oldfid; 1163 char *name; 1164 1165 P9_DPRINTK(P9_DEBUG_VFS, 1166 " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, 1167 old_dentry->d_name.name); 1168 1169 oldfid = v9fs_fid_clone(old_dentry); 1170 if (IS_ERR(oldfid)) 1171 return PTR_ERR(oldfid); 1172 1173 name = __getname(); 1174 if (unlikely(!name)) { 1175 retval = -ENOMEM; 1176 goto clunk_fid; 1177 } 1178 1179 sprintf(name, "%d\n", oldfid->fid); 1180 retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name); 1181 __putname(name); 1182 1183 clunk_fid: 1184 p9_client_clunk(oldfid); 1185 return retval; 1186 } 1187 1188 /** 1189 * v9fs_vfs_mknod - create a special file 1190 * @dir: inode destination for new link 1191 * @dentry: dentry for file 1192 * @mode: mode for creation 1193 * @rdev: device associated with special file 1194 * 1195 */ 1196 1197 static int 1198 v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) 1199 { 1200 int retval; 1201 char *name; 1202 1203 P9_DPRINTK(P9_DEBUG_VFS, 1204 " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, 1205 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); 1206 1207 if (!new_valid_dev(rdev)) 1208 return -EINVAL; 1209 1210 name = __getname(); 1211 if (!name) 1212 return -ENOMEM; 1213 /* build extension */ 1214 if (S_ISBLK(mode)) 1215 sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev)); 1216 else if (S_ISCHR(mode)) 1217 sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev)); 1218 else if (S_ISFIFO(mode)) 1219 *name = 0; 1220 else if (S_ISSOCK(mode)) 1221 *name = 0; 1222 else { 1223 __putname(name); 1224 return -EINVAL; 1225 } 1226 1227 retval = v9fs_vfs_mkspecial(dir, dentry, mode, name); 1228 __putname(name); 1229 1230 return retval; 1231 } 1232 1233 static const struct inode_operations v9fs_dir_inode_operations_dotu = { 1234 .create = v9fs_vfs_create, 1235 .lookup = v9fs_vfs_lookup, 1236 .symlink = v9fs_vfs_symlink, 1237 .link = v9fs_vfs_link, 1238 .unlink = v9fs_vfs_unlink, 1239 .mkdir = v9fs_vfs_mkdir, 1240 .rmdir = v9fs_vfs_rmdir, 1241 .mknod = v9fs_vfs_mknod, 1242 .rename = v9fs_vfs_rename, 1243 .getattr = v9fs_vfs_getattr, 1244 .setattr = v9fs_vfs_setattr, 1245 }; 1246 1247 static const struct inode_operations v9fs_dir_inode_operations_dotl = { 1248 .create = v9fs_vfs_create, 1249 .lookup = v9fs_vfs_lookup, 1250 .symlink = v9fs_vfs_symlink, 1251 .link = v9fs_vfs_link, 1252 .unlink = v9fs_vfs_unlink, 1253 .mkdir = v9fs_vfs_mkdir, 1254 .rmdir = v9fs_vfs_rmdir, 1255 .mknod = v9fs_vfs_mknod, 1256 .rename = v9fs_vfs_rename, 1257 .getattr = v9fs_vfs_getattr, 1258 .setattr = v9fs_vfs_setattr, 1259 }; 1260 1261 static const struct inode_operations v9fs_dir_inode_operations = { 1262 .create = v9fs_vfs_create, 1263 .lookup = v9fs_vfs_lookup, 1264 .unlink = v9fs_vfs_unlink, 1265 .mkdir = v9fs_vfs_mkdir, 1266 .rmdir = v9fs_vfs_rmdir, 1267 .mknod = v9fs_vfs_mknod, 1268 .rename = v9fs_vfs_rename, 1269 .getattr = v9fs_vfs_getattr, 1270 .setattr = v9fs_vfs_setattr, 1271 }; 1272 1273 static const struct inode_operations v9fs_file_inode_operations = { 1274 .getattr = v9fs_vfs_getattr, 1275 .setattr = v9fs_vfs_setattr, 1276 }; 1277 1278 static const struct inode_operations v9fs_file_inode_operations_dotl = { 1279 .getattr = v9fs_vfs_getattr, 1280 .setattr = v9fs_vfs_setattr, 1281 }; 1282 1283 static const struct inode_operations v9fs_symlink_inode_operations = { 1284 .readlink = generic_readlink, 1285 .follow_link = v9fs_vfs_follow_link, 1286 .put_link = v9fs_vfs_put_link, 1287 .getattr = v9fs_vfs_getattr, 1288 .setattr = v9fs_vfs_setattr, 1289 }; 1290 1291 static const struct inode_operations v9fs_symlink_inode_operations_dotl = { 1292 .readlink = generic_readlink, 1293 .follow_link = v9fs_vfs_follow_link, 1294 .put_link = v9fs_vfs_put_link, 1295 .getattr = v9fs_vfs_getattr, 1296 .setattr = v9fs_vfs_setattr, 1297 }; 1298