diff options
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 145 |
1 files changed, 126 insertions, 19 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 50a56edca0b5..7d2d6c72aa78 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -98,7 +98,7 @@ u64 nfs_compat_user_ino64(u64 fileid) | |||
98 | return ino; | 98 | return ino; |
99 | } | 99 | } |
100 | 100 | ||
101 | void nfs_clear_inode(struct inode *inode) | 101 | static void nfs_clear_inode(struct inode *inode) |
102 | { | 102 | { |
103 | /* | 103 | /* |
104 | * The following should never happen... | 104 | * The following should never happen... |
@@ -110,6 +110,13 @@ void nfs_clear_inode(struct inode *inode) | |||
110 | nfs_fscache_release_inode_cookie(inode); | 110 | nfs_fscache_release_inode_cookie(inode); |
111 | } | 111 | } |
112 | 112 | ||
113 | void nfs_evict_inode(struct inode *inode) | ||
114 | { | ||
115 | truncate_inode_pages(&inode->i_data, 0); | ||
116 | end_writeback(inode); | ||
117 | nfs_clear_inode(inode); | ||
118 | } | ||
119 | |||
113 | /** | 120 | /** |
114 | * nfs_sync_mapping - helper to flush all mmapped dirty data to disk | 121 | * nfs_sync_mapping - helper to flush all mmapped dirty data to disk |
115 | */ | 122 | */ |
@@ -393,8 +400,8 @@ int | |||
393 | nfs_setattr(struct dentry *dentry, struct iattr *attr) | 400 | nfs_setattr(struct dentry *dentry, struct iattr *attr) |
394 | { | 401 | { |
395 | struct inode *inode = dentry->d_inode; | 402 | struct inode *inode = dentry->d_inode; |
396 | struct nfs_fattr fattr; | 403 | struct nfs_fattr *fattr; |
397 | int error; | 404 | int error = -ENOMEM; |
398 | 405 | ||
399 | nfs_inc_stats(inode, NFSIOS_VFSSETATTR); | 406 | nfs_inc_stats(inode, NFSIOS_VFSSETATTR); |
400 | 407 | ||
@@ -413,18 +420,22 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
413 | return 0; | 420 | return 0; |
414 | 421 | ||
415 | /* Write all dirty data */ | 422 | /* Write all dirty data */ |
416 | if (S_ISREG(inode->i_mode)) { | 423 | if (S_ISREG(inode->i_mode)) |
417 | filemap_write_and_wait(inode->i_mapping); | ||
418 | nfs_wb_all(inode); | 424 | nfs_wb_all(inode); |
419 | } | 425 | |
426 | fattr = nfs_alloc_fattr(); | ||
427 | if (fattr == NULL) | ||
428 | goto out; | ||
420 | /* | 429 | /* |
421 | * Return any delegations if we're going to change ACLs | 430 | * Return any delegations if we're going to change ACLs |
422 | */ | 431 | */ |
423 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) | 432 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) |
424 | nfs_inode_return_delegation(inode); | 433 | nfs_inode_return_delegation(inode); |
425 | error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); | 434 | error = NFS_PROTO(inode)->setattr(dentry, fattr, attr); |
426 | if (error == 0) | 435 | if (error == 0) |
427 | nfs_refresh_inode(inode, &fattr); | 436 | nfs_refresh_inode(inode, fattr); |
437 | nfs_free_fattr(fattr); | ||
438 | out: | ||
428 | return error; | 439 | return error; |
429 | } | 440 | } |
430 | 441 | ||
@@ -524,6 +535,68 @@ out: | |||
524 | return err; | 535 | return err; |
525 | } | 536 | } |
526 | 537 | ||
538 | static void nfs_init_lock_context(struct nfs_lock_context *l_ctx) | ||
539 | { | ||
540 | atomic_set(&l_ctx->count, 1); | ||
541 | l_ctx->lockowner = current->files; | ||
542 | l_ctx->pid = current->tgid; | ||
543 | INIT_LIST_HEAD(&l_ctx->list); | ||
544 | } | ||
545 | |||
546 | static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context *ctx) | ||
547 | { | ||
548 | struct nfs_lock_context *pos; | ||
549 | |||
550 | list_for_each_entry(pos, &ctx->lock_context.list, list) { | ||
551 | if (pos->lockowner != current->files) | ||
552 | continue; | ||
553 | if (pos->pid != current->tgid) | ||
554 | continue; | ||
555 | atomic_inc(&pos->count); | ||
556 | return pos; | ||
557 | } | ||
558 | return NULL; | ||
559 | } | ||
560 | |||
561 | struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx) | ||
562 | { | ||
563 | struct nfs_lock_context *res, *new = NULL; | ||
564 | struct inode *inode = ctx->path.dentry->d_inode; | ||
565 | |||
566 | spin_lock(&inode->i_lock); | ||
567 | res = __nfs_find_lock_context(ctx); | ||
568 | if (res == NULL) { | ||
569 | spin_unlock(&inode->i_lock); | ||
570 | new = kmalloc(sizeof(*new), GFP_KERNEL); | ||
571 | if (new == NULL) | ||
572 | return NULL; | ||
573 | nfs_init_lock_context(new); | ||
574 | spin_lock(&inode->i_lock); | ||
575 | res = __nfs_find_lock_context(ctx); | ||
576 | if (res == NULL) { | ||
577 | list_add_tail(&new->list, &ctx->lock_context.list); | ||
578 | new->open_context = ctx; | ||
579 | res = new; | ||
580 | new = NULL; | ||
581 | } | ||
582 | } | ||
583 | spin_unlock(&inode->i_lock); | ||
584 | kfree(new); | ||
585 | return res; | ||
586 | } | ||
587 | |||
588 | void nfs_put_lock_context(struct nfs_lock_context *l_ctx) | ||
589 | { | ||
590 | struct nfs_open_context *ctx = l_ctx->open_context; | ||
591 | struct inode *inode = ctx->path.dentry->d_inode; | ||
592 | |||
593 | if (!atomic_dec_and_lock(&l_ctx->count, &inode->i_lock)) | ||
594 | return; | ||
595 | list_del(&l_ctx->list); | ||
596 | spin_unlock(&inode->i_lock); | ||
597 | kfree(l_ctx); | ||
598 | } | ||
599 | |||
527 | /** | 600 | /** |
528 | * nfs_close_context - Common close_context() routine NFSv2/v3 | 601 | * nfs_close_context - Common close_context() routine NFSv2/v3 |
529 | * @ctx: pointer to context | 602 | * @ctx: pointer to context |
@@ -560,11 +633,11 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct | |||
560 | path_get(&ctx->path); | 633 | path_get(&ctx->path); |
561 | ctx->cred = get_rpccred(cred); | 634 | ctx->cred = get_rpccred(cred); |
562 | ctx->state = NULL; | 635 | ctx->state = NULL; |
563 | ctx->lockowner = current->files; | ||
564 | ctx->flags = 0; | 636 | ctx->flags = 0; |
565 | ctx->error = 0; | 637 | ctx->error = 0; |
566 | ctx->dir_cookie = 0; | 638 | ctx->dir_cookie = 0; |
567 | atomic_set(&ctx->count, 1); | 639 | nfs_init_lock_context(&ctx->lock_context); |
640 | ctx->lock_context.open_context = ctx; | ||
568 | } | 641 | } |
569 | return ctx; | 642 | return ctx; |
570 | } | 643 | } |
@@ -572,7 +645,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct | |||
572 | struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) | 645 | struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) |
573 | { | 646 | { |
574 | if (ctx != NULL) | 647 | if (ctx != NULL) |
575 | atomic_inc(&ctx->count); | 648 | atomic_inc(&ctx->lock_context.count); |
576 | return ctx; | 649 | return ctx; |
577 | } | 650 | } |
578 | 651 | ||
@@ -580,7 +653,7 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync) | |||
580 | { | 653 | { |
581 | struct inode *inode = ctx->path.dentry->d_inode; | 654 | struct inode *inode = ctx->path.dentry->d_inode; |
582 | 655 | ||
583 | if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock)) | 656 | if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock)) |
584 | return; | 657 | return; |
585 | list_del(&ctx->list); | 658 | list_del(&ctx->list); |
586 | spin_unlock(&inode->i_lock); | 659 | spin_unlock(&inode->i_lock); |
@@ -682,7 +755,7 @@ int | |||
682 | __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 755 | __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
683 | { | 756 | { |
684 | int status = -ESTALE; | 757 | int status = -ESTALE; |
685 | struct nfs_fattr fattr; | 758 | struct nfs_fattr *fattr = NULL; |
686 | struct nfs_inode *nfsi = NFS_I(inode); | 759 | struct nfs_inode *nfsi = NFS_I(inode); |
687 | 760 | ||
688 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", | 761 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", |
@@ -693,8 +766,13 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
693 | if (NFS_STALE(inode)) | 766 | if (NFS_STALE(inode)) |
694 | goto out; | 767 | goto out; |
695 | 768 | ||
769 | status = -ENOMEM; | ||
770 | fattr = nfs_alloc_fattr(); | ||
771 | if (fattr == NULL) | ||
772 | goto out; | ||
773 | |||
696 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); | 774 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); |
697 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); | 775 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr); |
698 | if (status != 0) { | 776 | if (status != 0) { |
699 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", | 777 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", |
700 | inode->i_sb->s_id, | 778 | inode->i_sb->s_id, |
@@ -707,7 +785,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
707 | goto out; | 785 | goto out; |
708 | } | 786 | } |
709 | 787 | ||
710 | status = nfs_refresh_inode(inode, &fattr); | 788 | status = nfs_refresh_inode(inode, fattr); |
711 | if (status) { | 789 | if (status) { |
712 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", | 790 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", |
713 | inode->i_sb->s_id, | 791 | inode->i_sb->s_id, |
@@ -723,6 +801,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
723 | (long long)NFS_FILEID(inode)); | 801 | (long long)NFS_FILEID(inode)); |
724 | 802 | ||
725 | out: | 803 | out: |
804 | nfs_free_fattr(fattr); | ||
726 | return status; | 805 | return status; |
727 | } | 806 | } |
728 | 807 | ||
@@ -730,9 +809,14 @@ int nfs_attribute_timeout(struct inode *inode) | |||
730 | { | 809 | { |
731 | struct nfs_inode *nfsi = NFS_I(inode); | 810 | struct nfs_inode *nfsi = NFS_I(inode); |
732 | 811 | ||
812 | return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo); | ||
813 | } | ||
814 | |||
815 | static int nfs_attribute_cache_expired(struct inode *inode) | ||
816 | { | ||
733 | if (nfs_have_delegated_attributes(inode)) | 817 | if (nfs_have_delegated_attributes(inode)) |
734 | return 0; | 818 | return 0; |
735 | return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo); | 819 | return nfs_attribute_timeout(inode); |
736 | } | 820 | } |
737 | 821 | ||
738 | /** | 822 | /** |
@@ -745,7 +829,7 @@ int nfs_attribute_timeout(struct inode *inode) | |||
745 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 829 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
746 | { | 830 | { |
747 | if (!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR) | 831 | if (!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR) |
748 | && !nfs_attribute_timeout(inode)) | 832 | && !nfs_attribute_cache_expired(inode)) |
749 | return NFS_STALE(inode) ? -ESTALE : 0; | 833 | return NFS_STALE(inode) ? -ESTALE : 0; |
750 | return __nfs_revalidate_inode(server, inode); | 834 | return __nfs_revalidate_inode(server, inode); |
751 | } | 835 | } |
@@ -782,7 +866,8 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
782 | int ret = 0; | 866 | int ret = 0; |
783 | 867 | ||
784 | if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) | 868 | if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) |
785 | || nfs_attribute_timeout(inode) || NFS_STALE(inode)) { | 869 | || nfs_attribute_cache_expired(inode) |
870 | || NFS_STALE(inode)) { | ||
786 | ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode); | 871 | ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode); |
787 | if (ret < 0) | 872 | if (ret < 0) |
788 | goto out; | 873 | goto out; |
@@ -916,6 +1001,26 @@ void nfs_fattr_init(struct nfs_fattr *fattr) | |||
916 | fattr->gencount = nfs_inc_attr_generation_counter(); | 1001 | fattr->gencount = nfs_inc_attr_generation_counter(); |
917 | } | 1002 | } |
918 | 1003 | ||
1004 | struct nfs_fattr *nfs_alloc_fattr(void) | ||
1005 | { | ||
1006 | struct nfs_fattr *fattr; | ||
1007 | |||
1008 | fattr = kmalloc(sizeof(*fattr), GFP_NOFS); | ||
1009 | if (fattr != NULL) | ||
1010 | nfs_fattr_init(fattr); | ||
1011 | return fattr; | ||
1012 | } | ||
1013 | |||
1014 | struct nfs_fh *nfs_alloc_fhandle(void) | ||
1015 | { | ||
1016 | struct nfs_fh *fh; | ||
1017 | |||
1018 | fh = kmalloc(sizeof(struct nfs_fh), GFP_NOFS); | ||
1019 | if (fh != NULL) | ||
1020 | fh->size = 0; | ||
1021 | return fh; | ||
1022 | } | ||
1023 | |||
919 | /** | 1024 | /** |
920 | * nfs_inode_attrs_need_update - check if the inode attributes need updating | 1025 | * nfs_inode_attrs_need_update - check if the inode attributes need updating |
921 | * @inode - pointer to inode | 1026 | * @inode - pointer to inode |
@@ -1300,8 +1405,10 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1300 | * to open() calls that passed nfs_atomic_lookup, but failed to call | 1405 | * to open() calls that passed nfs_atomic_lookup, but failed to call |
1301 | * nfs_open(). | 1406 | * nfs_open(). |
1302 | */ | 1407 | */ |
1303 | void nfs4_clear_inode(struct inode *inode) | 1408 | void nfs4_evict_inode(struct inode *inode) |
1304 | { | 1409 | { |
1410 | truncate_inode_pages(&inode->i_data, 0); | ||
1411 | end_writeback(inode); | ||
1305 | /* If we are holding a delegation, return it! */ | 1412 | /* If we are holding a delegation, return it! */ |
1306 | nfs_inode_return_delegation_noreclaim(inode); | 1413 | nfs_inode_return_delegation_noreclaim(inode); |
1307 | /* First call standard NFS clear_inode() code */ | 1414 | /* First call standard NFS clear_inode() code */ |