aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-09-14 14:03:14 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-09-22 23:25:02 -0400
commit5f004cf2aa8494708fd8d78e78142b7b2748e765 (patch)
treec4f10f43217737e08d68167e1866ef5b305ac571 /fs/nfs
parent2dec51466a08ac1c67da41bfd0518d43d983a2eb (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/nfs')
-rw-r--r--fs/nfs/read.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index dae33c1e8a7..69f1549da2b 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);
716out:
704 return ret; 717 return ret;
705} 718}
706 719