xref: /linux/fs/qnx4/bitmap.c (revision 7a1119b1fc87cc347d3932b8aee051e86b32818f)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * QNX4 file system, Linux implementation.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Version : 0.2.1
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Using parts of the xiafs filesystem.
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  * History :
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * 28-05-1998 by Richard Frowijn : first release.
111da177e4SLinus Torvalds  * 20-06-1998 by Frank Denis : basic optimisations.
121da177e4SLinus Torvalds  * 25-06-1998 by Frank Denis : qnx4_is_free, qnx4_set_bitmap, qnx4_bmap .
131da177e4SLinus Torvalds  * 28-06-1998 by Frank Denis : qnx4_free_inode (to be fixed) .
141da177e4SLinus Torvalds  */
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds #include <linux/config.h>
171da177e4SLinus Torvalds #include <linux/time.h>
181da177e4SLinus Torvalds #include <linux/fs.h>
191da177e4SLinus Torvalds #include <linux/qnx4_fs.h>
201da177e4SLinus Torvalds #include <linux/stat.h>
211da177e4SLinus Torvalds #include <linux/kernel.h>
221da177e4SLinus Torvalds #include <linux/string.h>
231da177e4SLinus Torvalds #include <linux/buffer_head.h>
241da177e4SLinus Torvalds #include <linux/bitops.h>
251da177e4SLinus Torvalds 
26*7a1119b1SAdrian Bunk #if 0
271da177e4SLinus Torvalds int qnx4_new_block(struct super_block *sb)
281da177e4SLinus Torvalds {
291da177e4SLinus Torvalds 	return 0;
301da177e4SLinus Torvalds }
31*7a1119b1SAdrian Bunk #endif  /*  0  */
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds static void count_bits(register const char *bmPart, register int size,
341da177e4SLinus Torvalds 		       int *const tf)
351da177e4SLinus Torvalds {
361da177e4SLinus Torvalds 	char b;
371da177e4SLinus Torvalds 	int tot = *tf;
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds 	if (size > QNX4_BLOCK_SIZE) {
401da177e4SLinus Torvalds 		size = QNX4_BLOCK_SIZE;
411da177e4SLinus Torvalds 	}
421da177e4SLinus Torvalds 	do {
431da177e4SLinus Torvalds 		b = *bmPart++;
441da177e4SLinus Torvalds 		if ((b & 1) == 0)
451da177e4SLinus Torvalds 			tot++;
461da177e4SLinus Torvalds 		if ((b & 2) == 0)
471da177e4SLinus Torvalds 			tot++;
481da177e4SLinus Torvalds 		if ((b & 4) == 0)
491da177e4SLinus Torvalds 			tot++;
501da177e4SLinus Torvalds 		if ((b & 8) == 0)
511da177e4SLinus Torvalds 			tot++;
521da177e4SLinus Torvalds 		if ((b & 16) == 0)
531da177e4SLinus Torvalds 			tot++;
541da177e4SLinus Torvalds 		if ((b & 32) == 0)
551da177e4SLinus Torvalds 			tot++;
561da177e4SLinus Torvalds 		if ((b & 64) == 0)
571da177e4SLinus Torvalds 			tot++;
581da177e4SLinus Torvalds 		if ((b & 128) == 0)
591da177e4SLinus Torvalds 			tot++;
601da177e4SLinus Torvalds 		size--;
611da177e4SLinus Torvalds 	} while (size != 0);
621da177e4SLinus Torvalds 	*tf = tot;
631da177e4SLinus Torvalds }
641da177e4SLinus Torvalds 
651da177e4SLinus Torvalds unsigned long qnx4_count_free_blocks(struct super_block *sb)
661da177e4SLinus Torvalds {
671da177e4SLinus Torvalds 	int start = le32_to_cpu(qnx4_sb(sb)->BitMap->di_first_xtnt.xtnt_blk) - 1;
681da177e4SLinus Torvalds 	int total = 0;
691da177e4SLinus Torvalds 	int total_free = 0;
701da177e4SLinus Torvalds 	int offset = 0;
711da177e4SLinus Torvalds 	int size = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size);
721da177e4SLinus Torvalds 	struct buffer_head *bh;
731da177e4SLinus Torvalds 
741da177e4SLinus Torvalds 	while (total < size) {
751da177e4SLinus Torvalds 		if ((bh = sb_bread(sb, start + offset)) == NULL) {
761da177e4SLinus Torvalds 			printk("qnx4: I/O error in counting free blocks\n");
771da177e4SLinus Torvalds 			break;
781da177e4SLinus Torvalds 		}
791da177e4SLinus Torvalds 		count_bits(bh->b_data, size - total, &total_free);
801da177e4SLinus Torvalds 		brelse(bh);
811da177e4SLinus Torvalds 		total += QNX4_BLOCK_SIZE;
821da177e4SLinus Torvalds 		offset++;
831da177e4SLinus Torvalds 	}
841da177e4SLinus Torvalds 
851da177e4SLinus Torvalds 	return total_free;
861da177e4SLinus Torvalds }
871da177e4SLinus Torvalds 
881da177e4SLinus Torvalds #ifdef CONFIG_QNX4FS_RW
891da177e4SLinus Torvalds 
901da177e4SLinus Torvalds int qnx4_is_free(struct super_block *sb, long block)
911da177e4SLinus Torvalds {
921da177e4SLinus Torvalds 	int start = le32_to_cpu(qnx4_sb(sb)->BitMap->di_first_xtnt.xtnt_blk) - 1;
931da177e4SLinus Torvalds 	int size = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size);
941da177e4SLinus Torvalds 	struct buffer_head *bh;
951da177e4SLinus Torvalds 	const char *g;
961da177e4SLinus Torvalds 	int ret = -EIO;
971da177e4SLinus Torvalds 
981da177e4SLinus Torvalds 	start += block / (QNX4_BLOCK_SIZE * 8);
991da177e4SLinus Torvalds 	QNX4DEBUG(("qnx4: is_free requesting block [%lu], bitmap in block [%lu]\n",
1001da177e4SLinus Torvalds 		   (unsigned long) block, (unsigned long) start));
1011da177e4SLinus Torvalds 	(void) size;		/* CHECKME */
1021da177e4SLinus Torvalds 	bh = sb_bread(sb, start);
1031da177e4SLinus Torvalds 	if (bh == NULL) {
1041da177e4SLinus Torvalds 		return -EIO;
1051da177e4SLinus Torvalds 	}
1061da177e4SLinus Torvalds 	g = bh->b_data + (block % QNX4_BLOCK_SIZE);
1071da177e4SLinus Torvalds 	if (((*g) & (1 << (block % 8))) == 0) {
1081da177e4SLinus Torvalds 		QNX4DEBUG(("qnx4: is_free -> block is free\n"));
1091da177e4SLinus Torvalds 		ret = 1;
1101da177e4SLinus Torvalds 	} else {
1111da177e4SLinus Torvalds 		QNX4DEBUG(("qnx4: is_free -> block is busy\n"));
1121da177e4SLinus Torvalds 		ret = 0;
1131da177e4SLinus Torvalds 	}
1141da177e4SLinus Torvalds 	brelse(bh);
1151da177e4SLinus Torvalds 
1161da177e4SLinus Torvalds 	return ret;
1171da177e4SLinus Torvalds }
1181da177e4SLinus Torvalds 
1191da177e4SLinus Torvalds int qnx4_set_bitmap(struct super_block *sb, long block, int busy)
1201da177e4SLinus Torvalds {
1211da177e4SLinus Torvalds 	int start = le32_to_cpu(qnx4_sb(sb)->BitMap->di_first_xtnt.xtnt_blk) - 1;
1221da177e4SLinus Torvalds 	int size = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size);
1231da177e4SLinus Torvalds 	struct buffer_head *bh;
1241da177e4SLinus Torvalds 	char *g;
1251da177e4SLinus Torvalds 
1261da177e4SLinus Torvalds 	start += block / (QNX4_BLOCK_SIZE * 8);
1271da177e4SLinus Torvalds 	QNX4DEBUG(("qnx4: set_bitmap requesting block [%lu], bitmap in block [%lu]\n",
1281da177e4SLinus Torvalds 		   (unsigned long) block, (unsigned long) start));
1291da177e4SLinus Torvalds 	(void) size;		/* CHECKME */
1301da177e4SLinus Torvalds 	bh = sb_bread(sb, start);
1311da177e4SLinus Torvalds 	if (bh == NULL) {
1321da177e4SLinus Torvalds 		return -EIO;
1331da177e4SLinus Torvalds 	}
1341da177e4SLinus Torvalds 	g = bh->b_data + (block % QNX4_BLOCK_SIZE);
1351da177e4SLinus Torvalds 	if (busy == 0) {
1361da177e4SLinus Torvalds 		(*g) &= ~(1 << (block % 8));
1371da177e4SLinus Torvalds 	} else {
1381da177e4SLinus Torvalds 		(*g) |= (1 << (block % 8));
1391da177e4SLinus Torvalds 	}
1401da177e4SLinus Torvalds 	mark_buffer_dirty(bh);
1411da177e4SLinus Torvalds 	brelse(bh);
1421da177e4SLinus Torvalds 
1431da177e4SLinus Torvalds 	return 0;
1441da177e4SLinus Torvalds }
1451da177e4SLinus Torvalds 
1461da177e4SLinus Torvalds static void qnx4_clear_inode(struct inode *inode)
1471da177e4SLinus Torvalds {
1481da177e4SLinus Torvalds 	struct qnx4_inode_entry *qnx4_ino = qnx4_raw_inode(inode);
1491da177e4SLinus Torvalds 	/* What for? */
1501da177e4SLinus Torvalds 	memset(qnx4_ino->di_fname, 0, sizeof qnx4_ino->di_fname);
1511da177e4SLinus Torvalds 	qnx4_ino->di_size = 0;
1521da177e4SLinus Torvalds 	qnx4_ino->di_num_xtnts = 0;
1531da177e4SLinus Torvalds 	qnx4_ino->di_mode = 0;
1541da177e4SLinus Torvalds 	qnx4_ino->di_status = 0;
1551da177e4SLinus Torvalds }
1561da177e4SLinus Torvalds 
1571da177e4SLinus Torvalds void qnx4_free_inode(struct inode *inode)
1581da177e4SLinus Torvalds {
1591da177e4SLinus Torvalds 	if (inode->i_ino < 1) {
1601da177e4SLinus Torvalds 		printk("free_inode: inode 0 or nonexistent inode\n");
1611da177e4SLinus Torvalds 		return;
1621da177e4SLinus Torvalds 	}
1631da177e4SLinus Torvalds 	qnx4_clear_inode(inode);
1641da177e4SLinus Torvalds 	clear_inode(inode);
1651da177e4SLinus Torvalds }
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds #endif
168