diff options
Diffstat (limited to 'fs/9p/vfs_inode.c')
| -rw-r--r-- | fs/9p/vfs_inode.c | 307 |
1 files changed, 222 insertions, 85 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index b76a40bdf4c2..8a2c232f708a 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -203,26 +203,25 @@ v9fs_blank_wstat(struct p9_wstat *wstat) | |||
| 203 | wstat->extension = NULL; | 203 | wstat->extension = NULL; |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | #ifdef CONFIG_9P_FSCACHE | ||
| 207 | /** | 206 | /** |
| 208 | * v9fs_alloc_inode - helper function to allocate an inode | 207 | * 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 | * | 208 | * |
| 212 | */ | 209 | */ |
| 213 | |||
| 214 | struct inode *v9fs_alloc_inode(struct super_block *sb) | 210 | struct inode *v9fs_alloc_inode(struct super_block *sb) |
| 215 | { | 211 | { |
| 216 | struct v9fs_cookie *vcookie; | 212 | struct v9fs_inode *v9inode; |
| 217 | vcookie = (struct v9fs_cookie *)kmem_cache_alloc(vcookie_cache, | 213 | v9inode = (struct v9fs_inode *)kmem_cache_alloc(v9fs_inode_cache, |
| 218 | GFP_KERNEL); | 214 | GFP_KERNEL); |
| 219 | if (!vcookie) | 215 | if (!v9inode) |
| 220 | return NULL; | 216 | return NULL; |
| 221 | 217 | #ifdef CONFIG_9P_FSCACHE | |
| 222 | vcookie->fscache = NULL; | 218 | v9inode->fscache = NULL; |
| 223 | vcookie->qid = NULL; | 219 | v9inode->fscache_key = NULL; |
| 224 | spin_lock_init(&vcookie->lock); | 220 | spin_lock_init(&v9inode->fscache_lock); |
| 225 | return &vcookie->inode; | 221 | #endif |
| 222 | v9inode->writeback_fid = NULL; | ||
| 223 | v9inode->cache_validity = 0; | ||
| 224 | return &v9inode->vfs_inode; | ||
| 226 | } | 225 | } |
| 227 | 226 | ||
| 228 | /** | 227 | /** |
| @@ -234,35 +233,18 @@ static void v9fs_i_callback(struct rcu_head *head) | |||
| 234 | { | 233 | { |
| 235 | struct inode *inode = container_of(head, struct inode, i_rcu); | 234 | struct inode *inode = container_of(head, struct inode, i_rcu); |
| 236 | INIT_LIST_HEAD(&inode->i_dentry); | 235 | INIT_LIST_HEAD(&inode->i_dentry); |
| 237 | kmem_cache_free(vcookie_cache, v9fs_inode2cookie(inode)); | 236 | kmem_cache_free(v9fs_inode_cache, V9FS_I(inode)); |
| 238 | } | 237 | } |
| 239 | 238 | ||
| 240 | void v9fs_destroy_inode(struct inode *inode) | 239 | void v9fs_destroy_inode(struct inode *inode) |
| 241 | { | 240 | { |
| 242 | call_rcu(&inode->i_rcu, v9fs_i_callback); | 241 | call_rcu(&inode->i_rcu, v9fs_i_callback); |
| 243 | } | 242 | } |
| 244 | #endif | ||
| 245 | 243 | ||
| 246 | /** | 244 | int v9fs_init_inode(struct v9fs_session_info *v9ses, |
| 247 | * v9fs_get_inode - helper function to setup an inode | 245 | struct inode *inode, int mode) |
| 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 | { | 246 | { |
| 255 | int err; | 247 | int err = 0; |
| 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 | 248 | ||
| 267 | inode_init_owner(inode, NULL, mode); | 249 | inode_init_owner(inode, NULL, mode); |
| 268 | inode->i_blocks = 0; | 250 | inode->i_blocks = 0; |
| @@ -292,14 +274,20 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) | |||
| 292 | case S_IFREG: | 274 | case S_IFREG: |
| 293 | if (v9fs_proto_dotl(v9ses)) { | 275 | if (v9fs_proto_dotl(v9ses)) { |
| 294 | inode->i_op = &v9fs_file_inode_operations_dotl; | 276 | inode->i_op = &v9fs_file_inode_operations_dotl; |
| 295 | inode->i_fop = &v9fs_file_operations_dotl; | 277 | if (v9ses->cache) |
| 278 | inode->i_fop = | ||
| 279 | &v9fs_cached_file_operations_dotl; | ||
| 280 | else | ||
| 281 | inode->i_fop = &v9fs_file_operations_dotl; | ||
| 296 | } else { | 282 | } else { |
| 297 | inode->i_op = &v9fs_file_inode_operations; | 283 | inode->i_op = &v9fs_file_inode_operations; |
| 298 | inode->i_fop = &v9fs_file_operations; | 284 | if (v9ses->cache) |
| 285 | inode->i_fop = &v9fs_cached_file_operations; | ||
| 286 | else | ||
| 287 | inode->i_fop = &v9fs_file_operations; | ||
| 299 | } | 288 | } |
| 300 | 289 | ||
| 301 | break; | 290 | break; |
| 302 | |||
| 303 | case S_IFLNK: | 291 | case S_IFLNK: |
| 304 | if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) { | 292 | if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) { |
| 305 | P9_DPRINTK(P9_DEBUG_ERROR, "extended modes used with " | 293 | P9_DPRINTK(P9_DEBUG_ERROR, "extended modes used with " |
| @@ -335,12 +323,37 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) | |||
| 335 | err = -EINVAL; | 323 | err = -EINVAL; |
| 336 | goto error; | 324 | goto error; |
| 337 | } | 325 | } |
| 326 | error: | ||
| 327 | return err; | ||
| 338 | 328 | ||
| 339 | return inode; | 329 | } |
| 340 | 330 | ||
| 341 | error: | 331 | /** |
| 342 | iput(inode); | 332 | * v9fs_get_inode - helper function to setup an inode |
| 343 | return ERR_PTR(err); | 333 | * @sb: superblock |
| 334 | * @mode: mode to setup inode with | ||
| 335 | * | ||
| 336 | */ | ||
| 337 | |||
| 338 | struct inode *v9fs_get_inode(struct super_block *sb, int mode) | ||
| 339 | { | ||
| 340 | int err; | ||
| 341 | struct inode *inode; | ||
| 342 | struct v9fs_session_info *v9ses = sb->s_fs_info; | ||
| 343 | |||
| 344 | P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); | ||
| 345 | |||
| 346 | inode = new_inode(sb); | ||
| 347 | if (!inode) { | ||
| 348 | P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n"); | ||
| 349 | return ERR_PTR(-ENOMEM); | ||
| 350 | } | ||
| 351 | err = v9fs_init_inode(v9ses, inode, mode); | ||
| 352 | if (err) { | ||
| 353 | iput(inode); | ||
| 354 | return ERR_PTR(err); | ||
| 355 | } | ||
| 356 | return inode; | ||
| 344 | } | 357 | } |
| 345 | 358 | ||
| 346 | /* | 359 | /* |
| @@ -403,6 +416,8 @@ error: | |||
| 403 | */ | 416 | */ |
| 404 | void v9fs_evict_inode(struct inode *inode) | 417 | void v9fs_evict_inode(struct inode *inode) |
| 405 | { | 418 | { |
| 419 | struct v9fs_inode *v9inode = V9FS_I(inode); | ||
| 420 | |||
| 406 | truncate_inode_pages(inode->i_mapping, 0); | 421 | truncate_inode_pages(inode->i_mapping, 0); |
| 407 | end_writeback(inode); | 422 | end_writeback(inode); |
| 408 | filemap_fdatawrite(inode->i_mapping); | 423 | filemap_fdatawrite(inode->i_mapping); |
| @@ -410,41 +425,67 @@ void v9fs_evict_inode(struct inode *inode) | |||
| 410 | #ifdef CONFIG_9P_FSCACHE | 425 | #ifdef CONFIG_9P_FSCACHE |
| 411 | v9fs_cache_inode_put_cookie(inode); | 426 | v9fs_cache_inode_put_cookie(inode); |
| 412 | #endif | 427 | #endif |
| 428 | /* clunk the fid stashed in writeback_fid */ | ||
| 429 | if (v9inode->writeback_fid) { | ||
| 430 | p9_client_clunk(v9inode->writeback_fid); | ||
| 431 | v9inode->writeback_fid = NULL; | ||
| 432 | } | ||
| 413 | } | 433 | } |
| 414 | 434 | ||
| 415 | struct inode * | 435 | static struct inode *v9fs_qid_iget(struct super_block *sb, |
| 416 | v9fs_inode(struct v9fs_session_info *v9ses, struct p9_fid *fid, | 436 | struct p9_qid *qid, |
| 417 | struct super_block *sb) | 437 | struct p9_wstat *st) |
| 418 | { | 438 | { |
| 419 | int err, umode; | 439 | int retval, umode; |
| 420 | struct inode *ret = NULL; | 440 | unsigned long i_ino; |
| 421 | struct p9_wstat *st; | 441 | struct inode *inode; |
| 422 | 442 | struct v9fs_session_info *v9ses = sb->s_fs_info; | |
| 423 | st = p9_client_stat(fid); | ||
| 424 | if (IS_ERR(st)) | ||
| 425 | return ERR_CAST(st); | ||
| 426 | 443 | ||
| 444 | i_ino = v9fs_qid2ino(qid); | ||
| 445 | inode = iget_locked(sb, i_ino); | ||
| 446 | if (!inode) | ||
| 447 | return ERR_PTR(-ENOMEM); | ||
| 448 | if (!(inode->i_state & I_NEW)) | ||
| 449 | return inode; | ||
| 450 | /* | ||
| 451 | * initialize the inode with the stat info | ||
| 452 | * FIXME!! we may need support for stale inodes | ||
| 453 | * later. | ||
| 454 | */ | ||
| 427 | umode = p9mode2unixmode(v9ses, st->mode); | 455 | umode = p9mode2unixmode(v9ses, st->mode); |
| 428 | ret = v9fs_get_inode(sb, umode); | 456 | retval = v9fs_init_inode(v9ses, inode, umode); |
| 429 | if (IS_ERR(ret)) { | 457 | if (retval) |
| 430 | err = PTR_ERR(ret); | ||
| 431 | goto error; | 458 | goto error; |
| 432 | } | ||
| 433 | |||
| 434 | v9fs_stat2inode(st, ret, sb); | ||
| 435 | ret->i_ino = v9fs_qid2ino(&st->qid); | ||
| 436 | 459 | ||
| 460 | v9fs_stat2inode(st, inode, sb); | ||
| 437 | #ifdef CONFIG_9P_FSCACHE | 461 | #ifdef CONFIG_9P_FSCACHE |
| 438 | v9fs_vcookie_set_qid(ret, &st->qid); | 462 | v9fs_fscache_set_key(inode, &st->qid); |
| 439 | v9fs_cache_inode_get_cookie(ret); | 463 | v9fs_cache_inode_get_cookie(inode); |
| 440 | #endif | 464 | #endif |
| 441 | p9stat_free(st); | 465 | unlock_new_inode(inode); |
| 442 | kfree(st); | 466 | return inode; |
| 443 | return ret; | ||
| 444 | error: | 467 | error: |
| 468 | unlock_new_inode(inode); | ||
| 469 | iput(inode); | ||
| 470 | return ERR_PTR(retval); | ||
| 471 | |||
| 472 | } | ||
| 473 | |||
| 474 | struct inode * | ||
| 475 | v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, | ||
| 476 | struct super_block *sb) | ||
| 477 | { | ||
| 478 | struct p9_wstat *st; | ||
| 479 | struct inode *inode = NULL; | ||
| 480 | |||
| 481 | st = p9_client_stat(fid); | ||
| 482 | if (IS_ERR(st)) | ||
| 483 | return ERR_CAST(st); | ||
| 484 | |||
| 485 | inode = v9fs_qid_iget(sb, &st->qid, st); | ||
| 445 | p9stat_free(st); | 486 | p9stat_free(st); |
| 446 | kfree(st); | 487 | kfree(st); |
| 447 | return ERR_PTR(err); | 488 | return inode; |
| 448 | } | 489 | } |
| 449 | 490 | ||
| 450 | /** | 491 | /** |
| @@ -458,8 +499,8 @@ error: | |||
| 458 | static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | 499 | static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) |
| 459 | { | 500 | { |
| 460 | int retval; | 501 | int retval; |
| 461 | struct inode *file_inode; | ||
| 462 | struct p9_fid *v9fid; | 502 | struct p9_fid *v9fid; |
| 503 | struct inode *file_inode; | ||
| 463 | 504 | ||
| 464 | P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file, | 505 | P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file, |
| 465 | rmdir); | 506 | rmdir); |
| @@ -470,8 +511,20 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
| 470 | return PTR_ERR(v9fid); | 511 | return PTR_ERR(v9fid); |
| 471 | 512 | ||
| 472 | retval = p9_client_remove(v9fid); | 513 | retval = p9_client_remove(v9fid); |
| 473 | if (!retval) | 514 | if (!retval) { |
| 474 | drop_nlink(file_inode); | 515 | /* |
| 516 | * directories on unlink should have zero | ||
| 517 | * link count | ||
| 518 | */ | ||
| 519 | if (rmdir) { | ||
| 520 | clear_nlink(file_inode); | ||
| 521 | drop_nlink(dir); | ||
| 522 | } else | ||
| 523 | drop_nlink(file_inode); | ||
| 524 | |||
| 525 | v9fs_invalidate_inode_attr(file_inode); | ||
| 526 | v9fs_invalidate_inode_attr(dir); | ||
| 527 | } | ||
| 475 | return retval; | 528 | return retval; |
| 476 | } | 529 | } |
| 477 | 530 | ||
| @@ -531,7 +584,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, | |||
| 531 | } | 584 | } |
| 532 | 585 | ||
| 533 | /* instantiate inode and assign the unopened fid to the dentry */ | 586 | /* instantiate inode and assign the unopened fid to the dentry */ |
| 534 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); | 587 | inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); |
| 535 | if (IS_ERR(inode)) { | 588 | if (IS_ERR(inode)) { |
| 536 | err = PTR_ERR(inode); | 589 | err = PTR_ERR(inode); |
| 537 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); | 590 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); |
| @@ -570,9 +623,10 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 570 | int err; | 623 | int err; |
| 571 | u32 perm; | 624 | u32 perm; |
| 572 | int flags; | 625 | int flags; |
| 573 | struct v9fs_session_info *v9ses; | ||
| 574 | struct p9_fid *fid; | ||
| 575 | struct file *filp; | 626 | struct file *filp; |
| 627 | struct v9fs_inode *v9inode; | ||
| 628 | struct v9fs_session_info *v9ses; | ||
| 629 | struct p9_fid *fid, *inode_fid; | ||
| 576 | 630 | ||
| 577 | err = 0; | 631 | err = 0; |
| 578 | fid = NULL; | 632 | fid = NULL; |
| @@ -592,8 +646,25 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 592 | goto error; | 646 | goto error; |
| 593 | } | 647 | } |
| 594 | 648 | ||
| 649 | v9fs_invalidate_inode_attr(dir); | ||
| 595 | /* if we are opening a file, assign the open fid to the file */ | 650 | /* if we are opening a file, assign the open fid to the file */ |
| 596 | if (nd && nd->flags & LOOKUP_OPEN) { | 651 | if (nd && nd->flags & LOOKUP_OPEN) { |
| 652 | v9inode = V9FS_I(dentry->d_inode); | ||
| 653 | if (v9ses->cache && !v9inode->writeback_fid) { | ||
| 654 | /* | ||
| 655 | * clone a fid and add it to writeback_fid | ||
| 656 | * we do it during open time instead of | ||
| 657 | * page dirty time via write_begin/page_mkwrite | ||
| 658 | * because we want write after unlink usecase | ||
| 659 | * to work. | ||
| 660 | */ | ||
| 661 | inode_fid = v9fs_writeback_fid(dentry); | ||
| 662 | if (IS_ERR(inode_fid)) { | ||
| 663 | err = PTR_ERR(inode_fid); | ||
| 664 | goto error; | ||
| 665 | } | ||
| 666 | v9inode->writeback_fid = (void *) inode_fid; | ||
| 667 | } | ||
| 597 | filp = lookup_instantiate_filp(nd, dentry, generic_file_open); | 668 | filp = lookup_instantiate_filp(nd, dentry, generic_file_open); |
| 598 | if (IS_ERR(filp)) { | 669 | if (IS_ERR(filp)) { |
| 599 | err = PTR_ERR(filp); | 670 | err = PTR_ERR(filp); |
| @@ -601,6 +672,10 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 601 | } | 672 | } |
| 602 | 673 | ||
| 603 | filp->private_data = fid; | 674 | filp->private_data = fid; |
| 675 | #ifdef CONFIG_9P_FSCACHE | ||
| 676 | if (v9ses->cache) | ||
| 677 | v9fs_cache_inode_set_cookie(dentry->d_inode, filp); | ||
| 678 | #endif | ||
| 604 | } else | 679 | } else |
| 605 | p9_client_clunk(fid); | 680 | p9_client_clunk(fid); |
| 606 | 681 | ||
| @@ -625,8 +700,8 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 625 | { | 700 | { |
| 626 | int err; | 701 | int err; |
| 627 | u32 perm; | 702 | u32 perm; |
| 628 | struct v9fs_session_info *v9ses; | ||
| 629 | struct p9_fid *fid; | 703 | struct p9_fid *fid; |
| 704 | struct v9fs_session_info *v9ses; | ||
| 630 | 705 | ||
| 631 | P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); | 706 | P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); |
| 632 | err = 0; | 707 | err = 0; |
| @@ -636,6 +711,9 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 636 | if (IS_ERR(fid)) { | 711 | if (IS_ERR(fid)) { |
| 637 | err = PTR_ERR(fid); | 712 | err = PTR_ERR(fid); |
| 638 | fid = NULL; | 713 | fid = NULL; |
| 714 | } else { | ||
| 715 | inc_nlink(dir); | ||
| 716 | v9fs_invalidate_inode_attr(dir); | ||
| 639 | } | 717 | } |
| 640 | 718 | ||
| 641 | if (fid) | 719 | if (fid) |
| @@ -687,7 +765,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 687 | return ERR_PTR(result); | 765 | return ERR_PTR(result); |
| 688 | } | 766 | } |
| 689 | 767 | ||
| 690 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); | 768 | inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); |
| 691 | if (IS_ERR(inode)) { | 769 | if (IS_ERR(inode)) { |
| 692 | result = PTR_ERR(inode); | 770 | result = PTR_ERR(inode); |
| 693 | inode = NULL; | 771 | inode = NULL; |
| @@ -747,17 +825,19 @@ int | |||
| 747 | v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | 825 | v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, |
| 748 | struct inode *new_dir, struct dentry *new_dentry) | 826 | struct inode *new_dir, struct dentry *new_dentry) |
| 749 | { | 827 | { |
| 828 | int retval; | ||
| 750 | struct inode *old_inode; | 829 | struct inode *old_inode; |
| 830 | struct inode *new_inode; | ||
| 751 | struct v9fs_session_info *v9ses; | 831 | struct v9fs_session_info *v9ses; |
| 752 | struct p9_fid *oldfid; | 832 | struct p9_fid *oldfid; |
| 753 | struct p9_fid *olddirfid; | 833 | struct p9_fid *olddirfid; |
| 754 | struct p9_fid *newdirfid; | 834 | struct p9_fid *newdirfid; |
| 755 | struct p9_wstat wstat; | 835 | struct p9_wstat wstat; |
| 756 | int retval; | ||
| 757 | 836 | ||
| 758 | P9_DPRINTK(P9_DEBUG_VFS, "\n"); | 837 | P9_DPRINTK(P9_DEBUG_VFS, "\n"); |
| 759 | retval = 0; | 838 | retval = 0; |
| 760 | old_inode = old_dentry->d_inode; | 839 | old_inode = old_dentry->d_inode; |
| 840 | new_inode = new_dentry->d_inode; | ||
| 761 | v9ses = v9fs_inode2v9ses(old_inode); | 841 | v9ses = v9fs_inode2v9ses(old_inode); |
| 762 | oldfid = v9fs_fid_lookup(old_dentry); | 842 | oldfid = v9fs_fid_lookup(old_dentry); |
| 763 | if (IS_ERR(oldfid)) | 843 | if (IS_ERR(oldfid)) |
| @@ -798,9 +878,30 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 798 | retval = p9_client_wstat(oldfid, &wstat); | 878 | retval = p9_client_wstat(oldfid, &wstat); |
| 799 | 879 | ||
| 800 | clunk_newdir: | 880 | clunk_newdir: |
| 801 | if (!retval) | 881 | if (!retval) { |
| 882 | if (new_inode) { | ||
| 883 | if (S_ISDIR(new_inode->i_mode)) | ||
| 884 | clear_nlink(new_inode); | ||
| 885 | else | ||
| 886 | drop_nlink(new_inode); | ||
| 887 | /* | ||
| 888 | * Work around vfs rename rehash bug with | ||
| 889 | * FS_RENAME_DOES_D_MOVE | ||
| 890 | */ | ||
| 891 | v9fs_invalidate_inode_attr(new_inode); | ||
| 892 | } | ||
| 893 | if (S_ISDIR(old_inode->i_mode)) { | ||
| 894 | if (!new_inode) | ||
| 895 | inc_nlink(new_dir); | ||
| 896 | drop_nlink(old_dir); | ||
| 897 | } | ||
| 898 | v9fs_invalidate_inode_attr(old_inode); | ||
| 899 | v9fs_invalidate_inode_attr(old_dir); | ||
| 900 | v9fs_invalidate_inode_attr(new_dir); | ||
| 901 | |||
| 802 | /* successful rename */ | 902 | /* successful rename */ |
| 803 | d_move(old_dentry, new_dentry); | 903 | d_move(old_dentry, new_dentry); |
| 904 | } | ||
| 804 | up_write(&v9ses->rename_sem); | 905 | up_write(&v9ses->rename_sem); |
| 805 | p9_client_clunk(newdirfid); | 906 | p9_client_clunk(newdirfid); |
| 806 | 907 | ||
| @@ -831,9 +932,10 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 831 | P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); | 932 | P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); |
| 832 | err = -EPERM; | 933 | err = -EPERM; |
| 833 | v9ses = v9fs_inode2v9ses(dentry->d_inode); | 934 | v9ses = v9fs_inode2v9ses(dentry->d_inode); |
| 834 | if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) | 935 | if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { |
| 835 | return simple_getattr(mnt, dentry, stat); | 936 | generic_fillattr(dentry->d_inode, stat); |
| 836 | 937 | return 0; | |
| 938 | } | ||
| 837 | fid = v9fs_fid_lookup(dentry); | 939 | fid = v9fs_fid_lookup(dentry); |
| 838 | if (IS_ERR(fid)) | 940 | if (IS_ERR(fid)) |
| 839 | return PTR_ERR(fid); | 941 | return PTR_ERR(fid); |
| @@ -891,17 +993,20 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
| 891 | if (iattr->ia_valid & ATTR_GID) | 993 | if (iattr->ia_valid & ATTR_GID) |
| 892 | wstat.n_gid = iattr->ia_gid; | 994 | wstat.n_gid = iattr->ia_gid; |
| 893 | } | 995 | } |
| 894 | |||
| 895 | retval = p9_client_wstat(fid, &wstat); | ||
| 896 | if (retval < 0) | ||
| 897 | return retval; | ||
| 898 | |||
| 899 | if ((iattr->ia_valid & ATTR_SIZE) && | 996 | if ((iattr->ia_valid & ATTR_SIZE) && |
| 900 | iattr->ia_size != i_size_read(dentry->d_inode)) { | 997 | iattr->ia_size != i_size_read(dentry->d_inode)) { |
| 901 | retval = vmtruncate(dentry->d_inode, iattr->ia_size); | 998 | retval = vmtruncate(dentry->d_inode, iattr->ia_size); |
| 902 | if (retval) | 999 | if (retval) |
| 903 | return retval; | 1000 | return retval; |
| 904 | } | 1001 | } |
| 1002 | /* Write all dirty data */ | ||
| 1003 | if (S_ISREG(dentry->d_inode->i_mode)) | ||
| 1004 | filemap_write_and_wait(dentry->d_inode->i_mapping); | ||
| 1005 | |||
| 1006 | retval = p9_client_wstat(fid, &wstat); | ||
| 1007 | if (retval < 0) | ||
| 1008 | return retval; | ||
| 1009 | v9fs_invalidate_inode_attr(dentry->d_inode); | ||
| 905 | 1010 | ||
| 906 | setattr_copy(dentry->d_inode, iattr); | 1011 | setattr_copy(dentry->d_inode, iattr); |
| 907 | mark_inode_dirty(dentry->d_inode); | 1012 | mark_inode_dirty(dentry->d_inode); |
| @@ -924,6 +1029,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, | |||
| 924 | char tag_name[14]; | 1029 | char tag_name[14]; |
| 925 | unsigned int i_nlink; | 1030 | unsigned int i_nlink; |
| 926 | struct v9fs_session_info *v9ses = sb->s_fs_info; | 1031 | struct v9fs_session_info *v9ses = sb->s_fs_info; |
| 1032 | struct v9fs_inode *v9inode = V9FS_I(inode); | ||
| 927 | 1033 | ||
| 928 | inode->i_nlink = 1; | 1034 | inode->i_nlink = 1; |
| 929 | 1035 | ||
| @@ -983,6 +1089,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, | |||
| 983 | 1089 | ||
| 984 | /* not real number of blocks, but 512 byte ones ... */ | 1090 | /* not real number of blocks, but 512 byte ones ... */ |
| 985 | inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9; | 1091 | inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9; |
| 1092 | v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR; | ||
| 986 | } | 1093 | } |
| 987 | 1094 | ||
| 988 | /** | 1095 | /** |
| @@ -1115,8 +1222,8 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, | |||
| 1115 | int mode, const char *extension) | 1222 | int mode, const char *extension) |
| 1116 | { | 1223 | { |
| 1117 | u32 perm; | 1224 | u32 perm; |
| 1118 | struct v9fs_session_info *v9ses; | ||
| 1119 | struct p9_fid *fid; | 1225 | struct p9_fid *fid; |
| 1226 | struct v9fs_session_info *v9ses; | ||
| 1120 | 1227 | ||
| 1121 | v9ses = v9fs_inode2v9ses(dir); | 1228 | v9ses = v9fs_inode2v9ses(dir); |
| 1122 | if (!v9fs_proto_dotu(v9ses)) { | 1229 | if (!v9fs_proto_dotu(v9ses)) { |
| @@ -1130,6 +1237,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, | |||
| 1130 | if (IS_ERR(fid)) | 1237 | if (IS_ERR(fid)) |
| 1131 | return PTR_ERR(fid); | 1238 | return PTR_ERR(fid); |
| 1132 | 1239 | ||
| 1240 | v9fs_invalidate_inode_attr(dir); | ||
| 1133 | p9_client_clunk(fid); | 1241 | p9_client_clunk(fid); |
| 1134 | return 0; | 1242 | return 0; |
| 1135 | } | 1243 | } |
| @@ -1166,8 +1274,8 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | |||
| 1166 | struct dentry *dentry) | 1274 | struct dentry *dentry) |
| 1167 | { | 1275 | { |
| 1168 | int retval; | 1276 | int retval; |
| 1169 | struct p9_fid *oldfid; | ||
| 1170 | char *name; | 1277 | char *name; |
| 1278 | struct p9_fid *oldfid; | ||
| 1171 | 1279 | ||
| 1172 | P9_DPRINTK(P9_DEBUG_VFS, | 1280 | P9_DPRINTK(P9_DEBUG_VFS, |
| 1173 | " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, | 1281 | " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, |
| @@ -1186,7 +1294,10 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | |||
| 1186 | sprintf(name, "%d\n", oldfid->fid); | 1294 | sprintf(name, "%d\n", oldfid->fid); |
| 1187 | retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name); | 1295 | retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name); |
| 1188 | __putname(name); | 1296 | __putname(name); |
| 1189 | 1297 | if (!retval) { | |
| 1298 | v9fs_refresh_inode(oldfid, old_dentry->d_inode); | ||
| 1299 | v9fs_invalidate_inode_attr(dir); | ||
| 1300 | } | ||
| 1190 | clunk_fid: | 1301 | clunk_fid: |
| 1191 | p9_client_clunk(oldfid); | 1302 | p9_client_clunk(oldfid); |
| 1192 | return retval; | 1303 | return retval; |
| @@ -1237,6 +1348,32 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
| 1237 | return retval; | 1348 | return retval; |
| 1238 | } | 1349 | } |
| 1239 | 1350 | ||
| 1351 | int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode) | ||
| 1352 | { | ||
| 1353 | loff_t i_size; | ||
| 1354 | struct p9_wstat *st; | ||
| 1355 | struct v9fs_session_info *v9ses; | ||
| 1356 | |||
| 1357 | v9ses = v9fs_inode2v9ses(inode); | ||
| 1358 | st = p9_client_stat(fid); | ||
| 1359 | if (IS_ERR(st)) | ||
| 1360 | return PTR_ERR(st); | ||
| 1361 | |||
| 1362 | spin_lock(&inode->i_lock); | ||
| 1363 | /* | ||
| 1364 | * We don't want to refresh inode->i_size, | ||
| 1365 | * because we may have cached data | ||
| 1366 | */ | ||
| 1367 | i_size = inode->i_size; | ||
| 1368 | v9fs_stat2inode(st, inode, inode->i_sb); | ||
| 1369 | if (v9ses->cache) | ||
| 1370 | inode->i_size = i_size; | ||
| 1371 | spin_unlock(&inode->i_lock); | ||
| 1372 | p9stat_free(st); | ||
| 1373 | kfree(st); | ||
| 1374 | return 0; | ||
| 1375 | } | ||
| 1376 | |||
| 1240 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { | 1377 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { |
| 1241 | .create = v9fs_vfs_create, | 1378 | .create = v9fs_vfs_create, |
| 1242 | .lookup = v9fs_vfs_lookup, | 1379 | .lookup = v9fs_vfs_lookup, |
