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 */ |
