scoutfs: fix livelock in item_set_batch

scoutfs_item_set_batch() first tries to populate the item cache with the
range of keys it's going to be modifying.  It does this by walking
the input key range and trying to read any missing regions.

It made a bad assumption that reading from the final present key of a
cached range would read more items into the cache.  That was often the
case when the last present key landed in a segment that contained more
keys.  But if the last present key was at the end of a segment the read
wouldn't make any difference.  It'd keep trying to read that final
present key indefinitely.

The fix is to try and populate the item cache starting with the first
key that's missing from the cache by incrementing the last key that we
found in the cache.

This stopped scoutfs/507 from reliably getting stuck trying to modify an
xattr whose single item happened to land at the end of a segment.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2018-02-08 13:45:07 -08:00
committed by Zach Brown
parent 4ff1e3020f
commit d42a3115c9

View File

@@ -1310,8 +1310,10 @@ int scoutfs_item_set_batch(struct super_block *sb, struct list_head *list,
if (check_range(sb, &cac->ranges, range_end, range_end)) {
if (scoutfs_key_compare(range_end, last) >= 0)
break;
/* start reading from hole starting at range_end */
/* start reading after the last key we have cached */
scoutfs_key_inc(range_end);
} else {
/* start reading from the missing first */
scoutfs_key_copy(range_end, first);
}