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

📄 inode.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include "cformat.h"#include "lru.h"#include "bcache.h"#include "disk.h"#include "inode.h"#include "stats.h"/* *  read the inode blocks and make sure they *  haven't been trashed. * *  make the in-core table of qid to inode mappings. *	N.B. this is just an array. we need a linear search to find *	     a particular inode. this could be done faster. * *  nab is the first inode block. */intiinit(Icache *ic, int f, int psize){	Ibuf *b;	Imap *m;	ulong ino;	Bbuf *bb;	Dinode *bi;	/*	 *  get basic sizes and allocation info from disk	 */	if(dinit(ic, f, psize) < 0)		return -1;	/*	 *  read first inode block to get number of inodes	 */	bb = bcread(ic, ic->nab);	if(bb == 0){		fprint(2, "iinit: can't read disk\n");		return -1;	}	bi = (Dinode*)bb->data;	if(bi->nino==0 || bi->nino>2048){		fprint(2, "iinit: bad nino\n");		return -1;	}	ic->nino = bi->nino;	/*	 *  set up sizing constants	 */	ic->i2b = (ic->bsize - sizeof(Dihdr))/sizeof(Inode);	ic->nib = (ic->nino + ic->i2b - 1)/ic->i2b;	/*	 *  allocate the in-core qid/inode map, build it's lru	 */	if(ic->map)		free(ic->map);	ic->map = malloc(sizeof(Imap)*ic->nino);	if(ic->map == 0){		fprint(2, "iinit: can't alloc map\n");		return -1;	}	lruinit(&ic->mlru);	for(m = ic->map; m < &ic->map[ic->nino]; m++){		m->inuse = 0;		m->b = 0;		lruadd(&ic->mlru, m);	}	/*	 *  mark all cache buffers as empty, put them on the lru list	 */	lruinit(&ic->blru);	for(b = ic->ib; b < &ic->ib[Nicache]; b++){		b->inuse = 0;		lruadd(&ic->blru, b);	}	/*	 *  Read all inodes and	 *  build the in-core qid/inode map	 */	for(ino = 0; ino < ic->nino; ino++){		b = iread(ic, ino);		if(b == 0){			fprint(2, "iinit: can't read inode %ld\n", ino);			return -1;		}		if(b->inode.inuse){			m = &ic->map[ino];			m->inuse = 1;			m->qid = b->inode.qid;			lruref(&ic->mlru, m);		}	}	return 0;}/* *  format the inode blocks */intiformat(Icache *ic, int f, ulong nino, char *name, int bsize, int psize){	Bbuf *bb;	Dinode *bi;	ulong bno;	ulong i;	ulong i2b;	int nib;	/*	 *  first format disk allocation	 */	if(dformat(ic, f, name, bsize, psize) < 0)		return -1;	fprint(2, "formatting inodes\n");	i2b = (bsize - sizeof(Dihdr))/sizeof(Inode);	nib = (nino + i2b - 1)/i2b;	for(bno = ic->nab; bno < ic->nab + nib; bno++){		if(dalloc(ic, 0) == Notabno){			fprint(2, "iformat: balloc failed\n");			return -1;		}		bb = bcalloc(ic, bno);		if(bb == 0){			fprint(2, "iformat: bcalloc failed\n");			return -1;		}		bi = (Dinode*)bb->data;		bi->magic = Imagic;		bi->nino = nino;		for(i = 0; i < i2b; i++)			bi->inode[i].inuse = 0;		bcmark(ic, bb);	}	bcsync(ic);	return iinit(ic, f, psize);}/* *  allocate a cache buffer, use least recently used */Ibuf*ialloc(Icache *ic, ulong ino){	Imap *m;	Ibuf *b;	b = (Ibuf*)ic->blru.lnext;	if(b->inuse)		ic->map[b->ino].b = 0;	b->ino = ino;	b->inuse = 1;	m = &ic->map[ino];	m->b = b;	return b;}/* *  free a cache buffer */voidifree(Icache *ic, Ibuf *b){	b->inuse = 0;	if(b->inuse)		ic->map[b->ino].b = 0;	lruderef(&ic->blru, b);}/* *  get an inode into the cache.  if no inode exists for this qid, create one *  from an unused qid/inode map. */Ibuf *iget(Icache *ic, Qid qid){	Imap *m, *me;	Ibuf *b;	/*	 *  find map entry with same qid.path	 */	for(m = ic->map, me = &ic->map[ic->nino]; m < me; m++){		if(m->inuse && m->qid.path==qid.path){			if(m->qid.vers != qid.vers){				/*				 *  our info is old, forget it				 */				DPRINT(2, "updating old file %llud.%lud\n",					qid.path, qid.vers);				m->qid = qid;				iupdate(ic, m - ic->map, qid);			}			break;		}	}	/* 	 *  if an already existing inode, just get it	 */	if(m != me)		return iread(ic, m - ic->map);	/*	 *  create a new inode, throw out the least recently used inode	 *  if necessary	 */	m = (Imap*)ic->mlru.lnext;	if(m->inuse){		DPRINT(2, "superceding file %llud.%ld by %llud.%ld\n", m->qid.path,			m->qid.vers, qid.path, qid.vers);		if(iremove(ic, m - ic->map) < 0)			return 0;	}	if(statson){		cfsstat.ninsert++;	}	/*	 *  init inode and write to disk	 */	DPRINT(2, "new file %llud.%ld ino %ld\n", qid.path, qid.vers, m - ic->map);	b = ialloc(ic, m - ic->map);	b->inode.inuse = m->inuse = 1;	b->inode.qid = qid;	b->inode.length = 0x7fffffffffffffffLL;	m->qid = qid;	b->inode.ptr.bno = Notabno;	iwrite(ic, b);	return b;}/* *  read an inode into the cache * *  ASSUMPTION: the inode is valid */Ibuf*iread(Icache *ic, ulong ino){	Ibuf *b;	Imap *m;	ulong bno;	Bbuf *bb;	Dinode *bi;	/*	 *  first see if we already have it in a cache entry	 */	m = &ic->map[ino];	if(m->inuse && m->b){		b = m->b;		goto out;	}	/*	 *  read it	 */	b = ialloc(ic, ino);	bno = ic->nab + ino/ic->i2b;	bb = bcread(ic, bno);	if(bb == 0){		ifree(ic, b);		return 0;	}	bi = (Dinode*)bb->data;	b->inode = bi->inode[ino % ic->i2b];	/*	 *  consistency check	 */	if(bi->nino!=ic->nino || bi->magic!=Imagic){		fprint(2, "iread: inconsistent inode block\n");		ifree(ic, b);		return 0;	}out:	b->inuse = 1;	m->b = b;	if(b->inode.inuse)		lruref(&ic->mlru, m);	lruref(&ic->blru, b);	return b;}/* *  write an inode back to disk */intiwrite(Icache *ic, Ibuf *b){	ulong bno;	Bbuf *bb;	Dinode *bi;	bno = ic->nab + b->ino/ic->i2b;	bb = bcread(ic, bno);	if(bb == 0)		return 0;	bi = (Dinode*)bb->data;	bi->inode[b->ino % ic->i2b] = b->inode;	bcmark(ic, bb);	lruref(&ic->mlru, &ic->map[b->ino]);	lruref(&ic->blru, b);	return 0;}/* *  Forget what we know about an inode without removing it * *	N.B: ordering of iwrite and dfree is important */intiupdate(Icache *ic, ulong ino, Qid qid){	Ibuf *b;	Imap *m;	Dptr d;	if(statson){		cfsstat.nupdate++;	}	b = iread(ic, ino);	if(b == 0)		return -1;	/*	 *  update inode and map	 */	b->inode.qid = qid;	b->inode.length = 0x7fffffffffffffffLL;	/* Set to maximum */	m = &ic->map[ino];	m->qid = qid;	/*	 *  the free is not done if the write fails!	 *  this is important	 */	d = b->inode.ptr;	b->inode.ptr.bno = Notabno;	if(iwrite(ic, b) < 0)		return -1;	dfree(ic, &d);	return 0;}/* *  remove an inode * *	N.B: ordering of iwrite and dfree is important */intiremove(Icache *ic, ulong ino){	Ibuf *b;	Imap *m;	if(statson){		cfsstat.ndelete++;	}	m = &ic->map[ino];	/*	 *  read in inode	 */	b = iread(ic, ino);	if(b == 0)		return -1;	/*	 *  mark it unused on disk	 */	b->inode.inuse = 0;	if(iwrite(ic, b) < 0)		return -1;	/*	 *  throw out it's data pages	 */	dfree(ic, &b->inode.ptr);	/*	 *  free the inode buffer	 */	ifree(ic, b);	/*	 *  make map entry least recently used	 */	lruderef(&ic->mlru, m);	return 0;}/* *  increment our version number */voidiinc(Icache *ic, Ibuf *b){	b->inode.qid.vers++;	ic->map[b->ino].qid = b->inode.qid;	iwrite(ic, b);}

⌨️ 快捷键说明

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