aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4proc.c
diff options
context:
space:
mode:
authorDavid Shaw <dshaw@jabberwocky.com>2009-03-05 20:16:14 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-03-18 17:38:40 -0400
commit31dec2538e45e9fff2007ea1f4c6bae9f78db724 (patch)
treec2b42679c73c1c6f31312f38a1b1d049e918d635 /fs/nfsd/nfs4proc.c
parent1e685ec270cb97680be4eb8cf6b615f5f7f1403a (diff)
Short write in nfsd becomes a full write to the client
If a filesystem being written to via NFS returns a short write count (as opposed to an error) to nfsd, nfsd treats that as a success for the entire write, rather than the short count that actually succeeded. For example, given a 8192 byte write, if the underlying filesystem only writes 4096 bytes, nfsd will ack back to the nfs client that all 8192 bytes were written. The nfs client does have retry logic for short writes, but this is never called as the client is told the complete write succeeded. There are probably other ways it could happen, but in my case it happened with a fuse (filesystem in userspace) filesystem which can rather easily have a partial write. Here is a patch to properly return the short write count to the client. Signed-off-by: David Shaw <dshaw@jabberwocky.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs/nfsd/nfs4proc.c')
-rw-r--r--fs/nfsd/nfs4proc.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 77f584f69dfe..283d77a47120 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -682,6 +682,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
682 struct file *filp = NULL; 682 struct file *filp = NULL;
683 u32 *p; 683 u32 *p;
684 __be32 status = nfs_ok; 684 __be32 status = nfs_ok;
685 unsigned long cnt;
685 686
686 /* no need to check permission - this will be done in nfsd_write() */ 687 /* no need to check permission - this will be done in nfsd_write() */
687 688
@@ -700,7 +701,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
700 return status; 701 return status;
701 } 702 }
702 703
703 write->wr_bytes_written = write->wr_buflen; 704 cnt = write->wr_buflen;
704 write->wr_how_written = write->wr_stable_how; 705 write->wr_how_written = write->wr_stable_how;
705 p = (u32 *)write->wr_verifier.data; 706 p = (u32 *)write->wr_verifier.data;
706 *p++ = nfssvc_boot.tv_sec; 707 *p++ = nfssvc_boot.tv_sec;
@@ -708,10 +709,12 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
708 709
709 status = nfsd_write(rqstp, &cstate->current_fh, filp, 710 status = nfsd_write(rqstp, &cstate->current_fh, filp,
710 write->wr_offset, rqstp->rq_vec, write->wr_vlen, 711 write->wr_offset, rqstp->rq_vec, write->wr_vlen,
711 write->wr_buflen, &write->wr_how_written); 712 &cnt, &write->wr_how_written);
712 if (filp) 713 if (filp)
713 fput(filp); 714 fput(filp);
714 715
716 write->wr_bytes_written = cnt;
717
715 if (status == nfserr_symlink) 718 if (status == nfserr_symlink)
716 status = nfserr_inval; 719 status = nfserr_inval;
717 return status; 720 return status;