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