[PATCH] cramfs mounts provide corrupted content since 2.6.15
Fix handling of cramfs images created by util-linux containing empty regular files. Images created by cramfstools 1.x were ok. Fill out inode contents in cramfs_iget5_set() instead of get_cramfs_inode() to prevent issues if cramfs_iget5_test() is called with I_LOCK|I_NEW still set. Signed-off-by: Dave Johnson <djohnson+linux-kernel@sw.starentnetworks.com> Cc: Olaf Hering <olh@suse.de> Cc: Chris Mason <mason@suse.com> Cc: Andreas Gruenbacher <agruen@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
9888e6fa7b
Коммит
ff3aea0e68
|
@ -36,7 +36,7 @@ static DECLARE_MUTEX(read_mutex);
|
|||
|
||||
/* These two macros may change in future, to provide better st_ino
|
||||
semantics. */
|
||||
#define CRAMINO(x) ((x)->offset?(x)->offset<<2:1)
|
||||
#define CRAMINO(x) (((x)->offset && (x)->size)?(x)->offset<<2:1)
|
||||
#define OFFSET(x) ((x)->i_ino)
|
||||
|
||||
|
||||
|
@ -66,8 +66,36 @@ static int cramfs_iget5_test(struct inode *inode, void *opaque)
|
|||
|
||||
static int cramfs_iget5_set(struct inode *inode, void *opaque)
|
||||
{
|
||||
static struct timespec zerotime;
|
||||
struct cramfs_inode *cramfs_inode = opaque;
|
||||
inode->i_mode = cramfs_inode->mode;
|
||||
inode->i_uid = cramfs_inode->uid;
|
||||
inode->i_size = cramfs_inode->size;
|
||||
inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1;
|
||||
inode->i_blksize = PAGE_CACHE_SIZE;
|
||||
inode->i_gid = cramfs_inode->gid;
|
||||
/* Struct copy intentional */
|
||||
inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime;
|
||||
inode->i_ino = CRAMINO(cramfs_inode);
|
||||
/* inode->i_nlink is left 1 - arguably wrong for directories,
|
||||
but it's the best we can do without reading the directory
|
||||
contents. 1 yields the right result in GNU find, even
|
||||
without -noleaf option. */
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
inode->i_fop = &generic_ro_fops;
|
||||
inode->i_data.a_ops = &cramfs_aops;
|
||||
} else if (S_ISDIR(inode->i_mode)) {
|
||||
inode->i_op = &cramfs_dir_inode_operations;
|
||||
inode->i_fop = &cramfs_directory_operations;
|
||||
} else if (S_ISLNK(inode->i_mode)) {
|
||||
inode->i_op = &page_symlink_inode_operations;
|
||||
inode->i_data.a_ops = &cramfs_aops;
|
||||
} else {
|
||||
inode->i_size = 0;
|
||||
inode->i_blocks = 0;
|
||||
init_special_inode(inode, inode->i_mode,
|
||||
old_decode_dev(cramfs_inode->size));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -77,37 +105,7 @@ static struct inode *get_cramfs_inode(struct super_block *sb,
|
|||
struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode),
|
||||
cramfs_iget5_test, cramfs_iget5_set,
|
||||
cramfs_inode);
|
||||
static struct timespec zerotime;
|
||||
|
||||
if (inode && (inode->i_state & I_NEW)) {
|
||||
inode->i_mode = cramfs_inode->mode;
|
||||
inode->i_uid = cramfs_inode->uid;
|
||||
inode->i_size = cramfs_inode->size;
|
||||
inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1;
|
||||
inode->i_blksize = PAGE_CACHE_SIZE;
|
||||
inode->i_gid = cramfs_inode->gid;
|
||||
/* Struct copy intentional */
|
||||
inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime;
|
||||
inode->i_ino = CRAMINO(cramfs_inode);
|
||||
/* inode->i_nlink is left 1 - arguably wrong for directories,
|
||||
but it's the best we can do without reading the directory
|
||||
contents. 1 yields the right result in GNU find, even
|
||||
without -noleaf option. */
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
inode->i_fop = &generic_ro_fops;
|
||||
inode->i_data.a_ops = &cramfs_aops;
|
||||
} else if (S_ISDIR(inode->i_mode)) {
|
||||
inode->i_op = &cramfs_dir_inode_operations;
|
||||
inode->i_fop = &cramfs_directory_operations;
|
||||
} else if (S_ISLNK(inode->i_mode)) {
|
||||
inode->i_op = &page_symlink_inode_operations;
|
||||
inode->i_data.a_ops = &cramfs_aops;
|
||||
} else {
|
||||
inode->i_size = 0;
|
||||
inode->i_blocks = 0;
|
||||
init_special_inode(inode, inode->i_mode,
|
||||
old_decode_dev(cramfs_inode->size));
|
||||
}
|
||||
unlock_new_inode(inode);
|
||||
}
|
||||
return inode;
|
||||
|
|
Загрузка…
Ссылка в новой задаче