diff options
Diffstat (limited to 'fs/squashfs/cache.c')
-rw-r--r-- | fs/squashfs/cache.c | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c index f744be98cd5a..af0b73802592 100644 --- a/fs/squashfs/cache.c +++ b/fs/squashfs/cache.c | |||
@@ -70,11 +70,15 @@ struct squashfs_cache_entry *squashfs_cache_get(struct super_block *sb, | |||
70 | spin_lock(&cache->lock); | 70 | spin_lock(&cache->lock); |
71 | 71 | ||
72 | while (1) { | 72 | while (1) { |
73 | for (i = 0; i < cache->entries; i++) | 73 | for (i = cache->curr_blk, n = 0; n < cache->entries; n++) { |
74 | if (cache->entry[i].block == block) | 74 | if (cache->entry[i].block == block) { |
75 | cache->curr_blk = i; | ||
75 | break; | 76 | break; |
77 | } | ||
78 | i = (i + 1) % cache->entries; | ||
79 | } | ||
76 | 80 | ||
77 | if (i == cache->entries) { | 81 | if (n == cache->entries) { |
78 | /* | 82 | /* |
79 | * Block not in cache, if all cache entries are used | 83 | * Block not in cache, if all cache entries are used |
80 | * go to sleep waiting for one to become available. | 84 | * go to sleep waiting for one to become available. |
@@ -245,6 +249,7 @@ struct squashfs_cache *squashfs_cache_init(char *name, int entries, | |||
245 | goto cleanup; | 249 | goto cleanup; |
246 | } | 250 | } |
247 | 251 | ||
252 | cache->curr_blk = 0; | ||
248 | cache->next_blk = 0; | 253 | cache->next_blk = 0; |
249 | cache->unused = entries; | 254 | cache->unused = entries; |
250 | cache->entries = entries; | 255 | cache->entries = entries; |
@@ -332,17 +337,20 @@ int squashfs_read_metadata(struct super_block *sb, void *buffer, | |||
332 | u64 *block, int *offset, int length) | 337 | u64 *block, int *offset, int length) |
333 | { | 338 | { |
334 | struct squashfs_sb_info *msblk = sb->s_fs_info; | 339 | struct squashfs_sb_info *msblk = sb->s_fs_info; |
335 | int bytes, copied = length; | 340 | int bytes, res = length; |
336 | struct squashfs_cache_entry *entry; | 341 | struct squashfs_cache_entry *entry; |
337 | 342 | ||
338 | TRACE("Entered squashfs_read_metadata [%llx:%x]\n", *block, *offset); | 343 | TRACE("Entered squashfs_read_metadata [%llx:%x]\n", *block, *offset); |
339 | 344 | ||
340 | while (length) { | 345 | while (length) { |
341 | entry = squashfs_cache_get(sb, msblk->block_cache, *block, 0); | 346 | entry = squashfs_cache_get(sb, msblk->block_cache, *block, 0); |
342 | if (entry->error) | 347 | if (entry->error) { |
343 | return entry->error; | 348 | res = entry->error; |
344 | else if (*offset >= entry->length) | 349 | goto error; |
345 | return -EIO; | 350 | } else if (*offset >= entry->length) { |
351 | res = -EIO; | ||
352 | goto error; | ||
353 | } | ||
346 | 354 | ||
347 | bytes = squashfs_copy_data(buffer, entry, *offset, length); | 355 | bytes = squashfs_copy_data(buffer, entry, *offset, length); |
348 | if (buffer) | 356 | if (buffer) |
@@ -358,7 +366,11 @@ int squashfs_read_metadata(struct super_block *sb, void *buffer, | |||
358 | squashfs_cache_put(entry); | 366 | squashfs_cache_put(entry); |
359 | } | 367 | } |
360 | 368 | ||
361 | return copied; | 369 | return res; |
370 | |||
371 | error: | ||
372 | squashfs_cache_put(entry); | ||
373 | return res; | ||
362 | } | 374 | } |
363 | 375 | ||
364 | 376 | ||