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

📄 jfs_dtree.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	memcpy(dirtab_slot, slot, sizeof(struct dir_table_slot));	if (mp)		release_metapage(mp);	return 0;}/* *	dtSearch() * * function: *	Search for the entry with specified key * * parameter: * * return: 0 - search result on stack, leaf page pinned; *	   errno - I/O error */int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,	     struct btstack * btstack, int flag){	int rc = 0;	int cmp = 1;		/* init for empty page */	s64 bn;	struct metapage *mp;	dtpage_t *p;	s8 *stbl;	int base, index, lim;	struct btframe *btsp;	pxd_t *pxd;	int psize = 288;	/* initial in-line directory */	ino_t inumber;	struct component_name ciKey;	struct super_block *sb = ip->i_sb;	ciKey.name =	    (wchar_t *) kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),				GFP_NOFS);	if (ciKey.name == 0) {		rc = -ENOMEM;		goto dtSearch_Exit2;	}	/* uppercase search key for c-i directory */	UniStrcpy(ciKey.name, key->name);	ciKey.namlen = key->namlen;	/* only uppercase if case-insensitive support is on */	if ((JFS_SBI(sb)->mntflag & JFS_OS2) == JFS_OS2) {		ciToUpper(&ciKey);	}	BT_CLR(btstack);	/* reset stack */	/* init level count for max pages to split */	btstack->nsplit = 1;	/*	 *      search down tree from root:	 *	 * between two consecutive entries of <Ki, Pi> and <Kj, Pj> of	 * internal page, child page Pi contains entry with k, Ki <= K < Kj.	 *	 * if entry with search key K is not found	 * internal page search find the entry with largest key Ki	 * less than K which point to the child page to search;	 * leaf page search find the entry with smallest key Kj	 * greater than K so that the returned index is the position of	 * the entry to be shifted right for insertion of new entry.	 * for empty tree, search key is greater than any key of the tree.	 *	 * by convention, root bn = 0.	 */	for (bn = 0;;) {		/* get/pin the page to search */		DT_GETPAGE(ip, bn, mp, psize, p, rc);		if (rc)			goto dtSearch_Exit1;		/* get sorted entry table of the page */		stbl = DT_GETSTBL(p);		/*		 * binary search with search key K on the current page.		 */		for (base = 0, lim = p->header.nextindex; lim; lim >>= 1) {			index = base + (lim >> 1);			if (p->header.flag & BT_LEAF) {				/* uppercase leaf name to compare */				cmp =				    ciCompare(&ciKey, p, stbl[index],					      JFS_SBI(sb)->mntflag);			} else {				/* router key is in uppercase */				cmp = dtCompare(&ciKey, p, stbl[index]);			}			if (cmp == 0) {				/*				 *      search hit				 */				/* search hit - leaf page:				 * return the entry found				 */				if (p->header.flag & BT_LEAF) {					inumber = le32_to_cpu(			((struct ldtentry *) & p->slot[stbl[index]])->inumber);					/*					 * search for JFS_LOOKUP					 */					if (flag == JFS_LOOKUP) {						*data = inumber;						rc = 0;						goto out;					}					/*					 * search for JFS_CREATE					 */					if (flag == JFS_CREATE) {						*data = inumber;						rc = -EEXIST;						goto out;					}					/*					 * search for JFS_REMOVE or JFS_RENAME					 */					if ((flag == JFS_REMOVE ||					     flag == JFS_RENAME) &&					    *data != inumber) {						rc = -ESTALE;						goto out;					}					/*					 * JFS_REMOVE|JFS_FINDDIR|JFS_RENAME					 */					/* save search result */					*data = inumber;					btsp = btstack->top;					btsp->bn = bn;					btsp->index = index;					btsp->mp = mp;					rc = 0;					goto dtSearch_Exit1;				}				/* search hit - internal page:				 * descend/search its child page				 */				goto getChild;			}			if (cmp > 0) {				base = index + 1;				--lim;			}		}		/*		 *      search miss		 *		 * base is the smallest index with key (Kj) greater than		 * search key (K) and may be zero or (maxindex + 1) index.		 */		/*		 * search miss - leaf page		 *		 * return location of entry (base) where new entry with		 * search key K is to be inserted.		 */		if (p->header.flag & BT_LEAF) {			/*			 * search for JFS_LOOKUP, JFS_REMOVE, or JFS_RENAME			 */			if (flag == JFS_LOOKUP || flag == JFS_REMOVE ||			    flag == JFS_RENAME) {				rc = -ENOENT;				goto out;			}			/*			 * search for JFS_CREATE|JFS_FINDDIR:			 *			 * save search result			 */			*data = 0;			btsp = btstack->top;			btsp->bn = bn;			btsp->index = base;			btsp->mp = mp;			rc = 0;			goto dtSearch_Exit1;		}		/*		 * search miss - internal page		 *		 * if base is non-zero, decrement base by one to get the parent		 * entry of the child page to search.		 */		index = base ? base - 1 : base;		/*		 * go down to child page		 */	      getChild:		/* update max. number of pages to split */		if (BT_STACK_FULL(btstack)) {			/* Something's corrupted, mark filesytem dirty so			 * chkdsk will fix it.			 */			jfs_error(sb, "stack overrun in dtSearch!");			BT_STACK_DUMP(btstack);			rc = -EIO;			goto out;		}		btstack->nsplit++;		/* push (bn, index) of the parent page/entry */		BT_PUSH(btstack, bn, index);		/* get the child page block number */		pxd = (pxd_t *) & p->slot[stbl[index]];		bn = addressPXD(pxd);		psize = lengthPXD(pxd) << JFS_SBI(ip->i_sb)->l2bsize;		/* unpin the parent page */		DT_PUTPAGE(mp);	}      out:	DT_PUTPAGE(mp);      dtSearch_Exit1:	kfree(ciKey.name);      dtSearch_Exit2:	return rc;}/* *	dtInsert() * * function: insert an entry to directory tree * * parameter: * * return: 0 - success; *	   errno - failure; */int dtInsert(tid_t tid, struct inode *ip,	 struct component_name * name, ino_t * fsn, struct btstack * btstack){	int rc = 0;	struct metapage *mp;	/* meta-page buffer */	dtpage_t *p;		/* base B+-tree index page */	s64 bn;	int index;	struct dtsplit split;	/* split information */	ddata_t data;	struct dt_lock *dtlck;	int n;	struct tlock *tlck;	struct lv *lv;	/*	 *      retrieve search result	 *	 * dtSearch() returns (leaf page pinned, index at which to insert).	 * n.b. dtSearch() may return index of (maxindex + 1) of	 * the full page.	 */	DT_GETSEARCH(ip, btstack->top, bn, mp, p, index);	/*	 *      insert entry for new key	 */	if (DO_INDEX(ip)) {		if (JFS_IP(ip)->next_index == DIREND) {			DT_PUTPAGE(mp);			return -EMLINK;		}		n = NDTLEAF(name->namlen);		data.leaf.tid = tid;		data.leaf.ip = ip;	} else {		n = NDTLEAF_LEGACY(name->namlen);		data.leaf.ip = 0;	/* signifies legacy directory format */	}	data.leaf.ino = cpu_to_le32(*fsn);	/*	 *      leaf page does not have enough room for new entry:	 *	 *      extend/split the leaf page;	 *	 * dtSplitUp() will insert the entry and unpin the leaf page.	 */	if (n > p->header.freecnt) {		split.mp = mp;		split.index = index;		split.nslot = n;		split.key = name;		split.data = &data;		rc = dtSplitUp(tid, ip, &split, btstack);		return rc;	}	/*	 *      leaf page does have enough room for new entry:	 *	 *      insert the new data entry into the leaf page;	 */	BT_MARK_DIRTY(mp, ip);	/*	 * acquire a transaction lock on the leaf page	 */	tlck = txLock(tid, ip, mp, tlckDTREE | tlckENTRY);	dtlck = (struct dt_lock *) & tlck->lock;	ASSERT(dtlck->index == 0);	lv = & dtlck->lv[0];	/* linelock header */	lv->offset = 0;	lv->length = 1;	dtlck->index++;	dtInsertEntry(p, index, name, &data, &dtlck);	/* linelock stbl of non-root leaf page */	if (!(p->header.flag & BT_ROOT)) {		if (dtlck->index >= dtlck->maxcnt)			dtlck = (struct dt_lock *) txLinelock(dtlck);		lv = & dtlck->lv[dtlck->index];		n = index >> L2DTSLOTSIZE;		lv->offset = p->header.stblindex + n;		lv->length =		    ((p->header.nextindex - 1) >> L2DTSLOTSIZE) - n + 1;		dtlck->index++;	}	/* unpin the leaf page */	DT_PUTPAGE(mp);	return 0;}/* *	dtSplitUp() * * function: propagate insertion bottom up; * * parameter: * * return: 0 - success; *	   errno - failure; * 	leaf page unpinned; */static int dtSplitUp(tid_t tid,	  struct inode *ip, struct dtsplit * split, struct btstack * btstack){	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);	int rc = 0;	struct metapage *smp;	dtpage_t *sp;		/* split page */	struct metapage *rmp;	dtpage_t *rp;		/* new right page split from sp */	pxd_t rpxd;		/* new right page extent descriptor */	struct metapage *lmp;	dtpage_t *lp;		/* left child page */	int skip;		/* index of entry of insertion */	struct btframe *parent;	/* parent page entry on traverse stack */	s64 xaddr, nxaddr;	int xlen, xsize;	struct pxdlist pxdlist;	pxd_t *pxd;	struct component_name key = { 0, 0 };	ddata_t *data = split->data;	int n;	struct dt_lock *dtlck;	struct tlock *tlck;	struct lv *lv;	/* get split page */	smp = split->mp;	sp = DT_PAGE(ip, smp);	key.name =	    (wchar_t *) kmalloc((JFS_NAME_MAX + 2) * sizeof(wchar_t),				GFP_NOFS);	if (key.name == 0) {		DT_PUTPAGE(smp);		rc = -ENOMEM;		goto dtSplitUp_Exit;	}	/*	 *      split leaf page	 *	 * The split routines insert the new entry, and	 * acquire txLock as appropriate.	 */	/*	 *      split root leaf page:	 */	if (sp->header.flag & BT_ROOT) {		/*		 * allocate a single extent child page		 */		xlen = 1;		n = sbi->bsize >> L2DTSLOTSIZE;		n -= (n + 31) >> L2DTSLOTSIZE;	/* stbl size */		n -= DTROOTMAXSLOT - sp->header.freecnt; /* header + entries */		if (n <= split->nslot)			xlen++;		if ((rc = dbAlloc(ip, 0, (s64) xlen, &xaddr))) {			DT_PUTPAGE(smp);			goto freeKeyName;		}		pxdlist.maxnpxd = 1;		pxdlist.npxd = 0;		pxd = &pxdlist.pxd[0];		PXDaddress(pxd, xaddr);		PXDlength(pxd, xlen);		split->pxdlist = &pxdlist;		rc = dtSplitRoot(tid, ip, split, &rmp);		if (!rc)			DT_PUTPAGE(rmp);		DT_PUTPAGE(smp);		goto freeKeyName;	}	/*	 *      extend first leaf page	 *	 * extend the 1st extent if less than buffer page size	 * (dtExtendPage() reurns leaf page unpinned)	 */	pxd = &sp->header.self;	xlen = lengthPXD(pxd);	xsize = xlen << sbi->l2bsize;	if (xsize < PSIZE) {		xaddr = addressPXD(pxd);		n = xsize >> L2DTSLOTSIZE;		n -= (n + 31) >> L2DTSLOTSIZE;	/* stbl size */		if ((n + sp->header.freecnt) <= split->nslot)			n = xlen + (xlen << 1);		else			n = xlen;		if ((rc = dbReAlloc(sbi->ipbmap, xaddr, (s64) xlen,				    (s64) n, &nxaddr)))			goto extendOut;		pxdlist.maxnpxd = 1;		pxdlist.npxd = 0;		pxd = &pxdlist.pxd[0];		PXDaddress(pxd, nxaddr)		    PXDlength(pxd, xlen + n);		split->pxdlist = &pxdlist;		if ((rc = dtExtendPage(tid, ip, split, btstack))) {			nxaddr = addressPXD(pxd);			if (xaddr != nxaddr) {				/* free relocated extent */				xlen = lengthPXD(pxd);				dbFree(ip, nxaddr, (s64) xlen);			} else {				/* free extended delta */				xlen = lengthPXD(pxd) - n;				xaddr = addressPXD(pxd) + xlen;				dbFree(ip, xaddr, (s64) n);			}		}	      extendOut:		DT_PUTPAGE(smp);		goto freeKeyName;	}	/*	 *      split leaf page <sp> into <sp> and a new right page <rp>.	 *	 * return <rp> pinned and its extent descriptor <rpxd>	 */	/*	 * allocate new directory page extent and	 * new index page(s) to cover page split(s)	 *	 * allocation hint: ?	 */	n = btstack->nsplit;	pxdlist.maxnpxd = pxdlist.npxd = 0;	xlen = sbi->nbperpage;	for (pxd = pxdlist.pxd; n > 0; n--, pxd++) {		if ((rc = dbAlloc(ip, 0, (s64) xlen, &xaddr)) == 0) {			PXDaddress(pxd, xaddr);			PXDlength(pxd, xlen);			pxdlist.maxnpxd++;			continue;		}		DT_PUTPAGE(smp);		/* undo allocation */		goto splitOut;	}	split->pxdlist = &pxdlist;	if ((rc = dtSplitPage(tid, ip, split, &rmp, &rp, &rpxd))) {		DT_PUTPAGE(smp);		/* undo allocation */		goto splitOut;	}	/*	 * propagate up the router entry for the leaf page just split	 *	 * insert a router entry for the new page into the parent page,	 * propagate the insert/split up the tree by walking back the stack	 * of (bn of parent page, index of child page entry in parent page)	 * that were traversed during the search for the page that split.	 *	 * the propagation of insert/split up the tree stops if the root	 * splits or the page inserted into doesn't have to split to hold	 * the new entry.	 *	 * the parent entry for the split page remains the same, and	 * a new entry is inserted at its right with the first key and	 * block number of the new right page.	 *	 * There are a maximum of 4 pages pinned at any time:	 * two children, left parent and right parent (when the parent splits).

⌨️ 快捷键说明

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