Commit 96e80a7851b44f3decaac0625665cd64e550b71d
Exists in
master
and in
6 other branches
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-next
* git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-next: Squashfs: fix i_blocks calculation with extended regular files Squashfs: fix mount time sanity check for corrupted superblock Squashfs: optimise squashfs_cache_get entry search Squashfs: Update documentation to include xattrs Squashfs: add missing block release on error condition
Showing 5 changed files Side-by-side Diff
Documentation/filesystems/squashfs.txt
... | ... | @@ -93,8 +93,8 @@ |
93 | 93 | |
94 | 94 | Compressed data blocks are written to the filesystem as files are read from |
95 | 95 | the source directory, and checked for duplicates. Once all file data has been |
96 | -written the completed inode, directory, fragment, export and uid/gid lookup | |
97 | -tables are written. | |
96 | +written the completed inode, directory, fragment, export, uid/gid lookup and | |
97 | +xattr tables are written. | |
98 | 98 | |
99 | 99 | 3.1 Compression options |
100 | 100 | ----------------------- |
... | ... | @@ -151,7 +151,7 @@ |
151 | 151 | and at lookup the index is scanned linearly looking for the first filename |
152 | 152 | alphabetically larger than the filename being looked up. At this point the |
153 | 153 | location of the metadata block the filename is in has been found. |
154 | -The general idea of the index is ensure only one metadata block needs to be | |
154 | +The general idea of the index is to ensure only one metadata block needs to be | |
155 | 155 | decompressed to do a lookup irrespective of the length of the directory. |
156 | 156 | This scheme has the advantage that it doesn't require extra memory overhead |
157 | 157 | and doesn't require much extra storage on disk. |
fs/squashfs/cache.c
... | ... | @@ -70,11 +70,15 @@ |
70 | 70 | spin_lock(&cache->lock); |
71 | 71 | |
72 | 72 | while (1) { |
73 | - for (i = 0; i < cache->entries; i++) | |
74 | - if (cache->entry[i].block == block) | |
73 | + for (i = cache->curr_blk, n = 0; n < cache->entries; n++) { | |
74 | + if (cache->entry[i].block == block) { | |
75 | + cache->curr_blk = i; | |
75 | 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 | 83 | * Block not in cache, if all cache entries are used |
80 | 84 | * go to sleep waiting for one to become available. |
... | ... | @@ -245,6 +249,7 @@ |
245 | 249 | goto cleanup; |
246 | 250 | } |
247 | 251 | |
252 | + cache->curr_blk = 0; | |
248 | 253 | cache->next_blk = 0; |
249 | 254 | cache->unused = entries; |
250 | 255 | cache->entries = entries; |
251 | 256 | |
... | ... | @@ -332,17 +337,20 @@ |
332 | 337 | u64 *block, int *offset, int length) |
333 | 338 | { |
334 | 339 | struct squashfs_sb_info *msblk = sb->s_fs_info; |
335 | - int bytes, copied = length; | |
340 | + int bytes, res = length; | |
336 | 341 | struct squashfs_cache_entry *entry; |
337 | 342 | |
338 | 343 | TRACE("Entered squashfs_read_metadata [%llx:%x]\n", *block, *offset); |
339 | 344 | |
340 | 345 | while (length) { |
341 | 346 | entry = squashfs_cache_get(sb, msblk->block_cache, *block, 0); |
342 | - if (entry->error) | |
343 | - return entry->error; | |
344 | - else if (*offset >= entry->length) | |
345 | - return -EIO; | |
347 | + if (entry->error) { | |
348 | + res = entry->error; | |
349 | + goto error; | |
350 | + } else if (*offset >= entry->length) { | |
351 | + res = -EIO; | |
352 | + goto error; | |
353 | + } | |
346 | 354 | |
347 | 355 | bytes = squashfs_copy_data(buffer, entry, *offset, length); |
348 | 356 | if (buffer) |
... | ... | @@ -358,7 +366,11 @@ |
358 | 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 |
fs/squashfs/inode.c
... | ... | @@ -208,8 +208,8 @@ |
208 | 208 | inode->i_op = &squashfs_inode_ops; |
209 | 209 | inode->i_fop = &generic_ro_fops; |
210 | 210 | inode->i_mode |= S_IFREG; |
211 | - inode->i_blocks = ((inode->i_size - | |
212 | - le64_to_cpu(sqsh_ino->sparse) - 1) >> 9) + 1; | |
211 | + inode->i_blocks = (inode->i_size - | |
212 | + le64_to_cpu(sqsh_ino->sparse) + 511) >> 9; | |
213 | 213 | |
214 | 214 | squashfs_i(inode)->fragment_block = frag_blk; |
215 | 215 | squashfs_i(inode)->fragment_size = frag_size; |
fs/squashfs/squashfs_fs_sb.h
fs/squashfs/super.c