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