X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fisofs%2Finode.c;h=ea55b6c469ecdc8f0cb97a050f5b1d9ad0d04038;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=491dcde30a0e4b488f142306cfe7b3571bd50c3a;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 491dcde30..ea55b6c46 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -11,39 +11,22 @@ * 2004 Paul Serice - NFS Export Operations */ -#include +#include #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include #include #include -#include -#include -#include +#include +#include #include -#include -#include +#include "isofs.h" #include "zisofs.h" #define BEQUIET -#ifdef LEAK_CHECK -static int check_malloc; -static int check_bread; -#endif - static int isofs_hashi(struct dentry *parent, struct qstr *qstr); static int isofs_hash(struct dentry *parent, struct qstr *qstr); static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b); @@ -66,25 +49,20 @@ static void isofs_put_super(struct super_block *sb) } #endif -#ifdef LEAK_CHECK - printk("Outstanding mallocs:%d, outstanding buffers: %d\n", - check_malloc, check_bread); -#endif - kfree(sbi); sb->s_fs_info = NULL; return; } static void isofs_read_inode(struct inode *); -static int isofs_statfs (struct super_block *, struct kstatfs *); +static int isofs_statfs (struct dentry *, struct kstatfs *); -static kmem_cache_t *isofs_inode_cachep; +static struct kmem_cache *isofs_inode_cachep; static struct inode *isofs_alloc_inode(struct super_block *sb) { struct iso_inode_info *ei; - ei = (struct iso_inode_info *)kmem_cache_alloc(isofs_inode_cachep, SLAB_KERNEL); + ei = kmem_cache_alloc(isofs_inode_cachep, GFP_KERNEL); if (!ei) return NULL; return &ei->vfs_inode; @@ -95,9 +73,9 @@ static void isofs_destroy_inode(struct inode *inode) kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode)); } -static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags) { - struct iso_inode_info *ei = (struct iso_inode_info *) foo; + struct iso_inode_info *ei = foo; if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) @@ -108,7 +86,8 @@ static int init_inodecache(void) { isofs_inode_cachep = kmem_cache_create("isofs_inode_cache", sizeof(struct iso_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, (SLAB_RECLAIM_ACCOUNT| + SLAB_MEM_SPREAD), init_once, NULL); if (isofs_inode_cachep == NULL) return -ENOMEM; @@ -117,8 +96,7 @@ static int init_inodecache(void) static void destroy_inodecache(void) { - if (kmem_cache_destroy(isofs_inode_cachep)) - printk(KERN_INFO "iso_inode_cache: not all structures were freed\n"); + kmem_cache_destroy(isofs_inode_cachep); } static int isofs_remount(struct super_block *sb, int *flags, char *data) @@ -155,7 +133,7 @@ static struct dentry_operations isofs_dentry_ops[] = { { .d_hash = isofs_hashi_ms, .d_compare = isofs_dentry_cmpi_ms, - } + }, #endif }; @@ -164,7 +142,8 @@ struct iso9660_options{ char rock; char joliet; char cruft; - char unhide; + char hide; + char showassoc; char nocompress; unsigned char check; unsigned int blocksize; @@ -230,8 +209,8 @@ isofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms) /* * Case insensitive compare of two isofs names. */ -static int -isofs_dentry_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms) +static int isofs_dentry_cmpi_common(struct dentry *dentry, struct qstr *a, + struct qstr *b, int ms) { int alen, blen; @@ -254,8 +233,8 @@ isofs_dentry_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int /* * Case sensitive compare of two isofs names. */ -static int -isofs_dentry_cmp_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms) +static int isofs_dentry_cmp_common(struct dentry *dentry, struct qstr *a, + struct qstr *b, int ms) { int alen, blen; @@ -329,13 +308,15 @@ enum { Opt_block, Opt_check_r, Opt_check_s, Opt_cruft, Opt_gid, Opt_ignore, Opt_iocharset, Opt_map_a, Opt_map_n, Opt_map_o, Opt_mode, Opt_nojoliet, Opt_norock, Opt_sb, Opt_session, Opt_uid, Opt_unhide, Opt_utf8, Opt_err, - Opt_nocompress, + Opt_nocompress, Opt_hide, Opt_showassoc, }; static match_table_t tokens = { {Opt_norock, "norock"}, {Opt_nojoliet, "nojoliet"}, {Opt_unhide, "unhide"}, + {Opt_hide, "hide"}, + {Opt_showassoc, "showassoc"}, {Opt_cruft, "cruft"}, {Opt_utf8, "utf8"}, {Opt_iocharset, "iocharset=%s"}, @@ -367,7 +348,7 @@ static match_table_t tokens = { {Opt_err, NULL} }; -static int parse_options(char *options, struct iso9660_options * popt) +static int parse_options(char *options, struct iso9660_options *popt) { char *p; int option; @@ -376,7 +357,8 @@ static int parse_options(char *options, struct iso9660_options * popt) popt->rock = 'y'; popt->joliet = 'y'; popt->cruft = 'n'; - popt->unhide = 'n'; + popt->hide = 'n'; + popt->showassoc = 'n'; popt->check = 'u'; /* unset */ popt->nocompress = 0; popt->blocksize = 1024; @@ -409,8 +391,12 @@ static int parse_options(char *options, struct iso9660_options * popt) case Opt_nojoliet: popt->joliet = 'n'; break; + case Opt_hide: + popt->hide = 'y'; + break; case Opt_unhide: - popt->unhide = 'y'; + case Opt_showassoc: + popt->showassoc = 'y'; break; case Opt_cruft: popt->cruft = 'y'; @@ -504,7 +490,7 @@ static int parse_options(char *options, struct iso9660_options * popt) */ #define WE_OBEY_THE_WRITTEN_STANDARDS 1 -static unsigned int isofs_get_last_session(struct super_block *sb,s32 session ) +static unsigned int isofs_get_last_session(struct super_block *sb, s32 session) { struct cdrom_multisession ms_info; unsigned int vol_desc_start; @@ -529,7 +515,8 @@ static unsigned int isofs_get_last_session(struct super_block *sb,s32 session ) printk(KERN_ERR "Invalid session number or type of track\n"); } i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info); - if(session > 0) printk(KERN_ERR "Invalid session number\n"); + if (session > 0) + printk(KERN_ERR "Invalid session number\n"); #if 0 printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i); if (i==0) { @@ -568,13 +555,12 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) struct iso9660_options opt; struct isofs_sb_info * sbi; - sbi = kmalloc(sizeof(struct isofs_sb_info), GFP_KERNEL); + sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) return -ENOMEM; s->s_fs_info = sbi; - memset(sbi, 0, sizeof(struct isofs_sb_info)); - if (!parse_options((char *) data, &opt)) + if (!parse_options((char *)data, &opt)) goto out_freesbi; /* @@ -685,6 +671,8 @@ root_found: sbi->s_log_zone_size = isonum_723 (h_pri->logical_block_size); sbi->s_max_size = isonum_733(h_pri->volume_space_size); } else { + if (!pri) + goto out_freebh; rootp = (struct iso_directory_record *) pri->root_directory_record; sbi->s_nzones = isonum_733 (pri->volume_space_size); sbi->s_log_zone_size = isonum_723 (pri->logical_block_size); @@ -715,6 +703,7 @@ root_found: } s->s_magic = ISOFS_SUPER_MAGIC; + s->s_maxbytes = 0xffffffff; /* We can handle files up to 4 GB */ /* The CDROM is read-only, has no nodes (devices) on it, and since all of the files appear to be owned by root, we really do not want @@ -800,7 +789,8 @@ root_found: sbi->s_rock = (opt.rock == 'y' ? 2 : 0); sbi->s_rock_offset = -1; /* initial offset, will guess until SP is found*/ sbi->s_cruft = opt.cruft; - sbi->s_unhide = opt.unhide; + sbi->s_hide = opt.hide; + sbi->s_showassoc = opt.showassoc; sbi->s_uid = opt.uid; sbi->s_gid = opt.gid; sbi->s_utf8 = opt.utf8; @@ -862,8 +852,7 @@ root_found: if (opt.check == 'r') table++; s->s_root->d_op = &isofs_dentry_ops[table]; - if (opt.iocharset) - kfree(opt.iocharset); + kfree(opt.iocharset); return 0; @@ -902,15 +891,16 @@ out_unknown_format: out_freebh: brelse(bh); out_freesbi: - if (opt.iocharset) - kfree(opt.iocharset); + kfree(opt.iocharset); kfree(sbi); s->s_fs_info = NULL; return -EINVAL; } -static int isofs_statfs (struct super_block *sb, struct kstatfs *buf) +static int isofs_statfs (struct dentry *dentry, struct kstatfs *buf) { + struct super_block *sb = dentry->d_sb; + buf->f_type = ISOFS_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_blocks = (ISOFS_SB(sb)->s_nzones @@ -970,30 +960,30 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s, goto abort; } - if (nextblk) { - while (b_off >= (offset + sect_size)) { - struct inode *ninode; - - offset += sect_size; - if (nextblk == 0) - goto abort; - ninode = isofs_iget(inode->i_sb, nextblk, nextoff); - if (!ninode) - goto abort; - firstext = ISOFS_I(ninode)->i_first_extent; - sect_size = ISOFS_I(ninode)->i_section_size >> ISOFS_BUFFER_BITS(ninode); - nextblk = ISOFS_I(ninode)->i_next_section_block; - nextoff = ISOFS_I(ninode)->i_next_section_offset; - iput(ninode); - - if (++section > 100) { - printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n"); - printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u " - "nextblk=%lu nextoff=%lu\n", - iblock, firstext, (unsigned) sect_size, - nextblk, nextoff); - goto abort; - } + /* On the last section, nextblk == 0, section size is likely to + * exceed sect_size by a partial block, and access beyond the + * end of the file will reach beyond the section size, too. + */ + while (nextblk && (b_off >= (offset + sect_size))) { + struct inode *ninode; + + offset += sect_size; + ninode = isofs_iget(inode->i_sb, nextblk, nextoff); + if (!ninode) + goto abort; + firstext = ISOFS_I(ninode)->i_first_extent; + sect_size = ISOFS_I(ninode)->i_section_size >> ISOFS_BUFFER_BITS(ninode); + nextblk = ISOFS_I(ninode)->i_next_section_block; + nextoff = ISOFS_I(ninode)->i_next_section_offset; + iput(ninode); + + if (++section > 100) { + printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n"); + printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u " + "nextblk=%lu nextoff=%lu\n", + iblock, firstext, (unsigned) sect_size, + nextblk, nextoff); + goto abort; } } @@ -1010,7 +1000,6 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s, rv++; } - abort: unlock_kernel(); return rv; @@ -1022,7 +1011,7 @@ abort: static int isofs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) { - if ( create ) { + if (create) { printk("isofs_get_block: Kernel tries to allocate a block\n"); return -EROFS; } @@ -1061,7 +1050,7 @@ static sector_t _isofs_bmap(struct address_space *mapping, sector_t block) return generic_block_bmap(mapping,block,isofs_get_block); } -static struct address_space_operations isofs_aops = { +static const struct address_space_operations isofs_aops = { .readpage = isofs_readpage, .sync_page = block_sync_page, .bmap = _isofs_bmap @@ -1069,19 +1058,17 @@ static struct address_space_operations isofs_aops = { static inline void test_and_set_uid(uid_t *p, uid_t value) { - if(value) { + if (value) *p = value; - } } static inline void test_and_set_gid(gid_t *p, gid_t value) { - if(value) { + if (value) *p = value; - } } -static int isofs_read_level3_size(struct inode * inode) +static int isofs_read_level3_size(struct inode *inode) { unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra; @@ -1144,7 +1131,7 @@ static int isofs_read_level3_size(struct inode * inode) bh = sb_bread(inode->i_sb, block); if (!bh) goto out_noread; - memcpy((void *) tmpde + slop, bh->b_data, offset); + memcpy((void *)tmpde+slop, bh->b_data, offset); } de = tmpde; } @@ -1158,12 +1145,11 @@ static int isofs_read_level3_size(struct inode * inode) more_entries = de->flags[-high_sierra] & 0x80; i++; - if(i > 100) + if (i > 100) goto out_toomany; - } while(more_entries); + } while (more_entries); out: - if (tmpde) - kfree(tmpde); + kfree(tmpde); if (bh) brelse(bh); return 0; @@ -1175,8 +1161,7 @@ out_nomem: out_noread: printk(KERN_INFO "ISOFS: unable to read i-node block %lu\n", block); - if (tmpde) - kfree(tmpde); + kfree(tmpde); return -EIO; out_toomany: @@ -1187,7 +1172,7 @@ out_toomany: goto out; } -static void isofs_read_inode(struct inode * inode) +static void isofs_read_inode(struct inode *inode) { struct super_block *sb = inode->i_sb; struct isofs_sb_info *sbi = ISOFS_SB(sb); @@ -1250,14 +1235,14 @@ static void isofs_read_inode(struct inode * inode) } inode->i_uid = sbi->s_uid; inode->i_gid = sbi->s_gid; - inode->i_blocks = inode->i_blksize = 0; + inode->i_blocks = 0; ei->i_format_parm[0] = 0; ei->i_format_parm[1] = 0; ei->i_format_parm[2] = 0; ei->i_section_size = isonum_733 (de->size); - if(de->flags[-high_sierra] & 0x80) { + if (de->flags[-high_sierra] & 0x80) { if(isofs_read_level3_size(inode)) goto fail; } else { ei->i_next_section_block = 0; @@ -1306,7 +1291,6 @@ static void isofs_read_inode(struct inode * inode) isonum_711 (de->ext_attr_length)); /* Set the number of blocks for stat() - should be done before RR */ - inode->i_blksize = PAGE_CACHE_SIZE; /* For stat() only */ inode->i_blocks = (inode->i_size + 511) >> 9; /* @@ -1344,16 +1328,15 @@ static void isofs_read_inode(struct inode * inode) /* XXX - parse_rock_ridge_inode() had already set i_rdev. */ init_special_inode(inode, inode->i_mode, inode->i_rdev); - out: - if (tmpde) - kfree(tmpde); +out: + kfree(tmpde); if (bh) brelse(bh); return; - out_badread: +out_badread: printk(KERN_WARNING "ISOFS: unable to read i-node block\n"); - fail: +fail: make_bad_inode(inode); goto out; } @@ -1394,16 +1377,16 @@ struct inode *isofs_iget(struct super_block *sb, struct inode *inode; struct isofs_iget5_callback_data data; + if (offset >= 1ul << sb->s_blocksize_bits) + return NULL; + data.block = block; data.offset = offset; hashval = (block << sb->s_blocksize_bits) | offset; - inode = iget5_locked(sb, - hashval, - &isofs_iget5_test, - &isofs_iget5_set, - &data); + inode = iget5_locked(sb, hashval, &isofs_iget5_test, + &isofs_iget5_set, &data); if (inode && (inode->i_state & I_NEW)) { sb->s_op->read_inode(inode); @@ -1413,40 +1396,11 @@ struct inode *isofs_iget(struct super_block *sb, return inode; } -#ifdef LEAK_CHECK -#undef malloc -#undef free_s -#undef sb_bread -#undef brelse - -void * leak_check_malloc(unsigned int size){ - void * tmp; - check_malloc++; - tmp = kmalloc(size, GFP_KERNEL); - return tmp; -} - -void leak_check_free_s(void * obj, int size){ - check_malloc--; - return kfree(obj); -} - -struct buffer_head * leak_check_bread(struct super_block *sb, int block){ - check_bread++; - return sb_bread(sb, block); -} - -void leak_check_brelse(struct buffer_head * bh){ - check_bread--; - return brelse(bh); -} - -#endif - -static struct super_block *isofs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data) +static int isofs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { - return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super); + return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super, + mnt); } static struct file_system_type iso9660_fs_type = {