Details
-
Bug
-
Resolution: Fixed
-
Minor
-
Lustre 2.3.0
-
SLES11SP1/SP2. Lustre 2.x.
-
3
-
7438
Description
When a file is opened with O_APPEND set, and data is written, the resulting value of the file pointer is incorrect. This is observed when using lseek with SEEK_CUR set.
This does not result in corruption on subsequent writes because with O_APPEND set, the file pointer is reset to EOF before each write. (See ULK3 on VFS)
I'm attaching a trivial reproducer for this problem.
A bit of debugging showed me that a correct value of the file pointer is available at the same point where it is set to the incorrect value in ll_file_io_generic.
Here's the sample (this is from 2.3, but the code is effectively the same in all 2.x releases) with my debug code in it to make clear exactly what I'm talking about:
ppos_out = (unsigned long) *ppos; printk(KERN_NOTICE "ll_file_io_generic (before if) ppos: %lu\n",ppos_out); if (io->ci_nob > 0) { result = io->ci_nob; *ppos = io->u.ci_wr.wr.crw_pos; ppos_out = (unsigned long) *ppos; printk(KERN_NOTICE "ll_file_io_generic io->u.ci_wr.wr.crw_pos ppos: %lu\n",ppos_out); }
The value of ppos before the *ppos = io->u.ci_wr.wr.crw_pos is correct, but the value in io->u.ci_wr.wr.crw_pos is not. It is greater than expected by approximately the number of bytes in the write. (See comment for further details.)
An if statement around the assignment checking for O_APPEND corrects the issue and passes acceptance-small sanity:
if(!cl_io_is_append(io)) {
*ppos = io->u.ci_wr.wr.crw_pos;
}
Still, I am concerned this is a band-aid and a deeper fix may be necessary.
I have some more detailed information on exactly how much io->u.ci_wr.wr.crw_pos; that I'll put in a subsequent comment - It's lengthy, and may not be relevant to fixing the issue.