00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "fs.h"
00015 #include <string.h>
00016 #include <minix/com.h>
00017 #include "buf.h"
00018 #include "inode.h"
00019 #include "super.h"
00020 #include "const.h"
00021
00022
00023
00024
00025 PUBLIC bit_t alloc_bit(sp, map, origin)
00026 struct super_block *sp;
00027 int map;
00028 bit_t origin;
00029 {
00030
00031
00032 block_t start_block;
00033 bit_t map_bits;
00034 unsigned bit_blocks;
00035 unsigned block, word, bcount;
00036 struct buf *bp;
00037 bitchunk_t *wptr, *wlim, k;
00038 bit_t i, b;
00039
00040 if (sp->s_rd_only)
00041 panic(__FILE__,"can't allocate bit on read-only filesys.", NO_NUM);
00042
00043 if (map == IMAP) {
00044 start_block = START_BLOCK;
00045 map_bits = sp->s_ninodes + 1;
00046 bit_blocks = sp->s_imap_blocks;
00047 } else {
00048 start_block = START_BLOCK + sp->s_imap_blocks;
00049 map_bits = sp->s_zones - (sp->s_firstdatazone - 1);
00050 bit_blocks = sp->s_zmap_blocks;
00051 }
00052
00053
00054 if (origin >= map_bits) origin = 0;
00055
00056
00057 block = origin / FS_BITS_PER_BLOCK(sp->s_block_size);
00058 word = (origin % FS_BITS_PER_BLOCK(sp->s_block_size)) / FS_BITCHUNK_BITS;
00059
00060
00061 bcount = bit_blocks + 1;
00062 do {
00063 bp = get_block(sp->s_dev, start_block + block, NORMAL);
00064 wlim = &bp->b_bitmap[FS_BITMAP_CHUNKS(sp->s_block_size)];
00065
00066
00067 for (wptr = &bp->b_bitmap[word]; wptr < wlim; wptr++) {
00068
00069
00070 if (*wptr == (bitchunk_t) ~0) continue;
00071
00072
00073 k = conv2(sp->s_native, (int) *wptr);
00074 for (i = 0; (k & (1 << i)) != 0; ++i) {}
00075
00076
00077 b = ((bit_t) block * FS_BITS_PER_BLOCK(sp->s_block_size))
00078 + (wptr - &bp->b_bitmap[0]) * FS_BITCHUNK_BITS
00079 + i;
00080
00081
00082 if (b >= map_bits) break;
00083
00084
00085 k |= 1 << i;
00086 *wptr = conv2(sp->s_native, (int) k);
00087 bp->b_dirt = DIRTY;
00088 put_block(bp, MAP_BLOCK);
00089 return(b);
00090 }
00091 put_block(bp, MAP_BLOCK);
00092 if (++block >= bit_blocks) block = 0;
00093 word = 0;
00094 } while (--bcount > 0);
00095 return(NO_BIT);
00096 }
00097
00098
00099
00100
00101 PUBLIC void free_bit(sp, map, bit_returned)
00102 struct super_block *sp;
00103 int map;
00104 bit_t bit_returned;
00105 {
00106
00107
00108 unsigned block, word, bit;
00109 struct buf *bp;
00110 bitchunk_t k, mask;
00111 block_t start_block;
00112
00113 if (sp->s_rd_only)
00114 panic(__FILE__,"can't free bit on read-only filesys.", NO_NUM);
00115
00116 if (map == IMAP) {
00117 start_block = START_BLOCK;
00118 } else {
00119 start_block = START_BLOCK + sp->s_imap_blocks;
00120 }
00121 block = bit_returned / FS_BITS_PER_BLOCK(sp->s_block_size);
00122 word = (bit_returned % FS_BITS_PER_BLOCK(sp->s_block_size))
00123 / FS_BITCHUNK_BITS;
00124
00125 bit = bit_returned % FS_BITCHUNK_BITS;
00126 mask = 1 << bit;
00127
00128 bp = get_block(sp->s_dev, start_block + block, NORMAL);
00129
00130 k = conv2(sp->s_native, (int) bp->b_bitmap[word]);
00131 if (!(k & mask)) {
00132 panic(__FILE__,map == IMAP ? "tried to free unused inode" :
00133 "tried to free unused block", bit_returned);
00134 }
00135
00136 k &= ~mask;
00137 bp->b_bitmap[word] = conv2(sp->s_native, (int) k);
00138 bp->b_dirt = DIRTY;
00139
00140 put_block(bp, MAP_BLOCK);
00141 }
00142
00143
00144
00145
00146 PUBLIC struct super_block *get_super(dev)
00147 dev_t dev;
00148 {
00149
00150
00151 register struct super_block *sp;
00152
00153 if (dev == NO_DEV)
00154 panic(__FILE__,"request for super_block of NO_DEV", NO_NUM);
00155
00156 for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
00157 if (sp->s_dev == dev) return(sp);
00158
00159
00160 panic(__FILE__,"can't find superblock for device (in decimal)", (int) dev);
00161
00162 return(NIL_SUPER);
00163 }
00164
00165
00166
00167
00168 PUBLIC int get_block_size(dev_t dev)
00169 {
00170
00171
00172 register struct super_block *sp;
00173
00174 if (dev == NO_DEV)
00175 panic(__FILE__,"request for block size of NO_DEV", NO_NUM);
00176
00177 for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++) {
00178 if (sp->s_dev == dev) {
00179 return(sp->s_block_size);
00180 }
00181 }
00182
00183
00184 return _MIN_BLOCK_SIZE;
00185 }
00186
00187
00188
00189
00190 PUBLIC int mounted(rip)
00191 register struct inode *rip;
00192 {
00193
00194
00195 register struct super_block *sp;
00196 register dev_t dev;
00197
00198 dev = (dev_t) rip->i_zone[0];
00199 if (dev == root_dev) return(TRUE);
00200
00201 for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
00202 if (sp->s_dev == dev) return(TRUE);
00203
00204 return(FALSE);
00205 }
00206
00207
00208
00209
00210 PUBLIC int read_super(sp)
00211 register struct super_block *sp;
00212 {
00213
00214 dev_t dev;
00215 int magic;
00216 int version, native, r;
00217 static char sbbuf[_MIN_BLOCK_SIZE];
00218
00219 dev = sp->s_dev;
00220 if (dev == NO_DEV)
00221 panic(__FILE__,"request for super_block of NO_DEV", NO_NUM);
00222 r = dev_io(DEV_READ, dev, FS_PROC_NR,
00223 sbbuf, SUPER_BLOCK_BYTES, _MIN_BLOCK_SIZE, 0);
00224 if (r != _MIN_BLOCK_SIZE) {
00225 return EINVAL;
00226 }
00227 memcpy(sp, sbbuf, sizeof(*sp));
00228 sp->s_dev = NO_DEV;
00229 magic = sp->s_magic;
00230
00231
00232 if (magic == SUPER_MAGIC || magic == conv2(BYTE_SWAP, SUPER_MAGIC)) {
00233 version = V1;
00234 native = (magic == SUPER_MAGIC);
00235 } else if (magic == SUPER_V2 || magic == conv2(BYTE_SWAP, SUPER_V2)) {
00236 version = V2;
00237 native = (magic == SUPER_V2);
00238 } else if (magic == SUPER_V3) {
00239 version = V3;
00240 native = 1;
00241 } else {
00242 return(EINVAL);
00243 }
00244
00245
00246
00247 sp->s_ninodes = conv4(native, sp->s_ninodes);
00248 sp->s_nzones = conv2(native, (int) sp->s_nzones);
00249 sp->s_imap_blocks = conv2(native, (int) sp->s_imap_blocks);
00250 sp->s_zmap_blocks = conv2(native, (int) sp->s_zmap_blocks);
00251 sp->s_firstdatazone = conv2(native, (int) sp->s_firstdatazone);
00252 sp->s_log_zone_size = conv2(native, (int) sp->s_log_zone_size);
00253 sp->s_max_size = conv4(native, sp->s_max_size);
00254 sp->s_zones = conv4(native, sp->s_zones);
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 if (version == V1) {
00268 sp->s_block_size = _STATIC_BLOCK_SIZE;
00269 sp->s_zones = sp->s_nzones;
00270 sp->s_inodes_per_block = V1_INODES_PER_BLOCK;
00271 sp->s_ndzones = V1_NR_DZONES;
00272 sp->s_nindirs = V1_INDIRECTS;
00273 } else {
00274 if (version == V2)
00275 sp->s_block_size = _STATIC_BLOCK_SIZE;
00276 if (sp->s_block_size < _MIN_BLOCK_SIZE)
00277 return EINVAL;
00278 sp->s_inodes_per_block = V2_INODES_PER_BLOCK(sp->s_block_size);
00279 sp->s_ndzones = V2_NR_DZONES;
00280 sp->s_nindirs = V2_INDIRECTS(sp->s_block_size);
00281 }
00282
00283 if (sp->s_block_size < _MIN_BLOCK_SIZE) {
00284 return EINVAL;
00285 }
00286 if (sp->s_block_size > _MAX_BLOCK_SIZE) {
00287 printf("Filesystem block size is %d kB; maximum filesystem\n"
00288 "block size is %d kB. This limit can be increased by recompiling.\n",
00289 sp->s_block_size/1024, _MAX_BLOCK_SIZE/1024);
00290 return EINVAL;
00291 }
00292 if ((sp->s_block_size % 512) != 0) {
00293 return EINVAL;
00294 }
00295 if (SUPER_SIZE > sp->s_block_size) {
00296 return EINVAL;
00297 }
00298 if ((sp->s_block_size % V2_INODE_SIZE) != 0 ||
00299 (sp->s_block_size % V1_INODE_SIZE) != 0) {
00300 return EINVAL;
00301 }
00302
00303 sp->s_isearch = 0;
00304 sp->s_zsearch = 0;
00305 sp->s_version = version;
00306 sp->s_native = native;
00307
00308
00309 if (sp->s_imap_blocks < 1 || sp->s_zmap_blocks < 1
00310 || sp->s_ninodes < 1 || sp->s_zones < 1
00311 || (unsigned) sp->s_log_zone_size > 4) {
00312 printf("not enough imap or zone map blocks, \n");
00313 printf("or not enough inodes, or not enough zones, "
00314 "or zone size too large\n");
00315 return(EINVAL);
00316 }
00317 sp->s_dev = dev;
00318 return(OK);
00319 }