Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull filesystem fixes from Jan Kara: "udf, isofs, and ext3 bug fixes" * 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: ext3: Count internal journal as bsddf overhead in ext3_statfs isofs: Fix unbounded recursion when processing relocated directories udf: avoid unneeded up_write when fail to add entry in ->symlink
This commit is contained in:
commit
92075f9f64
5 changed files with 60 additions and 25 deletions
|
@ -2828,8 +2828,9 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
|
||||||
*/
|
*/
|
||||||
overhead += ngroups * (2 + sbi->s_itb_per_group);
|
overhead += ngroups * (2 + sbi->s_itb_per_group);
|
||||||
|
|
||||||
/* Add the journal blocks as well */
|
/* Add the internal journal blocks as well */
|
||||||
overhead += sbi->s_journal->j_maxlen;
|
if (sbi->s_journal && !sbi->journal_bdev)
|
||||||
|
overhead += sbi->s_journal->j_maxlen;
|
||||||
|
|
||||||
sbi->s_overhead_last = overhead;
|
sbi->s_overhead_last = overhead;
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
|
|
|
@ -61,7 +61,7 @@ static void isofs_put_super(struct super_block *sb)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int isofs_read_inode(struct inode *);
|
static int isofs_read_inode(struct inode *, int relocated);
|
||||||
static int isofs_statfs (struct dentry *, struct kstatfs *);
|
static int isofs_statfs (struct dentry *, struct kstatfs *);
|
||||||
|
|
||||||
static struct kmem_cache *isofs_inode_cachep;
|
static struct kmem_cache *isofs_inode_cachep;
|
||||||
|
@ -1259,7 +1259,7 @@ out_toomany:
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int isofs_read_inode(struct inode *inode)
|
static int isofs_read_inode(struct inode *inode, int relocated)
|
||||||
{
|
{
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
struct isofs_sb_info *sbi = ISOFS_SB(sb);
|
struct isofs_sb_info *sbi = ISOFS_SB(sb);
|
||||||
|
@ -1404,7 +1404,7 @@ static int isofs_read_inode(struct inode *inode)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!high_sierra) {
|
if (!high_sierra) {
|
||||||
parse_rock_ridge_inode(de, inode);
|
parse_rock_ridge_inode(de, inode, relocated);
|
||||||
/* if we want uid/gid set, override the rock ridge setting */
|
/* if we want uid/gid set, override the rock ridge setting */
|
||||||
if (sbi->s_uid_set)
|
if (sbi->s_uid_set)
|
||||||
inode->i_uid = sbi->s_uid;
|
inode->i_uid = sbi->s_uid;
|
||||||
|
@ -1483,9 +1483,10 @@ static int isofs_iget5_set(struct inode *ino, void *data)
|
||||||
* offset that point to the underlying meta-data for the inode. The
|
* offset that point to the underlying meta-data for the inode. The
|
||||||
* code below is otherwise similar to the iget() code in
|
* code below is otherwise similar to the iget() code in
|
||||||
* include/linux/fs.h */
|
* include/linux/fs.h */
|
||||||
struct inode *isofs_iget(struct super_block *sb,
|
struct inode *__isofs_iget(struct super_block *sb,
|
||||||
unsigned long block,
|
unsigned long block,
|
||||||
unsigned long offset)
|
unsigned long offset,
|
||||||
|
int relocated)
|
||||||
{
|
{
|
||||||
unsigned long hashval;
|
unsigned long hashval;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
|
@ -1507,7 +1508,7 @@ struct inode *isofs_iget(struct super_block *sb,
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
if (inode->i_state & I_NEW) {
|
if (inode->i_state & I_NEW) {
|
||||||
ret = isofs_read_inode(inode);
|
ret = isofs_read_inode(inode, relocated);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
iget_failed(inode);
|
iget_failed(inode);
|
||||||
inode = ERR_PTR(ret);
|
inode = ERR_PTR(ret);
|
||||||
|
|
|
@ -107,7 +107,7 @@ extern int iso_date(char *, int);
|
||||||
|
|
||||||
struct inode; /* To make gcc happy */
|
struct inode; /* To make gcc happy */
|
||||||
|
|
||||||
extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *);
|
extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *, int relocated);
|
||||||
extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *);
|
extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *);
|
||||||
extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *);
|
extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *);
|
||||||
|
|
||||||
|
@ -118,9 +118,24 @@ extern struct dentry *isofs_lookup(struct inode *, struct dentry *, unsigned int
|
||||||
extern struct buffer_head *isofs_bread(struct inode *, sector_t);
|
extern struct buffer_head *isofs_bread(struct inode *, sector_t);
|
||||||
extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long);
|
extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long);
|
||||||
|
|
||||||
extern struct inode *isofs_iget(struct super_block *sb,
|
struct inode *__isofs_iget(struct super_block *sb,
|
||||||
unsigned long block,
|
unsigned long block,
|
||||||
unsigned long offset);
|
unsigned long offset,
|
||||||
|
int relocated);
|
||||||
|
|
||||||
|
static inline struct inode *isofs_iget(struct super_block *sb,
|
||||||
|
unsigned long block,
|
||||||
|
unsigned long offset)
|
||||||
|
{
|
||||||
|
return __isofs_iget(sb, block, offset, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct inode *isofs_iget_reloc(struct super_block *sb,
|
||||||
|
unsigned long block,
|
||||||
|
unsigned long offset)
|
||||||
|
{
|
||||||
|
return __isofs_iget(sb, block, offset, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Because the inode number is no longer relevant to finding the
|
/* Because the inode number is no longer relevant to finding the
|
||||||
* underlying meta-data for an inode, we are free to choose a more
|
* underlying meta-data for an inode, we are free to choose a more
|
||||||
|
|
|
@ -288,12 +288,16 @@ eio:
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RR_REGARD_XA 1
|
||||||
|
#define RR_RELOC_DE 2
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parse_rock_ridge_inode_internal(struct iso_directory_record *de,
|
parse_rock_ridge_inode_internal(struct iso_directory_record *de,
|
||||||
struct inode *inode, int regard_xa)
|
struct inode *inode, int flags)
|
||||||
{
|
{
|
||||||
int symlink_len = 0;
|
int symlink_len = 0;
|
||||||
int cnt, sig;
|
int cnt, sig;
|
||||||
|
unsigned int reloc_block;
|
||||||
struct inode *reloc;
|
struct inode *reloc;
|
||||||
struct rock_ridge *rr;
|
struct rock_ridge *rr;
|
||||||
int rootflag;
|
int rootflag;
|
||||||
|
@ -305,7 +309,7 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de,
|
||||||
|
|
||||||
init_rock_state(&rs, inode);
|
init_rock_state(&rs, inode);
|
||||||
setup_rock_ridge(de, inode, &rs);
|
setup_rock_ridge(de, inode, &rs);
|
||||||
if (regard_xa) {
|
if (flags & RR_REGARD_XA) {
|
||||||
rs.chr += 14;
|
rs.chr += 14;
|
||||||
rs.len -= 14;
|
rs.len -= 14;
|
||||||
if (rs.len < 0)
|
if (rs.len < 0)
|
||||||
|
@ -485,12 +489,22 @@ repeat:
|
||||||
"relocated directory\n");
|
"relocated directory\n");
|
||||||
goto out;
|
goto out;
|
||||||
case SIG('C', 'L'):
|
case SIG('C', 'L'):
|
||||||
ISOFS_I(inode)->i_first_extent =
|
if (flags & RR_RELOC_DE) {
|
||||||
isonum_733(rr->u.CL.location);
|
printk(KERN_ERR
|
||||||
reloc =
|
"ISOFS: Recursive directory relocation "
|
||||||
isofs_iget(inode->i_sb,
|
"is not supported\n");
|
||||||
ISOFS_I(inode)->i_first_extent,
|
goto eio;
|
||||||
0);
|
}
|
||||||
|
reloc_block = isonum_733(rr->u.CL.location);
|
||||||
|
if (reloc_block == ISOFS_I(inode)->i_iget5_block &&
|
||||||
|
ISOFS_I(inode)->i_iget5_offset == 0) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"ISOFS: Directory relocation points to "
|
||||||
|
"itself\n");
|
||||||
|
goto eio;
|
||||||
|
}
|
||||||
|
ISOFS_I(inode)->i_first_extent = reloc_block;
|
||||||
|
reloc = isofs_iget_reloc(inode->i_sb, reloc_block, 0);
|
||||||
if (IS_ERR(reloc)) {
|
if (IS_ERR(reloc)) {
|
||||||
ret = PTR_ERR(reloc);
|
ret = PTR_ERR(reloc);
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -637,9 +651,11 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
|
||||||
return rpnt;
|
return rpnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode)
|
int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode,
|
||||||
|
int relocated)
|
||||||
{
|
{
|
||||||
int result = parse_rock_ridge_inode_internal(de, inode, 0);
|
int flags = relocated ? RR_RELOC_DE : 0;
|
||||||
|
int result = parse_rock_ridge_inode_internal(de, inode, flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if rockridge flag was reset and we didn't look for attributes
|
* if rockridge flag was reset and we didn't look for attributes
|
||||||
|
@ -647,7 +663,8 @@ int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode)
|
||||||
*/
|
*/
|
||||||
if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1)
|
if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1)
|
||||||
&& (ISOFS_SB(inode->i_sb)->s_rock == 2)) {
|
&& (ISOFS_SB(inode->i_sb)->s_rock == 2)) {
|
||||||
result = parse_rock_ridge_inode_internal(de, inode, 14);
|
result = parse_rock_ridge_inode_internal(de, inode,
|
||||||
|
flags | RR_REGARD_XA);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1014,7 +1014,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
||||||
|
|
||||||
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
|
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
|
||||||
if (!fi)
|
if (!fi)
|
||||||
goto out_no_entry;
|
goto out_fail;
|
||||||
cfi.icb.extLength = cpu_to_le32(sb->s_blocksize);
|
cfi.icb.extLength = cpu_to_le32(sb->s_blocksize);
|
||||||
cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
|
cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
|
||||||
if (UDF_SB(inode->i_sb)->s_lvid_bh) {
|
if (UDF_SB(inode->i_sb)->s_lvid_bh) {
|
||||||
|
@ -1036,6 +1036,7 @@ out:
|
||||||
|
|
||||||
out_no_entry:
|
out_no_entry:
|
||||||
up_write(&iinfo->i_data_sem);
|
up_write(&iinfo->i_data_sem);
|
||||||
|
out_fail:
|
||||||
inode_dec_link_count(inode);
|
inode_dec_link_count(inode);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
goto out;
|
goto out;
|
||||||
|
|
Loading…
Add table
Reference in a new issue