btw, looking at the implementation the read side was buggy. First it's
pointless to read both version1 and version2 before reading the isize,
secondly if you increase version1 first (in the writer), the reader has
to read version2 before i_size and version1 after i_size. While you're
doing the opposite, you compare v1 (version1) read before i_size with
version2 after i_size.
So while merging it I rewrote it this way (I also change the type of the
sequence number to int, 2^16 can overflow quite fast in a multighz cpu,
mostly for paranoid of course, and to go safe with the atomic granularty
provided by archs, int certainly has to be atomic-granular).
loff_t i_size;
int v1, v2;
/* Retry if i_size was possibly modified while sampling. */
do {
v1 = inode->i_size_version1;
rmb();
i_size = inode->i_size;
rmb();
v2 = inode->i_size_version2;
} while (v1 != v2);
return i_size;
and the new writer side:
inode->i_size_version2++;
wmb();
inode->i_size = i_size;
wmb();
inode->i_size_version1++;
wmb(); /* make it visible ASAP */
Andrea
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/