Parcourir la source

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
Linus Torvalds il y a 13 ans
Parent
commit
96e80a7851

+ 3 - 3
Documentation/filesystems/squashfs.txt

@@ -93,8 +93,8 @@ byte alignment:
 
 
 Compressed data blocks are written to the filesystem as files are read from
 Compressed data blocks are written to the filesystem as files are read from
 the source directory, and checked for duplicates.  Once all file data has been
 the source directory, and checked for duplicates.  Once all file data has been
-written the completed inode, directory, fragment, export and uid/gid lookup
-tables are written.
+written the completed inode, directory, fragment, export, uid/gid lookup and
+xattr tables are written.
 
 
 3.1 Compression options
 3.1 Compression options
 -----------------------
 -----------------------
@@ -151,7 +151,7 @@ in each metadata block.  Directories are sorted in alphabetical order,
 and at lookup the index is scanned linearly looking for the first filename
 and at lookup the index is scanned linearly looking for the first filename
 alphabetically larger than the filename being looked up.  At this point the
 alphabetically larger than the filename being looked up.  At this point the
 location of the metadata block the filename is in has been found.
 location of the metadata block the filename is in has been found.
-The general idea of the index is ensure only one metadata block needs to be
+The general idea of the index is to ensure only one metadata block needs to be
 decompressed to do a lookup irrespective of the length of the directory.
 decompressed to do a lookup irrespective of the length of the directory.
 This scheme has the advantage that it doesn't require extra memory overhead
 This scheme has the advantage that it doesn't require extra memory overhead
 and doesn't require much extra storage on disk.
 and doesn't require much extra storage on disk.

+ 21 - 9
fs/squashfs/cache.c

@@ -70,11 +70,15 @@ struct squashfs_cache_entry *squashfs_cache_get(struct super_block *sb,
 	spin_lock(&cache->lock);
 	spin_lock(&cache->lock);
 
 
 	while (1) {
 	while (1) {
-		for (i = 0; i < cache->entries; i++)
-			if (cache->entry[i].block == block)
+		for (i = cache->curr_blk, n = 0; n < cache->entries; n++) {
+			if (cache->entry[i].block == block) {
+				cache->curr_blk = i;
 				break;
 				break;
+			}
+			i = (i + 1) % cache->entries;
+		}
 
 
-		if (i == cache->entries) {
+		if (n == cache->entries) {
 			/*
 			/*
 			 * Block not in cache, if all cache entries are used
 			 * Block not in cache, if all cache entries are used
 			 * go to sleep waiting for one to become available.
 			 * go to sleep waiting for one to become available.
@@ -245,6 +249,7 @@ struct squashfs_cache *squashfs_cache_init(char *name, int entries,
 		goto cleanup;
 		goto cleanup;
 	}
 	}
 
 
+	cache->curr_blk = 0;
 	cache->next_blk = 0;
 	cache->next_blk = 0;
 	cache->unused = entries;
 	cache->unused = entries;
 	cache->entries = entries;
 	cache->entries = entries;
@@ -332,17 +337,20 @@ int squashfs_read_metadata(struct super_block *sb, void *buffer,
 		u64 *block, int *offset, int length)
 		u64 *block, int *offset, int length)
 {
 {
 	struct squashfs_sb_info *msblk = sb->s_fs_info;
 	struct squashfs_sb_info *msblk = sb->s_fs_info;
-	int bytes, copied = length;
+	int bytes, res = length;
 	struct squashfs_cache_entry *entry;
 	struct squashfs_cache_entry *entry;
 
 
 	TRACE("Entered squashfs_read_metadata [%llx:%x]\n", *block, *offset);
 	TRACE("Entered squashfs_read_metadata [%llx:%x]\n", *block, *offset);
 
 
 	while (length) {
 	while (length) {
 		entry = squashfs_cache_get(sb, msblk->block_cache, *block, 0);
 		entry = squashfs_cache_get(sb, msblk->block_cache, *block, 0);
-		if (entry->error)
-			return entry->error;
-		else if (*offset >= entry->length)
-			return -EIO;
+		if (entry->error) {
+			res = entry->error;
+			goto error;
+		} else if (*offset >= entry->length) {
+			res = -EIO;
+			goto error;
+		}
 
 
 		bytes = squashfs_copy_data(buffer, entry, *offset, length);
 		bytes = squashfs_copy_data(buffer, entry, *offset, length);
 		if (buffer)
 		if (buffer)
@@ -358,7 +366,11 @@ int squashfs_read_metadata(struct super_block *sb, void *buffer,
 		squashfs_cache_put(entry);
 		squashfs_cache_put(entry);
 	}
 	}
 
 
-	return copied;
+	return res;
+
+error:
+	squashfs_cache_put(entry);
+	return res;
 }
 }
 
 
 
 

+ 2 - 2
fs/squashfs/inode.c

@@ -208,8 +208,8 @@ int squashfs_read_inode(struct inode *inode, long long ino)
 		inode->i_op = &squashfs_inode_ops;
 		inode->i_op = &squashfs_inode_ops;
 		inode->i_fop = &generic_ro_fops;
 		inode->i_fop = &generic_ro_fops;
 		inode->i_mode |= S_IFREG;
 		inode->i_mode |= S_IFREG;
-		inode->i_blocks = ((inode->i_size -
-				le64_to_cpu(sqsh_ino->sparse) - 1) >> 9) + 1;
+		inode->i_blocks = (inode->i_size -
+				le64_to_cpu(sqsh_ino->sparse) + 511) >> 9;
 
 
 		squashfs_i(inode)->fragment_block = frag_blk;
 		squashfs_i(inode)->fragment_block = frag_blk;
 		squashfs_i(inode)->fragment_size = frag_size;
 		squashfs_i(inode)->fragment_size = frag_size;

+ 1 - 0
fs/squashfs/squashfs_fs_sb.h

@@ -28,6 +28,7 @@
 struct squashfs_cache {
 struct squashfs_cache {
 	char			*name;
 	char			*name;
 	int			entries;
 	int			entries;
+	int			curr_blk;
 	int			next_blk;
 	int			next_blk;
 	int			num_waiters;
 	int			num_waiters;
 	int			unused;
 	int			unused;

+ 1 - 1
fs/squashfs/super.c

@@ -290,7 +290,7 @@ handle_fragments:
 
 
 check_directory_table:
 check_directory_table:
 	/* Sanity check directory_table */
 	/* Sanity check directory_table */
-	if (msblk->directory_table >= next_table) {
+	if (msblk->directory_table > next_table) {
 		err = -EINVAL;
 		err = -EINVAL;
 		goto failed_mount;
 		goto failed_mount;
 	}
 	}