⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 super.c

📁 一个简单的操作系统minix的核心代码
💻 C
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
				src/fs/super.c	 	 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

21900	/* This file manages the super block table and the related data structures,
21901	 * namely, the bit maps that keep track of which zones and which inodes are
21902	 * allocated and which are free.  When a new inode or zone is needed, the
21903	 * appropriate bit map is searched for a free entry.
21904	 *
21905	 * The entry points into this file are
21906	 *   alloc_bit:       somebody wants to allocate a zone or inode; find one
21907	 *   free_bit:        indicate that a zone or inode is available for allocation
21908	 *   get_super:       search the 'superblock' table for a device
21909	 *   mounted:         tells if file inode is on mounted (or ROOT) file system
21910	 *   read_super:      read a superblock
21911	 */
21912	
21913	#include "fs.h"
21914	#include <string.h>
21915	#include <minix/boot.h>
21916	#include "buf.h"
21917	#include "inode.h"
21918	#include "super.h"
21919	
21920	#define BITCHUNK_BITS   (usizeof(bitchunk_t) * CHAR_BIT)
21921	#define BITS_PER_BLOCK  (BITMAP_CHUNKS * BITCHUNK_BITS)
21922	
21923	/*===========================================================================*
21924	 *                              alloc_bit                                    *
21925	 *===========================================================================*/
21926	PUBLIC bit_t alloc_bit(sp, map, origin)
21927	struct super_block *sp;         /* the filesystem to allocate from */
21928	int map;                        /* IMAP (inode map) or ZMAP (zone map) */
21929	bit_t origin;                   /* number of bit to start searching at */
21930	{
21931	/* Allocate a bit from a bit map and return its bit number. */
21932	
21933	  block_t start_block;          /* first bit block */
21934	  bit_t map_bits;               /* how many bits are there in the bit map? */
21935	  unsigned bit_blocks;          /* how many blocks are there in the bit map? */
21936	  unsigned block, word, bcount, wcount;
21937	  struct buf *bp;
21938	  bitchunk_t *wptr, *wlim, k;
21939	  bit_t i, b;
21940	
21941	  if (sp->s_rd_only)
21942	        panic("can't allocate bit on read-only filesys.", NO_NUM);
21943	
21944	  if (map == IMAP) {
21945	        start_block = SUPER_BLOCK + 1;
21946	        map_bits = sp->s_ninodes + 1;
21947	        bit_blocks = sp->s_imap_blocks;
21948	  } else {
21949	        start_block = SUPER_BLOCK + 1 + sp->s_imap_blocks;
21950	        map_bits = sp->s_zones - (sp->s_firstdatazone - 1);
21951	        bit_blocks = sp->s_zmap_blocks;
21952	  }
21953	
21954	  /* Figure out where to start the bit search (depends on 'origin'). */
21955	  if (origin >= map_bits) origin = 0;   /* for robustness */
21956	
21957	  /* Locate the starting place. */
21958	  block = origin / BITS_PER_BLOCK;
21959	  word = (origin % BITS_PER_BLOCK) / BITCHUNK_BITS;
21960	
21961	  /* Iterate over all blocks plus one, because we start in the middle. */
21962	  bcount = bit_blocks + 1;
21963	  do {
21964	        bp = get_block(sp->s_dev, start_block + block, NORMAL);
21965	        wlim = &bp->b_bitmap[BITMAP_CHUNKS];
21966	
21967	        /* Iterate over the words in block. */
21968	        for (wptr = &bp->b_bitmap[word]; wptr < wlim; wptr++) {
21969	
21970	                /* Does this word contain a free bit? */
21971	                if (*wptr == (bitchunk_t) ~0) continue;
21972	
21973	                /* Find and allocate the free bit. */
21974	                k = conv2(sp->s_native, (int) *wptr);
21975	                for (i = 0; (k & (1 << i)) != 0; ++i) {}
21976	
21977	                /* Bit number from the start of the bit map. */
21978	                b = ((bit_t) block * BITS_PER_BLOCK)
21979	                    + (wptr - &bp->b_bitmap[0]) * BITCHUNK_BITS
21980	                    + i;
21981	
21982	                /* Don't allocate bits beyond the end of the map. */
21983	                if (b >= map_bits) break;
21984	
21985	                /* Allocate and return bit number. */
21986	                k |= 1 << i;
21987	                *wptr = conv2(sp->s_native, (int) k);
21988	                bp->b_dirt = DIRTY;
21989	                put_block(bp, MAP_BLOCK);
21990	                return(b);
21991	        }
21992	        put_block(bp, MAP_BLOCK);
21993	        if (++block >= bit_blocks) block = 0;   /* last block, wrap around */
21994	        word = 0;
21995	  } while (--bcount > 0);
21996	  return(NO_BIT);               /* no bit could be allocated */
21997	}
	
	
22000	/*===========================================================================*
22001	 *                              free_bit                                     *
22002	 *===========================================================================*/
22003	PUBLIC void free_bit(sp, map, bit_returned)
22004	struct super_block *sp;         /* the filesystem to operate on */
22005	int map;                        /* IMAP (inode map) or ZMAP (zone map) */
22006	bit_t bit_returned;             /* number of bit to insert into the map */
22007	{
22008	/* Return a zone or inode by turning off its bitmap bit. */
22009	
22010	  unsigned block, word, bit;
22011	  struct buf *bp;
22012	  bitchunk_t k, mask;
22013	  block_t start_block;
22014	
22015	  if (sp->s_rd_only)
22016	        panic("can't free bit on read-only filesys.", NO_NUM);
22017	
22018	  if (map == IMAP) {
22019	        start_block = SUPER_BLOCK + 1;
22020	  } else {
22021	        start_block = SUPER_BLOCK + 1 + sp->s_imap_blocks;
22022	  }
22023	  block = bit_returned / BITS_PER_BLOCK;
22024	  word = (bit_returned % BITS_PER_BLOCK) / BITCHUNK_BITS;
22025	  bit = bit_returned % BITCHUNK_BITS;
22026	  mask = 1 << bit;
22027	
22028	  bp = get_block(sp->s_dev, start_block + block, NORMAL);
22029	
22030	  k = conv2(sp->s_native, (int) bp->b_bitmap[word]);
22031	  if (!(k & mask)) {
22032	        panic(map == IMAP ? "tried to free unused inode" :
22033	              "tried to free unused block", NO_NUM);
22034	  }
22035	
22036	  k &= ~mask;
22037	  bp->b_bitmap[word] = conv2(sp->s_native, (int) k);
22038	  bp->b_dirt = DIRTY;
22039	
22040	  put_block(bp, MAP_BLOCK);
22041	}
	
	
22044	/*===========================================================================*
22045	 *                              get_super                                    *
22046	 *===========================================================================*/
22047	PUBLIC struct super_block *get_super(dev)
22048	dev_t dev;                      /* device number whose super_block is sought */
22049	{
22050	/* Search the superblock table for this device.  It is supposed to be there. */
22051	
22052	  register struct super_block *sp;
22053	
22054	  for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
22055	        if (sp->s_dev == dev) return(sp);
22056	
22057	  /* Search failed.  Something wrong. */
22058	  panic("can't find superblock for device (in decimal)", (int) dev);
22059	
22060	  return(NIL_SUPER);            /* to keep the compiler and lint quiet */
22061	}
	
	
22064	/*===========================================================================*
22065	 *                              mounted                                      *
22066	 *===========================================================================*/
22067	PUBLIC int mounted(rip)
22068	register struct inode *rip;     /* pointer to inode */
22069	{
22070	/* Report on whether the given inode is on a mounted (or ROOT) file system. */
22071	
22072	  register struct super_block *sp;
22073	  register dev_t dev;
22074	
22075	  dev = (dev_t) rip->i_zone[0];
22076	  if (dev == ROOT_DEV) return(TRUE);    /* inode is on root file system */
22077	
22078	  for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
22079	        if (sp->s_dev == dev) return(TRUE);
22080	
22081	  return(FALSE);
22082	}
	
	
22085	/*===========================================================================*
22086	 *                              read_super                                   *
22087	 *===========================================================================*/
22088	PUBLIC int read_super(sp)
22089	register struct super_block *sp; /* pointer to a superblock */
22090	{
22091	/* Read a superblock. */
22092	
22093	  register struct buf *bp;
22094	  dev_t dev;
22095	  int magic;
22096	  int version, native;
22097	
22098	  dev = sp->s_dev;              /* save device (will be overwritten by copy) */
22099	  bp = get_block(sp->s_dev, SUPER_BLOCK, NORMAL);
22100	  memcpy( (char *) sp, bp->b_data, (size_t) SUPER_SIZE);
22101	  put_block(bp, ZUPER_BLOCK);
22102	  sp->s_dev = NO_DEV;           /* restore later */
22103	  magic = sp->s_magic;          /* determines file system type */
22104	
22105	  /* Get file system version and type. */
22106	  if (magic == SUPER_MAGIC || magic == conv2(BYTE_SWAP, SUPER_MAGIC)) {
22107	        version = V1;
22108	        native  = (magic == SUPER_MAGIC);
22109	  } else if (magic == SUPER_V2 || magic == conv2(BYTE_SWAP, SUPER_V2)) {
22110	        version = V2;
22111	        native  = (magic == SUPER_V2);
22112	  } else {
22113	        return(EINVAL);
22114	  }
22115	
22116	  /* If the super block has the wrong byte order, swap the fields; the magic
22117	   * number doesn't need conversion. */
22118	  sp->s_ninodes =       conv2(native, (int) sp->s_ninodes);
22119	  sp->s_nzones =        conv2(native, (int) sp->s_nzones);
22120	  sp->s_imap_blocks =   conv2(native, (int) sp->s_imap_blocks);
22121	  sp->s_zmap_blocks =   conv2(native, (int) sp->s_zmap_blocks);
22122	  sp->s_firstdatazone = conv2(native, (int) sp->s_firstdatazone);
22123	  sp->s_log_zone_size = conv2(native, (int) sp->s_log_zone_size);
22124	  sp->s_max_size =      conv4(native, sp->s_max_size);
22125	  sp->s_zones =         conv4(native, sp->s_zones);
22126	
22127	  /* In V1, the device size was kept in a short, s_nzones, which limited
22128	   * devices to 32K zones.  For V2, it was decided to keep the size as a
22129	   * long.  However, just changing s_nzones to a long would not work, since
22130	   * then the position of s_magic in the super block would not be the same
22131	   * in V1 and V2 file systems, and there would be no way to tell whether
22132	   * a newly mounted file system was V1 or V2.  The solution was to introduce
22133	   * a new variable, s_zones, and copy the size there.
22134	   *
22135	   * Calculate some other numbers that depend on the version here too, to
22136	   * hide some of the differences.
22137	   */
22138	  if (version == V1) {
22139	        sp->s_zones = sp->s_nzones;     /* only V1 needs this copy */
22140	        sp->s_inodes_per_block = V1_INODES_PER_BLOCK;
22141	        sp->s_ndzones = V1_NR_DZONES;
22142	        sp->s_nindirs = V1_INDIRECTS;
22143	  } else {
22144	        sp->s_inodes_per_block = V2_INODES_PER_BLOCK;
22145	        sp->s_ndzones = V2_NR_DZONES;
22146	        sp->s_nindirs = V2_INDIRECTS;
22147	  }
22148	
22149	  sp->s_isearch = 0;            /* inode searches initially start at 0 */
22150	  sp->s_zsearch = 0;            /* zone searches initially start at 0 */
22151	  sp->s_version = version;
22152	  sp->s_native  = native;
22153	
22154	  /* Make a few basic checks to see if super block looks reasonable. */
22155	  if (sp->s_imap_blocks < 1 || sp->s_zmap_blocks < 1
22156	                                || sp->s_ninodes < 1 || sp->s_zones < 1
22157	                                || (unsigned) sp->s_log_zone_size > 4) {
22158	        return(EINVAL);
22159	  }
22160	  sp->s_dev = dev;              /* restore device number */
22161	  return(OK);
22162	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -