patch-1.3.54 linux/fs/minix/inode.c

Next file: linux/fs/minix/truncate.c
Previous file: linux/fs/minix/fsync.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.53/linux/fs/minix/inode.c linux/fs/minix/inode.c
@@ -2,6 +2,9 @@
  *  linux/fs/minix/inode.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Copyright (C) 1996  Gertjan van Wingerde    (gertjan@cs.vu.nl)
+ *	Minix V2 fs support.
  */
 
 #include <linux/module.h>
@@ -114,7 +117,6 @@
 	return 0;
 }
 
-
 struct super_block *minix_read_super(struct super_block *s,void *data, 
 				     int silent)
 {
@@ -124,7 +126,9 @@
 	kdev_t dev = s->s_dev;
 
 	if (32 != sizeof (struct minix_inode))
-		panic("bad i-node size");
+		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);
@@ -142,7 +146,6 @@
 	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;
@@ -150,9 +153,23 @@
 	s->u.minix_sb.s_max_size = ms->s_max_size;
 	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 {
@@ -160,7 +177,7 @@
 		unlock_super(s);
 		brelse(bh);
 		if (!silent)
-			printk("VFS: Can't find a minix filesystem on dev "
+			printk("VFS: Can't find a minix or minix V2 filesystem on dev "
 			       "%s.\n", kdevname(dev));
 		MOD_DEC_USE_COUNT;
 		return NULL;
@@ -224,8 +241,8 @@
 {
 	struct statfs tmp;
 
-	tmp.f_type = MINIX_SUPER_MAGIC;
-	tmp.f_bsize = 1024;
+	tmp.f_type = sb->s_magic;
+	tmp.f_bsize = sb->s_blocksize;
 	tmp.f_blocks = (sb->u.minix_sb.s_nzones - sb->u.minix_sb.s_firstdatazone) << sb->u.minix_sb.s_log_zone_size;
 	tmp.f_bfree = minix_count_free_blocks(sb);
 	tmp.f_bavail = tmp.f_bfree;
@@ -235,9 +252,12 @@
 	memcpy_tofs(buf, &tmp, bufsiz);
 }
 
-#define inode_bmap(inode,nr) ((inode)->u.minix_i.i_data[(nr)])
+/*
+ * The minix V1 fs bmap functions.
+ */
+#define V1_inode_bmap(inode,nr) (((unsigned short *)(inode)->u.minix_i.u.i1_data)[(nr)])
 
-static int block_bmap(struct buffer_head * bh, int nr)
+static int V1_block_bmap(struct buffer_head * bh, int nr)
 {
 	int tmp;
 
@@ -248,7 +268,7 @@
 	return tmp;
 }
 
-int minix_bmap(struct inode * inode,int block)
+static int V1_minix_bmap(struct inode * inode,int block)
 {
 	int i;
 
@@ -256,36 +276,110 @@
 		printk("minix_bmap: block<0");
 		return 0;
 	}
-	if (block >= 7+512+512*512) {
+	if (block >= (inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)) {
 		printk("minix_bmap: block>big");
 		return 0;
 	}
 	if (block < 7)
-		return inode_bmap(inode,block);
+		return V1_inode_bmap(inode,block);
 	block -= 7;
 	if (block < 512) {
-		i = inode_bmap(inode,7);
+		i = V1_inode_bmap(inode,7);
 		if (!i)
 			return 0;
-		return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block);
+		return V1_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block);
 	}
 	block -= 512;
-	i = inode_bmap(inode,8);
+	i = V1_inode_bmap(inode,8);
+	if (!i)
+		return 0;
+	i = V1_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>9);
+	if (!i)
+		return 0;
+	return V1_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 511);
+}
+
+/*
+ * The minix V2 fs bmap functions.
+ */
+#define V2_inode_bmap(inode,nr) (((unsigned long  *)(inode)->u.minix_i.u.i2_data)[(nr)])
+static int V2_block_bmap(struct buffer_head * bh, int nr)
+{
+	int tmp;
+
+	if (!bh)
+		return 0;
+	tmp = ((unsigned long *) bh->b_data)[nr];
+	brelse(bh);
+	return tmp;
+}
+
+int V2_minix_bmap(struct inode * inode,int block)
+{
+	int i;
+
+	if (block<0) {
+		printk("minix_bmap: block<0");
+		return 0;
+	}
+	if (block >= (inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE)) {
+		printk("minix_bmap: block>big");
+		return 0;
+	}
+	if (block < 7)
+		return V2_inode_bmap(inode,block);
+	block -= 7;
+	if (block < 256) {
+		i = V2_inode_bmap(inode,7);
+		if (!i)
+			return 0;
+		return V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block);
+	}
+	block -= 256;
+	if (block < 256*256) {
+		i = V2_inode_bmap(inode,8);
+		if (!i)
+			return 0;
+		i = V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block >> 8);
+		if (!i)
+			return 0;
+		return V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
+	}
+	block -= 256*256;
+	i = V2_inode_bmap(inode,9);
+	if (!i)
+		return 0;
+	i = V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block >> 16);
 	if (!i)
 		return 0;
-	i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>9);
+	i = V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),(block >> 8) & 255);
 	if (!i)
 		return 0;
-	return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 511);
+	return V2_block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
 }
 
-static struct buffer_head * inode_getblk(struct inode * inode, int nr, int create)
+/*
+ * The global minix fs bmap function.
+ */
+int minix_bmap(struct inode * inode,int block)
+{
+	if (INODE_VERSION(inode) == MINIX_V1)
+		return V1_minix_bmap(inode, block);
+	else
+		return V2_minix_bmap(inode, block);
+}
+
+/*
+ * The minix V1 fs getblk functions.
+ */
+static struct buffer_head * V1_inode_getblk(struct inode * inode, int nr, 
+					    int create)
 {
 	int tmp;
 	unsigned short *p;
 	struct buffer_head * result;
 
-	p = inode->u.minix_i.i_data + nr;
+	p = inode->u.minix_i.u.i1_data + nr;
 repeat:
 	tmp = *p;
 	if (tmp) {
@@ -312,7 +406,7 @@
 	return result;
 }
 
-static struct buffer_head * block_getblk(struct inode * inode, 
+static struct buffer_head * V1_block_getblk(struct inode * inode, 
 	struct buffer_head * bh, int nr, int create)
 {
 	int tmp;
@@ -362,7 +456,8 @@
 	return result;
 }
 
-struct buffer_head * minix_getblk(struct inode * inode, int block, int create)
+static struct buffer_head * V1_minix_getblk(struct inode * inode, int block, 
+					    int create)
 {
 	struct buffer_head * bh;
 
@@ -370,21 +465,152 @@
 		printk("minix_getblk: block<0");
 		return NULL;
 	}
-	if (block >= 7+512+512*512) {
+	if (block >= inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE) {
 		printk("minix_getblk: block>big");
 		return NULL;
 	}
 	if (block < 7)
-		return inode_getblk(inode,block,create);
+		return V1_inode_getblk(inode,block,create);
 	block -= 7;
 	if (block < 512) {
-		bh = inode_getblk(inode,7,create);
-		return block_getblk(inode, bh, block, create);
+		bh = V1_inode_getblk(inode,7,create);
+		return V1_block_getblk(inode, bh, block, create);
 	}
 	block -= 512;
-	bh = inode_getblk(inode,8,create);
-	bh = block_getblk(inode, bh, block>>9, create);
-	return block_getblk(inode, bh, block & 511, create);
+	bh = V1_inode_getblk(inode,8,create);
+	bh = V1_block_getblk(inode, bh, (block>>9) & 511, create);
+	return V1_block_getblk(inode, bh, block & 511, create);
+}
+
+/*
+ * The minix V2 fs getblk functions.
+ */
+static struct buffer_head * V2_inode_getblk(struct inode * inode, int nr, 
+					    int create)
+{
+	int tmp;
+	unsigned long *p;
+	struct buffer_head * result;
+
+	p = (unsigned long *) inode->u.minix_i.u.i2_data + nr;
+repeat:
+	tmp = *p;
+	if (tmp) {
+		result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
+		if (tmp == *p)
+			return result;
+		brelse(result);
+		goto repeat;
+	}
+	if (!create)
+		return NULL;
+	tmp = minix_new_block(inode->i_sb);
+	if (!tmp)
+		return NULL;
+	result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
+	if (*p) {
+		minix_free_block(inode->i_sb,tmp);
+		brelse(result);
+		goto repeat;
+	}
+	*p = tmp;
+	inode->i_ctime = CURRENT_TIME;
+	inode->i_dirt = 1;
+	return result;
+}
+
+static struct buffer_head * V2_block_getblk(struct inode * inode, 
+	struct buffer_head * bh, int nr, int create)
+{
+	int tmp;
+	unsigned long *p;
+	struct buffer_head * result;
+
+	if (!bh)
+		return NULL;
+	if (!buffer_uptodate(bh)) {
+		ll_rw_block(READ, 1, &bh);
+		wait_on_buffer(bh);
+		if (!buffer_uptodate(bh)) {
+			brelse(bh);
+			return NULL;
+		}
+	}
+	p = nr + (unsigned long *) bh->b_data;
+repeat:
+	tmp = *p;
+	if (tmp) {
+		result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
+		if (tmp == *p) {
+			brelse(bh);
+			return result;
+		}
+		brelse(result);
+		goto repeat;
+	}
+	if (!create) {
+		brelse(bh);
+		return NULL;
+	}
+	tmp = minix_new_block(inode->i_sb);
+	if (!tmp) {
+		brelse(bh);
+		return NULL;
+	}
+	result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
+	if (*p) {
+		minix_free_block(inode->i_sb,tmp);
+		brelse(result);
+		goto repeat;
+	}
+	*p = tmp;
+	mark_buffer_dirty(bh, 1);
+	brelse(bh);
+	return result;
+}
+
+static struct buffer_head * V2_minix_getblk(struct inode * inode, int block, 
+					    int create)
+{
+	struct buffer_head * bh;
+
+	if (block<0) {
+		printk("minix_getblk: block<0");
+		return NULL;
+	}
+	if (block >= inode->i_sb->u.minix_sb.s_max_size/BLOCK_SIZE) {
+		printk("minix_getblk: block>big");
+		return NULL;
+	}
+	if (block < 7)
+		return V2_inode_getblk(inode,block,create);
+	block -= 7;
+	if (block < 256) {
+		bh = V2_inode_getblk(inode,7,create);
+		return V2_block_getblk(inode, bh, block, create);
+	}
+	block -= 256;
+	if (block < 256*256) {
+		bh = V2_inode_getblk(inode,8,create);
+		bh = V2_block_getblk(inode, bh, (block>>8) & 255, create);
+		return V2_block_getblk(inode, bh, block & 255, create);
+	}
+	block -= 256*256;
+	bh = V2_inode_getblk(inode,9,create);
+	bh = V2_block_getblk(inode, bh, (block >> 16) & 255, create);
+	bh = V2_block_getblk(inode, bh, (block >> 8) & 255, create);
+	return V2_block_getblk(inode, bh, block & 255, create);
+}
+
+/*
+ * the global minix fs getblk function.
+ */
+struct buffer_head * minix_getblk(struct inode * inode, int block, int create)
+{
+	if (INODE_VERSION(inode) == MINIX_V1)
+		return V1_minix_getblk(inode,block,create);
+	else
+		return V2_minix_getblk(inode,block,create);
 }
 
 struct buffer_head * minix_bread(struct inode * inode, int block, int create)
@@ -402,7 +628,10 @@
 	return NULL;
 }
 
-void minix_read_inode(struct inode * inode)
+/*
+ * The minix V1 function to read an inode.
+ */
+static void V1_minix_read_inode(struct inode * inode)
 {
 	struct buffer_head * bh;
 	struct minix_inode * raw_inode;
@@ -437,7 +666,63 @@
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 		inode->i_rdev = to_kdev_t(raw_inode->i_zone[0]);
 	else for (block = 0; block < 9; block++)
-		inode->u.minix_i.i_data[block] = raw_inode->i_zone[block];
+		inode->u.minix_i.u.i1_data[block] = raw_inode->i_zone[block];
+	brelse(bh);
+	if (S_ISREG(inode->i_mode))
+		inode->i_op = &minix_file_inode_operations;
+	else if (S_ISDIR(inode->i_mode))
+		inode->i_op = &minix_dir_inode_operations;
+	else if (S_ISLNK(inode->i_mode))
+		inode->i_op = &minix_symlink_inode_operations;
+	else if (S_ISCHR(inode->i_mode))
+		inode->i_op = &chrdev_inode_operations;
+	else if (S_ISBLK(inode->i_mode))
+		inode->i_op = &blkdev_inode_operations;
+	else if (S_ISFIFO(inode->i_mode))
+		init_fifo(inode);
+}
+
+/*
+ * The minix V2 function to read an inode.
+ */
+static void V2_minix_read_inode(struct inode * inode)
+{
+	struct buffer_head * bh;
+	struct minix2_inode * raw_inode;
+	int block, ino;
+
+	ino = inode->i_ino;
+	inode->i_op = NULL;
+	inode->i_mode = 0;
+	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;
+	}
+	block = 2 + inode->i_sb->u.minix_sb.s_imap_blocks +
+		    inode->i_sb->u.minix_sb.s_zmap_blocks +
+		    (ino-1)/MINIX2_INODES_PER_BLOCK;
+	if (!(bh=bread(inode->i_dev,block, BLOCK_SIZE))) {
+		printk("Major problem: unable to read inode from dev "
+		       "%s\n", kdevname(inode->i_dev));
+		return;
+	}
+	raw_inode = ((struct minix2_inode *) bh->b_data) +
+		    (ino-1)%MINIX2_INODES_PER_BLOCK;
+	inode->i_mode = raw_inode->i_mode;
+	inode->i_uid = raw_inode->i_uid;
+	inode->i_gid = raw_inode->i_gid;
+	inode->i_nlink = raw_inode->i_nlinks;
+	inode->i_size = raw_inode->i_size;
+	inode->i_mtime = raw_inode->i_mtime;
+	inode->i_atime = raw_inode->i_atime;
+	inode->i_ctime = raw_inode->i_ctime;
+	inode->i_blocks = inode->i_blksize = 0;
+	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
+		inode->i_rdev = to_kdev_t(raw_inode->i_zone[0]);
+	else for (block = 0; block < 10; block++)
+		inode->u.minix_i.u.i2_data[block] = raw_inode->i_zone[block];
 	brelse(bh);
 	if (S_ISREG(inode->i_mode))
 		inode->i_op = &minix_file_inode_operations;
@@ -453,7 +738,21 @@
 		init_fifo(inode);
 }
 
-static struct buffer_head * minix_update_inode(struct inode * inode)
+/*
+ * The global function to read an inode.
+ */
+void minix_read_inode(struct inode * inode)
+{
+	if (INODE_VERSION(inode) == MINIX_V1)
+		V1_minix_read_inode(inode);
+	else
+		V2_minix_read_inode(inode);
+}
+
+/*
+ * The minix V1 function to synchronize an inode.
+ */
+static struct buffer_head * V1_minix_update_inode(struct inode * inode)
 {
 	struct buffer_head * bh;
 	struct minix_inode * raw_inode;
@@ -485,15 +784,67 @@
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 		raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
 	else for (block = 0; block < 9; block++)
-		raw_inode->i_zone[block] = inode->u.minix_i.i_data[block];
+		raw_inode->i_zone[block] = inode->u.minix_i.u.i1_data[block];
 	inode->i_dirt=0;
 	mark_buffer_dirty(bh, 1);
 	return bh;
 }
 
+/*
+ * The minix V2 function to synchronize an inode.
+ */
+static struct buffer_head * V2_minix_update_inode(struct inode * inode)
+{
+	struct buffer_head * bh;
+	struct minix2_inode * raw_inode;
+	int ino, block;
+
+	ino = inode->i_ino;
+	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);
+		inode->i_dirt = 0;
+		return 0;
+	}
+	block = 2 + inode->i_sb->u.minix_sb.s_imap_blocks + inode->i_sb->u.minix_sb.s_zmap_blocks +
+		(ino-1)/MINIX2_INODES_PER_BLOCK;
+	if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE))) {
+		printk("unable to read i-node block\n");
+		inode->i_dirt = 0;
+		return 0;
+	}
+	raw_inode = ((struct minix2_inode *)bh->b_data) +
+		(ino-1)%MINIX2_INODES_PER_BLOCK;
+	raw_inode->i_mode = inode->i_mode;
+	raw_inode->i_uid = inode->i_uid;
+	raw_inode->i_gid = inode->i_gid;
+	raw_inode->i_nlinks = inode->i_nlink;
+	raw_inode->i_size = inode->i_size;
+	raw_inode->i_mtime = inode->i_mtime;
+	raw_inode->i_atime = inode->i_atime;
+	raw_inode->i_ctime = inode->i_ctime;
+	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
+		raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
+	else for (block = 0; block < 10; block++)
+		raw_inode->i_zone[block] = inode->u.minix_i.u.i2_data[block];
+	inode->i_dirt=0;
+	mark_buffer_dirty(bh, 1);
+	return bh;
+}
+
+struct buffer_head *minix_update_inode(struct inode *inode)
+{
+	if (INODE_VERSION(inode) == MINIX_V1)
+		return V1_minix_update_inode(inode);
+	else
+		return V2_minix_update_inode(inode);
+}
+
 void minix_write_inode(struct inode * inode)
 {
 	struct buffer_head *bh;
+
 	bh = minix_update_inode(inode);
 	brelse(bh);
 }
@@ -539,4 +890,3 @@
 }
 
 #endif
-

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this