summaryrefslogtreecommitdiffstats
path: root/fs/minix
diff options
context:
space:
mode:
Diffstat (limited to 'fs/minix')
-rw-r--r--fs/minix/.cvsignore1
-rw-r--r--fs/minix/bitmap.c30
-rw-r--r--fs/minix/inode.c182
-rw-r--r--fs/minix/namei.c33
-rw-r--r--fs/minix/symlink.c12
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;