aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-13 13:34:57 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-13 13:34:57 -0500
commit96e80a7851b44f3decaac0625665cd64e550b71d (patch)
treea24d9f46c43b5fcf824c49b93d37982ab668aade
parent57e6a7dde8cfca9ac1d6702cf9104d22bc11ba90 (diff)
parent3d4a1c80c4eb97187b3a61b3bfa8c804327f7a45 (diff)
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
-rw-r--r--Documentation/filesystems/squashfs.txt6
-rw-r--r--fs/squashfs/cache.c30
-rw-r--r--fs/squashfs/inode.c4
-rw-r--r--fs/squashfs/squashfs_fs_sb.h1
-rw-r--r--fs/squashfs/super.c2
5 files changed, 28 insertions, 15 deletions
diff --git a/Documentation/filesystems/squashfs.txt b/Documentation/filesystems/squashfs.txt
index 7db3ebda5a4c..403c090aca39 100644
--- a/Documentation/filesystems/squashfs.txt
+++ b/Documentation/filesystems/squashfs.txt
@@ -93,8 +93,8 @@ byte alignment:
93 93
94Compressed data blocks are written to the filesystem as files are read from 94Compressed data blocks are written to the filesystem as files are read from
95the source directory, and checked for duplicates. Once all file data has been 95the source directory, and checked for duplicates. Once all file data has been
96written the completed inode, directory, fragment, export and uid/gid lookup 96written the completed inode, directory, fragment, export, uid/gid lookup and
97tables are written. 97xattr tables are written.
98 98
993.1 Compression options 993.1 Compression options
100----------------------- 100-----------------------
@@ -151,7 +151,7 @@ in each metadata block. Directories are sorted in alphabetical order,
151and at lookup the index is scanned linearly looking for the first filename 151and at lookup the index is scanned linearly looking for the first filename
152alphabetically larger than the filename being looked up. At this point the 152alphabetically larger than the filename being looked up. At this point the
153location of the metadata block the filename is in has been found. 153location of the metadata block the filename is in has been found.
154The general idea of the index is ensure only one metadata block needs to be 154The general idea of the index is to ensure only one metadata block needs to be
155decompressed to do a lookup irrespective of the length of the directory. 155decompressed to do a lookup irrespective of the length of the directory.
156This scheme has the advantage that it doesn't require extra memory overhead 156This scheme has the advantage that it doesn't require extra memory overhead
157and doesn't require much extra storage on disk. 157and doesn't require much extra storage on disk.
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
371error:
372 squashfs_cache_put(entry);
373 return res;
362} 374}
363 375
364 376
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
index fd7b3b3bda13..81afbccfa843 100644
--- a/fs/squashfs/inode.c
+++ b/fs/squashfs/inode.c
@@ -208,8 +208,8 @@ int squashfs_read_inode(struct inode *inode, long long ino)
208 inode->i_op = &squashfs_inode_ops; 208 inode->i_op = &squashfs_inode_ops;
209 inode->i_fop = &generic_ro_fops; 209 inode->i_fop = &generic_ro_fops;
210 inode->i_mode |= S_IFREG; 210 inode->i_mode |= S_IFREG;
211 inode->i_blocks = ((inode->i_size - 211 inode->i_blocks = (inode->i_size -
212 le64_to_cpu(sqsh_ino->sparse) - 1) >> 9) + 1; 212 le64_to_cpu(sqsh_ino->sparse) + 511) >> 9;
213 213
214 squashfs_i(inode)->fragment_block = frag_blk; 214 squashfs_i(inode)->fragment_block = frag_blk;
215 squashfs_i(inode)->fragment_size = frag_size; 215 squashfs_i(inode)->fragment_size = frag_size;
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index 651f0b31d296..52934a22f296 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -28,6 +28,7 @@
28struct squashfs_cache { 28struct squashfs_cache {
29 char *name; 29 char *name;
30 int entries; 30 int entries;
31 int curr_blk;
31 int next_blk; 32 int next_blk;
32 int num_waiters; 33 int num_waiters;
33 int unused; 34 int unused;
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index d0858c2d9a47..ecaa2f7bdb8f 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -290,7 +290,7 @@ handle_fragments:
290 290
291check_directory_table: 291check_directory_table:
292 /* Sanity check directory_table */ 292 /* Sanity check directory_table */
293 if (msblk->directory_table >= next_table) { 293 if (msblk->directory_table > next_table) {
294 err = -EINVAL; 294 err = -EINVAL;
295 goto failed_mount; 295 goto failed_mount;
296 } 296 }