patch-2.1.120 linux/fs/qnx4/bitmap.c

Next file: linux/fs/qnx4/dir.c
Previous file: linux/fs/qnx4/TODO
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.119/linux/fs/qnx4/bitmap.c linux/fs/qnx4/bitmap.c
@@ -0,0 +1,196 @@
+/* 
+ * QNX4 file system, Linux implementation.
+ * 
+ * Version : 0.1
+ * 
+ * Using parts of the xiafs filesystem.
+ * 
+ * History :
+ * 
+ * 28-05-1998 by Richard Frowijn : first release.
+ * 20-06-1998 by Frank Denis : basic optimisations.
+ * 25-06-1998 by Frank Denis : qnx4_is_free, qnx4_set_bitmap, qnx4_bmap .
+ * 28-06-1998 by Frank Denis : qnx4_free_inode (to be fixed) .
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/qnx4_fs.h>
+#include <linux/stat.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/bitops.h>
+
+int qnx4_new_block(struct super_block *sb)
+{
+	return 0;
+}
+
+void count_bits(const register char *bmPart, register int size,
+		int *const tf)
+{
+	char b;
+	int tot = *tf;
+
+	if (size > QNX4_BLOCK_SIZE) {
+		size = QNX4_BLOCK_SIZE;
+	}
+	do {
+		b = *bmPart++;
+		if ((b & 1) == 0)
+			tot++;
+		if ((b & 2) == 0)
+			tot++;
+		if ((b & 4) == 0)
+			tot++;
+		if ((b & 8) == 0)
+			tot++;
+		if ((b & 16) == 0)
+			tot++;
+		if ((b & 32) == 0)
+			tot++;
+		if ((b & 64) == 0)
+			tot++;
+		if ((b & 128) == 0)
+			tot++;
+		size--;
+	} while (size != 0);
+	*tf = tot;
+}
+
+unsigned long qnx4_count_free_blocks(struct super_block *sb)
+{
+	int start = sb->u.qnx4_sb.BitMap->di_first_xtnt.xtnt_blk - 1;
+	int total = 0;
+	int total_free = 0;
+	int offset = 0;
+	int size = sb->u.qnx4_sb.BitMap->di_size;
+	struct buffer_head *bh;
+
+	while (total < size) {
+		if ((bh = bread(sb->s_dev, start + offset, QNX4_BLOCK_SIZE)) == NULL) {
+			printk("qnx4: I/O error in counting free blocks\n");
+			break;
+		}
+		count_bits(bh->b_data, size - total, &total_free);
+		brelse(bh);
+		total += QNX4_BLOCK_SIZE;
+	}
+
+	return total_free;
+}
+
+unsigned long qnx4_count_free_inodes(struct super_block *sb)
+{
+	return qnx4_count_free_blocks(sb) * QNX4_INODES_PER_BLOCK;	/* FIXME */
+}
+
+int qnx4_is_free(struct super_block *sb, int block)
+{
+	int start = sb->u.qnx4_sb.BitMap->di_first_xtnt.xtnt_blk - 1;
+	int size = sb->u.qnx4_sb.BitMap->di_size;
+	struct buffer_head *bh;
+	const char *g;
+	int ret = -EIO;
+
+	start += block / (QNX4_BLOCK_SIZE * 8);
+	QNX4DEBUG(("qnx4: is_free requesting block [%lu], bitmap in block [%lu]\n",
+		   (unsigned long) block, (unsigned long) start));
+	(void) size;		/* CHECKME */
+	bh = bread(sb->s_dev, start, QNX4_BLOCK_SIZE);
+	if (bh == NULL) {
+		return -EIO;
+	}
+	g = bh->b_data + (block % QNX4_BLOCK_SIZE);
+	if (((*g) & (1 << (block % 8))) == 0) {
+		QNX4DEBUG(("qnx4: is_free -> block is free\n"));
+		ret = 1;
+	} else {
+		QNX4DEBUG(("qnx4: is_free -> block is busy\n"));
+		ret = 0;
+	}
+	brelse(bh);
+
+	return ret;
+}
+
+int qnx4_bmap(struct inode *inode, int block)
+{
+   QNX4DEBUG(("qnx4: bmap on block [%d]\n", block));
+   if (block < 0) {
+      return 0;
+   }
+   return !qnx4_is_free(inode->i_sb, block);
+}
+
+#ifdef CONFIG_QNX4FS_RW
+
+int qnx4_set_bitmap(struct super_block *sb, int block, int busy)
+{
+	int start = sb->u.qnx4_sb.BitMap->di_first_xtnt.xtnt_blk - 1;
+	int size = sb->u.qnx4_sb.BitMap->di_size;
+	struct buffer_head *bh;
+	char *g;
+
+	start += block / (QNX4_BLOCK_SIZE * 8);
+	QNX4DEBUG(("qnx4: set_bitmap requesting block [%lu], bitmap in block [%lu]\n",
+		   (unsigned long) block, (unsigned long) start));
+	(void) size;		/* CHECKME */
+	bh = bread(sb->s_dev, start, QNX4_BLOCK_SIZE);
+	if (bh == NULL) {
+		return -EIO;
+	}
+	g = bh->b_data + (block % QNX4_BLOCK_SIZE);
+	if (busy == 0) {
+		(*g) &= ~(1 << (block % 8));
+	} else {
+		(*g) |= (1 << (block % 8));
+	}
+	mark_buffer_dirty(bh, 1);
+	brelse(bh);
+
+	return 0;
+}
+
+static void qnx4_clear_inode(struct inode *inode)
+{
+	struct qnx4_inode_info *qnx4_ino = &inode->u.qnx4_i;
+
+	memset(qnx4_ino->i_reserved, 0, sizeof qnx4_ino->i_reserved);
+	qnx4_ino->i_size = 0;
+	qnx4_ino->i_num_xtnts = 0;
+	qnx4_ino->i_mode = 0;
+	qnx4_ino->i_status = 0;
+}
+
+void qnx4_free_inode(struct inode *inode)
+{
+	if (!inode) {
+		return;
+	}
+	if (!inode->i_dev) {
+		printk("free_inode: inode has no device\n");
+		return;
+	}
+	if (inode->i_count > 1) {
+		printk("free_inode: inode has count=%d\n", inode->i_count);
+		return;
+	}
+	if (inode->i_nlink) {
+		printk("free_inode: inode has nlink=%d\n", inode->i_nlink);
+		return;
+	}
+	if (!inode->i_sb) {
+		printk("free_inode: inode on nonexistent device\n");
+		return;
+	}
+	if (inode->i_ino < 1) {
+		printk("free_inode: inode 0 or nonexistent inode\n");
+		return;
+	}
+	qnx4_clear_inode(inode);
+	clear_inode(inode);
+}
+
+#endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov