diff options
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 87 |
1 files changed, 78 insertions, 9 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 099b3518feea..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 | */ |
@@ -413,10 +420,8 @@ 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 | } | ||
420 | 425 | ||
421 | fattr = nfs_alloc_fattr(); | 426 | fattr = nfs_alloc_fattr(); |
422 | if (fattr == NULL) | 427 | if (fattr == NULL) |
@@ -530,6 +535,68 @@ out: | |||
530 | return err; | 535 | return err; |
531 | } | 536 | } |
532 | 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 | |||
533 | /** | 600 | /** |
534 | * nfs_close_context - Common close_context() routine NFSv2/v3 | 601 | * nfs_close_context - Common close_context() routine NFSv2/v3 |
535 | * @ctx: pointer to context | 602 | * @ctx: pointer to context |
@@ -566,11 +633,11 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct | |||
566 | path_get(&ctx->path); | 633 | path_get(&ctx->path); |
567 | ctx->cred = get_rpccred(cred); | 634 | ctx->cred = get_rpccred(cred); |
568 | ctx->state = NULL; | 635 | ctx->state = NULL; |
569 | ctx->lockowner = current->files; | ||
570 | ctx->flags = 0; | 636 | ctx->flags = 0; |
571 | ctx->error = 0; | 637 | ctx->error = 0; |
572 | ctx->dir_cookie = 0; | 638 | ctx->dir_cookie = 0; |
573 | atomic_set(&ctx->count, 1); | 639 | nfs_init_lock_context(&ctx->lock_context); |
640 | ctx->lock_context.open_context = ctx; | ||
574 | } | 641 | } |
575 | return ctx; | 642 | return ctx; |
576 | } | 643 | } |
@@ -578,7 +645,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct | |||
578 | 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) |
579 | { | 646 | { |
580 | if (ctx != NULL) | 647 | if (ctx != NULL) |
581 | atomic_inc(&ctx->count); | 648 | atomic_inc(&ctx->lock_context.count); |
582 | return ctx; | 649 | return ctx; |
583 | } | 650 | } |
584 | 651 | ||
@@ -586,7 +653,7 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync) | |||
586 | { | 653 | { |
587 | struct inode *inode = ctx->path.dentry->d_inode; | 654 | struct inode *inode = ctx->path.dentry->d_inode; |
588 | 655 | ||
589 | if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock)) | 656 | if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock)) |
590 | return; | 657 | return; |
591 | list_del(&ctx->list); | 658 | list_del(&ctx->list); |
592 | spin_unlock(&inode->i_lock); | 659 | spin_unlock(&inode->i_lock); |
@@ -1338,8 +1405,10 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1338 | * 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 |
1339 | * nfs_open(). | 1406 | * nfs_open(). |
1340 | */ | 1407 | */ |
1341 | void nfs4_clear_inode(struct inode *inode) | 1408 | void nfs4_evict_inode(struct inode *inode) |
1342 | { | 1409 | { |
1410 | truncate_inode_pages(&inode->i_data, 0); | ||
1411 | end_writeback(inode); | ||
1343 | /* If we are holding a delegation, return it! */ | 1412 | /* If we are holding a delegation, return it! */ |
1344 | nfs_inode_return_delegation_noreclaim(inode); | 1413 | nfs_inode_return_delegation_noreclaim(inode); |
1345 | /* First call standard NFS clear_inode() code */ | 1414 | /* First call standard NFS clear_inode() code */ |