diff options
Diffstat (limited to 'fs/minix')
-rw-r--r-- | fs/minix/.cvsignore | 1 | ||||
-rw-r--r-- | fs/minix/bitmap.c | 30 | ||||
-rw-r--r-- | fs/minix/inode.c | 182 | ||||
-rw-r--r-- | fs/minix/namei.c | 33 | ||||
-rw-r--r-- | fs/minix/symlink.c | 12 |
5 files changed, 141 insertions, 117 deletions
diff --git a/fs/minix/.cvsignore b/fs/minix/.cvsignore index 4671378ae..857dd22e9 100644 --- a/fs/minix/.cvsignore +++ b/fs/minix/.cvsignore @@ -1 +1,2 @@ .depend +.*.flags diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index 69b8e4e4c..3d6f0a426 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c @@ -21,17 +21,31 @@ static int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 }; -static unsigned long count_free(struct buffer_head *map[], unsigned numblocks) +static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, __u32 numbits) { unsigned i, j, sum = 0; struct buffer_head *bh; - for (i=0; i<numblocks; i++) { + for (i=0; i<numblocks-1; i++) { if (!(bh=map[i])) return(0); for (j=0; j<BLOCK_SIZE; j++) - sum += nibblemap[bh->b_data[j] & 0xf] - + nibblemap[(bh->b_data[j]>>4)&0xf]; + sum += nibblemap[bh->b_data[j] & 0xf] + + nibblemap[(bh->b_data[j]>>4) & 0xf]; + } + + if (numblocks==0 || !(bh=map[numblocks-1])) + return(0); + i = (numbits-(numblocks-1)*BLOCK_SIZE*8)/8; + for (j=0; j<i; j++) { + sum += nibblemap[bh->b_data[j] & 0xf] + + nibblemap[(bh->b_data[j]>>4) & 0xf]; + } + + i = numbits%8; + if (i!=0) { + i = bh->b_data[j] | ~((1<<i) - 1); + sum += nibblemap[i & 0xf] + nibblemap[(i>>4) & 0xf]; } return(sum); } @@ -108,8 +122,9 @@ repeat: unsigned long minix_count_free_blocks(struct super_block *sb) { - return (count_free(sb->u.minix_sb.s_zmap,sb->u.minix_sb.s_zmap_blocks) - << sb->u.minix_sb.s_log_zone_size); + return (count_free(sb->u.minix_sb.s_zmap, sb->u.minix_sb.s_zmap_blocks, + sb->u.minix_sb.s_nzones - sb->u.minix_sb.s_firstdatazone + 1) + << sb->u.minix_sb.s_log_zone_size); } static struct buffer_head *V1_minix_clear_inode(struct inode *inode) @@ -266,5 +281,6 @@ struct inode * minix_new_inode(const struct inode * dir) unsigned long minix_count_free_inodes(struct super_block *sb) { - return count_free(sb->u.minix_sb.s_imap,sb->u.minix_sb.s_imap_blocks); + return count_free(sb->u.minix_sb.s_imap, sb->u.minix_sb.s_imap_blocks, + sb->u.minix_sb.s_ninodes + 1); } diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 898f56f19..05bf6706d 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -12,9 +12,9 @@ #include <linux/module.h> #include <linux/sched.h> -#include <linux/minix_fs.h> #include <linux/kernel.h> #include <linux/mm.h> +#include <linux/malloc.h> #include <linux/string.h> #include <linux/stat.h> #include <linux/locks.h> @@ -24,6 +24,8 @@ #include <asm/uaccess.h> #include <asm/bitops.h> +#include <linux/minix_fs.h> + static void minix_delete_inode(struct inode *inode) { inode->i_size = 0; @@ -62,12 +64,13 @@ void minix_put_super(struct super_block *sb) sb->u.minix_sb.s_ms->s_state = sb->u.minix_sb.s_mount_state; mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1); } - sb->s_dev = 0; for(i = 0 ; i < MINIX_I_MAP_SLOTS ; i++) brelse(sb->u.minix_sb.s_imap[i]); for(i = 0 ; i < MINIX_Z_MAP_SLOTS ; i++) brelse(sb->u.minix_sb.s_zmap[i]); brelse (sb->u.minix_sb.s_sbh); + kfree(sb->u.minix_sb.s_imap); + sb->s_dev = 0; unlock_super(sb); MOD_DEC_USE_COUNT; return; @@ -161,30 +164,29 @@ static const char * minix_checkroot(struct super_block *s, struct inode *dir) return errmsg; } -struct super_block *minix_read_super(struct super_block *s,void *data, +struct super_block *minix_read_super(struct super_block *s, void *data, int silent) { struct buffer_head *bh; + struct buffer_head **map; struct minix_super_block *ms; int i, block; kdev_t dev = s->s_dev; const char * errmsg; struct inode *root_inode; + /* N.B. These should be compile-time tests */ if (32 != sizeof (struct minix_inode)) panic("bad V1 i-node size"); if (64 != sizeof(struct minix2_inode)) panic("bad V2 i-node size"); + MOD_INC_USE_COUNT; lock_super(s); set_blocksize(dev, BLOCK_SIZE); - if (!(bh = bread(dev,1,BLOCK_SIZE))) { - s->s_dev = 0; - unlock_super(s); - printk("MINIX-fs: unable to read superblock\n"); - MOD_DEC_USE_COUNT; - return NULL; - } + if (!(bh = bread(dev,1,BLOCK_SIZE))) + goto out_bad_sb; + ms = (struct minix_super_block *) bh->b_data; s->u.minix_sb.s_ms = ms; s->u.minix_sb.s_sbh = bh; @@ -192,6 +194,7 @@ struct super_block *minix_read_super(struct super_block *s,void *data, s->s_blocksize = 1024; s->s_blocksize_bits = 10; s->u.minix_sb.s_ninodes = ms->s_ninodes; + s->u.minix_sb.s_nzones = ms->s_nzones; s->u.minix_sb.s_imap_blocks = ms->s_imap_blocks; s->u.minix_sb.s_zmap_blocks = ms->s_zmap_blocks; s->u.minix_sb.s_firstdatazone = ms->s_firstdatazone; @@ -200,103 +203,74 @@ struct super_block *minix_read_super(struct super_block *s,void *data, s->s_magic = ms->s_magic; if (s->s_magic == MINIX_SUPER_MAGIC) { s->u.minix_sb.s_version = MINIX_V1; - s->u.minix_sb.s_nzones = ms->s_nzones; s->u.minix_sb.s_dirsize = 16; s->u.minix_sb.s_namelen = 14; } else if (s->s_magic == MINIX_SUPER_MAGIC2) { s->u.minix_sb.s_version = MINIX_V1; - s->u.minix_sb.s_nzones = ms->s_nzones; s->u.minix_sb.s_dirsize = 32; s->u.minix_sb.s_namelen = 30; } else if (s->s_magic == MINIX2_SUPER_MAGIC) { s->u.minix_sb.s_version = MINIX_V2; - s->u.minix_sb.s_nzones = ms->s_zones; s->u.minix_sb.s_dirsize = 16; s->u.minix_sb.s_namelen = 14; } else if (s->s_magic == MINIX2_SUPER_MAGIC2) { s->u.minix_sb.s_version = MINIX_V2; - s->u.minix_sb.s_nzones = ms->s_zones; s->u.minix_sb.s_dirsize = 32; s->u.minix_sb.s_namelen = 30; - } else { - s->s_dev = 0; - unlock_super(s); - brelse(bh); - if (!silent) - printk("VFS: Can't find a minix or minix V2 filesystem on dev " - "%s.\n", kdevname(dev)); - MOD_DEC_USE_COUNT; - return NULL; - } - for (i=0;i < MINIX_I_MAP_SLOTS;i++) - s->u.minix_sb.s_imap[i] = NULL; - for (i=0;i < MINIX_Z_MAP_SLOTS;i++) - s->u.minix_sb.s_zmap[i] = NULL; - if (s->u.minix_sb.s_zmap_blocks > MINIX_Z_MAP_SLOTS) { - s->s_dev = 0; - unlock_super (s); - brelse (bh); - if (!silent) - printk ("MINIX-fs: filesystem too big\n"); - MOD_DEC_USE_COUNT; - return NULL; - } + } else + goto out_no_fs; + + if (s->u.minix_sb.s_zmap_blocks > MINIX_Z_MAP_SLOTS) + goto out_too_big; + /* + * Allocate the buffer map to keep the superblock small. + */ + i = (MINIX_I_MAP_SLOTS + MINIX_Z_MAP_SLOTS) * sizeof(bh); + map = kmalloc(i, GFP_KERNEL); + if (!map) + goto out_no_map; + memset(map, 0, i); + s->u.minix_sb.s_imap = &map[0]; + s->u.minix_sb.s_zmap = &map[MINIX_I_MAP_SLOTS]; + block=2; - for (i=0 ; i < s->u.minix_sb.s_imap_blocks ; i++) - if ((s->u.minix_sb.s_imap[i]=bread(dev,block,BLOCK_SIZE)) != NULL) - block++; - else - break; - for (i=0 ; i < s->u.minix_sb.s_zmap_blocks ; i++) - if ((s->u.minix_sb.s_zmap[i]=bread(dev,block,BLOCK_SIZE)) != NULL) - block++; - else - break; - if (block != 2+s->u.minix_sb.s_imap_blocks+s->u.minix_sb.s_zmap_blocks) { - for(i=0;i<MINIX_I_MAP_SLOTS;i++) - brelse(s->u.minix_sb.s_imap[i]); - for(i=0;i<MINIX_Z_MAP_SLOTS;i++) - brelse(s->u.minix_sb.s_zmap[i]); - s->s_dev = 0; - unlock_super(s); - brelse(bh); - printk("MINIX-fs: bad superblock or unable to read bitmaps\n"); - MOD_DEC_USE_COUNT; - return NULL; + for (i=0 ; i < s->u.minix_sb.s_imap_blocks ; i++) { + if (!(s->u.minix_sb.s_imap[i]=bread(dev,block,BLOCK_SIZE))) + goto out_no_bitmap; + block++; + } + for (i=0 ; i < s->u.minix_sb.s_zmap_blocks ; i++) { + if (!(s->u.minix_sb.s_zmap[i]=bread(dev,block,BLOCK_SIZE))) + goto out_no_bitmap; + block++; } + if (block != 2+s->u.minix_sb.s_imap_blocks+s->u.minix_sb.s_zmap_blocks) + goto out_no_bitmap; + minix_set_bit(0,s->u.minix_sb.s_imap[0]->b_data); minix_set_bit(0,s->u.minix_sb.s_zmap[0]->b_data); - unlock_super(s); /* set up enough so that it can read an inode */ - s->s_dev = dev; s->s_op = &minix_sops; - root_inode = iget(s,MINIX_ROOT_INO); - s->s_root = d_alloc_root(root_inode, NULL); - if (!s->s_root) { - s->s_dev = 0; - brelse(bh); - if (!silent) - printk("MINIX-fs: get root inode failed\n"); - MOD_DEC_USE_COUNT; - return NULL; - } - + root_inode = iget(s, MINIX_ROOT_INO); + if (!root_inode) + goto out_no_root; + /* + * Check the fs before we get the root dentry ... + */ errmsg = minix_checkroot(s, root_inode); - if (errmsg) { - if (!silent) - printk("MINIX-fs: %s\n", errmsg); - d_delete(s->s_root); /* XXX Is this enough? */ - s->s_dev = 0; - brelse (bh); - MOD_DEC_USE_COUNT; - return NULL; - } + if (errmsg) + goto out_bad_root; + + s->s_root = d_alloc_root(root_inode, NULL); + if (!s->s_root) + goto out_iput; if (!(s->s_flags & MS_RDONLY)) { ms->s_state &= ~MINIX_VALID_FS; mark_buffer_dirty(bh, 1); s->s_dirt = 1; } + unlock_super(s); if (!(s->u.minix_sb.s_mount_state & MINIX_VALID_FS)) printk ("MINIX-fs: mounting unchecked file system, " "running fsck is recommended.\n"); @@ -304,6 +278,54 @@ struct super_block *minix_read_super(struct super_block *s,void *data, printk ("MINIX-fs: mounting file system with errors, " "running fsck is recommended.\n"); return s; + +out_bad_root: + if (!silent) + printk("MINIX-fs: %s\n", errmsg); +out_iput: + iput(root_inode); + goto out_freemap; + +out_no_root: + if (!silent) + printk("MINIX-fs: get root inode failed\n"); + goto out_freemap; + +out_no_bitmap: + printk("MINIX-fs: bad superblock or unable to read bitmaps\n"); + out_freemap: + for(i=0;i<MINIX_I_MAP_SLOTS;i++) + brelse(s->u.minix_sb.s_imap[i]); + for(i=0;i<MINIX_Z_MAP_SLOTS;i++) + brelse(s->u.minix_sb.s_zmap[i]); + kfree(s->u.minix_sb.s_imap); + goto out_release; + +out_no_map: + if (!silent) + printk ("MINIX-fs: can't allocate map\n"); + goto out_release; + +out_too_big: + if (!silent) + printk ("MINIX-fs: filesystem too big\n"); + goto out_release; + +out_no_fs: + if (!silent) + printk("VFS: Can't find a minix or minix V2 filesystem on dev " + "%s.\n", kdevname(dev)); + out_release: + brelse(bh); + goto out_unlock; + +out_bad_sb: + printk("MINIX-fs: unable to read superblock\n"); + out_unlock: + s->s_dev = 0; + unlock_super(s); + MOD_DEC_USE_COUNT; + return NULL; } int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) diff --git a/fs/minix/namei.c b/fs/minix/namei.c index dbd9e9ce4..e6bf93e4b 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -414,9 +414,9 @@ int minix_rmdir(struct inode * dir, struct dentry *dentry) retval = -EPERM; inode = dentry->d_inode; - if ((dir->i_mode & S_ISVTX) && !fsuser() && + if ((dir->i_mode & S_ISVTX) && current->fsuid != inode->i_uid && - current->fsuid != dir->i_uid) + current->fsuid != dir->i_uid && !fsuser()) goto end_rmdir; if (inode->i_dev != dir->i_dev) goto end_rmdir; @@ -480,9 +480,9 @@ repeat: schedule(); goto repeat; } - if ((dir->i_mode & S_ISVTX) && !fsuser() && + if ((dir->i_mode & S_ISVTX) && current->fsuid != inode->i_uid && - current->fsuid != dir->i_uid) + current->fsuid != dir->i_uid && !fsuser()) goto end_unlink; if (de->inode != inode->i_ino) { retval = -ENOENT; @@ -562,10 +562,11 @@ int minix_symlink(struct inode * dir, struct dentry *dentry, return 0; } -int minix_link(struct inode * inode, struct inode * dir, +int minix_link(struct dentry * old_dentry, struct inode * dir, struct dentry *dentry) { int error; + struct inode *inode = old_dentry->d_inode; struct minix_dir_entry * de; struct buffer_head * bh; @@ -598,24 +599,6 @@ int minix_link(struct inode * inode, struct inode * dir, return 0; } -static int subdir(struct dentry * new_dentry, struct dentry * old_dentry) -{ - int result = 0; - - for (;;) { - if (new_dentry != old_dentry) { - struct dentry * parent = new_dentry->d_parent; - if (parent == new_dentry) - break; - new_dentry = parent; - continue; - } - result = 1; - break; - } - return result; -} - #define PARENT_INO(buffer) \ (((struct minix_dir_entry *) ((buffer)+info->s_dirsize))->inode) @@ -678,7 +661,7 @@ start_up: if (!S_ISDIR(old_inode->i_mode)) goto end_rename; retval = -EINVAL; - if (subdir(new_dentry, old_dentry)) + if (is_subdir(new_dentry, old_dentry)) goto end_rename; retval = -ENOTEMPTY; if (!empty_dir(new_inode)) @@ -697,7 +680,7 @@ start_up: if (new_inode && !S_ISDIR(new_inode->i_mode)) goto end_rename; retval = -EINVAL; - if (subdir(new_dentry, old_dentry)) + if (is_subdir(new_dentry, old_dentry)) goto end_rename; retval = -EIO; dir_bh = minix_bread(old_inode,0,0); diff --git a/fs/minix/symlink.c b/fs/minix/symlink.c index 9f759ecc9..cdc237235 100644 --- a/fs/minix/symlink.c +++ b/fs/minix/symlink.c @@ -14,8 +14,8 @@ #include <asm/uaccess.h> -static int minix_readlink(struct inode *, char *, int); -static struct dentry *minix_follow_link(struct inode *, struct dentry *); +static int minix_readlink(struct dentry *, char *, int); +static struct dentry *minix_follow_link(struct dentry *, struct dentry *); /* * symlinks can't do much... @@ -40,8 +40,10 @@ struct inode_operations minix_symlink_inode_operations = { NULL /* permission */ }; -static struct dentry * minix_follow_link(struct inode * inode, struct dentry * base) +static struct dentry * minix_follow_link(struct dentry * dentry, + struct dentry * base) { + struct inode *inode = dentry->d_inode; struct buffer_head * bh; bh = minix_bread(inode, 0, 0); @@ -55,7 +57,7 @@ static struct dentry * minix_follow_link(struct inode * inode, struct dentry * b return base; } -static int minix_readlink(struct inode * inode, char * buffer, int buflen) +static int minix_readlink(struct dentry * dentry, char * buffer, int buflen) { struct buffer_head * bh; int i; @@ -63,7 +65,7 @@ static int minix_readlink(struct inode * inode, char * buffer, int buflen) if (buflen > 1023) buflen = 1023; - bh = minix_bread(inode, 0, 0); + bh = minix_bread(dentry->d_inode, 0, 0); if (!bh) return 0; i = 0; |