patch-pre2.0.6 linux/fs/affs/inode.c

Next file: linux/fs/affs/namei.c
Previous file: linux/fs/affs/file.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file pre2.0.5/linux/fs/affs/inode.c linux/fs/affs/inode.c
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/affs/inode.c
  *
- *  (c) 1996  Hans-Joachim Widmaier - rewritten
+ *  (c) 1996  Hans-Joachim Widmaier - Rewritten
  *
  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
  * 
@@ -25,12 +25,15 @@
 #include <linux/genhd.h>
 #include <linux/amigaffs.h>
 #include <linux/major.h>
+#include <linux/blkdev.h>
 #include <asm/system.h>
 #include <asm/segment.h>
 
 extern int *blk_size[];
 extern struct timezone sys_tz;
 
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
 void
 affs_put_super(struct super_block *sb)
 {
@@ -39,15 +42,13 @@
 	pr_debug("affs_put_super()\n");
 
 	lock_super(sb);
-	if (!(sb->s_flags & MS_RDONLY)) {
-		for (i = 0; i < sb->u.affs_sb.s_bm_count; i++)
-			affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh);
-		ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = htonl(1);
-		secs_to_datestamp(CURRENT_TIME,
-				  &ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered);
-		affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5);
-		mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1);
-	}
+	for (i = 0; i < sb->u.affs_sb.s_bm_count; i++)
+		affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh);
+	ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = htonl(1);
+	secs_to_datestamp(CURRENT_TIME,&ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered);
+	affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5);
+	mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1);
+
 	if (sb->u.affs_sb.s_flags & SF_PREFIX)
 		kfree(sb->u.affs_sb.s_prefix);
 	kfree(sb->u.affs_sb.s_bitmap);
@@ -62,15 +63,24 @@
 static void
 affs_write_super(struct super_block *sb)
 {
-	int	 i, clean = 2;
+	int			 i, clean = 2;
 
+	if ((sb->u.affs_sb.s_flags & SF_USE_MP) && !sb->u.affs_sb.s_uid && sb->s_covered) {
+		sb->s_mounted->i_uid = sb->u.affs_sb.s_uid = sb->s_covered->i_uid;
+		sb->s_mounted->i_gid = sb->u.affs_sb.s_gid = sb->s_covered->i_gid;
+		sb->u.affs_sb.s_flags &= ~SF_USE_MP;
+	}
 	if (!(sb->s_flags & MS_RDONLY)) {
+		lock_super(sb);
 		for (i = 0, clean = 1; i < sb->u.affs_sb.s_bm_count; i++) {
-			if (buffer_dirty(sb->u.affs_sb.s_bitmap[i].bm_bh)) {
-				clean = 0;
-				break;
+			if (sb->u.affs_sb.s_bitmap[i].bm_bh) {
+				if (buffer_dirty(sb->u.affs_sb.s_bitmap[i].bm_bh)) {
+					clean = 0;
+					break;
+				}
 			}
 		}
+		unlock_super(sb);
 		ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = htonl(clean);
 		secs_to_datestamp(CURRENT_TIME,
 				  &ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered);
@@ -108,7 +118,6 @@
 	return dir->u.affs_i.i_parent;
 }
 
-
 static int
 parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, int *root,
 		int *blocksize, char **prefix, char *volume, unsigned long *mount_opts)
@@ -140,6 +149,13 @@
 			}
 			*mount_opts |= SF_IMMUTABLE;
 		}
+		if (!strcmp(this_char,"usemp")) {
+			if (value) {
+				printk("AFFS: option usemp does not take an argument\n");
+				return 0;
+			}
+			*mount_opts |= SF_USE_MP;
+		}
 		else if (!strcmp(this_char,"verbose")) {
 			if (value) {
 				printk("AFFS: option verbose does not take an argument\n");
@@ -251,6 +267,10 @@
 	return 1;
 }
 
+/* This function definately needs to be split up. Some fine day I'll
+ * hopefully have the guts to do so. Until then: sorry for the mess.
+ */
+
 struct super_block *
 affs_read_super(struct super_block *s,void *data, int silent)
 {
@@ -259,26 +279,26 @@
 	kdev_t			 dev = s->s_dev;
 	int			 root_block;
 	int			 size;
-	ULONG			 chksum;
-	ULONG			*bm;
-	LONG			 ptype, stype;
-	int			 mapidx = 0;
+	__u32			 chksum;
+	__u32			*bm;
+	int			 ptype, stype;
+	int			 mapidx;
 	int			 num_bm;
-	int			 i;
+	int			 i, j;
 	int			 key;
 	int			 blocksize;
 	uid_t			 uid;
 	gid_t			 gid;
-	int			 mode, reserved;
-	int			 zm_size;
+	int			 reserved;
+	int			 az_no;
 	unsigned long		 mount_flags;
-	ULONG			 offset;
+	unsigned long		 offset;
 
-	pr_debug("affs_read_super(%s)\n",(const char *)data);
+	pr_debug("affs_read_super(%s)\n",data ? (const char *)data : "no options");
 
 	MOD_INC_USE_COUNT;
 
-	if (!parse_options(data,&uid,&gid,&mode,&reserved,&root_block,
+	if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
 	    &blocksize,&s->u.affs_sb.s_prefix,s->u.affs_sb.s_volume,&mount_flags)) {
 		s->s_dev = 0;
 		printk("AFFS: error parsing options.\n");
@@ -292,13 +312,15 @@
 	 * blocks, we will have to change it.
 	 */
 
-	size                      = 2 * blk_size[MAJOR(dev)][MINOR(dev)];
-	s->u.affs_sb.s_bitmap     = NULL;
-	s->u.affs_sb.s_root_bh    = NULL;
-	s->u.affs_sb.s_flags      = mount_flags;
-	s->u.affs_sb.s_mode       = mode;
-	s->u.affs_sb.s_uid        = uid;
-	s->u.affs_sb.s_gid        = gid;
+	size = blksize_size[MAJOR(dev)][MINOR(dev)];
+	size = (size ? size : BLOCK_SIZE) / 512 * blk_size[MAJOR(dev)][MINOR(dev)];
+
+	s->u.affs_sb.s_bitmap  = NULL;
+	s->u.affs_sb.s_root_bh = NULL;
+	s->u.affs_sb.s_flags   = mount_flags;
+	s->u.affs_sb.s_mode    = i;
+	s->u.affs_sb.s_uid     = uid;
+	s->u.affs_sb.s_gid     = gid;
 
 	if (size == 0) {
 		s->s_dev = 0;
@@ -320,15 +342,12 @@
 		num_bm = 4096;
 	}
 	for (blocksize = chksum; blocksize <= num_bm; blocksize <<= 1, size >>= 1) {
-	        if (root_block < 0){
-		    if (MAJOR(dev) == FLOPPY_MAJOR)
-		        s->u.affs_sb.s_root_block = size/4;
-		    else
+		if (root_block < 0)
 			s->u.affs_sb.s_root_block = (reserved + size - 1) / 2;
-		}else
+		else
 			s->u.affs_sb.s_root_block = root_block;
 		pr_debug("Trying bs=%d bytes, root at %d, size=%d blocks (%d reserved)\n",
-			blocksize,s->u.affs_sb.s_root_block,size,reserved);
+			 blocksize,s->u.affs_sb.s_root_block,size,reserved);
 		set_blocksize(dev,blocksize);
 		bh = affs_bread(dev,s->u.affs_sb.s_root_block,blocksize);
 		if (!bh) {
@@ -360,7 +379,7 @@
 	/* Find out which kind of FS we have */
 	bb = affs_bread(dev,0,s->s_blocksize);
 	if (bb) {
-		chksum = htonl(*(ULONG *)bb->b_data);
+		chksum = htonl(*(__u32 *)bb->b_data);
 		switch (chksum) {
 			case MUFS_FS:
 			case MUFS_INTLFFS:
@@ -422,20 +441,28 @@
 		goto out;
 	}
 
-	/* Allocate space for bitmap pointers and read the bitmap */
+	/* Allocate space for bitmaps, zones and others */
 
-	size    = s->u.affs_sb.s_partition_size - reserved;
-	num_bm  = (size + s->s_blocksize * 8 - 32 - 1) / (s->s_blocksize * 8 - 32);
-	zm_size = (num_bm *  (1 << (s->s_blocksize_bits - 8)) + 7) / 8;
-	ptype   = num_bm * sizeof(struct affs_bm_info) + zm_size +
-		  MAX_ZONES * sizeof(struct affs_zone);
+	size   = s->u.affs_sb.s_partition_size - reserved;
+	num_bm = (size + s->s_blocksize * 8 - 32 - 1) / (s->s_blocksize * 8 - 32);
+	az_no  = (size + AFFS_ZONE_SIZE - 1) / (AFFS_ZONE_SIZE - 32);
+	ptype  = num_bm * sizeof(struct affs_bm_info) + 
+		 az_no * sizeof(struct affs_alloc_zone) +
+		 MAX_ZONES * sizeof(struct affs_zone);
+	pr_debug("num_bm=%d, az_no=%d, sum=%d\n",num_bm,az_no,ptype);
 	if (!(s->u.affs_sb.s_bitmap = kmalloc(ptype,GFP_KERNEL))) {
-		printk("AFFS: Can't get memory for bitmap info.\n");
+		printk("AFFS: Not enough memory.\n");
 		goto out;
 	}
 	memset(s->u.affs_sb.s_bitmap,0,ptype);
 
-	if( (ULONG)((UBYTE *)bh->b_data + s->s_blocksize - 200) == 0 ) {
+	s->u.affs_sb.s_zones   = (struct affs_zone *)&s->u.affs_sb.s_bitmap[num_bm];
+	s->u.affs_sb.s_alloc   = (struct affs_alloc_zone *)&s->u.affs_sb.s_zones[MAX_ZONES];
+	s->u.affs_sb.s_num_az  = az_no;
+
+	mapidx = 0;
+
+	if (ROOT_END_S(bh->b_data,s)->bm_flag == 0) {
 		if (!(s->s_flags & MS_RDONLY)) {
 			printk("AFFS: Bitmap invalid - mounting %s read only.\n",kdevname(dev));
 			s->s_flags |= MS_RDONLY;
@@ -445,14 +472,17 @@
 		goto nobitmap;
 	}
 
-	pr_debug("AFFS: %d bitmap blocks\n",num_bm);
+	/* The following section is ugly, I know. Especially because of the
+	 * reuse of some variables that are not named properly.
+	 */
 
 	key    = root_block;
 	ptype  = s->s_blocksize / 4 - 49;
 	stype  = ptype + 25;
 	offset = s->u.affs_sb.s_reserved;
+	az_no  = 0;
 	while (bh) {
-		bm = (ULONG *)bh->b_data;
+		bm = (__u32 *)bh->b_data;
 		for (i = ptype; i < stype && bm[i]; i++, mapidx++) {
 			if (mapidx >= num_bm) {
 				printk("AFFS: Not enough bitmap space!?\n");
@@ -460,21 +490,22 @@
 			}
 			bb = affs_bread(s->s_dev,htonl(bm[i]),s->s_blocksize);
 			if (bb) {
-				if (affs_checksum_block(s->s_blocksize,bb->b_data,NULL,NULL) /*&&
-				    !(s->s_flags & MS_RDONLY)*/) {
+				if (affs_checksum_block(s->s_blocksize,bb->b_data,NULL,NULL) &&
+				    !(s->s_flags & MS_RDONLY)) {
 					printk("AFFS: Bitmap (%d,key=%lu) invalid - "
 					       "mounting %s read only.\n",mapidx,htonl(bm[i]),
 						kdevname(dev));
 					s->s_flags |= MS_RDONLY;
 				}
+				/* Mark unused bits in the last word as allocated */
 				if (size <= s->s_blocksize * 8 - 32) {	/* last bitmap */
 					ptype = size / 32 + 1;		/* word number */
 					key   = size & 0x1F;		/* used bits */
 					if (key) {
 						chksum = ntohl(0x7FFFFFFF >> (31 - key));
-						((ULONG *)bb->b_data)[ptype] &= chksum;
+						((__u32 *)bb->b_data)[ptype] &= chksum;
 						affs_fix_checksum(s->s_blocksize,bb->b_data,0);
-						/* no need to mark buffer as dirty */
+						mark_buffer_dirty(bb,1);
 					}
 					ptype = (size + 31) & ~0x1F;
 					size  = 0;
@@ -485,11 +516,19 @@
 					size -= ptype;
 				}
 				s->u.affs_sb.s_bitmap[mapidx].bm_firstblk = offset;
-				s->u.affs_sb.s_bitmap[mapidx].bm_size     = ptype;
-				s->u.affs_sb.s_bitmap[mapidx].bm_bh       = bb;
-				s->u.affs_sb.s_bitmap[mapidx].bm_free     =
-						affs_count_free_bits(ptype / 8,bb->b_data + 4);
+				s->u.affs_sb.s_bitmap[mapidx].bm_bh       = NULL;
+				s->u.affs_sb.s_bitmap[mapidx].bm_key      = htonl(bm[i]);
+				s->u.affs_sb.s_bitmap[mapidx].bm_count    = 0;
 				offset += ptype;
+
+				for (j = 0; ptype > 0; j++, az_no++, ptype -= key) {
+					key = MIN(ptype,AFFS_ZONE_SIZE);	/* size in bits */
+					s->u.affs_sb.s_alloc[az_no].az_size = key / 32;
+					s->u.affs_sb.s_alloc[az_no].az_free =
+						affs_count_free_bits(key / 8,bb->b_data +
+								     j * (AFFS_ZONE_SIZE / 8) + 4);
+				}
+				affs_brelse(bb);
 			} else {
 				printk("AFFS: Can't read bitmap.\n");
 				goto out;
@@ -511,18 +550,15 @@
 		printk("AFFS: Got only %d bitmap blocks, expected %d\n",mapidx,num_bm);
 		goto out;
 	}
-	s->u.affs_sb.s_num_zones = ((num_bm - 1) << (s->s_blocksize_bits - 8)) +
-				   (s->u.affs_sb.s_bitmap[num_bm - 1].bm_size + 2047) / 2048;
 nobitmap:
 	s->u.affs_sb.s_bm_count  = mapidx;
-	s->u.affs_sb.s_zones     = (struct affs_zone *)&s->u.affs_sb.s_bitmap[num_bm];
-	s->u.affs_sb.s_zonemap   = (char *)&s->u.affs_sb.s_zones[MAX_ZONES];
 
 	/* set up enough so that it can read an inode */
 
 	s->s_dev       = dev;
 	s->s_op        = &affs_sops;
 	s->s_mounted   = iget(s,root_block);
+	s->s_dirt      = 1;
 	unlock_super(s);
 
 	if (!(s->s_mounted)) {
@@ -532,7 +568,7 @@
 		return NULL;
 	}
 
-	/* If the fs is mounted r/w, create data zones, else free bitmaps. */
+	/* create data zones if the fs is mounted r/w */
 
 	if (!(s->s_flags & MS_RDONLY)) {
 		ROOT_END(s->u.affs_sb.s_root_bh->b_data,s->s_mounted)->bm_flag = 0;
@@ -541,13 +577,7 @@
 		affs_fix_checksum(s->s_blocksize,s->u.affs_sb.s_root_bh->b_data,5);
 		mark_buffer_dirty(s->u.affs_sb.s_root_bh,1);
 		affs_make_zones(s);
-	} else {
-		for (i = 0; i < s->u.affs_sb.s_bm_count; i++) {
-			affs_brelse(s->u.affs_sb.s_bitmap[i].bm_bh);
-			s->u.affs_sb.s_bitmap[i].bm_bh = NULL;
-		}
 	}
-		
 
 	pr_debug("AFFS: s_flags=%lX\n",s->s_flags);
 	return s;
@@ -555,11 +585,8 @@
  out: /* Kick out for various error conditions */
 	affs_brelse (bh);
 	affs_brelse(s->u.affs_sb.s_root_bh);
-	if (s->u.affs_sb.s_bitmap) {
-		for (i = 0; i < mapidx; i++)
-			affs_brelse(s->u.affs_sb.s_bitmap[i].bm_bh);
+	if (s->u.affs_sb.s_bitmap)
 		kfree(s->u.affs_sb.s_bitmap);
-	}
 	s->s_dev = 0;
 	unlock_super(s);
 	MOD_DEC_USE_COUNT;
@@ -569,7 +596,7 @@
 void
 affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
 {
-	ULONG		 free;
+	int		 free;
 	struct statfs	 tmp;
 
 	pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",sb->u.affs_sb.s_partition_size,
@@ -592,9 +619,9 @@
 	struct buffer_head	*bh, *lbh;
 	struct file_front	*file_front;
 	struct file_end		*file_end;
-	LONG			 block;
-	ULONG			 prot;
-	LONG			 ptype, stype;
+	int			 block;
+	unsigned long		 prot;
+	int			 ptype, stype;
 	unsigned short		 id;
 
 	pr_debug("AFFS: read_inode(%lu)\n",inode->i_ino);
@@ -817,7 +844,7 @@
 {
 	struct inode		*inode;
 	struct super_block	*sb;
-	ULONG			 block;
+	int			 block;
 
 	if (!dir || !(inode = get_empty_inode()))
 		return NULL;
@@ -863,15 +890,15 @@
 
 int
 affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode,
-	       const char *name, int len, LONG type)
+	       const char *name, int len, int type)
 {
 	struct buffer_head	*dir_bh;
 	struct buffer_head	*inode_bh;
 	struct buffer_head	*link_bh;
-	ULONG			 hash;
+	int			 hash;
 
-	pr_debug("AFFS: add_entry(dir=%lu,inode=%lu,\"%*s\",type=%ld\n",dir->i_ino,inode->i_ino,
-		len,name,type);
+	pr_debug("AFFS: add_entry(dir=%lu,inode=%lu,\"%*s\",type=%d\n",dir->i_ino,inode->i_ino,
+		 len,name,type);
 
 	dir_bh      = affs_bread(dir->i_dev,dir->i_ino,AFFS_I2BSIZE(dir));
 	inode_bh    = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));

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