File s390-tools-sles11sp2-cmsfs-fuse-disk_full.patch of Package s390-tools

Description: cmsfs-fuse: Update the number of records on disk full condition
Symptom:     Unreadable file after disk ran full.
Problem:     If the disk runs out of free blocks, the highest record number,
             stored in a pointer entry for a variable format record, can be
             too high.
Solution:    Update the highest record number according to the number of
             records written before the disk is full.
Problem-ID:  75963 
---
 cmsfs-fuse/cmsfs-fuse.c |   23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

--- a/cmsfs-fuse/cmsfs-fuse.c
+++ b/cmsfs-fuse/cmsfs-fuse.c
@@ -180,6 +180,8 @@ struct write_state {
 	int		var_record_state;
 	/* remaining record bytes for a write request */
 	int		var_record_len;
+	/* only used for var records hi_record_nr by now */
+	int		var_records_written;
 };
 
 /*
@@ -3536,8 +3538,11 @@ static int write_prepare_block(struct fi
 				f->write_ptr = get_filled_block();
 			else
 				f->write_ptr = get_zero_block();
-			if (f->write_ptr < 0)
-				return f->write_ptr;
+			if (f->write_ptr < 0) {
+				/* reset to catch subsequent writes */
+				f->write_ptr = 0;
+				return -ENOSPC;
+			}
 			new_block = 1;
 			len = cmsfs.blksize;
 		} else
@@ -3577,6 +3582,7 @@ static int write_var_header(struct file
 		f->write_ptr++;
 		f->wstate->block_free--;
 		f->wstate->var_record_state = RWS_HEADER_COMPLETE;
+		f->wstate->var_records_written++;
 		return 1;
 	}
 
@@ -3592,6 +3598,7 @@ static int write_var_header(struct file
 		f->wstate->block_free -= 2;
 		f->wstate->var_record_len = vheader;
 		f->wstate->var_record_state = RWS_HEADER_COMPLETE;
+		f->wstate->var_records_written++;
 		return 2;
 	} else {
 		/* len = 1, write first header byte */
@@ -3939,6 +3946,7 @@ static void reset_write_state(struct fil
 {
 	f->wstate->var_record_state = RWS_RECORD_COMPLETE;
 	f->wstate->var_record_len = 0;
+	f->wstate->var_records_written = 0;
 }
 
 /*
@@ -3984,9 +3992,16 @@ static int write_append(struct file *f,
 	for (i = 0; i < nblocks; i++) {
 		len = extend_block(f, buf, size, rlen);
 		if (len < 0) {
-			if (copied > 0)
+			if (copied > 0) {
+				/*
+				 * Not all records may be written, need to
+				 * update nrecords to store a correct
+				 * hi_record_nr in the last vptr.
+				 */
+				if (f->fst->record_format == RECORD_LEN_VARIABLE)
+					nrecords = f->wstate->var_records_written;
 				goto out;
-			else
+			} else
 				return len;
 		}
 		copied += len;