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, |