1 /* 2 * QNX4 file system, Linux implementation. 3 * 4 * Version : 0.2.1 5 * 6 * Using parts of the xiafs filesystem. 7 * 8 * History : 9 * 10 * 28-05-1998 by Richard Frowijn : first release. 11 * 20-06-1998 by Frank Denis : basic optimisations. 12 * 25-06-1998 by Frank Denis : qnx4_is_free, qnx4_set_bitmap, qnx4_bmap . 13 * 28-06-1998 by Frank Denis : qnx4_free_inode (to be fixed) . 14 */ 15 16 #include <linux/buffer_head.h> 17 #include <linux/bitops.h> 18 #include "qnx4.h" 19 20 #if 0 21 int qnx4_new_block(struct super_block *sb) 22 { 23 return 0; 24 } 25 #endif /* 0 */ 26 27 static void count_bits(register const char *bmPart, register int size, 28 int *const tf) 29 { 30 char b; 31 int tot = *tf; 32 33 if (size > QNX4_BLOCK_SIZE) { 34 size = QNX4_BLOCK_SIZE; 35 } 36 do { 37 b = *bmPart++; 38 if ((b & 1) == 0) 39 tot++; 40 if ((b & 2) == 0) 41 tot++; 42 if ((b & 4) == 0) 43 tot++; 44 if ((b & 8) == 0) 45 tot++; 46 if ((b & 16) == 0) 47 tot++; 48 if ((b & 32) == 0) 49 tot++; 50 if ((b & 64) == 0) 51 tot++; 52 if ((b & 128) == 0) 53 tot++; 54 size--; 55 } while (size != 0); 56 *tf = tot; 57 } 58 59 unsigned long qnx4_count_free_blocks(struct super_block *sb) 60 { 61 int start = le32_to_cpu(qnx4_sb(sb)->BitMap->di_first_xtnt.xtnt_blk) - 1; 62 int total = 0; 63 int total_free = 0; 64 int offset = 0; 65 int size = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size); 66 struct buffer_head *bh; 67 68 while (total < size) { 69 if ((bh = sb_bread(sb, start + offset)) == NULL) { 70 printk("qnx4: I/O error in counting free blocks\n"); 71 break; 72 } 73 count_bits(bh->b_data, size - total, &total_free); 74 brelse(bh); 75 total += QNX4_BLOCK_SIZE; 76 offset++; 77 } 78 79 return total_free; 80 } 81 82 #ifdef CONFIG_QNX4FS_RW 83 84 int qnx4_is_free(struct super_block *sb, long block) 85 { 86 int start = le32_to_cpu(qnx4_sb(sb)->BitMap->di_first_xtnt.xtnt_blk) - 1; 87 int size = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size); 88 struct buffer_head *bh; 89 const char *g; 90 int ret = -EIO; 91 92 start += block / (QNX4_BLOCK_SIZE * 8); 93 QNX4DEBUG(("qnx4: is_free requesting block [%lu], bitmap in block [%lu]\n", 94 (unsigned long) block, (unsigned long) start)); 95 (void) size; /* CHECKME */ 96 bh = sb_bread(sb, start); 97 if (bh == NULL) { 98 return -EIO; 99 } 100 g = bh->b_data + (block % QNX4_BLOCK_SIZE); 101 if (((*g) & (1 << (block % 8))) == 0) { 102 QNX4DEBUG(("qnx4: is_free -> block is free\n")); 103 ret = 1; 104 } else { 105 QNX4DEBUG(("qnx4: is_free -> block is busy\n")); 106 ret = 0; 107 } 108 brelse(bh); 109 110 return ret; 111 } 112 113 int qnx4_set_bitmap(struct super_block *sb, long block, int busy) 114 { 115 int start = le32_to_cpu(qnx4_sb(sb)->BitMap->di_first_xtnt.xtnt_blk) - 1; 116 int size = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size); 117 struct buffer_head *bh; 118 char *g; 119 120 start += block / (QNX4_BLOCK_SIZE * 8); 121 QNX4DEBUG(("qnx4: set_bitmap requesting block [%lu], bitmap in block [%lu]\n", 122 (unsigned long) block, (unsigned long) start)); 123 (void) size; /* CHECKME */ 124 bh = sb_bread(sb, start); 125 if (bh == NULL) { 126 return -EIO; 127 } 128 g = bh->b_data + (block % QNX4_BLOCK_SIZE); 129 if (busy == 0) { 130 (*g) &= ~(1 << (block % 8)); 131 } else { 132 (*g) |= (1 << (block % 8)); 133 } 134 mark_buffer_dirty(bh); 135 brelse(bh); 136 137 return 0; 138 } 139 140 static void qnx4_clear_inode(struct inode *inode) 141 { 142 struct qnx4_inode_entry *qnx4_ino = qnx4_raw_inode(inode); 143 /* What for? */ 144 memset(qnx4_ino->di_fname, 0, sizeof qnx4_ino->di_fname); 145 qnx4_ino->di_size = 0; 146 qnx4_ino->di_num_xtnts = 0; 147 qnx4_ino->di_mode = 0; 148 qnx4_ino->di_status = 0; 149 } 150 151 void qnx4_free_inode(struct inode *inode) 152 { 153 if (inode->i_ino < 1) { 154 printk("free_inode: inode 0 or nonexistent inode\n"); 155 return; 156 } 157 qnx4_clear_inode(inode); 158 clear_inode(inode); 159 } 160 161 #endif 162