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;