xref: /linux/fs/qnx4/bitmap.c (revision 964f5369667b342994fe3f384e9ba41d404ee796)
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/buffer_head.h>
171da177e4SLinus Torvalds #include <linux/bitops.h>
18*964f5369SAl Viro #include "qnx4.h"
191da177e4SLinus Torvalds 
207a1119b1SAdrian Bunk #if 0
211da177e4SLinus Torvalds int qnx4_new_block(struct super_block *sb)
221da177e4SLinus Torvalds {
231da177e4SLinus Torvalds 	return 0;
241da177e4SLinus Torvalds }
257a1119b1SAdrian Bunk #endif  /*  0  */
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds static void count_bits(register const char *bmPart, register int size,
281da177e4SLinus Torvalds 		       int *const tf)
291da177e4SLinus Torvalds {
301da177e4SLinus Torvalds 	char b;
311da177e4SLinus Torvalds 	int tot = *tf;
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds 	if (size > QNX4_BLOCK_SIZE) {
341da177e4SLinus Torvalds 		size = QNX4_BLOCK_SIZE;
351da177e4SLinus Torvalds 	}
361da177e4SLinus Torvalds 	do {
371da177e4SLinus Torvalds 		b = *bmPart++;
381da177e4SLinus Torvalds 		if ((b & 1) == 0)
391da177e4SLinus Torvalds 			tot++;
401da177e4SLinus Torvalds 		if ((b & 2) == 0)
411da177e4SLinus Torvalds 			tot++;
421da177e4SLinus Torvalds 		if ((b & 4) == 0)
431da177e4SLinus Torvalds 			tot++;
441da177e4SLinus Torvalds 		if ((b & 8) == 0)
451da177e4SLinus Torvalds 			tot++;
461da177e4SLinus Torvalds 		if ((b & 16) == 0)
471da177e4SLinus Torvalds 			tot++;
481da177e4SLinus Torvalds 		if ((b & 32) == 0)
491da177e4SLinus Torvalds 			tot++;
501da177e4SLinus Torvalds 		if ((b & 64) == 0)
511da177e4SLinus Torvalds 			tot++;
521da177e4SLinus Torvalds 		if ((b & 128) == 0)
531da177e4SLinus Torvalds 			tot++;
541da177e4SLinus Torvalds 		size--;
551da177e4SLinus Torvalds 	} while (size != 0);
561da177e4SLinus Torvalds 	*tf = tot;
571da177e4SLinus Torvalds }
581da177e4SLinus Torvalds 
591da177e4SLinus Torvalds unsigned long qnx4_count_free_blocks(struct super_block *sb)
601da177e4SLinus Torvalds {
611da177e4SLinus Torvalds 	int start = le32_to_cpu(qnx4_sb(sb)->BitMap->di_first_xtnt.xtnt_blk) - 1;
621da177e4SLinus Torvalds 	int total = 0;
631da177e4SLinus Torvalds 	int total_free = 0;
641da177e4SLinus Torvalds 	int offset = 0;
651da177e4SLinus Torvalds 	int size = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size);
661da177e4SLinus Torvalds 	struct buffer_head *bh;
671da177e4SLinus Torvalds 
681da177e4SLinus Torvalds 	while (total < size) {
691da177e4SLinus Torvalds 		if ((bh = sb_bread(sb, start + offset)) == NULL) {
701da177e4SLinus Torvalds 			printk("qnx4: I/O error in counting free blocks\n");
711da177e4SLinus Torvalds 			break;
721da177e4SLinus Torvalds 		}
731da177e4SLinus Torvalds 		count_bits(bh->b_data, size - total, &total_free);
741da177e4SLinus Torvalds 		brelse(bh);
751da177e4SLinus Torvalds 		total += QNX4_BLOCK_SIZE;
761da177e4SLinus Torvalds 		offset++;
771da177e4SLinus Torvalds 	}
781da177e4SLinus Torvalds 
791da177e4SLinus Torvalds 	return total_free;
801da177e4SLinus Torvalds }
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds #ifdef CONFIG_QNX4FS_RW
831da177e4SLinus Torvalds 
841da177e4SLinus Torvalds int qnx4_is_free(struct super_block *sb, long block)
851da177e4SLinus Torvalds {
861da177e4SLinus Torvalds 	int start = le32_to_cpu(qnx4_sb(sb)->BitMap->di_first_xtnt.xtnt_blk) - 1;
871da177e4SLinus Torvalds 	int size = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size);
881da177e4SLinus Torvalds 	struct buffer_head *bh;
891da177e4SLinus Torvalds 	const char *g;
901da177e4SLinus Torvalds 	int ret = -EIO;
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds 	start += block / (QNX4_BLOCK_SIZE * 8);
931da177e4SLinus Torvalds 	QNX4DEBUG(("qnx4: is_free requesting block [%lu], bitmap in block [%lu]\n",
941da177e4SLinus Torvalds 		   (unsigned long) block, (unsigned long) start));
951da177e4SLinus Torvalds 	(void) size;		/* CHECKME */
961da177e4SLinus Torvalds 	bh = sb_bread(sb, start);
971da177e4SLinus Torvalds 	if (bh == NULL) {
981da177e4SLinus Torvalds 		return -EIO;
991da177e4SLinus Torvalds 	}
1001da177e4SLinus Torvalds 	g = bh->b_data + (block % QNX4_BLOCK_SIZE);
1011da177e4SLinus Torvalds 	if (((*g) & (1 << (block % 8))) == 0) {
1021da177e4SLinus Torvalds 		QNX4DEBUG(("qnx4: is_free -> block is free\n"));
1031da177e4SLinus Torvalds 		ret = 1;
1041da177e4SLinus Torvalds 	} else {
1051da177e4SLinus Torvalds 		QNX4DEBUG(("qnx4: is_free -> block is busy\n"));
1061da177e4SLinus Torvalds 		ret = 0;
1071da177e4SLinus Torvalds 	}
1081da177e4SLinus Torvalds 	brelse(bh);
1091da177e4SLinus Torvalds 
1101da177e4SLinus Torvalds 	return ret;
1111da177e4SLinus Torvalds }
1121da177e4SLinus Torvalds 
1131da177e4SLinus Torvalds int qnx4_set_bitmap(struct super_block *sb, long block, int busy)
1141da177e4SLinus Torvalds {
1151da177e4SLinus Torvalds 	int start = le32_to_cpu(qnx4_sb(sb)->BitMap->di_first_xtnt.xtnt_blk) - 1;
1161da177e4SLinus Torvalds 	int size = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size);
1171da177e4SLinus Torvalds 	struct buffer_head *bh;
1181da177e4SLinus Torvalds 	char *g;
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds 	start += block / (QNX4_BLOCK_SIZE * 8);
1211da177e4SLinus Torvalds 	QNX4DEBUG(("qnx4: set_bitmap requesting block [%lu], bitmap in block [%lu]\n",
1221da177e4SLinus Torvalds 		   (unsigned long) block, (unsigned long) start));
1231da177e4SLinus Torvalds 	(void) size;		/* CHECKME */
1241da177e4SLinus Torvalds 	bh = sb_bread(sb, start);
1251da177e4SLinus Torvalds 	if (bh == NULL) {
1261da177e4SLinus Torvalds 		return -EIO;
1271da177e4SLinus Torvalds 	}
1281da177e4SLinus Torvalds 	g = bh->b_data + (block % QNX4_BLOCK_SIZE);
1291da177e4SLinus Torvalds 	if (busy == 0) {
1301da177e4SLinus Torvalds 		(*g) &= ~(1 << (block % 8));
1311da177e4SLinus Torvalds 	} else {
1321da177e4SLinus Torvalds 		(*g) |= (1 << (block % 8));
1331da177e4SLinus Torvalds 	}
1341da177e4SLinus Torvalds 	mark_buffer_dirty(bh);
1351da177e4SLinus Torvalds 	brelse(bh);
1361da177e4SLinus Torvalds 
1371da177e4SLinus Torvalds 	return 0;
1381da177e4SLinus Torvalds }
1391da177e4SLinus Torvalds 
1401da177e4SLinus Torvalds static void qnx4_clear_inode(struct inode *inode)
1411da177e4SLinus Torvalds {
1421da177e4SLinus Torvalds 	struct qnx4_inode_entry *qnx4_ino = qnx4_raw_inode(inode);
1431da177e4SLinus Torvalds 	/* What for? */
1441da177e4SLinus Torvalds 	memset(qnx4_ino->di_fname, 0, sizeof qnx4_ino->di_fname);
1451da177e4SLinus Torvalds 	qnx4_ino->di_size = 0;
1461da177e4SLinus Torvalds 	qnx4_ino->di_num_xtnts = 0;
1471da177e4SLinus Torvalds 	qnx4_ino->di_mode = 0;
1481da177e4SLinus Torvalds 	qnx4_ino->di_status = 0;
1491da177e4SLinus Torvalds }
1501da177e4SLinus Torvalds 
1511da177e4SLinus Torvalds void qnx4_free_inode(struct inode *inode)
1521da177e4SLinus Torvalds {
1531da177e4SLinus Torvalds 	if (inode->i_ino < 1) {
1541da177e4SLinus Torvalds 		printk("free_inode: inode 0 or nonexistent inode\n");
1551da177e4SLinus Torvalds 		return;
1561da177e4SLinus Torvalds 	}
1571da177e4SLinus Torvalds 	qnx4_clear_inode(inode);
1581da177e4SLinus Torvalds 	clear_inode(inode);
1591da177e4SLinus Torvalds }
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds #endif
162