summaryrefslogtreecommitdiffstats
path: root/fs/minix
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-08-25 09:12:35 +0000
commitc7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch)
tree3682407a599b8f9f03fc096298134cafba1c9b2f /fs/minix
parent1d793fade8b063fde3cf275bf1a5c2d381292cd9 (diff)
o Merge with Linux 2.1.116.
o New Newport console code. o New G364 console code.
Diffstat (limited to 'fs/minix')
-rw-r--r--fs/minix/Makefile6
-rw-r--r--fs/minix/bitmap.c44
-rw-r--r--fs/minix/file.c2
-rw-r--r--fs/minix/inode.c44
-rw-r--r--fs/minix/namei.c76
-rw-r--r--fs/minix/truncate.c2
6 files changed, 99 insertions, 75 deletions
diff --git a/fs/minix/Makefile b/fs/minix/Makefile
index 60bb07d97..537127b2d 100644
--- a/fs/minix/Makefile
+++ b/fs/minix/Makefile
@@ -1,11 +1,11 @@
#
-# Makefile for the linux minix-filesystem routines.
+# Makefile for the Linux minix filesystem routines.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
+# unless it's something special (not a .c file).
#
-# Note 2! The CFLAGS definitions are now in the main makefile...
+# Note 2! The CFLAGS definitions are now in the main makefile.
O_TARGET := minix.o
O_OBJS := bitmap.o truncate.o namei.o inode.o file.o dir.o symlink.o fsync.o
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index 3d6f0a426..49dde4e44 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -36,16 +36,17 @@ static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, _
if (numblocks==0 || !(bh=map[numblocks-1]))
return(0);
- i = (numbits-(numblocks-1)*BLOCK_SIZE*8)/8;
+ i = ((numbits-(numblocks-1)*BLOCK_SIZE*8)/16)*2;
for (j=0; j<i; j++) {
sum += nibblemap[bh->b_data[j] & 0xf]
+ nibblemap[(bh->b_data[j]>>4) & 0xf];
}
- i = numbits%8;
+ i = numbits%16;
if (i!=0) {
- i = bh->b_data[j] | ~((1<<i) - 1);
+ i = *(__u16 *)(&bh->b_data[j]) | ~((1<<i) - 1);
sum += nibblemap[i & 0xf] + nibblemap[(i>>4) & 0xf];
+ sum += nibblemap[(i>>8) & 0xf] + nibblemap[(i>>12) & 0xf];
}
return(sum);
}
@@ -71,11 +72,11 @@ void minix_free_block(struct super_block * sb, int block)
zone = block - sb->u.minix_sb.s_firstdatazone + 1;
bit = zone & 8191;
zone >>= 13;
- bh = sb->u.minix_sb.s_zmap[zone];
- if (!bh) {
+ if (zone >= sb->u.minix_sb.s_zmap_blocks) {
printk("minix_free_block: nonexistent bitmap buffer\n");
return;
}
+ bh = sb->u.minix_sb.s_zmap[zone];
if (!minix_clear_bit(bit,bh->b_data))
printk("free_block (%s:%d): bit already cleared\n",
kdevname(sb->s_dev), block);
@@ -94,11 +95,13 @@ int minix_new_block(struct super_block * sb)
}
repeat:
j = 8192;
- for (i=0 ; i<64 ; i++)
- if ((bh=sb->u.minix_sb.s_zmap[i]) != NULL)
- if ((j=minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
- break;
- if (i>=64 || !bh || j>=8192)
+ bh = NULL;
+ for (i = 0; i < sb->u.minix_sb.s_zmap_blocks; i++) {
+ bh = sb->u.minix_sb.s_zmap[i];
+ if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
+ break;
+ }
+ if (!bh || j >= 8192)
return 0;
if (minix_set_bit(j,bh->b_data)) {
printk("new_block: bit already set");
@@ -134,7 +137,7 @@ static struct buffer_head *V1_minix_clear_inode(struct inode *inode)
int ino, block;
ino = inode->i_ino;
- if (!ino || ino >= inode->i_sb->u.minix_sb.s_ninodes) {
+ if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) {
printk("Bad inode number on dev %s: %d is out of range\n",
kdevname(inode->i_dev), ino);
return 0;
@@ -162,7 +165,7 @@ static struct buffer_head *V2_minix_clear_inode(struct inode *inode)
int ino, block;
ino = inode->i_ino;
- if (!ino || ino >= inode->i_sb->u.minix_sb.s_ninodes) {
+ if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) {
printk("Bad inode number on dev %s: %d is out of range\n",
kdevname(inode->i_dev), ino);
return 0;
@@ -218,15 +221,16 @@ void minix_free_inode(struct inode * inode)
printk("free_inode: inode on nonexistent device\n");
return;
}
- if (inode->i_ino < 1 || inode->i_ino >= inode->i_sb->u.minix_sb.s_ninodes) {
+ if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->u.minix_sb.s_ninodes) {
printk("free_inode: inode 0 or nonexistent inode\n");
return;
}
ino = inode->i_ino;
- if (!(bh=inode->i_sb->u.minix_sb.s_imap[ino >> 13])) {
+ if ((ino >> 13) >= inode->i_sb->u.minix_sb.s_imap_blocks) {
printk("free_inode: nonexistent imap in superblock\n");
return;
}
+ bh = inode->i_sb->u.minix_sb.s_imap[ino >> 13];
minix_clear_inode(inode);
clear_inode(inode);
if (!minix_clear_bit(ino & 8191, bh->b_data))
@@ -247,10 +251,12 @@ struct inode * minix_new_inode(const struct inode * dir)
inode->i_sb = sb;
inode->i_flags = inode->i_sb->s_flags;
j = 8192;
- for (i=0 ; i<8 ; i++)
- if ((bh = inode->i_sb->u.minix_sb.s_imap[i]) != NULL)
- if ((j=minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
- break;
+ bh = NULL;
+ for (i = 0; i < sb->u.minix_sb.s_imap_blocks; i++) {
+ bh = inode->i_sb->u.minix_sb.s_imap[i];
+ if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
+ break;
+ }
if (!bh || j >= 8192) {
iput(inode);
return NULL;
@@ -262,7 +268,7 @@ struct inode * minix_new_inode(const struct inode * dir)
}
mark_buffer_dirty(bh, 1);
j += i*8192;
- if (!j || j >= inode->i_sb->u.minix_sb.s_ninodes) {
+ if (!j || j > inode->i_sb->u.minix_sb.s_ninodes) {
iput(inode);
return NULL;
}
diff --git a/fs/minix/file.c b/fs/minix/file.c
index 5aaef83b2..a44a635b0 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -30,7 +30,7 @@
static ssize_t minix_file_write(struct file *, const char *, size_t, loff_t *);
/*
- * We have mostly NULL's here: the current defaults are ok for
+ * We have mostly NULLs here: the current defaults are OK for
* the minix filesystem.
*/
static struct file_operations minix_file_operations = {
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 8934dc012..46ae5c11c 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -63,9 +63,9 @@ 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);
}
- for(i = 0 ; i < MINIX_I_MAP_SLOTS ; i++)
+ for (i = 0; i < sb->u.minix_sb.s_imap_blocks; i++)
brelse(sb->u.minix_sb.s_imap[i]);
- for(i = 0 ; i < MINIX_Z_MAP_SLOTS ; i++)
+ for (i = 0; i < sb->u.minix_sb.s_zmap_blocks; i++)
brelse(sb->u.minix_sb.s_zmap[i]);
brelse (sb->u.minix_sb.s_sbh);
kfree(sb->u.minix_sb.s_imap);
@@ -122,7 +122,7 @@ int minix_remount (struct super_block * sb, int * flags, char * data)
/*
* Check the root directory of the filesystem to make sure
- * it really _is_ a minix filesystem, and to check the size
+ * it really _is_ a Minix filesystem, and to check the size
* of the directory entry.
*/
static const char * minix_checkroot(struct super_block *s, struct inode *dir)
@@ -173,7 +173,8 @@ struct super_block *minix_read_super(struct super_block *s, void *data,
const char * errmsg;
struct inode *root_inode;
- /* N.B. These should be compile-time tests */
+ /* N.B. These should be compile-time tests.
+ Unfortunately that is impossible. */
if (32 != sizeof (struct minix_inode))
panic("bad V1 i-node size");
if (64 != sizeof(struct minix2_inode))
@@ -203,33 +204,37 @@ struct super_block *minix_read_super(struct super_block *s, void *data,
s->u.minix_sb.s_version = MINIX_V1;
s->u.minix_sb.s_dirsize = 16;
s->u.minix_sb.s_namelen = 14;
+ s->u.minix_sb.s_link_max = MINIX_LINK_MAX;
} else if (s->s_magic == MINIX_SUPER_MAGIC2) {
s->u.minix_sb.s_version = MINIX_V1;
s->u.minix_sb.s_dirsize = 32;
s->u.minix_sb.s_namelen = 30;
+ s->u.minix_sb.s_link_max = MINIX_LINK_MAX;
} 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;
+ s->u.minix_sb.s_link_max = MINIX2_LINK_MAX;
} 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;
+ s->u.minix_sb.s_link_max = MINIX2_LINK_MAX;
} 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);
+ i = (s->u.minix_sb.s_imap_blocks + s->u.minix_sb.s_zmap_blocks) * 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];
+ s->u.minix_sb.s_zmap = &map[s->u.minix_sb.s_imap_blocks];
block=2;
for (i=0 ; i < s->u.minix_sb.s_imap_blocks ; i++) {
@@ -242,8 +247,6 @@ struct super_block *minix_read_super(struct super_block *s, void *data,
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);
@@ -263,6 +266,8 @@ struct super_block *minix_read_super(struct super_block *s, void *data,
if (!s->s_root)
goto out_iput;
+ s->s_root->d_op = &minix_dentry_operations;
+
if (!(s->s_flags & MS_RDONLY)) {
ms->s_state &= ~MINIX_VALID_FS;
mark_buffer_dirty(bh, 1);
@@ -292,9 +297,9 @@ out_no_root:
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++)
+ for (i = 0; i < s->u.minix_sb.s_imap_blocks; i++)
brelse(s->u.minix_sb.s_imap[i]);
- for(i=0;i<MINIX_Z_MAP_SLOTS;i++)
+ for (i = 0; i < s->u.minix_sb.s_zmap_blocks; i++)
brelse(s->u.minix_sb.s_zmap[i]);
kfree(s->u.minix_sb.s_imap);
goto out_release;
@@ -304,14 +309,9 @@ out_no_map:
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 "
+ printk("VFS: Can't find a Minix or Minix V2 filesystem on device "
"%s.\n", kdevname(dev));
out_release:
brelse(bh);
@@ -729,7 +729,7 @@ static void V1_minix_read_inode(struct inode * inode)
ino = inode->i_ino;
inode->i_op = NULL;
inode->i_mode = 0;
- if (!ino || ino >= inode->i_sb->u.minix_sb.s_ninodes) {
+ if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) {
printk("Bad inode number on dev %s"
": %d is out of range\n",
kdevname(inode->i_dev), ino);
@@ -783,7 +783,7 @@ static void V2_minix_read_inode(struct inode * inode)
ino = inode->i_ino;
inode->i_op = NULL;
inode->i_mode = 0;
- if (!ino || ino >= inode->i_sb->u.minix_sb.s_ninodes) {
+ if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) {
printk("Bad inode number on dev %s"
": %d is out of range\n",
kdevname(inode->i_dev), ino);
@@ -848,7 +848,7 @@ static struct buffer_head * V1_minix_update_inode(struct inode * inode)
int ino, block;
ino = inode->i_ino;
- if (!ino || ino >= inode->i_sb->u.minix_sb.s_ninodes) {
+ if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) {
printk("Bad inode number on dev %s"
": %d is out of range\n",
kdevname(inode->i_dev), ino);
@@ -886,7 +886,7 @@ static struct buffer_head * V2_minix_update_inode(struct inode * inode)
int ino, block;
ino = inode->i_ino;
- if (!ino || ino >= inode->i_sb->u.minix_sb.s_ninodes) {
+ if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) {
printk("Bad inode number on dev %s"
": %d is out of range\n",
kdevname(inode->i_dev), ino);
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index 3155e72e4..17ff53aed 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -23,34 +23,12 @@
static inline int namecompare(int len, int maxlen,
const char * name, const char * buffer)
{
- if (len > maxlen)
- return 0;
if (len < maxlen && buffer[len])
return 0;
return !memcmp(name, buffer, len);
}
/*
- * ok, we cannot use strncmp, as the name is not in our data space.
- * Thus we'll have to use minix_match. No big problem. Match also makes
- * some sanity tests.
- *
- * NOTE! unlike strncmp, minix_match returns 1 for success, 0 for failure.
- */
-static int minix_match(int len, const char * name,
- struct buffer_head * bh, unsigned long * offset,
- struct minix_sb_info * info)
-{
- struct minix_dir_entry * de;
-
- de = (struct minix_dir_entry *) (bh->b_data + *offset);
- *offset += info->s_dirsize;
- if (!de->inode || len > info->s_namelen)
- return 0;
- return namecompare(len,info->s_namelen,name,de->name);
-}
-
-/*
* minix_find_entry()
*
* finds an entry in the specified directory with the wanted name. It
@@ -64,6 +42,7 @@ static struct buffer_head * minix_find_entry(struct inode * dir,
unsigned long block, offset;
struct buffer_head * bh;
struct minix_sb_info * info;
+ struct minix_dir_entry *de;
*res_dir = NULL;
if (!dir || !dir->i_sb)
@@ -86,9 +65,12 @@ static struct buffer_head * minix_find_entry(struct inode * dir,
continue;
}
}
- *res_dir = (struct minix_dir_entry *) (bh->b_data + offset);
- if (minix_match(namelen,name,bh,&offset,info))
+ de = (struct minix_dir_entry *) (bh->b_data + offset);
+ offset += info->s_dirsize;
+ if (de->inode && namecompare(namelen,info->s_namelen,name,de->name)) {
+ *res_dir = de;
return bh;
+ }
if (offset < bh->b_size)
continue;
brelse(bh);
@@ -97,16 +79,52 @@ static struct buffer_head * minix_find_entry(struct inode * dir,
block++;
}
brelse(bh);
- *res_dir = NULL;
return NULL;
}
+#ifndef NO_TRUNCATE
+
+static int minix_hash(struct dentry *dentry, struct qstr *qstr)
+{
+ unsigned long hash;
+ int i;
+ const char *name;
+
+ i = dentry->d_inode->i_sb->u.minix_sb.s_namelen;
+ if (i >= qstr->len)
+ return 0;
+ /* Truncate the name in place, avoids having to define a compare
+ function. */
+ qstr->len = i;
+ name = qstr->name;
+ hash = init_name_hash();
+ while (i--)
+ hash = partial_name_hash(*name++, hash);
+ qstr->hash = end_name_hash(hash);
+ return 0;
+}
+
+#endif
+
+struct dentry_operations minix_dentry_operations = {
+ 0, /* revalidate */
+#ifndef NO_TRUNCATE
+ minix_hash,
+#else
+ 0,
+#endif
+ 0 /* compare */
+};
+
int minix_lookup(struct inode * dir, struct dentry *dentry)
{
struct inode * inode = NULL;
struct minix_dir_entry * de;
struct buffer_head * bh;
+#ifndef NO_TRUNCATE
+ dentry->d_op = &minix_dentry_operations;
+#endif
bh = minix_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
if (bh) {
int ino = de->inode;
@@ -296,7 +314,7 @@ int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
brelse(bh);
return -EEXIST;
}
- if (dir->i_nlink >= MINIX_LINK_MAX)
+ if (dir->i_nlink >= info->s_link_max)
return -EMLINK;
inode = minix_new_inode(dir);
if (!inode)
@@ -434,7 +452,7 @@ int minix_rmdir(struct inode * dir, struct dentry *dentry)
retval = -ENOENT;
goto end_rmdir;
}
- if (inode->i_count > 1) {
+ if (dentry->d_count > 1) {
retval = -EBUSY;
goto end_rmdir;
}
@@ -573,7 +591,7 @@ int minix_link(struct dentry * old_dentry, struct inode * dir,
if (S_ISDIR(inode->i_mode))
return -EPERM;
- if (inode->i_nlink >= MINIX_LINK_MAX)
+ if (inode->i_nlink >= inode->i_sb->u.minix_sb.s_link_max)
return -EMLINK;
bh = minix_find_entry(dir, dentry->d_name.name,
@@ -689,7 +707,7 @@ start_up:
if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
goto end_rename;
retval = -EMLINK;
- if (!new_inode && new_dir->i_nlink >= MINIX_LINK_MAX)
+ if (!new_inode && new_dir->i_nlink >= info->s_link_max)
goto end_rename;
}
if (!new_bh) {
diff --git a/fs/minix/truncate.c b/fs/minix/truncate.c
index 56b490841..0f0afa604 100644
--- a/fs/minix/truncate.c
+++ b/fs/minix/truncate.c
@@ -21,7 +21,7 @@
/*
* Truncate has the most races in the whole filesystem: coding it is
- * a pain in the a**. Especially as I don't do any locking...
+ * a pain in the a**, especially as I don't do any locking.
*
* The code may look a bit weird, but that's just because I've tried to
* handle things like file-size changes in a somewhat graceful manner.