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

📄 jfs_xtree.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		 *///fastSearch:		if ((jfs_ip->btorder & BT_SEQUENTIAL) &&		    (p->header.flag & BT_LEAF) &&		    (index = jfs_ip->btindex) <		    le16_to_cpu(p->header.nextindex)) {			xad = &p->xad[index];			t64 = offsetXAD(xad);			if (xoff < t64 + lengthXAD(xad)) {				if (xoff >= t64) {					*cmpp = 0;					goto out;				}				/* stop sequential access heuristics */				goto binarySearch;			} else {	/* (t64 + lengthXAD(xad)) <= xoff */				/* try next sequential entry */				index++;				if (index <				    le16_to_cpu(p->header.nextindex)) {					xad++;					t64 = offsetXAD(xad);					if (xoff < t64 + lengthXAD(xad)) {						if (xoff >= t64) {							*cmpp = 0;							goto out;						}						/* miss: key falls between						 * previous and this entry						 */						*cmpp = 1;						goto out;					}					/* (xoff >= t64 + lengthXAD(xad));					 * matching entry may be further out:					 * stop heuristic search					 */					/* stop sequential access heuristics */					goto binarySearch;				}				/* (index == p->header.nextindex);				 * miss: key entry does not exist in				 * the target leaf/tree				 */				*cmpp = 1;				goto out;			}			/*			 * if hit, return index of the entry found, and			 * if miss, where new entry with search key is			 * to be inserted;			 */		      out:			/* compute number of pages to split */			if (flag & XT_INSERT) {				if (p->header.nextindex ==	/* little-endian */				    p->header.maxentry)					nsplit++;				else					nsplit = 0;				btstack->nsplit = nsplit;			}			/* save search result */			btsp = btstack->top;			btsp->bn = bn;			btsp->index = index;			btsp->mp = mp;			/* update sequential access heuristics */			jfs_ip->btindex = index;			INCREMENT(xtStat.fastSearch);			return 0;		}		/* well, ... full search now */	      binarySearch:		lim = le16_to_cpu(p->header.nextindex) - XTENTRYSTART;		/*		 * binary search with search key K on the current page		 */		for (base = XTENTRYSTART; lim; lim >>= 1) {			index = base + (lim >> 1);			XT_CMP(cmp, xoff, &p->xad[index], t64);			if (cmp == 0) {				/*				 *      search hit				 */				/* search hit - leaf page:				 * return the entry found				 */				if (p->header.flag & BT_LEAF) {					*cmpp = cmp;					/* compute number of pages to split */					if (flag & XT_INSERT) {						if (p->header.nextindex ==						    p->header.maxentry)							nsplit++;						else							nsplit = 0;						btstack->nsplit = nsplit;					}					/* save search result */					btsp = btstack->top;					btsp->bn = bn;					btsp->index = index;					btsp->mp = mp;					/* init sequential access heuristics */					btindex = jfs_ip->btindex;					if (index == btindex ||					    index == btindex + 1)						jfs_ip->btorder = BT_SEQUENTIAL;					else						jfs_ip->btorder = BT_RANDOM;					jfs_ip->btindex = index;					return 0;				}				/* search hit - internal page:				 * descend/search its child page				 */				goto next;			}			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 maxentry 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) {			*cmpp = cmp;			/* compute number of pages to split */			if (flag & XT_INSERT) {				if (p->header.nextindex ==				    p->header.maxentry)					nsplit++;				else					nsplit = 0;				btstack->nsplit = nsplit;			}			/* save search result */			btsp = btstack->top;			btsp->bn = bn;			btsp->index = base;			btsp->mp = mp;			/* init sequential access heuristics */			btindex = jfs_ip->btindex;			if (base == btindex || base == btindex + 1)				jfs_ip->btorder = BT_SEQUENTIAL;			else				jfs_ip->btorder = BT_RANDOM;			jfs_ip->btindex = base;			return 0;		}		/*		 * search miss - non-leaf 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		 */	      next:		/* update number of pages to split */		if (p->header.nextindex == p->header.maxentry)			nsplit++;		else			nsplit = 0;		/* push (bn, index) of the parent page/entry */		BT_PUSH(btstack, bn, index);		/* get the child page block number */		bn = addressXAD(&p->xad[index]);		/* unpin the parent page */		XT_PUTPAGE(mp);	}}/* *      xtInsert() * * function: * * parameter: *      tid     - transaction id; *      ip      - file object; *      xflag   - extent flag (XAD_NOTRECORDED): *      xoff    - extent offset; *      xlen    - extent length; *      xaddrp  - extent address pointer (in/out): *              if (*xaddrp) *                      caller allocated data extent at *xaddrp; *              else *                      allocate data extent and return its xaddr; *      flag    - * * return: */int xtInsert(tid_t tid,		/* transaction id */	     struct inode *ip, int xflag, s64 xoff, s32 xlen, s64 * xaddrp,	     int flag){	int rc = 0;	s64 xaddr, hint;	struct metapage *mp;	/* meta-page buffer */	xtpage_t *p;		/* base B+-tree index page */	s64 bn;	int index, nextindex;	struct btstack btstack;	/* traverse stack */	struct xtsplit split;	/* split information */	xad_t *xad;	int cmp;	struct tlock *tlck;	struct xtlock *xtlck;	jfs_info("xtInsert: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen);	/*	 *      search for the entry location at which to insert:	 *	 * xtFastSearch() and xtSearch() both returns (leaf page	 * pinned, index at which to insert).	 * n.b. xtSearch() may return index of maxentry of	 * the full page.	 */	if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT)))		return rc;	/* retrieve search result */	XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);	/* This test must follow XT_GETSEARCH since mp must be valid if	 * we branch to out: */	if (cmp == 0) {		rc = -EEXIST;		goto out;	}	/*	 * allocate data extent requested	 *	 * allocation hint: last xad	 */	if ((xaddr = *xaddrp) == 0) {		if (index > XTENTRYSTART) {			xad = &p->xad[index - 1];			hint = addressXAD(xad) + lengthXAD(xad) - 1;		} else			hint = 0;		if ((rc = dbAlloc(ip, hint, (s64) xlen, &xaddr)))			goto out;	}	/*	 *      insert entry for new extent	 */	xflag |= XAD_NEW;	/*	 *      if the leaf page is full, split the page and	 *      propagate up the router entry for the new page from split	 *	 * The xtSplitUp() will insert the entry and unpin the leaf page.	 */	nextindex = le16_to_cpu(p->header.nextindex);	if (nextindex == le16_to_cpu(p->header.maxentry)) {		split.mp = mp;		split.index = index;		split.flag = xflag;		split.off = xoff;		split.len = xlen;		split.addr = xaddr;		split.pxdlist = NULL;		if ((rc = xtSplitUp(tid, ip, &split, &btstack))) {			/* undo data extent allocation */			if (*xaddrp == 0)				dbFree(ip, xaddr, (s64) xlen);			return rc;		}		*xaddrp = xaddr;		return 0;	}	/*	 *      insert the new entry into the leaf page	 */	/*	 * acquire a transaction lock on the leaf page;	 *	 * action: xad insertion/extension;	 */	BT_MARK_DIRTY(mp, ip);	/* if insert into middle, shift right remaining entries. */	if (index < nextindex)		memmove(&p->xad[index + 1], &p->xad[index],			(nextindex - index) * sizeof(xad_t));	/* insert the new entry: mark the entry NEW */	xad = &p->xad[index];	XT_PUTENTRY(xad, xflag, xoff, xlen, xaddr);	/* advance next available entry index */	p->header.nextindex =	    cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);	/* Don't log it if there are no links to the file */	if (!test_cflag(COMMIT_Nolink, ip)) {		tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW);		xtlck = (struct xtlock *) & tlck->lock;		xtlck->lwm.offset =		    (xtlck->lwm.offset) ? min(index,					      (int)xtlck->lwm.offset) : index;		xtlck->lwm.length =		    le16_to_cpu(p->header.nextindex) - xtlck->lwm.offset;	}	*xaddrp = xaddr;      out:	/* unpin the leaf page */	XT_PUTPAGE(mp);	return rc;}/* *      xtSplitUp() * * function: *      split full pages as propagating insertion up the tree * * parameter: *      tid     - transaction id; *      ip      - file object; *      split   - entry parameter descriptor; *      btstack - traverse stack from xtSearch() * * return: */static intxtSplitUp(tid_t tid,	  struct inode *ip, struct xtsplit * split, struct btstack * btstack){	int rc = 0;	struct metapage *smp;	xtpage_t *sp;		/* split page */	struct metapage *rmp;	s64 rbn;		/* new right page block number */	struct metapage *rcmp;	xtpage_t *rcp;		/* right child page */	s64 rcbn;		/* right child page block number */	int skip;		/* index of entry of insertion */	int nextindex;		/* next available entry index of p */	struct btframe *parent;	/* parent page entry on traverse stack */	xad_t *xad;	s64 xaddr;	int xlen;	int nsplit;		/* number of pages split */	struct pxdlist pxdlist;	pxd_t *pxd;	struct tlock *tlck;	struct xtlock *xtlck;	smp = split->mp;	sp = XT_PAGE(ip, smp);	/* is inode xtree root extension/inline EA area free ? */	if ((sp->header.flag & BT_ROOT) && (!S_ISDIR(ip->i_mode)) &&	    (sp->header.maxentry < cpu_to_le16(XTROOTMAXSLOT)) &&	    (JFS_IP(ip)->mode2 & INLINEEA)) {		sp->header.maxentry = cpu_to_le16(XTROOTMAXSLOT);		JFS_IP(ip)->mode2 &= ~INLINEEA;		BT_MARK_DIRTY(smp, ip);		/*		 * acquire a transaction lock on the leaf page;		 *		 * action: xad insertion/extension;		 */		/* if insert into middle, shift right remaining entries. */		skip = split->index;		nextindex = le16_to_cpu(sp->header.nextindex);		if (skip < nextindex)			memmove(&sp->xad[skip + 1], &sp->xad[skip],				(nextindex - skip) * sizeof(xad_t));		/* insert the new entry: mark the entry NEW */		xad = &sp->xad[skip];		XT_PUTENTRY(xad, split->flag, split->off, split->len,			    split->addr);		/* advance next available entry index */		sp->header.nextindex =		    cpu_to_le16(le16_to_cpu(sp->header.nextindex) + 1);		/* Don't log it if there are no links to the file */		if (!test_cflag(COMMIT_Nolink, ip)) {			tlck = txLock(tid, ip, smp, tlckXTREE | tlckGROW);			xtlck = (struct xtlock *) & tlck->lock;			xtlck->lwm.offset = (xtlck->lwm.offset) ?			    min(skip, (int)xtlck->lwm.offset) : skip;			xtlck->lwm.length =			    le16_to_cpu(sp->header.nextindex) -			    xtlck->lwm.offset;		}		return 0;	}	/*	 * allocate new index blocks to cover index page split(s)	 *	 * allocation hint: ?	 */	if (split->pxdlist == NULL) {		nsplit = btstack->nsplit;		split->pxdlist = &pxdlist;		pxdlist.maxnpxd = pxdlist.npxd = 0;		pxd = &pxdlist.pxd[0];		xlen = JFS_SBI(ip->i_sb)->nbperpage;		for (; nsplit > 0; nsplit--, pxd++) {			if ((rc = dbAlloc(ip, (s64) 0, (s64) xlen, &xaddr))			    == 0) {				PXDaddress(pxd, xaddr);				PXDlength(pxd, xlen);				pxdlist.maxnpxd++;				continue;			}			/* undo allocation */			XT_PUTPAGE(smp);			return rc;		}	}	/*	 * Split leaf page <sp> into <sp> and a new right page <rp>.	 *	 * The split routines insert the new entry into the leaf page,	 * and acquire txLock as appropriate.	 * return <rp> pinned and its block number <rpbn>.	 */	rc = (sp->header.flag & BT_ROOT) ?	    xtSplitRoot(tid, ip, split, &rmp) :	    xtSplitPage(tid, ip, split, &rmp, &rbn);	XT_PUTPAGE(smp);	if (rc)		return -EIO;	/*	 * 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 3 pages pinned at any time:	 * right child, left parent and right parent (when the parent splits)	 * to keep the child page pinned while working on the parent.	 * make sure that all pins are released at exit.	 */	while ((parent = BT_POP(btstack)) != NULL) {		/* parent page specified by stack frame <parent> */		/* keep current child pages <rcp> pinned */		rcmp = rmp;		rcbn = rbn;		rcp = XT_PAGE(ip, rcmp);		/*		 * insert router entry in parent for new right child page <rp>		 */		/* get/pin the parent page <sp> */		XT_GETPAGE(ip, parent->bn, smp, PSIZE, sp, rc);		if (rc) {			XT_PUTPAGE(rcmp);			return rc;		}		/*		 * The new key entry goes ONE AFTER the index of parent entry,		 * because the split was to the right.		 */		skip = parent->index + 1;		/*		 * split or shift right remaining entries of the parent page		 */		nextindex = le16_to_cpu(sp->header.nextindex);		/*		 * parent page is full - split the parent page		 */		if (nextindex == le16_to_cpu(sp->header.maxentry)) {

⌨️ 快捷键说明

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