diff mbox

[linux-cifs-client] cifs: Detect errors in cifs_writepages when called during background write-back

Message ID 20090424215924.GA25549@kay (mailing list archive)
State New, archived
Headers show

Commit Message

Peter Schwenke April 24, 2009, 9:59 p.m. UTC
The return code isn't checked in the case of cifs_writepages being
invoked as a result of pdflush and potentially other background
write-back. This results in data integrity problems when errors such as
a network break occur when CIFSSMBWrite2 is called.  The resulting error
isn't acted on.  This patch hangs on to the write-behind error so that it
is available for detection later on.

Signed-off-by: Peter Schwenke <peter@bluetoad.com.au>
---
 fs/cifs/file.c |   15 ++++++++++++++-
 1 files changed, 14 insertions(+), 1 deletions(-)

Comments

Peter Schwenke May 12, 2009, 8:18 a.m. UTC | #1
Peter Schwenke wrote:
> The return code isn't checked in the case of cifs_writepages being
> invoked as a result of pdflush and potentially other background
> write-back. This results in data integrity problems when errors such as
> a network break occur when CIFSSMBWrite2 is called.  The resulting error
> isn't acted on.  This patch hangs on to the write-behind error so that it
> is available for detection later on.
> 
> Signed-off-by: Peter Schwenke <peter@bluetoad.com.au>
> ---
>  fs/cifs/file.c |   15 ++++++++++++++-
>  1 files changed, 14 insertions(+), 1 deletions(-)
> 
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index 042b122..f1a5b1e 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -1200,6 +1200,7 @@ static int cifs_writepages(struct address_space *mapping,
>  	unsigned int bytes_to_write;
>  	unsigned int bytes_written;
>  	struct cifs_sb_info *cifs_sb;
> +	struct cifsInodeInfo *cifs_inode = CIFS_I(mapping->host);
>  	int done = 0;
>  	pgoff_t end;
>  	pgoff_t index;
> @@ -1354,7 +1355,7 @@ retry:
>  			 * CIFSSMBWrite2.  We can't rely on the last handle
>  			 * we used to still be valid
>  			 */
> -			open_file = find_writable_file(CIFS_I(mapping->host));
> +			open_file = find_writable_file(cifs_inode);
>  			if (!open_file) {
>  				cERROR(1, ("No writable handles for inode"));
>  				rc = -EBADF;
> @@ -1374,6 +1375,18 @@ retry:
>  						set_bit(AS_ENOSPC, &mapping->flags);
>  					else
>  						set_bit(AS_EIO, &mapping->flags);
> +					/*
> +					 * The return code isn't checked in the
> +					 * case of cifs_writepages being
> +					 * invoked from background write outs
> +					 * i.e. generic_sync_sb_inodes()
> +					 */
> +					if (wbc->sync_mode == WB_SYNC_NONE) {
> +						if (rc == -ENOSPC)
> +							cifs_inode->write_behind_rc =  rc;
> +						else
> +							cifs_inode->write_behind_rc =  -EIO;
> +					}
>  				} else {
>  					cifs_stats_bytes_written(cifs_sb->tcon,
>  								 bytes_written);

I was wondering if this patch was the correct way of fixing the problem.
   This was against 2.6.27
diff mbox

Patch

diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 042b122..f1a5b1e 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1200,6 +1200,7 @@  static int cifs_writepages(struct address_space *mapping,
 	unsigned int bytes_to_write;
 	unsigned int bytes_written;
 	struct cifs_sb_info *cifs_sb;
+	struct cifsInodeInfo *cifs_inode = CIFS_I(mapping->host);
 	int done = 0;
 	pgoff_t end;
 	pgoff_t index;
@@ -1354,7 +1355,7 @@  retry:
 			 * CIFSSMBWrite2.  We can't rely on the last handle
 			 * we used to still be valid
 			 */
-			open_file = find_writable_file(CIFS_I(mapping->host));
+			open_file = find_writable_file(cifs_inode);
 			if (!open_file) {
 				cERROR(1, ("No writable handles for inode"));
 				rc = -EBADF;
@@ -1374,6 +1375,18 @@  retry:
 						set_bit(AS_ENOSPC, &mapping->flags);
 					else
 						set_bit(AS_EIO, &mapping->flags);
+					/*
+					 * The return code isn't checked in the
+					 * case of cifs_writepages being
+					 * invoked from background write outs
+					 * i.e. generic_sync_sb_inodes()
+					 */
+					if (wbc->sync_mode == WB_SYNC_NONE) {
+						if (rc == -ENOSPC)
+							cifs_inode->write_behind_rc =  rc;
+						else
+							cifs_inode->write_behind_rc =  -EIO;
+					}
 				} else {
 					cifs_stats_bytes_written(cifs_sb->tcon,
 								 bytes_written);