1433d6423SLionel Sambuc /* This file manages the super block table and the related data structures, 2433d6423SLionel Sambuc * namely, the bit maps that keep track of which zones and which inodes are 3433d6423SLionel Sambuc * allocated and which are free. When a new inode or zone is needed, the 4433d6423SLionel Sambuc * appropriate bit map is searched for a free entry. 5433d6423SLionel Sambuc * 6433d6423SLionel Sambuc * The entry points into this file are 7433d6423SLionel Sambuc * alloc_bit: somebody wants to allocate a zone or inode; find one 8433d6423SLionel Sambuc * free_bit: indicate that a zone or inode is available for allocation 9433d6423SLionel Sambuc * get_super: search the 'superblock' table for a device 10433d6423SLionel Sambuc * mounted: tells if file inode is on mounted (or ROOT) file system 11433d6423SLionel Sambuc * read_super: read a superblock 12433d6423SLionel Sambuc */ 13433d6423SLionel Sambuc 14433d6423SLionel Sambuc #include "fs.h" 15433d6423SLionel Sambuc #include <string.h> 16433d6423SLionel Sambuc #include <assert.h> 17433d6423SLionel Sambuc #include <minix/com.h> 18433d6423SLionel Sambuc #include <minix/u64.h> 19433d6423SLionel Sambuc #include <minix/bdev.h> 20433d6423SLionel Sambuc #include <machine/param.h> 21433d6423SLionel Sambuc #include <machine/vmparam.h> 22433d6423SLionel Sambuc #include "buf.h" 23433d6423SLionel Sambuc #include "inode.h" 24433d6423SLionel Sambuc #include "super.h" 25433d6423SLionel Sambuc #include "const.h" 26433d6423SLionel Sambuc 27433d6423SLionel Sambuc /*===========================================================================* 28433d6423SLionel Sambuc * alloc_bit * 29433d6423SLionel Sambuc *===========================================================================*/ 30433d6423SLionel Sambuc bit_t alloc_bit(sp, map, origin) 31433d6423SLionel Sambuc struct super_block *sp; /* the filesystem to allocate from */ 32433d6423SLionel Sambuc int map; /* IMAP (inode map) or ZMAP (zone map) */ 33433d6423SLionel Sambuc bit_t origin; /* number of bit to start searching at */ 34433d6423SLionel Sambuc { 35433d6423SLionel Sambuc /* Allocate a bit from a bit map and return its bit number. */ 36433d6423SLionel Sambuc 37433d6423SLionel Sambuc block_t start_block; /* first bit block */ 38433d6423SLionel Sambuc block_t block; 39433d6423SLionel Sambuc bit_t map_bits; /* how many bits are there in the bit map? */ 40433d6423SLionel Sambuc short bit_blocks; /* how many blocks are there in the bit map? */ 41433d6423SLionel Sambuc unsigned word, bcount; 42433d6423SLionel Sambuc struct buf *bp; 43433d6423SLionel Sambuc bitchunk_t *wptr, *wlim, k; 44433d6423SLionel Sambuc bit_t i, b; 45433d6423SLionel Sambuc 46433d6423SLionel Sambuc if (sp->s_rd_only) 47433d6423SLionel Sambuc panic("can't allocate bit on read-only filesys"); 48433d6423SLionel Sambuc 49433d6423SLionel Sambuc if (map == IMAP) { 50433d6423SLionel Sambuc start_block = START_BLOCK; 51433d6423SLionel Sambuc map_bits = (bit_t) (sp->s_ninodes + 1); 52433d6423SLionel Sambuc bit_blocks = sp->s_imap_blocks; 53433d6423SLionel Sambuc } else { 54433d6423SLionel Sambuc start_block = START_BLOCK + sp->s_imap_blocks; 55433d6423SLionel Sambuc map_bits = (bit_t) (sp->s_zones - (sp->s_firstdatazone - 1)); 56433d6423SLionel Sambuc bit_blocks = sp->s_zmap_blocks; 57433d6423SLionel Sambuc } 58433d6423SLionel Sambuc 59433d6423SLionel Sambuc /* Figure out where to start the bit search (depends on 'origin'). */ 60433d6423SLionel Sambuc if (origin >= map_bits) origin = 0; /* for robustness */ 61433d6423SLionel Sambuc 62433d6423SLionel Sambuc /* Locate the starting place. */ 63433d6423SLionel Sambuc block = (block_t) (origin / FS_BITS_PER_BLOCK(sp->s_block_size)); 64433d6423SLionel Sambuc word = (origin % FS_BITS_PER_BLOCK(sp->s_block_size)) / FS_BITCHUNK_BITS; 65433d6423SLionel Sambuc 66433d6423SLionel Sambuc /* Iterate over all blocks plus one, because we start in the middle. */ 67433d6423SLionel Sambuc bcount = bit_blocks + 1; 68433d6423SLionel Sambuc do { 69433d6423SLionel Sambuc bp = get_block(sp->s_dev, start_block + block, NORMAL); 70433d6423SLionel Sambuc wlim = &b_bitmap(bp)[FS_BITMAP_CHUNKS(sp->s_block_size)]; 71433d6423SLionel Sambuc 72433d6423SLionel Sambuc /* Iterate over the words in block. */ 73433d6423SLionel Sambuc for (wptr = &b_bitmap(bp)[word]; wptr < wlim; wptr++) { 74433d6423SLionel Sambuc 75433d6423SLionel Sambuc /* Does this word contain a free bit? */ 76433d6423SLionel Sambuc if (*wptr == (bitchunk_t) ~0) continue; 77433d6423SLionel Sambuc 78433d6423SLionel Sambuc /* Find and allocate the free bit. */ 79433d6423SLionel Sambuc k = (bitchunk_t) conv4(sp->s_native, (int) *wptr); 80433d6423SLionel Sambuc for (i = 0; (k & (1 << i)) != 0; ++i) {} 81433d6423SLionel Sambuc 82433d6423SLionel Sambuc /* Bit number from the start of the bit map. */ 83433d6423SLionel Sambuc b = ((bit_t) block * FS_BITS_PER_BLOCK(sp->s_block_size)) 84433d6423SLionel Sambuc + (wptr - &b_bitmap(bp)[0]) * FS_BITCHUNK_BITS 85433d6423SLionel Sambuc + i; 86433d6423SLionel Sambuc 87433d6423SLionel Sambuc /* Don't allocate bits beyond the end of the map. */ 88433d6423SLionel Sambuc if (b >= map_bits) break; 89433d6423SLionel Sambuc 90433d6423SLionel Sambuc /* Allocate and return bit number. */ 91433d6423SLionel Sambuc k |= 1 << i; 92433d6423SLionel Sambuc *wptr = (bitchunk_t) conv4(sp->s_native, (int) k); 93433d6423SLionel Sambuc MARKDIRTY(bp); 940314acfbSDavid van Moolenbroek put_block(bp); 95433d6423SLionel Sambuc if(map == ZMAP) { 96*1311233cSDavid van Moolenbroek used_zones++; 97*1311233cSDavid van Moolenbroek lmfs_change_blockusage(1); 98433d6423SLionel Sambuc } 99433d6423SLionel Sambuc return(b); 100433d6423SLionel Sambuc } 1010314acfbSDavid van Moolenbroek put_block(bp); 102433d6423SLionel Sambuc if (++block >= (unsigned int) bit_blocks) /* last block, wrap around */ 103433d6423SLionel Sambuc block = 0; 104433d6423SLionel Sambuc word = 0; 105433d6423SLionel Sambuc } while (--bcount > 0); 106433d6423SLionel Sambuc return(NO_BIT); /* no bit could be allocated */ 107433d6423SLionel Sambuc } 108433d6423SLionel Sambuc 109433d6423SLionel Sambuc /*===========================================================================* 110433d6423SLionel Sambuc * free_bit * 111433d6423SLionel Sambuc *===========================================================================*/ 112433d6423SLionel Sambuc void free_bit(sp, map, bit_returned) 113433d6423SLionel Sambuc struct super_block *sp; /* the filesystem to operate on */ 114433d6423SLionel Sambuc int map; /* IMAP (inode map) or ZMAP (zone map) */ 115433d6423SLionel Sambuc bit_t bit_returned; /* number of bit to insert into the map */ 116433d6423SLionel Sambuc { 117433d6423SLionel Sambuc /* Return a zone or inode by turning off its bitmap bit. */ 118433d6423SLionel Sambuc 119433d6423SLionel Sambuc unsigned block, word, bit; 120433d6423SLionel Sambuc struct buf *bp; 121433d6423SLionel Sambuc bitchunk_t k, mask; 122433d6423SLionel Sambuc block_t start_block; 123433d6423SLionel Sambuc 124433d6423SLionel Sambuc if (sp->s_rd_only) 125433d6423SLionel Sambuc panic("can't free bit on read-only filesys"); 126433d6423SLionel Sambuc 127433d6423SLionel Sambuc if (map == IMAP) { 128433d6423SLionel Sambuc start_block = START_BLOCK; 129433d6423SLionel Sambuc } else { 130433d6423SLionel Sambuc start_block = START_BLOCK + sp->s_imap_blocks; 131433d6423SLionel Sambuc } 132433d6423SLionel Sambuc block = bit_returned / FS_BITS_PER_BLOCK(sp->s_block_size); 133433d6423SLionel Sambuc word = (bit_returned % FS_BITS_PER_BLOCK(sp->s_block_size)) 134433d6423SLionel Sambuc / FS_BITCHUNK_BITS; 135433d6423SLionel Sambuc 136433d6423SLionel Sambuc bit = bit_returned % FS_BITCHUNK_BITS; 137433d6423SLionel Sambuc mask = 1 << bit; 138433d6423SLionel Sambuc 139433d6423SLionel Sambuc bp = get_block(sp->s_dev, start_block + block, NORMAL); 140433d6423SLionel Sambuc 141433d6423SLionel Sambuc k = (bitchunk_t) conv4(sp->s_native, (int) b_bitmap(bp)[word]); 142433d6423SLionel Sambuc if (!(k & mask)) { 143433d6423SLionel Sambuc if (map == IMAP) panic("tried to free unused inode"); 144433d6423SLionel Sambuc else panic("tried to free unused block: %u", bit_returned); 145433d6423SLionel Sambuc } 146433d6423SLionel Sambuc 147433d6423SLionel Sambuc k &= ~mask; 148433d6423SLionel Sambuc b_bitmap(bp)[word] = (bitchunk_t) conv4(sp->s_native, (int) k); 149433d6423SLionel Sambuc MARKDIRTY(bp); 150433d6423SLionel Sambuc 1510314acfbSDavid van Moolenbroek put_block(bp); 152433d6423SLionel Sambuc 153433d6423SLionel Sambuc if(map == ZMAP) { 154*1311233cSDavid van Moolenbroek used_zones--; 155*1311233cSDavid van Moolenbroek lmfs_change_blockusage(-1); 156433d6423SLionel Sambuc } 157433d6423SLionel Sambuc } 158433d6423SLionel Sambuc 159433d6423SLionel Sambuc /*===========================================================================* 160433d6423SLionel Sambuc * get_super * 161433d6423SLionel Sambuc *===========================================================================*/ 162433d6423SLionel Sambuc struct super_block *get_super( 163433d6423SLionel Sambuc dev_t dev /* device number whose super_block is sought */ 164433d6423SLionel Sambuc ) 165433d6423SLionel Sambuc { 166433d6423SLionel Sambuc if (dev == NO_DEV) 167433d6423SLionel Sambuc panic("request for super_block of NO_DEV"); 168433d6423SLionel Sambuc 169433d6423SLionel Sambuc if(superblock.s_dev != dev) 170433d6423SLionel Sambuc panic("wrong superblock: 0x%x", (int) dev); 171433d6423SLionel Sambuc 172433d6423SLionel Sambuc return(&superblock); 173433d6423SLionel Sambuc } 174433d6423SLionel Sambuc 175433d6423SLionel Sambuc 176433d6423SLionel Sambuc /*===========================================================================* 177433d6423SLionel Sambuc * get_block_size * 178433d6423SLionel Sambuc *===========================================================================*/ 179433d6423SLionel Sambuc unsigned int get_block_size(dev_t dev) 180433d6423SLionel Sambuc { 181433d6423SLionel Sambuc if (dev == NO_DEV) 182433d6423SLionel Sambuc panic("request for block size of NO_DEV"); 183433d6423SLionel Sambuc 184433d6423SLionel Sambuc return(lmfs_fs_block_size()); 185433d6423SLionel Sambuc } 186433d6423SLionel Sambuc 187433d6423SLionel Sambuc 188433d6423SLionel Sambuc /*===========================================================================* 189433d6423SLionel Sambuc * rw_super * 190433d6423SLionel Sambuc *===========================================================================*/ 191433d6423SLionel Sambuc static int rw_super(struct super_block *sp, int writing) 192433d6423SLionel Sambuc { 193433d6423SLionel Sambuc /* Read/write a superblock. */ 194433d6423SLionel Sambuc dev_t save_dev = sp->s_dev; 195433d6423SLionel Sambuc struct buf *bp; 196433d6423SLionel Sambuc char *sbbuf; 197433d6423SLionel Sambuc 198433d6423SLionel Sambuc /* To keep the 1kb on disk clean, only read/write up to and including 199433d6423SLionel Sambuc * this field. 200433d6423SLionel Sambuc */ 201433d6423SLionel Sambuc #define LAST_ONDISK_FIELD s_disk_version 202433d6423SLionel Sambuc int ondisk_bytes = (int) ((char *) &sp->LAST_ONDISK_FIELD - (char *) sp) 203433d6423SLionel Sambuc + sizeof(sp->LAST_ONDISK_FIELD); 204433d6423SLionel Sambuc 205433d6423SLionel Sambuc assert(ondisk_bytes > 0); 206433d6423SLionel Sambuc assert(ondisk_bytes < PAGE_SIZE); 207433d6423SLionel Sambuc assert(ondisk_bytes < sizeof(struct super_block)); 208433d6423SLionel Sambuc 209433d6423SLionel Sambuc if (sp->s_dev == NO_DEV) 210433d6423SLionel Sambuc panic("request for super_block of NO_DEV"); 211433d6423SLionel Sambuc 212433d6423SLionel Sambuc /* we rely on the cache blocksize, before reading the 213433d6423SLionel Sambuc * superblock, being big enough that our complete superblock 214433d6423SLionel Sambuc * is in block 0. 215433d6423SLionel Sambuc * 216433d6423SLionel Sambuc * copy between the disk block and the superblock buffer (depending 217433d6423SLionel Sambuc * on direction). mark the disk block dirty if the copy is into the 218433d6423SLionel Sambuc * disk block. 219433d6423SLionel Sambuc */ 220433d6423SLionel Sambuc assert(lmfs_fs_block_size() >= sizeof(struct super_block) + SUPER_BLOCK_BYTES); 221433d6423SLionel Sambuc assert(SUPER_BLOCK_BYTES >= sizeof(struct super_block)); 222433d6423SLionel Sambuc assert(SUPER_BLOCK_BYTES >= ondisk_bytes); 223433d6423SLionel Sambuc if(!(bp = get_block(sp->s_dev, 0, NORMAL))) 224433d6423SLionel Sambuc panic("get_block of superblock failed"); 225433d6423SLionel Sambuc 226433d6423SLionel Sambuc /* sbbuf points to the disk block at the superblock offset */ 227433d6423SLionel Sambuc sbbuf = (char *) b_data(bp) + SUPER_BLOCK_BYTES; 228433d6423SLionel Sambuc 229433d6423SLionel Sambuc if(writing) { 230433d6423SLionel Sambuc memset(b_data(bp), 0, lmfs_fs_block_size()); 231433d6423SLionel Sambuc memcpy(sbbuf, sp, ondisk_bytes); 232433d6423SLionel Sambuc lmfs_markdirty(bp); 233433d6423SLionel Sambuc } else { 234433d6423SLionel Sambuc memset(sp, 0, sizeof(*sp)); 235433d6423SLionel Sambuc memcpy(sp, sbbuf, ondisk_bytes); 236433d6423SLionel Sambuc sp->s_dev = save_dev; 237433d6423SLionel Sambuc } 238433d6423SLionel Sambuc 2390314acfbSDavid van Moolenbroek put_block(bp); 240433d6423SLionel Sambuc lmfs_flushall(); 241433d6423SLionel Sambuc 242433d6423SLionel Sambuc return OK; 243433d6423SLionel Sambuc } 244433d6423SLionel Sambuc 245433d6423SLionel Sambuc /*===========================================================================* 246433d6423SLionel Sambuc * read_super * 247433d6423SLionel Sambuc *===========================================================================*/ 248433d6423SLionel Sambuc int read_super(struct super_block *sp) 249433d6423SLionel Sambuc { 250433d6423SLionel Sambuc unsigned int magic; 251433d6423SLionel Sambuc block_t offset; 252433d6423SLionel Sambuc int version, native, r; 253433d6423SLionel Sambuc 254433d6423SLionel Sambuc if((r=rw_super(sp, 0)) != OK) 255433d6423SLionel Sambuc return r; 256433d6423SLionel Sambuc 257433d6423SLionel Sambuc magic = sp->s_magic; /* determines file system type */ 258433d6423SLionel Sambuc 259433d6423SLionel Sambuc if(magic == SUPER_V2 || magic == SUPER_MAGIC) { 260433d6423SLionel Sambuc printf("MFS: only supports V3 filesystems.\n"); 261433d6423SLionel Sambuc return EINVAL; 262433d6423SLionel Sambuc } 263433d6423SLionel Sambuc 264433d6423SLionel Sambuc /* Get file system version and type - only support v3. */ 265433d6423SLionel Sambuc if(magic != SUPER_V3) { 266433d6423SLionel Sambuc return EINVAL; 267433d6423SLionel Sambuc } 268433d6423SLionel Sambuc version = V3; 269433d6423SLionel Sambuc native = 1; 270433d6423SLionel Sambuc 271433d6423SLionel Sambuc /* If the super block has the wrong byte order, swap the fields; the magic 272433d6423SLionel Sambuc * number doesn't need conversion. */ 273433d6423SLionel Sambuc sp->s_ninodes = (ino_t) conv4(native, (int) sp->s_ninodes); 274433d6423SLionel Sambuc sp->s_nzones = (zone1_t) conv2(native, (int) sp->s_nzones); 275433d6423SLionel Sambuc sp->s_imap_blocks = (short) conv2(native, (int) sp->s_imap_blocks); 276433d6423SLionel Sambuc sp->s_zmap_blocks = (short) conv2(native, (int) sp->s_zmap_blocks); 277433d6423SLionel Sambuc sp->s_firstdatazone_old =(zone1_t)conv2(native,(int)sp->s_firstdatazone_old); 278433d6423SLionel Sambuc sp->s_log_zone_size = (short) conv2(native, (int) sp->s_log_zone_size); 279433d6423SLionel Sambuc sp->s_max_size = (off_t) conv4(native, sp->s_max_size); 280433d6423SLionel Sambuc sp->s_zones = (zone_t)conv4(native, sp->s_zones); 281433d6423SLionel Sambuc 282*1311233cSDavid van Moolenbroek /* Zones consisting of multiple blocks are longer supported, so fail as early 283*1311233cSDavid van Moolenbroek * as possible. There is still a lot of code cleanup to do here, though. 284*1311233cSDavid van Moolenbroek */ 285*1311233cSDavid van Moolenbroek if (sp->s_log_zone_size != 0) { 286*1311233cSDavid van Moolenbroek printf("MFS: block and zone sizes are different\n"); 287*1311233cSDavid van Moolenbroek return EINVAL; 288*1311233cSDavid van Moolenbroek } 289*1311233cSDavid van Moolenbroek 290433d6423SLionel Sambuc /* Calculate some other numbers that depend on the version here too, to 291433d6423SLionel Sambuc * hide some of the differences. 292433d6423SLionel Sambuc */ 293433d6423SLionel Sambuc assert(version == V3); 294433d6423SLionel Sambuc sp->s_block_size = (unsigned short) conv2(native,(int) sp->s_block_size); 295433d6423SLionel Sambuc if (sp->s_block_size < PAGE_SIZE) { 296433d6423SLionel Sambuc return EINVAL; 297433d6423SLionel Sambuc } 298433d6423SLionel Sambuc sp->s_inodes_per_block = V2_INODES_PER_BLOCK(sp->s_block_size); 299433d6423SLionel Sambuc sp->s_ndzones = V2_NR_DZONES; 300433d6423SLionel Sambuc sp->s_nindirs = V2_INDIRECTS(sp->s_block_size); 301433d6423SLionel Sambuc 302433d6423SLionel Sambuc /* For even larger disks, a similar problem occurs with s_firstdatazone. 303433d6423SLionel Sambuc * If the on-disk field contains zero, we assume that the value was too 304433d6423SLionel Sambuc * large to fit, and compute it on the fly. 305433d6423SLionel Sambuc */ 306433d6423SLionel Sambuc if (sp->s_firstdatazone_old == 0) { 307433d6423SLionel Sambuc offset = START_BLOCK + sp->s_imap_blocks + sp->s_zmap_blocks; 308433d6423SLionel Sambuc offset += (sp->s_ninodes + sp->s_inodes_per_block - 1) / 309433d6423SLionel Sambuc sp->s_inodes_per_block; 310433d6423SLionel Sambuc 311433d6423SLionel Sambuc sp->s_firstdatazone = (offset + (1 << sp->s_log_zone_size) - 1) >> 312433d6423SLionel Sambuc sp->s_log_zone_size; 313433d6423SLionel Sambuc } else { 314433d6423SLionel Sambuc sp->s_firstdatazone = (zone_t) sp->s_firstdatazone_old; 315433d6423SLionel Sambuc } 316433d6423SLionel Sambuc 317433d6423SLionel Sambuc if (sp->s_block_size < PAGE_SIZE) 318433d6423SLionel Sambuc return(EINVAL); 319433d6423SLionel Sambuc 320433d6423SLionel Sambuc if ((sp->s_block_size % 512) != 0) 321433d6423SLionel Sambuc return(EINVAL); 322433d6423SLionel Sambuc 323433d6423SLionel Sambuc if (SUPER_SIZE > sp->s_block_size) 324433d6423SLionel Sambuc return(EINVAL); 325433d6423SLionel Sambuc 326433d6423SLionel Sambuc if ((sp->s_block_size % V2_INODE_SIZE) != 0) { 327433d6423SLionel Sambuc return(EINVAL); 328433d6423SLionel Sambuc } 329433d6423SLionel Sambuc 330433d6423SLionel Sambuc /* Limit s_max_size to LONG_MAX */ 331433d6423SLionel Sambuc if ((unsigned long)sp->s_max_size > LONG_MAX) 332433d6423SLionel Sambuc sp->s_max_size = LONG_MAX; 333433d6423SLionel Sambuc 334433d6423SLionel Sambuc sp->s_isearch = 0; /* inode searches initially start at 0 */ 335433d6423SLionel Sambuc sp->s_zsearch = 0; /* zone searches initially start at 0 */ 336433d6423SLionel Sambuc sp->s_version = version; 337433d6423SLionel Sambuc sp->s_native = native; 338433d6423SLionel Sambuc 339433d6423SLionel Sambuc /* Make a few basic checks to see if super block looks reasonable. */ 340433d6423SLionel Sambuc if (sp->s_imap_blocks < 1 || sp->s_zmap_blocks < 1 341433d6423SLionel Sambuc || sp->s_ninodes < 1 || sp->s_zones < 1 342433d6423SLionel Sambuc || sp->s_firstdatazone <= 4 343433d6423SLionel Sambuc || sp->s_firstdatazone >= sp->s_zones 344433d6423SLionel Sambuc || (unsigned) sp->s_log_zone_size > 4) { 345433d6423SLionel Sambuc printf("not enough imap or zone map blocks, \n"); 346433d6423SLionel Sambuc printf("or not enough inodes, or not enough zones, \n" 347433d6423SLionel Sambuc "or invalid first data zone, or zone size too large\n"); 348433d6423SLionel Sambuc return(EINVAL); 349433d6423SLionel Sambuc } 350433d6423SLionel Sambuc 351433d6423SLionel Sambuc 352433d6423SLionel Sambuc /* Check any flags we don't understand but are required to. Currently 353433d6423SLionel Sambuc * these don't exist so all such unknown bits are fatal. 354433d6423SLionel Sambuc */ 355433d6423SLionel Sambuc if(sp->s_flags & MFSFLAG_MANDATORY_MASK) { 356433d6423SLionel Sambuc printf("MFS: unsupported feature flags on this FS.\n" 357433d6423SLionel Sambuc "Please use a newer MFS to mount it.\n"); 358433d6423SLionel Sambuc return(EINVAL); 359433d6423SLionel Sambuc } 360433d6423SLionel Sambuc 361433d6423SLionel Sambuc return(OK); 362433d6423SLionel Sambuc } 363433d6423SLionel Sambuc 364433d6423SLionel Sambuc /*===========================================================================* 365433d6423SLionel Sambuc * write_super * 366433d6423SLionel Sambuc *===========================================================================*/ 367433d6423SLionel Sambuc int write_super(struct super_block *sp) 368433d6423SLionel Sambuc { 369433d6423SLionel Sambuc if(sp->s_rd_only) 370433d6423SLionel Sambuc panic("can't write superblock of readonly filesystem"); 371433d6423SLionel Sambuc return rw_super(sp, 1); 372433d6423SLionel Sambuc } 373