diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-09-14 14:03:14 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-09-22 23:25:02 -0400 |
commit | 5f004cf2aa8494708fd8d78e78142b7b2748e765 (patch) | |
tree | c4f10f43217737e08d68167e1866ef5b305ac571 /fs | |
parent | 2dec51466a08ac1c67da41bfd0518d43d983a2eb (diff) |
NFS: Make read() return an ESTALE if the file has been deleted
Currently, a read() request will return EIO even if the file has been
deleted on the server, simply because that is what the VM will return
if the call to readpage() fails to update the page.
Ensure that readpage() marks the inode as stale if it receives an ESTALE.
Then return that error to userland.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/read.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index dae33c1e8a77..69f1549da2b9 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -568,8 +568,13 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data) | |||
568 | 568 | ||
569 | nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, resp->count); | 569 | nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, resp->count); |
570 | 570 | ||
571 | /* Is this a short read? */ | 571 | if (task->tk_status < 0) { |
572 | if (task->tk_status >= 0 && resp->count < argp->count && !resp->eof) { | 572 | if (task->tk_status == -ESTALE) { |
573 | set_bit(NFS_INO_STALE, &NFS_FLAGS(data->inode)); | ||
574 | nfs_mark_for_revalidate(data->inode); | ||
575 | } | ||
576 | } else if (resp->count < argp->count && !resp->eof) { | ||
577 | /* This is a short read! */ | ||
573 | nfs_inc_stats(data->inode, NFSIOS_SHORTREAD); | 578 | nfs_inc_stats(data->inode, NFSIOS_SHORTREAD); |
574 | /* Has the server at least made some progress? */ | 579 | /* Has the server at least made some progress? */ |
575 | if (resp->count != 0) { | 580 | if (resp->count != 0) { |
@@ -616,6 +621,10 @@ int nfs_readpage(struct file *file, struct page *page) | |||
616 | if (error) | 621 | if (error) |
617 | goto out_error; | 622 | goto out_error; |
618 | 623 | ||
624 | error = -ESTALE; | ||
625 | if (NFS_STALE(inode)) | ||
626 | goto out_error; | ||
627 | |||
619 | if (file == NULL) { | 628 | if (file == NULL) { |
620 | ctx = nfs_find_open_context(inode, NULL, FMODE_READ); | 629 | ctx = nfs_find_open_context(inode, NULL, FMODE_READ); |
621 | if (ctx == NULL) | 630 | if (ctx == NULL) |
@@ -678,7 +687,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, | |||
678 | }; | 687 | }; |
679 | struct inode *inode = mapping->host; | 688 | struct inode *inode = mapping->host; |
680 | struct nfs_server *server = NFS_SERVER(inode); | 689 | struct nfs_server *server = NFS_SERVER(inode); |
681 | int ret; | 690 | int ret = -ESTALE; |
682 | 691 | ||
683 | dprintk("NFS: nfs_readpages (%s/%Ld %d)\n", | 692 | dprintk("NFS: nfs_readpages (%s/%Ld %d)\n", |
684 | inode->i_sb->s_id, | 693 | inode->i_sb->s_id, |
@@ -686,6 +695,9 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, | |||
686 | nr_pages); | 695 | nr_pages); |
687 | nfs_inc_stats(inode, NFSIOS_VFSREADPAGES); | 696 | nfs_inc_stats(inode, NFSIOS_VFSREADPAGES); |
688 | 697 | ||
698 | if (NFS_STALE(inode)) | ||
699 | goto out; | ||
700 | |||
689 | if (filp == NULL) { | 701 | if (filp == NULL) { |
690 | desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ); | 702 | desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ); |
691 | if (desc.ctx == NULL) | 703 | if (desc.ctx == NULL) |
@@ -701,6 +713,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, | |||
701 | ret = err; | 713 | ret = err; |
702 | } | 714 | } |
703 | put_nfs_open_context(desc.ctx); | 715 | put_nfs_open_context(desc.ctx); |
716 | out: | ||
704 | return ret; | 717 | return ret; |
705 | } | 718 | } |
706 | 719 | ||