jfs_xtree.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:103k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *   Copyright (c) International Business Machines Corp., 2000-2002
  3.  *
  4.  *   This program is free software;  you can redistribute it and/or modify
  5.  *   it under the terms of the GNU General Public License as published by
  6.  *   the Free Software Foundation; either version 2 of the License, or 
  7.  *   (at your option) any later version.
  8.  * 
  9.  *   This program is distributed in the hope that it will be useful,
  10.  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
  11.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  12.  *   the GNU General Public License for more details.
  13.  *
  14.  *   You should have received a copy of the GNU General Public License
  15.  *   along with this program;  if not, write to the Free Software 
  16.  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17.  */
  18. /*
  19.  *      jfs_xtree.c: extent allocation descriptor B+-tree manager
  20.  */
  21. #include <linux/fs.h>
  22. #include "jfs_incore.h"
  23. #include "jfs_filsys.h"
  24. #include "jfs_metapage.h"
  25. #include "jfs_dmap.h"
  26. #include "jfs_dinode.h"
  27. #include "jfs_superblock.h"
  28. #include "jfs_debug.h"
  29. /*
  30.  * xtree local flag
  31.  */
  32. #define XT_INSERT       0x00000001
  33. /*
  34.  *       xtree key/entry comparison: extent offset
  35.  *
  36.  * return:
  37.  *      -1: k < start of extent
  38.  *       0: start_of_extent <= k <= end_of_extent
  39.  *       1: k > end_of_extent
  40.  */
  41. #define XT_CMP(CMP, K, X, OFFSET64)
  42. {
  43.         OFFSET64 = offsetXAD(X);
  44.         (CMP) = ((K) >= OFFSET64 + lengthXAD(X)) ? 1 :
  45.               ((K) < OFFSET64) ? -1 : 0;
  46. }
  47. /* write a xad entry */
  48. #define XT_PUTENTRY(XAD, FLAG, OFF, LEN, ADDR)
  49. {
  50.         (XAD)->flag = (FLAG);
  51.         XADoffset((XAD), (OFF));
  52.         XADlength((XAD), (LEN));
  53.         XADaddress((XAD), (ADDR));
  54. }
  55. #define XT_PAGE(IP, MP) BT_PAGE(IP, MP, xtpage_t, i_xtroot)
  56. /* get page buffer for specified block address */
  57. #define XT_GETPAGE(IP, BN, MP, SIZE, P, RC)
  58. {
  59.         BT_GETPAGE(IP, BN, MP, xtpage_t, SIZE, P, RC, i_xtroot)
  60.         if (!(RC))
  61.         {
  62.                 if ((le16_to_cpu((P)->header.nextindex) < XTENTRYSTART) ||
  63.                     (le16_to_cpu((P)->header.nextindex) > le16_to_cpu((P)->header.maxentry)) ||
  64.                     (le16_to_cpu((P)->header.maxentry) > (((BN)==0)?XTROOTMAXSLOT:PSIZE>>L2XTSLOTSIZE)))
  65.                 {
  66.                         jERROR(1,("XT_GETPAGE: xtree page corruptn"));
  67. BT_PUTPAGE(MP);
  68. updateSuper((IP)->i_sb, FM_DIRTY);
  69. MP = NULL;
  70.                         RC = EIO;
  71.                 }
  72.         }
  73. }
  74. /* for consistency */
  75. #define XT_PUTPAGE(MP) BT_PUTPAGE(MP)
  76. #define XT_GETSEARCH(IP, LEAF, BN, MP,  P, INDEX) 
  77. BT_GETSEARCH(IP, LEAF, BN, MP, xtpage_t, P, INDEX, i_xtroot)
  78. /* xtree entry parameter descriptor */
  79. struct xtsplit {
  80. struct metapage *mp;
  81. s16 index;
  82. u8 flag;
  83. s64 off;
  84. s64 addr;
  85. int len;
  86. struct pxdlist *pxdlist;
  87. };
  88. /*
  89.  *      statistics
  90.  */
  91. #ifdef CONFIG_JFS_STATISTICS
  92. static struct {
  93. uint search;
  94. uint fastSearch;
  95. uint split;
  96. } xtStat;
  97. #endif
  98. /*
  99.  * forward references
  100.  */
  101. static int xtSearch(struct inode *ip,
  102.     s64 xoff, int *cmpp, struct btstack * btstack, int flag);
  103. static int xtSplitUp(tid_t tid,
  104.      struct inode *ip,
  105.      struct xtsplit * split, struct btstack * btstack);
  106. static int xtSplitPage(tid_t tid, struct inode *ip, struct xtsplit * split,
  107.        struct metapage ** rmpp, s64 * rbnp);
  108. static int xtSplitRoot(tid_t tid, struct inode *ip,
  109.        struct xtsplit * split, struct metapage ** rmpp);
  110. #ifdef _STILL_TO_PORT
  111. static int xtDeleteUp(tid_t tid, struct inode *ip, struct metapage * fmp,
  112.       xtpage_t * fp, struct btstack * btstack);
  113. static int xtSearchNode(struct inode *ip,
  114. xad_t * xad,
  115. int *cmpp, struct btstack * btstack, int flag);
  116. static int xtRelink(tid_t tid, struct inode *ip, xtpage_t * fp);
  117. #endif /*  _STILL_TO_PORT */
  118. /* External references */
  119. /*
  120.  *      debug control
  121.  */
  122. /*      #define _JFS_DEBUG_XTREE        1 */
  123. /*
  124.  *      xtLookup()
  125.  *
  126.  * function: map a single page into a physical extent;
  127.  */
  128. int xtLookup(struct inode *ip, s64 lstart,
  129.      s64 llen, int *pflag, s64 * paddr, s32 * plen, int no_check)
  130. {
  131. int rc = 0;
  132. struct btstack btstack;
  133. int cmp;
  134. s64 bn;
  135. struct metapage *mp;
  136. xtpage_t *p;
  137. int index;
  138. xad_t *xad;
  139. s64 size, xoff, xend;
  140. int xlen;
  141. s64 xaddr;
  142. *plen = 0;
  143. if (!no_check) {
  144. /* is lookup offset beyond eof ? */
  145. size = ((u64) ip->i_size + (JFS_SBI(ip->i_sb)->bsize - 1)) >>
  146.     JFS_SBI(ip->i_sb)->l2bsize;
  147. if (lstart >= size) {
  148. jERROR(1,
  149.        ("xtLookup: lstart (0x%lx) >= size (0x%lx)n",
  150. (ulong) lstart, (ulong) size));
  151. return 0;
  152. }
  153. }
  154. /*
  155.  * search for the xad entry covering the logical extent
  156.  */
  157. //search:
  158. if ((rc = xtSearch(ip, lstart, &cmp, &btstack, 0))) {
  159. jERROR(1, ("xtLookup: xtSearch returned %dn", rc));
  160. return rc;
  161. }
  162. /*
  163.  *      compute the physical extent covering logical extent
  164.  *
  165.  * N.B. search may have failed (e.g., hole in sparse file),
  166.  * and returned the index of the next entry.
  167.  */
  168. /* retrieve search result */
  169. XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
  170. /* is xad found covering start of logical extent ?
  171.  * lstart is a page start address,
  172.  * i.e., lstart cannot start in a hole;
  173.  */
  174. if (cmp) {
  175. jFYI(1, ("xtLookup: cmp = %dn", cmp));
  176. goto out;
  177. }
  178. /*
  179.  * lxd covered by xad
  180.  */
  181. xad = &p->xad[index];
  182. xoff = offsetXAD(xad);
  183. xlen = lengthXAD(xad);
  184. xend = xoff + xlen;
  185. xaddr = addressXAD(xad);
  186. jEVENT(0,
  187.        ("index = %d, xoff = 0x%lx, xlen = 0x%x, xaddr = 0x%lxn",
  188. index, (ulong) xoff, xlen, (ulong) xaddr));
  189. /* initialize new pxd */
  190. *pflag = xad->flag;
  191. *paddr = xaddr + (lstart - xoff);
  192. /* a page must be fully covered by an xad */
  193. *plen = min(xend - lstart, llen);
  194.       out:
  195. XT_PUTPAGE(mp);
  196. return rc;
  197. }
  198. /*
  199.  *      xtLookupList()
  200.  *
  201.  * function: map a single logical extent into a list of physical extent;
  202.  *
  203.  * parameter:
  204.  *      struct inode    *ip,
  205.  *      struct lxdlist  *lxdlist,       lxd list (in)
  206.  *      struct xadlist  *xadlist,       xad list (in/out)
  207.  *      int flag)
  208.  *
  209.  * coverage of lxd by xad under assumption of
  210.  * . lxd's are ordered and disjoint.
  211.  * . xad's are ordered and disjoint.
  212.  *
  213.  * return:
  214.  *      0:      success
  215.  *
  216.  * note: a page being written (even a single byte) is backed fully,
  217.  *      except the last page which is only backed with blocks
  218.  *      required to cover the last byte;
  219.  *      the extent backing a page is fully contained within an xad;
  220.  */
  221. int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
  222.  struct xadlist * xadlist, int flag)
  223. {
  224. int rc = 0;
  225. struct btstack btstack;
  226. int cmp;
  227. s64 bn;
  228. struct metapage *mp;
  229. xtpage_t *p;
  230. int index;
  231. lxd_t *lxd;
  232. xad_t *xad, *pxd;
  233. s64 size, lstart, lend, xstart, xend, pstart;
  234. s64 llen, xlen, plen;
  235. s64 xaddr, paddr;
  236. int nlxd, npxd, maxnpxd;
  237. npxd = xadlist->nxad = 0;
  238. maxnpxd = xadlist->maxnxad;
  239. pxd = xadlist->xad;
  240. nlxd = lxdlist->nlxd;
  241. lxd = lxdlist->lxd;
  242. lstart = offsetLXD(lxd);
  243. llen = lengthLXD(lxd);
  244. lend = lstart + llen;
  245. size = (ip->i_size + (JFS_SBI(ip->i_sb)->bsize - 1)) >>
  246.     JFS_SBI(ip->i_sb)->l2bsize;
  247. /*
  248.  * search for the xad entry covering the logical extent
  249.  */
  250.       search:
  251. if (lstart >= size)
  252. return 0;
  253. if ((rc = xtSearch(ip, lstart, &cmp, &btstack, 0)))
  254. return rc;
  255. /*
  256.  *      compute the physical extent covering logical extent
  257.  *
  258.  * N.B. search may have failed (e.g., hole in sparse file),
  259.  * and returned the index of the next entry.
  260.  */
  261. //map:
  262. /* retrieve search result */
  263. XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
  264. /* is xad on the next sibling page ? */
  265. if (index == le16_to_cpu(p->header.nextindex)) {
  266. if (p->header.flag & BT_ROOT)
  267. goto mapend;
  268. if ((bn = le64_to_cpu(p->header.next)) == 0)
  269. goto mapend;
  270. XT_PUTPAGE(mp);
  271. /* get next sibling page */
  272. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  273. if (rc)
  274. return rc;
  275. index = XTENTRYSTART;
  276. }
  277. xad = &p->xad[index];
  278. /*
  279.  * is lxd covered by xad ?
  280.  */
  281.       compare:
  282. xstart = offsetXAD(xad);
  283. xlen = lengthXAD(xad);
  284. xend = xstart + xlen;
  285. xaddr = addressXAD(xad);
  286.       compare1:
  287. if (xstart < lstart)
  288. goto compare2;
  289. /* (lstart <= xstart) */
  290. /* lxd is NOT covered by xad */
  291. if (lend <= xstart) {
  292. /*
  293.  * get next lxd
  294.  */
  295. if (--nlxd == 0)
  296. goto mapend;
  297. lxd++;
  298. lstart = offsetLXD(lxd);
  299. llen = lengthLXD(lxd);
  300. lend = lstart + llen;
  301. if (lstart >= size)
  302. goto mapend;
  303. /* compare with the current xad  */
  304. goto compare1;
  305. }
  306. /* lxd is covered by xad */
  307. else { /* (xstart < lend) */
  308. /* initialize new pxd */
  309. pstart = xstart;
  310. plen = min(lend - xstart, xlen);
  311. paddr = xaddr;
  312. goto cover;
  313. }
  314. /* (xstart < lstart) */
  315.       compare2:
  316. /* lxd is covered by xad */
  317. if (lstart < xend) {
  318. /* initialize new pxd */
  319. pstart = lstart;
  320. plen = min(xend - lstart, llen);
  321. paddr = xaddr + (lstart - xstart);
  322. goto cover;
  323. }
  324. /* lxd is NOT covered by xad */
  325. else { /* (xend <= lstart) */
  326. /*
  327.  * get next xad
  328.  *
  329.  * linear search next xad covering lxd on
  330.  * the current xad page, and then tree search
  331.  */
  332. if (index == le16_to_cpu(p->header.nextindex) - 1) {
  333. if (p->header.flag & BT_ROOT)
  334. goto mapend;
  335. XT_PUTPAGE(mp);
  336. goto search;
  337. } else {
  338. index++;
  339. xad++;
  340. /* compare with new xad */
  341. goto compare;
  342. }
  343. }
  344. /*
  345.  * lxd is covered by xad and a new pxd has been initialized
  346.  * (lstart <= xstart < lend) or (xstart < lstart < xend)
  347.  */
  348.       cover:
  349. /* finalize pxd corresponding to current xad */
  350. XT_PUTENTRY(pxd, xad->flag, pstart, plen, paddr);
  351. if (++npxd >= maxnpxd)
  352. goto mapend;
  353. pxd++;
  354. /*
  355.  * lxd is fully covered by xad
  356.  */
  357. if (lend <= xend) {
  358. /*
  359.  * get next lxd
  360.  */
  361. if (--nlxd == 0)
  362. goto mapend;
  363. lxd++;
  364. lstart = offsetLXD(lxd);
  365. llen = lengthLXD(lxd);
  366. lend = lstart + llen;
  367. if (lstart >= size)
  368. goto mapend;
  369. /*
  370.  * test for old xad covering new lxd
  371.  * (old xstart < new lstart)
  372.  */
  373. goto compare2;
  374. }
  375. /*
  376.  * lxd is partially covered by xad
  377.  */
  378. else { /* (xend < lend)  */
  379. /*
  380.  * get next xad
  381.  *
  382.  * linear search next xad covering lxd on
  383.  * the current xad page, and then next xad page search
  384.  */
  385. if (index == le16_to_cpu(p->header.nextindex) - 1) {
  386. if (p->header.flag & BT_ROOT)
  387. goto mapend;
  388. if ((bn = le64_to_cpu(p->header.next)) == 0)
  389. goto mapend;
  390. XT_PUTPAGE(mp);
  391. /* get next sibling page */
  392. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  393. if (rc)
  394. return rc;
  395. index = XTENTRYSTART;
  396. xad = &p->xad[index];
  397. } else {
  398. index++;
  399. xad++;
  400. }
  401. /*
  402.  * test for new xad covering old lxd
  403.  * (old lstart < new xstart)
  404.  */
  405. goto compare;
  406. }
  407.       mapend:
  408. xadlist->nxad = npxd;
  409. //out:
  410. XT_PUTPAGE(mp);
  411. return rc;
  412. }
  413. /*
  414.  *      xtSearch()
  415.  *
  416.  * function:    search for the xad entry covering specified offset.
  417.  *
  418.  * parameters:
  419.  *      ip      - file object;
  420.  *      xoff    - extent offset;
  421.  *      cmpp    - comparison result:
  422.  *      btstack - traverse stack;
  423.  *      flag    - search process flag (XT_INSERT);
  424.  *
  425.  * returns:
  426.  *      btstack contains (bn, index) of search path traversed to the entry.
  427.  *      *cmpp is set to result of comparison with the entry returned.
  428.  *      the page containing the entry is pinned at exit.
  429.  */
  430. static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */
  431.     int *cmpp, struct btstack * btstack, int flag)
  432. {
  433. struct jfs_inode_info *jfs_ip = JFS_IP(ip);
  434. int rc = 0;
  435. int cmp = 1; /* init for empty page */
  436. s64 bn; /* block number */
  437. struct metapage *mp; /* page buffer */
  438. xtpage_t *p; /* page */
  439. xad_t *xad;
  440. int base, index, lim, btindex;
  441. struct btframe *btsp;
  442. int nsplit = 0; /* number of pages to split */
  443. s64 t64;
  444. INCREMENT(xtStat.search);
  445. BT_CLR(btstack);
  446. btstack->nsplit = 0;
  447. /*
  448.  *      search down tree from root:
  449.  *
  450.  * between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
  451.  * internal page, child page Pi contains entry with k, Ki <= K < Kj.
  452.  *
  453.  * if entry with search key K is not found
  454.  * internal page search find the entry with largest key Ki
  455.  * less than K which point to the child page to search;
  456.  * leaf page search find the entry with smallest key Kj
  457.  * greater than K so that the returned index is the position of
  458.  * the entry to be shifted right for insertion of new entry.
  459.  * for empty tree, search key is greater than any key of the tree.
  460.  *
  461.  * by convention, root bn = 0.
  462.  */
  463. for (bn = 0;;) {
  464. /* get/pin the page to search */
  465. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  466. if (rc)
  467. return rc;
  468. /* try sequential access heuristics with the previous
  469.  * access entry in target leaf page:
  470.  * once search narrowed down into the target leaf,
  471.  * key must either match an entry in the leaf or
  472.  * key entry does not exist in the tree;
  473.  */
  474. //fastSearch:
  475. if ((jfs_ip->btorder & BT_SEQUENTIAL) &&
  476.     (p->header.flag & BT_LEAF) &&
  477.     (index = jfs_ip->btindex) <
  478.     le16_to_cpu(p->header.nextindex)) {
  479. xad = &p->xad[index];
  480. t64 = offsetXAD(xad);
  481. if (xoff < t64 + lengthXAD(xad)) {
  482. if (xoff >= t64) {
  483. *cmpp = 0;
  484. goto out;
  485. }
  486. /* stop sequential access heuristics */
  487. goto binarySearch;
  488. } else { /* (t64 + lengthXAD(xad)) <= xoff */
  489. /* try next sequential entry */
  490. index++;
  491. if (index <
  492.     le16_to_cpu(p->header.nextindex)) {
  493. xad++;
  494. t64 = offsetXAD(xad);
  495. if (xoff < t64 + lengthXAD(xad)) {
  496. if (xoff >= t64) {
  497. *cmpp = 0;
  498. goto out;
  499. }
  500. /* miss: key falls between
  501.  * previous and this entry
  502.  */
  503. *cmpp = 1;
  504. goto out;
  505. }
  506. /* (xoff >= t64 + lengthXAD(xad));
  507.  * matching entry may be further out:
  508.  * stop heuristic search
  509.  */
  510. /* stop sequential access heuristics */
  511. goto binarySearch;
  512. }
  513. /* (index == p->header.nextindex);
  514.  * miss: key entry does not exist in
  515.  * the target leaf/tree
  516.  */
  517. *cmpp = 1;
  518. goto out;
  519. }
  520. /*
  521.  * if hit, return index of the entry found, and
  522.  * if miss, where new entry with search key is
  523.  * to be inserted;
  524.  */
  525.       out:
  526. /* compute number of pages to split */
  527. if (flag & XT_INSERT) {
  528. if (p->header.nextindex == /* little-endian */
  529.     p->header.maxentry)
  530. nsplit++;
  531. else
  532. nsplit = 0;
  533. btstack->nsplit = nsplit;
  534. }
  535. /* save search result */
  536. btsp = btstack->top;
  537. btsp->bn = bn;
  538. btsp->index = index;
  539. btsp->mp = mp;
  540. /* update sequential access heuristics */
  541. jfs_ip->btindex = index;
  542. INCREMENT(xtStat.fastSearch);
  543. return 0;
  544. }
  545. /* well, ... full search now */
  546.       binarySearch:
  547. lim = le16_to_cpu(p->header.nextindex) - XTENTRYSTART;
  548. /*
  549.  * binary search with search key K on the current page
  550.  */
  551. for (base = XTENTRYSTART; lim; lim >>= 1) {
  552. index = base + (lim >> 1);
  553. XT_CMP(cmp, xoff, &p->xad[index], t64);
  554. if (cmp == 0) {
  555. /*
  556.  *      search hit
  557.  */
  558. /* search hit - leaf page:
  559.  * return the entry found
  560.  */
  561. if (p->header.flag & BT_LEAF) {
  562. *cmpp = cmp;
  563. /* compute number of pages to split */
  564. if (flag & XT_INSERT) {
  565. if (p->header.nextindex ==
  566.     p->header.maxentry)
  567. nsplit++;
  568. else
  569. nsplit = 0;
  570. btstack->nsplit = nsplit;
  571. }
  572. /* save search result */
  573. btsp = btstack->top;
  574. btsp->bn = bn;
  575. btsp->index = index;
  576. btsp->mp = mp;
  577. /* init sequential access heuristics */
  578. btindex = jfs_ip->btindex;
  579. if (index == btindex ||
  580.     index == btindex + 1)
  581. jfs_ip->btorder = BT_SEQUENTIAL;
  582. else
  583. jfs_ip->btorder = BT_RANDOM;
  584. jfs_ip->btindex = index;
  585. return 0;
  586. }
  587. /* search hit - internal page:
  588.  * descend/search its child page
  589.  */
  590. goto next;
  591. }
  592. if (cmp > 0) {
  593. base = index + 1;
  594. --lim;
  595. }
  596. }
  597. /*
  598.  *      search miss
  599.  *
  600.  * base is the smallest index with key (Kj) greater than
  601.  * search key (K) and may be zero or maxentry index.
  602.  */
  603. /*
  604.  * search miss - leaf page:
  605.  *
  606.  * return location of entry (base) where new entry with
  607.  * search key K is to be inserted.
  608.  */
  609. if (p->header.flag & BT_LEAF) {
  610. *cmpp = cmp;
  611. /* compute number of pages to split */
  612. if (flag & XT_INSERT) {
  613. if (p->header.nextindex ==
  614.     p->header.maxentry)
  615. nsplit++;
  616. else
  617. nsplit = 0;
  618. btstack->nsplit = nsplit;
  619. }
  620. /* save search result */
  621. btsp = btstack->top;
  622. btsp->bn = bn;
  623. btsp->index = base;
  624. btsp->mp = mp;
  625. /* init sequential access heuristics */
  626. btindex = jfs_ip->btindex;
  627. if (base == btindex || base == btindex + 1)
  628. jfs_ip->btorder = BT_SEQUENTIAL;
  629. else
  630. jfs_ip->btorder = BT_RANDOM;
  631. jfs_ip->btindex = base;
  632. return 0;
  633. }
  634. /*
  635.  * search miss - non-leaf page:
  636.  *
  637.  * if base is non-zero, decrement base by one to get the parent
  638.  * entry of the child page to search.
  639.  */
  640. index = base ? base - 1 : base;
  641. /*
  642.  * go down to child page
  643.  */
  644.       next:
  645. /* update number of pages to split */
  646. if (p->header.nextindex == p->header.maxentry)
  647. nsplit++;
  648. else
  649. nsplit = 0;
  650. /* push (bn, index) of the parent page/entry */
  651. BT_PUSH(btstack, bn, index);
  652. /* get the child page block number */
  653. bn = addressXAD(&p->xad[index]);
  654. /* unpin the parent page */
  655. XT_PUTPAGE(mp);
  656. }
  657. }
  658. /*
  659.  *      xtInsert()
  660.  *
  661.  * function:
  662.  *
  663.  * parameter:
  664.  *      tid     - transaction id;
  665.  *      ip      - file object;
  666.  *      xflag   - extent flag (XAD_NOTRECORDED):
  667.  *      xoff    - extent offset;
  668.  *      xlen    - extent length;
  669.  *      xaddrp  - extent address pointer (in/out):
  670.  *              if (*xaddrp)
  671.  *                      caller allocated data extent at *xaddrp;
  672.  *              else
  673.  *                      allocate data extent and return its xaddr;
  674.  *      flag    -
  675.  *
  676.  * return:
  677.  */
  678. int xtInsert(tid_t tid, /* transaction id */
  679.      struct inode *ip, int xflag, s64 xoff, s32 xlen, s64 * xaddrp,
  680.      int flag)
  681. {
  682. int rc = 0;
  683. s64 xaddr, hint;
  684. struct metapage *mp; /* meta-page buffer */
  685. xtpage_t *p; /* base B+-tree index page */
  686. s64 bn;
  687. int index, nextindex;
  688. struct btstack btstack; /* traverse stack */
  689. struct xtsplit split; /* split information */
  690. xad_t *xad;
  691. int cmp;
  692. struct tlock *tlck;
  693. struct xtlock *xtlck;
  694. jFYI(1,
  695.      ("xtInsert: nxoff:0x%lx nxlen:0x%xn", (ulong) xoff, xlen));
  696. /*
  697.  *      search for the entry location at which to insert:
  698.  *
  699.  * xtFastSearch() and xtSearch() both returns (leaf page
  700.  * pinned, index at which to insert).
  701.  * n.b. xtSearch() may return index of maxentry of
  702.  * the full page.
  703.  */
  704. if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT)))
  705. return rc;
  706. /* retrieve search result */
  707. XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
  708. /* This test must follow XT_GETSEARCH since mp must be valid if
  709.  * we branch to out: */
  710. if (cmp == 0) {
  711. rc = EEXIST;
  712. goto out;
  713. }
  714. /*
  715.  * allocate data extent requested
  716.  *
  717.  * allocation hint: last xad
  718.  */
  719. if ((xaddr = *xaddrp) == 0) {
  720. if (index > XTENTRYSTART) {
  721. xad = &p->xad[index - 1];
  722. hint = addressXAD(xad) + lengthXAD(xad) - 1;
  723. } else
  724. hint = 0;
  725. if ((rc = dbAlloc(ip, hint, (s64) xlen, &xaddr)))
  726. goto out;
  727. }
  728. /*
  729.  *      insert entry for new extent
  730.  */
  731. xflag |= XAD_NEW;
  732. /*
  733.  *      if the leaf page is full, split the page and
  734.  *      propagate up the router entry for the new page from split
  735.  *
  736.  * The xtSplitUp() will insert the entry and unpin the leaf page.
  737.  */
  738. nextindex = le16_to_cpu(p->header.nextindex);
  739. if (nextindex == le16_to_cpu(p->header.maxentry)) {
  740. split.mp = mp;
  741. split.index = index;
  742. split.flag = xflag;
  743. split.off = xoff;
  744. split.len = xlen;
  745. split.addr = xaddr;
  746. split.pxdlist = NULL;
  747. if ((rc = xtSplitUp(tid, ip, &split, &btstack))) {
  748. /* undo data extent allocation */
  749. if (*xaddrp == 0)
  750. dbFree(ip, xaddr, (s64) xlen);
  751. return rc;
  752. }
  753. *xaddrp = xaddr;
  754. return 0;
  755. }
  756. /*
  757.  *      insert the new entry into the leaf page
  758.  */
  759. /*
  760.  * acquire a transaction lock on the leaf page;
  761.  *
  762.  * action: xad insertion/extension;
  763.  */
  764. BT_MARK_DIRTY(mp, ip);
  765. /* if insert into middle, shift right remaining entries. */
  766. if (index < nextindex)
  767. memmove(&p->xad[index + 1], &p->xad[index],
  768. (nextindex - index) * sizeof(xad_t));
  769. /* insert the new entry: mark the entry NEW */
  770. xad = &p->xad[index];
  771. XT_PUTENTRY(xad, xflag, xoff, xlen, xaddr);
  772. /* advance next available entry index */
  773. p->header.nextindex =
  774.     cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
  775. /* Don't log it if there are no links to the file */
  776. if (!test_cflag(COMMIT_Nolink, ip)) {
  777. tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW);
  778. xtlck = (struct xtlock *) & tlck->lock;
  779. xtlck->lwm.offset =
  780.     (xtlck->lwm.offset) ? min(index,
  781.       (int)xtlck->lwm.offset) : index;
  782. xtlck->lwm.length =
  783.     le16_to_cpu(p->header.nextindex) - xtlck->lwm.offset;
  784. }
  785. *xaddrp = xaddr;
  786.       out:
  787. /* unpin the leaf page */
  788. XT_PUTPAGE(mp);
  789. return rc;
  790. }
  791. /*
  792.  *      xtSplitUp()
  793.  *
  794.  * function:
  795.  *      split full pages as propagating insertion up the tree
  796.  *
  797.  * parameter:
  798.  *      tid     - transaction id;
  799.  *      ip      - file object;
  800.  *      split   - entry parameter descriptor;
  801.  *      btstack - traverse stack from xtSearch()
  802.  *
  803.  * return:
  804.  */
  805. static int
  806. xtSplitUp(tid_t tid,
  807.   struct inode *ip, struct xtsplit * split, struct btstack * btstack)
  808. {
  809. int rc = 0;
  810. struct metapage *smp;
  811. xtpage_t *sp; /* split page */
  812. struct metapage *rmp;
  813. s64 rbn; /* new right page block number */
  814. struct metapage *rcmp;
  815. xtpage_t *rcp; /* right child page */
  816. s64 rcbn; /* right child page block number */
  817. int skip; /* index of entry of insertion */
  818. int nextindex; /* next available entry index of p */
  819. struct btframe *parent; /* parent page entry on traverse stack */
  820. xad_t *xad;
  821. s64 xaddr;
  822. int xlen;
  823. int nsplit; /* number of pages split */
  824. struct pxdlist pxdlist;
  825. pxd_t *pxd;
  826. struct tlock *tlck;
  827. struct xtlock *xtlck;
  828. smp = split->mp;
  829. sp = XT_PAGE(ip, smp);
  830. /* is inode xtree root extension/inline EA area free ? */
  831. if ((sp->header.flag & BT_ROOT) && (!S_ISDIR(ip->i_mode)) &&
  832.     (sp->header.maxentry < cpu_to_le16(XTROOTMAXSLOT)) &&
  833.     (JFS_IP(ip)->mode2 & INLINEEA)) {
  834. sp->header.maxentry = cpu_to_le16(XTROOTMAXSLOT);
  835. JFS_IP(ip)->mode2 &= ~INLINEEA;
  836. BT_MARK_DIRTY(smp, ip);
  837. /*
  838.  * acquire a transaction lock on the leaf page;
  839.  *
  840.  * action: xad insertion/extension;
  841.  */
  842. /* if insert into middle, shift right remaining entries. */
  843. skip = split->index;
  844. nextindex = le16_to_cpu(sp->header.nextindex);
  845. if (skip < nextindex)
  846. memmove(&sp->xad[skip + 1], &sp->xad[skip],
  847. (nextindex - skip) * sizeof(xad_t));
  848. /* insert the new entry: mark the entry NEW */
  849. xad = &sp->xad[skip];
  850. XT_PUTENTRY(xad, split->flag, split->off, split->len,
  851.     split->addr);
  852. /* advance next available entry index */
  853. sp->header.nextindex =
  854.     cpu_to_le16(le16_to_cpu(sp->header.nextindex) + 1);
  855. /* Don't log it if there are no links to the file */
  856. if (!test_cflag(COMMIT_Nolink, ip)) {
  857. tlck = txLock(tid, ip, smp, tlckXTREE | tlckGROW);
  858. xtlck = (struct xtlock *) & tlck->lock;
  859. xtlck->lwm.offset = (xtlck->lwm.offset) ?
  860.     min(skip, (int)xtlck->lwm.offset) : skip;
  861. xtlck->lwm.length =
  862.     le16_to_cpu(sp->header.nextindex) -
  863.     xtlck->lwm.offset;
  864. }
  865. return 0;
  866. }
  867. /*
  868.  * allocate new index blocks to cover index page split(s)
  869.  *
  870.  * allocation hint: ?
  871.  */
  872. if (split->pxdlist == NULL) {
  873. nsplit = btstack->nsplit;
  874. split->pxdlist = &pxdlist;
  875. pxdlist.maxnpxd = pxdlist.npxd = 0;
  876. pxd = &pxdlist.pxd[0];
  877. xlen = JFS_SBI(ip->i_sb)->nbperpage;
  878. for (; nsplit > 0; nsplit--, pxd++) {
  879. if ((rc = dbAlloc(ip, (s64) 0, (s64) xlen, &xaddr))
  880.     == 0) {
  881. PXDaddress(pxd, xaddr);
  882. PXDlength(pxd, xlen);
  883. pxdlist.maxnpxd++;
  884. continue;
  885. }
  886. /* undo allocation */
  887. XT_PUTPAGE(smp);
  888. return rc;
  889. }
  890. }
  891. /*
  892.  * Split leaf page <sp> into <sp> and a new right page <rp>.
  893.  *
  894.  * The split routines insert the new entry into the leaf page,
  895.  * and acquire txLock as appropriate.
  896.  * return <rp> pinned and its block number <rpbn>.
  897.  */
  898. rc = (sp->header.flag & BT_ROOT) ?
  899.     xtSplitRoot(tid, ip, split, &rmp) :
  900.     xtSplitPage(tid, ip, split, &rmp, &rbn);
  901. if (rc)
  902. return EIO;
  903. XT_PUTPAGE(smp);
  904. /*
  905.  * propagate up the router entry for the leaf page just split
  906.  *
  907.  * insert a router entry for the new page into the parent page,
  908.  * propagate the insert/split up the tree by walking back the stack
  909.  * of (bn of parent page, index of child page entry in parent page)
  910.  * that were traversed during the search for the page that split.
  911.  *
  912.  * the propagation of insert/split up the tree stops if the root
  913.  * splits or the page inserted into doesn't have to split to hold
  914.  * the new entry.
  915.  *
  916.  * the parent entry for the split page remains the same, and
  917.  * a new entry is inserted at its right with the first key and
  918.  * block number of the new right page.
  919.  *
  920.  * There are a maximum of 3 pages pinned at any time:
  921.  * right child, left parent and right parent (when the parent splits)
  922.  * to keep the child page pinned while working on the parent.
  923.  * make sure that all pins are released at exit.
  924.  */
  925. while ((parent = BT_POP(btstack)) != NULL) {
  926. /* parent page specified by stack frame <parent> */
  927. /* keep current child pages <rcp> pinned */
  928. rcmp = rmp;
  929. rcbn = rbn;
  930. rcp = XT_PAGE(ip, rcmp);
  931. /*
  932.  * insert router entry in parent for new right child page <rp>
  933.  */
  934. /* get/pin the parent page <sp> */
  935. XT_GETPAGE(ip, parent->bn, smp, PSIZE, sp, rc);
  936. if (rc)
  937. goto errout2;
  938. /*
  939.  * The new key entry goes ONE AFTER the index of parent entry,
  940.  * because the split was to the right.
  941.  */
  942. skip = parent->index + 1;
  943. /*
  944.  * split or shift right remaining entries of the parent page
  945.  */
  946. nextindex = le16_to_cpu(sp->header.nextindex);
  947. /*
  948.  * parent page is full - split the parent page
  949.  */
  950. if (nextindex == le16_to_cpu(sp->header.maxentry)) {
  951. /* init for parent page split */
  952. split->mp = smp;
  953. split->index = skip; /* index at insert */
  954. split->flag = XAD_NEW;
  955. split->off = offsetXAD(&rcp->xad[XTENTRYSTART]);
  956. split->len = JFS_SBI(ip->i_sb)->nbperpage;
  957. split->addr = rcbn;
  958. /* unpin previous right child page */
  959. XT_PUTPAGE(rcmp);
  960. /* The split routines insert the new entry,
  961.  * and acquire txLock as appropriate.
  962.  * return <rp> pinned and its block number <rpbn>.
  963.  */
  964. rc = (sp->header.flag & BT_ROOT) ?
  965.     xtSplitRoot(tid, ip, split, &rmp) :
  966.     xtSplitPage(tid, ip, split, &rmp, &rbn);
  967. if (rc)
  968. goto errout1;
  969. XT_PUTPAGE(smp);
  970. /* keep new child page <rp> pinned */
  971. }
  972. /*
  973.  * parent page is not full - insert in parent page
  974.  */
  975. else {
  976. /*
  977.  * insert router entry in parent for the right child
  978.  * page from the first entry of the right child page:
  979.  */
  980. /*
  981.  * acquire a transaction lock on the parent page;
  982.  *
  983.  * action: router xad insertion;
  984.  */
  985. BT_MARK_DIRTY(smp, ip);
  986. /*
  987.  * if insert into middle, shift right remaining entries
  988.  */
  989. if (skip < nextindex)
  990. memmove(&sp->xad[skip + 1], &sp->xad[skip],
  991. (nextindex -
  992.  skip) << L2XTSLOTSIZE);
  993. /* insert the router entry */
  994. xad = &sp->xad[skip];
  995. XT_PUTENTRY(xad, XAD_NEW,
  996.     offsetXAD(&rcp->xad[XTENTRYSTART]),
  997.     JFS_SBI(ip->i_sb)->nbperpage, rcbn);
  998. /* advance next available entry index. */
  999. sp->header.nextindex =
  1000.     cpu_to_le16(le16_to_cpu(sp->header.nextindex) +
  1001. 1);
  1002. /* Don't log it if there are no links to the file */
  1003. if (!test_cflag(COMMIT_Nolink, ip)) {
  1004. tlck = txLock(tid, ip, smp,
  1005.       tlckXTREE | tlckGROW);
  1006. xtlck = (struct xtlock *) & tlck->lock;
  1007. xtlck->lwm.offset = (xtlck->lwm.offset) ?
  1008.     min(skip, (int)xtlck->lwm.offset) : skip;
  1009. xtlck->lwm.length =
  1010.     le16_to_cpu(sp->header.nextindex) -
  1011.     xtlck->lwm.offset;
  1012. }
  1013. /* unpin parent page */
  1014. XT_PUTPAGE(smp);
  1015. /* exit propagate up */
  1016. break;
  1017. }
  1018. }
  1019. /* unpin current right page */
  1020. XT_PUTPAGE(rmp);
  1021. return 0;
  1022. /*
  1023.  * If something fails in the above loop we were already walking back
  1024.  * up the tree and the tree is now inconsistent.
  1025.  * release all pages we're holding.
  1026.  */
  1027.       errout1:
  1028. XT_PUTPAGE(smp);
  1029.       errout2:
  1030. XT_PUTPAGE(rcmp);
  1031. return rc;
  1032. }
  1033. /*
  1034.  *      xtSplitPage()
  1035.  *
  1036.  * function:
  1037.  *      split a full non-root page into
  1038.  *      original/split/left page and new right page
  1039.  *      i.e., the original/split page remains as left page.
  1040.  *
  1041.  * parameter:
  1042.  *      int tid,
  1043.  *      struct inode    *ip,
  1044.  *      struct xtsplit  *split,
  1045.  *      struct metapage **rmpp,
  1046.  *      u64 *rbnp,
  1047.  *
  1048.  * return:
  1049.  *      Pointer to page in which to insert or NULL on error.
  1050.  */
  1051. static int
  1052. xtSplitPage(tid_t tid, struct inode *ip,
  1053.     struct xtsplit * split, struct metapage ** rmpp, s64 * rbnp)
  1054. {
  1055. int rc = 0;
  1056. struct metapage *smp;
  1057. xtpage_t *sp;
  1058. struct metapage *rmp;
  1059. xtpage_t *rp; /* new right page allocated */
  1060. s64 rbn; /* new right page block number */
  1061. struct metapage *mp;
  1062. xtpage_t *p;
  1063. s64 nextbn;
  1064. int skip, maxentry, middle, righthalf, n;
  1065. xad_t *xad;
  1066. struct pxdlist *pxdlist;
  1067. pxd_t *pxd;
  1068. struct tlock *tlck;
  1069. struct xtlock *sxtlck = 0, *rxtlck = 0;
  1070. smp = split->mp;
  1071. sp = XT_PAGE(ip, smp);
  1072. INCREMENT(xtStat.split);
  1073. /*
  1074.  * allocate the new right page for the split
  1075.  */
  1076. pxdlist = split->pxdlist;
  1077. pxd = &pxdlist->pxd[pxdlist->npxd];
  1078. pxdlist->npxd++;
  1079. rbn = addressPXD(pxd);
  1080. rmp = get_metapage(ip, rbn, PSIZE, 1);
  1081. if (rmp == NULL)
  1082. return EIO;
  1083. jEVENT(0,
  1084.        ("xtSplitPage: ip:0x%p smp:0x%p rmp:0x%pn", ip, smp, rmp));
  1085. BT_MARK_DIRTY(rmp, ip);
  1086. /*
  1087.  * action: new page;
  1088.  */
  1089. rp = (xtpage_t *) rmp->data;
  1090. rp->header.self = *pxd;
  1091. rp->header.flag = sp->header.flag & BT_TYPE;
  1092. rp->header.maxentry = sp->header.maxentry; /* little-endian */
  1093. rp->header.nextindex = cpu_to_le16(XTENTRYSTART);
  1094. BT_MARK_DIRTY(smp, ip);
  1095. /* Don't log it if there are no links to the file */
  1096. if (!test_cflag(COMMIT_Nolink, ip)) {
  1097. /*
  1098.  * acquire a transaction lock on the new right page;
  1099.  */
  1100. tlck = txLock(tid, ip, rmp, tlckXTREE | tlckNEW);
  1101. rxtlck = (struct xtlock *) & tlck->lock;
  1102. rxtlck->lwm.offset = XTENTRYSTART;
  1103. /*
  1104.  * acquire a transaction lock on the split page
  1105.  */
  1106. tlck = txLock(tid, ip, smp, tlckXTREE | tlckGROW);
  1107. sxtlck = (struct xtlock *) & tlck->lock;
  1108. }
  1109. /*
  1110.  * initialize/update sibling pointers of <sp> and <rp>
  1111.  */
  1112. nextbn = le64_to_cpu(sp->header.next);
  1113. rp->header.next = cpu_to_le64(nextbn);
  1114. rp->header.prev = cpu_to_le64(addressPXD(&sp->header.self));
  1115. sp->header.next = cpu_to_le64(rbn);
  1116. skip = split->index;
  1117. /*
  1118.  *      sequential append at tail (after last entry of last page)
  1119.  *
  1120.  * if splitting the last page on a level because of appending
  1121.  * a entry to it (skip is maxentry), it's likely that the access is
  1122.  * sequential. adding an empty page on the side of the level is less
  1123.  * work and can push the fill factor much higher than normal.
  1124.  * if we're wrong it's no big deal -  we will do the split the right
  1125.  * way next time.
  1126.  * (it may look like it's equally easy to do a similar hack for
  1127.  * reverse sorted data, that is, split the tree left, but it's not.
  1128.  * Be my guest.)
  1129.  */
  1130. if (nextbn == 0 && skip == le16_to_cpu(sp->header.maxentry)) {
  1131. /*
  1132.  * acquire a transaction lock on the new/right page;
  1133.  *
  1134.  * action: xad insertion;
  1135.  */
  1136. /* insert entry at the first entry of the new right page */
  1137. xad = &rp->xad[XTENTRYSTART];
  1138. XT_PUTENTRY(xad, split->flag, split->off, split->len,
  1139.     split->addr);
  1140. rp->header.nextindex = cpu_to_le16(XTENTRYSTART + 1);
  1141. if (!test_cflag(COMMIT_Nolink, ip)) {
  1142. /* rxtlck->lwm.offset = XTENTRYSTART; */
  1143. rxtlck->lwm.length = 1;
  1144. }
  1145. *rmpp = rmp;
  1146. *rbnp = rbn;
  1147. ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
  1148. jEVENT(0, ("xtSplitPage: sp:0x%p rp:0x%pn", sp, rp));
  1149. return 0;
  1150. }
  1151. /*
  1152.  *      non-sequential insert (at possibly middle page)
  1153.  */
  1154. /*
  1155.  * update previous pointer of old next/right page of <sp>
  1156.  */
  1157. if (nextbn != 0) {
  1158. XT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);
  1159. if (rc) {
  1160. XT_PUTPAGE(rmp);
  1161. return rc;
  1162. }
  1163. BT_MARK_DIRTY(mp, ip);
  1164. /*
  1165.  * acquire a transaction lock on the next page;
  1166.  *
  1167.  * action:sibling pointer update;
  1168.  */
  1169. if (!test_cflag(COMMIT_Nolink, ip))
  1170. tlck = txLock(tid, ip, mp, tlckXTREE | tlckRELINK);
  1171. p->header.prev = cpu_to_le64(rbn);
  1172. /* sibling page may have been updated previously, or
  1173.  * it may be updated later;
  1174.  */
  1175. XT_PUTPAGE(mp);
  1176. }
  1177. /*
  1178.  * split the data between the split and new/right pages
  1179.  */
  1180. maxentry = le16_to_cpu(sp->header.maxentry);
  1181. middle = maxentry >> 1;
  1182. righthalf = maxentry - middle;
  1183. /*
  1184.  * skip index in old split/left page - insert into left page:
  1185.  */
  1186. if (skip <= middle) {
  1187. /* move right half of split page to the new right page */
  1188. memmove(&rp->xad[XTENTRYSTART], &sp->xad[middle],
  1189. righthalf << L2XTSLOTSIZE);
  1190. /* shift right tail of left half to make room for new entry */
  1191. if (skip < middle)
  1192. memmove(&sp->xad[skip + 1], &sp->xad[skip],
  1193. (middle - skip) << L2XTSLOTSIZE);
  1194. /* insert new entry */
  1195. xad = &sp->xad[skip];
  1196. XT_PUTENTRY(xad, split->flag, split->off, split->len,
  1197.     split->addr);
  1198. /* update page header */
  1199. sp->header.nextindex = cpu_to_le16(middle + 1);
  1200. if (!test_cflag(COMMIT_Nolink, ip)) {
  1201. sxtlck->lwm.offset = (sxtlck->lwm.offset) ?
  1202.     min(skip, (int)sxtlck->lwm.offset) : skip;
  1203. }
  1204. rp->header.nextindex =
  1205.     cpu_to_le16(XTENTRYSTART + righthalf);
  1206. }
  1207. /*
  1208.  * skip index in new right page - insert into right page:
  1209.  */
  1210. else {
  1211. /* move left head of right half to right page */
  1212. n = skip - middle;
  1213. memmove(&rp->xad[XTENTRYSTART], &sp->xad[middle],
  1214. n << L2XTSLOTSIZE);
  1215. /* insert new entry */
  1216. n += XTENTRYSTART;
  1217. xad = &rp->xad[n];
  1218. XT_PUTENTRY(xad, split->flag, split->off, split->len,
  1219.     split->addr);
  1220. /* move right tail of right half to right page */
  1221. if (skip < maxentry)
  1222. memmove(&rp->xad[n + 1], &sp->xad[skip],
  1223. (maxentry - skip) << L2XTSLOTSIZE);
  1224. /* update page header */
  1225. sp->header.nextindex = cpu_to_le16(middle);
  1226. if (!test_cflag(COMMIT_Nolink, ip)) {
  1227. sxtlck->lwm.offset = (sxtlck->lwm.offset) ?
  1228.     min(middle, (int)sxtlck->lwm.offset) : middle;
  1229. }
  1230. rp->header.nextindex = cpu_to_le16(XTENTRYSTART +
  1231.    righthalf + 1);
  1232. }
  1233. if (!test_cflag(COMMIT_Nolink, ip)) {
  1234. sxtlck->lwm.length = le16_to_cpu(sp->header.nextindex) -
  1235.     sxtlck->lwm.offset;
  1236. /* rxtlck->lwm.offset = XTENTRYSTART; */
  1237. rxtlck->lwm.length = le16_to_cpu(rp->header.nextindex) -
  1238.     XTENTRYSTART;
  1239. }
  1240. *rmpp = rmp;
  1241. *rbnp = rbn;
  1242. ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
  1243. jEVENT(0, ("xtSplitPage: sp:0x%p rp:0x%pn", sp, rp));
  1244. return rc;
  1245. }
  1246. /*
  1247.  *      xtSplitRoot()
  1248.  *
  1249.  * function:
  1250.  *      split the full root page into
  1251.  *      original/root/split page and new right page
  1252.  *      i.e., root remains fixed in tree anchor (inode) and
  1253.  *      the root is copied to a single new right child page
  1254.  *      since root page << non-root page, and
  1255.  *      the split root page contains a single entry for the
  1256.  *      new right child page.
  1257.  *
  1258.  * parameter:
  1259.  *      int tid,
  1260.  *      struct inode    *ip,
  1261.  *      struct xtsplit  *split,
  1262.  *      struct metapage **rmpp)
  1263.  *
  1264.  * return:
  1265.  *      Pointer to page in which to insert or NULL on error.
  1266.  */
  1267. static int
  1268. xtSplitRoot(tid_t tid,
  1269.     struct inode *ip, struct xtsplit * split, struct metapage ** rmpp)
  1270. {
  1271. xtpage_t *sp;
  1272. struct metapage *rmp;
  1273. xtpage_t *rp;
  1274. s64 rbn;
  1275. int skip, nextindex;
  1276. xad_t *xad;
  1277. pxd_t *pxd;
  1278. struct pxdlist *pxdlist;
  1279. struct tlock *tlck;
  1280. struct xtlock *xtlck;
  1281. sp = &JFS_IP(ip)->i_xtroot;
  1282. INCREMENT(xtStat.split);
  1283. /*
  1284.  *      allocate a single (right) child page
  1285.  */
  1286. pxdlist = split->pxdlist;
  1287. pxd = &pxdlist->pxd[pxdlist->npxd];
  1288. pxdlist->npxd++;
  1289. rbn = addressPXD(pxd);
  1290. rmp = get_metapage(ip, rbn, PSIZE, 1);
  1291. if (rmp == NULL)
  1292. return EIO;
  1293. jEVENT(0, ("xtSplitRoot: ip:0x%p rmp:0x%pn", ip, rmp));
  1294. /*
  1295.  * acquire a transaction lock on the new right page;
  1296.  *
  1297.  * action: new page;
  1298.  */
  1299. BT_MARK_DIRTY(rmp, ip);
  1300. rp = (xtpage_t *) rmp->data;
  1301. rp->header.flag =
  1302.     (sp->header.flag & BT_LEAF) ? BT_LEAF : BT_INTERNAL;
  1303. rp->header.self = *pxd;
  1304. rp->header.nextindex = cpu_to_le16(XTENTRYSTART);
  1305. rp->header.maxentry = cpu_to_le16(PSIZE >> L2XTSLOTSIZE);
  1306. /* initialize sibling pointers */
  1307. rp->header.next = 0;
  1308. rp->header.prev = 0;
  1309. /*
  1310.  * copy the in-line root page into new right page extent
  1311.  */
  1312. nextindex = le16_to_cpu(sp->header.maxentry);
  1313. memmove(&rp->xad[XTENTRYSTART], &sp->xad[XTENTRYSTART],
  1314. (nextindex - XTENTRYSTART) << L2XTSLOTSIZE);
  1315. /*
  1316.  * insert the new entry into the new right/child page
  1317.  * (skip index in the new right page will not change)
  1318.  */
  1319. skip = split->index;
  1320. /* if insert into middle, shift right remaining entries */
  1321. if (skip != nextindex)
  1322. memmove(&rp->xad[skip + 1], &rp->xad[skip],
  1323. (nextindex - skip) * sizeof(xad_t));
  1324. xad = &rp->xad[skip];
  1325. XT_PUTENTRY(xad, split->flag, split->off, split->len, split->addr);
  1326. /* update page header */
  1327. rp->header.nextindex = cpu_to_le16(nextindex + 1);
  1328. if (!test_cflag(COMMIT_Nolink, ip)) {
  1329. tlck = txLock(tid, ip, rmp, tlckXTREE | tlckNEW);
  1330. xtlck = (struct xtlock *) & tlck->lock;
  1331. xtlck->lwm.offset = XTENTRYSTART;
  1332. xtlck->lwm.length = le16_to_cpu(rp->header.nextindex) -
  1333.     XTENTRYSTART;
  1334. }
  1335. /*
  1336.  *      reset the root
  1337.  *
  1338.  * init root with the single entry for the new right page
  1339.  * set the 1st entry offset to 0, which force the left-most key
  1340.  * at any level of the tree to be less than any search key.
  1341.  */
  1342. /*
  1343.  * acquire a transaction lock on the root page (in-memory inode);
  1344.  *
  1345.  * action: root split;
  1346.  */
  1347. BT_MARK_DIRTY(split->mp, ip);
  1348. xad = &sp->xad[XTENTRYSTART];
  1349. XT_PUTENTRY(xad, XAD_NEW, 0, JFS_SBI(ip->i_sb)->nbperpage, rbn);
  1350. /* update page header of root */
  1351. sp->header.flag &= ~BT_LEAF;
  1352. sp->header.flag |= BT_INTERNAL;
  1353. sp->header.nextindex = cpu_to_le16(XTENTRYSTART + 1);
  1354. if (!test_cflag(COMMIT_Nolink, ip)) {
  1355. tlck = txLock(tid, ip, split->mp, tlckXTREE | tlckGROW);
  1356. xtlck = (struct xtlock *) & tlck->lock;
  1357. xtlck->lwm.offset = XTENTRYSTART;
  1358. xtlck->lwm.length = 1;
  1359. }
  1360. *rmpp = rmp;
  1361. ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
  1362. jEVENT(0, ("xtSplitRoot: sp:0x%p rp:0x%pn", sp, rp));
  1363. return 0;
  1364. }
  1365. /*
  1366.  *      xtExtend()
  1367.  *
  1368.  * function: extend in-place;
  1369.  *
  1370.  * note: existing extent may or may not have been committed.
  1371.  * caller is responsible for pager buffer cache update, and
  1372.  * working block allocation map update;
  1373.  * update pmap: alloc whole extended extent;
  1374.  */
  1375. int xtExtend(tid_t tid, /* transaction id */
  1376.      struct inode *ip, s64 xoff, /* delta extent offset */
  1377.      s32 xlen, /* delta extent length */
  1378.      int flag)
  1379. {
  1380. int rc = 0;
  1381. int cmp;
  1382. struct metapage *mp; /* meta-page buffer */
  1383. xtpage_t *p; /* base B+-tree index page */
  1384. s64 bn;
  1385. int index, nextindex, len;
  1386. struct btstack btstack; /* traverse stack */
  1387. struct xtsplit split; /* split information */
  1388. xad_t *xad;
  1389. s64 xaddr;
  1390. struct tlock *tlck;
  1391. struct xtlock *xtlck = 0;
  1392. int rootsplit = 0;
  1393. jFYI(1,
  1394.      ("xtExtend: nxoff:0x%lx nxlen:0x%xn", (ulong) xoff, xlen));
  1395. /* there must exist extent to be extended */
  1396. if ((rc = xtSearch(ip, xoff - 1, &cmp, &btstack, XT_INSERT)))
  1397. return rc;
  1398. assert(cmp == 0);
  1399. /* retrieve search result */
  1400. XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
  1401. /* extension must be contiguous */
  1402. xad = &p->xad[index];
  1403. jFYI(0, ("xtExtend: xoff:0x%lx xlen:0x%x xaddr:0x%lxn",
  1404.  (ulong) offsetXAD(xad), lengthXAD(xad),
  1405.  (ulong) addressXAD(xad)));
  1406. assert((offsetXAD(xad) + lengthXAD(xad)) == xoff);
  1407. /*
  1408.  * acquire a transaction lock on the leaf page;
  1409.  *
  1410.  * action: xad insertion/extension;
  1411.  */
  1412. BT_MARK_DIRTY(mp, ip);
  1413. if (!test_cflag(COMMIT_Nolink, ip)) {
  1414. tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW);
  1415. xtlck = (struct xtlock *) & tlck->lock;
  1416. }
  1417. /* extend will overflow extent ? */
  1418. xlen = lengthXAD(xad) + xlen;
  1419. if ((len = xlen - MAXXLEN) <= 0)
  1420. goto extendOld;
  1421. /*
  1422.  *      extent overflow: insert entry for new extent
  1423.  */
  1424. //insertNew:
  1425. xoff = offsetXAD(xad) + MAXXLEN;
  1426. xaddr = addressXAD(xad) + MAXXLEN;
  1427. nextindex = le16_to_cpu(p->header.nextindex);
  1428. /*
  1429.  *      if the leaf page is full, insert the new entry and
  1430.  *      propagate up the router entry for the new page from split
  1431.  *
  1432.  * The xtSplitUp() will insert the entry and unpin the leaf page.
  1433.  */
  1434. if (nextindex == le16_to_cpu(p->header.maxentry)) {
  1435. rootsplit = p->header.flag & BT_ROOT;
  1436. /* xtSpliUp() unpins leaf pages */
  1437. split.mp = mp;
  1438. split.index = index + 1;
  1439. split.flag = XAD_NEW;
  1440. split.off = xoff; /* split offset */
  1441. split.len = len;
  1442. split.addr = xaddr;
  1443. split.pxdlist = NULL;
  1444. if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
  1445. return rc;
  1446. /*
  1447.  * if leaf root has been split, original root has been
  1448.  * copied to new child page, i.e., original entry now
  1449.  * resides on the new child page;
  1450.  */
  1451. if (rootsplit) {
  1452. if (p->header.nextindex ==
  1453.     cpu_to_le16(XTENTRYSTART + 1)) {
  1454. xad = &p->xad[XTENTRYSTART];
  1455. bn = addressXAD(xad);
  1456. /* get new child page */
  1457. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  1458. BT_MARK_DIRTY(mp, ip);
  1459. if (!test_cflag(COMMIT_Nolink, ip)) {
  1460. tlck = txLock(tid, ip, mp,
  1461.       tlckXTREE |
  1462.       tlckGROW);
  1463. xtlck = (struct xtlock *) & tlck->lock;
  1464. }
  1465. }
  1466. } else
  1467. /* get back old page */
  1468. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  1469. }
  1470. /*
  1471.  *      insert the new entry into the leaf page
  1472.  */
  1473. else {
  1474. /* insert the new entry: mark the entry NEW */
  1475. xad = &p->xad[index + 1];
  1476. XT_PUTENTRY(xad, XAD_NEW, xoff, len, xaddr);
  1477. /* advance next available entry index */
  1478. p->header.nextindex =
  1479.     cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
  1480. }
  1481. /* get back old entry */
  1482. xad = &p->xad[index];
  1483. xlen = MAXXLEN;
  1484. /*
  1485.  * extend old extent
  1486.  */
  1487.       extendOld:
  1488. XADlength(xad, xlen);
  1489. if (!(xad->flag & XAD_NEW))
  1490. xad->flag |= XAD_EXTENDED;
  1491. if (!test_cflag(COMMIT_Nolink, ip)) {
  1492. xtlck->lwm.offset =
  1493.     (xtlck->lwm.offset) ? min(index,
  1494.       (int)xtlck->lwm.offset) : index;
  1495. xtlck->lwm.length =
  1496.     le16_to_cpu(p->header.nextindex) - xtlck->lwm.offset;
  1497. }
  1498. /* unpin the leaf page */
  1499. XT_PUTPAGE(mp);
  1500. return rc;
  1501. }
  1502. /*
  1503.  *      xtTailgate()
  1504.  *
  1505.  * function: split existing 'tail' extent
  1506.  *      (split offset >= start offset of tail extent), and
  1507.  *      relocate and extend the split tail half;
  1508.  *
  1509.  * note: existing extent may or may not have been committed.
  1510.  * caller is responsible for pager buffer cache update, and
  1511.  * working block allocation map update;
  1512.  * update pmap: free old split tail extent, alloc new extent;
  1513.  */
  1514. int xtTailgate(tid_t tid, /* transaction id */
  1515.        struct inode *ip, s64 xoff, /* split/new extent offset */
  1516.        s32 xlen, /* new extent length */
  1517.        s64 xaddr, /* new extent address */
  1518.        int flag)
  1519. {
  1520. int rc = 0;
  1521. int cmp;
  1522. struct metapage *mp; /* meta-page buffer */
  1523. xtpage_t *p; /* base B+-tree index page */
  1524. s64 bn;
  1525. int index, nextindex, llen, rlen;
  1526. struct btstack btstack; /* traverse stack */
  1527. struct xtsplit split; /* split information */
  1528. xad_t *xad;
  1529. struct tlock *tlck;
  1530. struct xtlock *xtlck = 0;
  1531. struct tlock *mtlck;
  1532. struct maplock *pxdlock;
  1533. int rootsplit = 0;
  1534. /*
  1535. printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lxn",
  1536.         (ulong)xoff, xlen, (ulong)xaddr);
  1537. */
  1538. /* there must exist extent to be tailgated */
  1539. if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT)))
  1540. return rc;
  1541. assert(cmp == 0);
  1542. /* retrieve search result */
  1543. XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
  1544. /* entry found must be last entry */
  1545. nextindex = le16_to_cpu(p->header.nextindex);
  1546. assert(index == nextindex - 1);
  1547. BT_MARK_DIRTY(mp, ip);
  1548. /*
  1549.  * acquire tlock of the leaf page containing original entry
  1550.  */
  1551. if (!test_cflag(COMMIT_Nolink, ip)) {
  1552. tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW);
  1553. xtlck = (struct xtlock *) & tlck->lock;
  1554. }
  1555. /* completely replace extent ? */
  1556. xad = &p->xad[index];
  1557. /*
  1558. printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lxn",
  1559.         (ulong)offsetXAD(xad), lengthXAD(xad), (ulong)addressXAD(xad));
  1560. */
  1561. if ((llen = xoff - offsetXAD(xad)) == 0)
  1562. goto updateOld;
  1563. /*
  1564.  *      partially replace extent: insert entry for new extent
  1565.  */
  1566. //insertNew:
  1567. /*
  1568.  *      if the leaf page is full, insert the new entry and
  1569.  *      propagate up the router entry for the new page from split
  1570.  *
  1571.  * The xtSplitUp() will insert the entry and unpin the leaf page.
  1572.  */
  1573. if (nextindex == le16_to_cpu(p->header.maxentry)) {
  1574. rootsplit = p->header.flag & BT_ROOT;
  1575. /* xtSpliUp() unpins leaf pages */
  1576. split.mp = mp;
  1577. split.index = index + 1;
  1578. split.flag = XAD_NEW;
  1579. split.off = xoff; /* split offset */
  1580. split.len = xlen;
  1581. split.addr = xaddr;
  1582. split.pxdlist = NULL;
  1583. if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
  1584. return rc;
  1585. /*
  1586.  * if leaf root has been split, original root has been
  1587.  * copied to new child page, i.e., original entry now
  1588.  * resides on the new child page;
  1589.  */
  1590. if (rootsplit) {
  1591. if (p->header.nextindex ==
  1592.     cpu_to_le16(XTENTRYSTART + 1)) {
  1593. xad = &p->xad[XTENTRYSTART];
  1594. bn = addressXAD(xad);
  1595. /* get new child page */
  1596. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  1597. BT_MARK_DIRTY(mp, ip);
  1598. if (!test_cflag(COMMIT_Nolink, ip)) {
  1599. tlck = txLock(tid, ip, mp,
  1600.       tlckXTREE |
  1601.       tlckGROW);
  1602. xtlck = (struct xtlock *) & tlck->lock;
  1603. }
  1604. }
  1605. } else
  1606. /* get back old page */
  1607. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  1608. }
  1609. /*
  1610.  *      insert the new entry into the leaf page
  1611.  */
  1612. else {
  1613. /* insert the new entry: mark the entry NEW */
  1614. xad = &p->xad[index + 1];
  1615. XT_PUTENTRY(xad, XAD_NEW, xoff, xlen, xaddr);
  1616. /* advance next available entry index */
  1617. p->header.nextindex =
  1618.     cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
  1619. }
  1620. /* get back old XAD */
  1621. xad = &p->xad[index];
  1622. /*
  1623.  * truncate/relocate old extent at split offset
  1624.  */
  1625.       updateOld:
  1626. /* update dmap for old/committed/truncated extent */
  1627. rlen = lengthXAD(xad) - llen;
  1628. if (!(xad->flag & XAD_NEW)) {
  1629. /* free from PWMAP at commit */
  1630. if (!test_cflag(COMMIT_Nolink, ip)) {
  1631. mtlck = txMaplock(tid, ip, tlckMAP);
  1632. pxdlock = (struct maplock *) & mtlck->lock;
  1633. pxdlock->flag = mlckFREEPXD;
  1634. PXDaddress(&pxdlock->pxd, addressXAD(xad) + llen);
  1635. PXDlength(&pxdlock->pxd, rlen);
  1636. pxdlock->index = 1;
  1637. }
  1638. jEVENT(0,
  1639.        ("xtTailgate: free extent xaddr:0x%lx xlen:0x%xn",
  1640. (ulong) addressPXD(&pxdlock->pxd),
  1641. lengthPXD(&pxdlock->pxd)));
  1642. } else
  1643. /* free from WMAP */
  1644. dbFree(ip, addressXAD(xad) + llen, (s64) rlen);
  1645. if (llen)
  1646. /* truncate */
  1647. XADlength(xad, llen);
  1648. else
  1649. /* replace */
  1650. XT_PUTENTRY(xad, XAD_NEW, xoff, xlen, xaddr);
  1651. if (!test_cflag(COMMIT_Nolink, ip)) {
  1652. xtlck->lwm.offset = (xtlck->lwm.offset) ?
  1653.     min(index, (int)xtlck->lwm.offset) : index;
  1654. xtlck->lwm.length = le16_to_cpu(p->header.nextindex) -
  1655.     xtlck->lwm.offset;
  1656. }
  1657. /* unpin the leaf page */
  1658. XT_PUTPAGE(mp);
  1659. return rc;
  1660. }
  1661. /*
  1662.  *      xtUpdate()
  1663.  *
  1664.  * function: update XAD;
  1665.  *
  1666.  *      update extent for allocated_but_not_recorded or
  1667.  *      compressed extent;
  1668.  *
  1669.  * parameter:
  1670.  *      nxad    - new XAD;
  1671.  *                logical extent of the specified XAD must be completely
  1672.  *                contained by an existing XAD;
  1673.  */
  1674. int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
  1675. { /* new XAD */
  1676. int rc = 0;
  1677. int cmp;
  1678. struct metapage *mp; /* meta-page buffer */
  1679. xtpage_t *p; /* base B+-tree index page */
  1680. s64 bn;
  1681. int index0, index, newindex, nextindex;
  1682. struct btstack btstack; /* traverse stack */
  1683. struct xtsplit split; /* split information */
  1684. xad_t *xad, *lxad, *rxad;
  1685. int xflag;
  1686. s64 nxoff, xoff;
  1687. int nxlen, xlen, lxlen, rxlen;
  1688. s64 nxaddr, xaddr;
  1689. struct tlock *tlck;
  1690. struct xtlock *xtlck = 0;
  1691. int rootsplit = 0, newpage = 0;
  1692. /* there must exist extent to be tailgated */
  1693. nxoff = offsetXAD(nxad);
  1694. nxlen = lengthXAD(nxad);
  1695. nxaddr = addressXAD(nxad);
  1696. /*
  1697. printf("xtUpdate: nxflag:0x%x nxoff:0x%lx nxlen:0x%x nxaddr:0x%lxn",
  1698.         nxad->flag, (ulong)nxoff, nxlen, (ulong)nxaddr);
  1699. */
  1700. if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT)))
  1701. return rc;
  1702. assert(cmp == 0);
  1703. /* retrieve search result */
  1704. XT_GETSEARCH(ip, btstack.top, bn, mp, p, index0);
  1705. BT_MARK_DIRTY(mp, ip);
  1706. /*
  1707.  * acquire tlock of the leaf page containing original entry
  1708.  */
  1709. if (!test_cflag(COMMIT_Nolink, ip)) {
  1710. tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW);
  1711. xtlck = (struct xtlock *) & tlck->lock;
  1712. }
  1713. xad = &p->xad[index0];
  1714. xflag = xad->flag;
  1715. xoff = offsetXAD(xad);
  1716. xlen = lengthXAD(xad);
  1717. xaddr = addressXAD(xad);
  1718. /*
  1719. printf("xtUpdate: xflag:0x%x xoff:0x%lx xlen:0x%x xaddr:0x%lxn",
  1720.         xflag, (ulong)xoff, xlen, (ulong)xaddr);
  1721. */
  1722. /* nXAD must be completely contained within XAD */
  1723. assert(xoff <= nxoff);
  1724. assert(nxoff + nxlen <= xoff + xlen);
  1725. index = index0;
  1726. newindex = index + 1;
  1727. nextindex = le16_to_cpu(p->header.nextindex);
  1728. #ifdef  _JFS_WIP_NOCOALESCE
  1729. if (xoff < nxoff)
  1730. goto updateRight;
  1731. /*
  1732.  * replace XAD with nXAD
  1733.  */
  1734.       replace: /* (nxoff == xoff) */
  1735. if (nxlen == xlen) {
  1736. /* replace XAD with nXAD:recorded */
  1737. *xad = *nxad;
  1738. xad->flag = xflag & ~XAD_NOTRECORDED;
  1739. goto out;
  1740. } else /* (nxlen < xlen) */
  1741. goto updateLeft;
  1742. #endif /* _JFS_WIP_NOCOALESCE */
  1743. /* #ifdef _JFS_WIP_COALESCE */
  1744. if (xoff < nxoff)
  1745. goto coalesceRight;
  1746. /*
  1747.  * coalesce with left XAD
  1748.  */
  1749. //coalesceLeft: /* (xoff == nxoff) */
  1750. /* is XAD first entry of page ? */
  1751. if (index == XTENTRYSTART)
  1752. goto replace;
  1753. /* is nXAD logically and physically contiguous with lXAD ? */
  1754. lxad = &p->xad[index - 1];
  1755. lxlen = lengthXAD(lxad);
  1756. if (!(lxad->flag & XAD_NOTRECORDED) &&
  1757.     (nxoff == offsetXAD(lxad) + lxlen) &&
  1758.     (nxaddr == addressXAD(lxad) + lxlen) &&
  1759.     (lxlen + nxlen < MAXXLEN)) {
  1760. /* extend right lXAD */
  1761. index0 = index - 1;
  1762. XADlength(lxad, lxlen + nxlen);
  1763. /* If we just merged two extents together, need to make sure the
  1764.  * right extent gets logged.  If the left one is marked XAD_NEW,
  1765.  * then we know it will be logged.  Otherwise, mark as
  1766.  * XAD_EXTENDED
  1767.  */
  1768. if (!(lxad->flag & XAD_NEW))
  1769. lxad->flag |= XAD_EXTENDED;
  1770. if (xlen > nxlen) {
  1771. /* truncate XAD */
  1772. XADoffset(xad, xoff + nxlen);
  1773. XADlength(xad, xlen - nxlen);
  1774. XADaddress(xad, xaddr + nxlen);
  1775. goto out;
  1776. } else { /* (xlen == nxlen) */
  1777. /* remove XAD */
  1778. if (index < nextindex - 1)
  1779. memmove(&p->xad[index], &p->xad[index + 1],
  1780. (nextindex - index -
  1781.  1) << L2XTSLOTSIZE);
  1782. p->header.nextindex =
  1783.     cpu_to_le16(le16_to_cpu(p->header.nextindex) -
  1784. 1);
  1785. index = index0;
  1786. newindex = index + 1;
  1787. nextindex = le16_to_cpu(p->header.nextindex);
  1788. xoff = nxoff = offsetXAD(lxad);
  1789. xlen = nxlen = lxlen + nxlen;
  1790. xaddr = nxaddr = addressXAD(lxad);
  1791. goto coalesceRight;
  1792. }
  1793. }
  1794. /*
  1795.  * replace XAD with nXAD
  1796.  */
  1797.       replace: /* (nxoff == xoff) */
  1798. if (nxlen == xlen) {
  1799. /* replace XAD with nXAD:recorded */
  1800. *xad = *nxad;
  1801. xad->flag = xflag & ~XAD_NOTRECORDED;
  1802. goto coalesceRight;
  1803. } else /* (nxlen < xlen) */
  1804. goto updateLeft;
  1805. /*
  1806.  * coalesce with right XAD
  1807.  */
  1808.       coalesceRight: /* (xoff <= nxoff) */
  1809. /* is XAD last entry of page ? */
  1810. if (newindex == nextindex) {
  1811. if (xoff == nxoff)
  1812. goto out;
  1813. goto updateRight;
  1814. }
  1815. /* is nXAD logically and physically contiguous with rXAD ? */
  1816. rxad = &p->xad[index + 1];
  1817. rxlen = lengthXAD(rxad);
  1818. if (!(rxad->flag & XAD_NOTRECORDED) &&
  1819.     (nxoff + nxlen == offsetXAD(rxad)) &&
  1820.     (nxaddr + nxlen == addressXAD(rxad)) &&
  1821.     (rxlen + nxlen < MAXXLEN)) {
  1822. /* extend left rXAD */
  1823. XADoffset(rxad, nxoff);
  1824. XADlength(rxad, rxlen + nxlen);
  1825. XADaddress(rxad, nxaddr);
  1826. /* If we just merged two extents together, need to make sure
  1827.  * the left extent gets logged.  If the right one is marked
  1828.  * XAD_NEW, then we know it will be logged.  Otherwise, mark as
  1829.  * XAD_EXTENDED
  1830.  */
  1831. if (!(rxad->flag & XAD_NEW))
  1832. rxad->flag |= XAD_EXTENDED;
  1833. if (xlen > nxlen)
  1834. /* truncate XAD */
  1835. XADlength(xad, xlen - nxlen);
  1836. else { /* (xlen == nxlen) */
  1837. /* remove XAD */
  1838. memmove(&p->xad[index], &p->xad[index + 1],
  1839. (nextindex - index - 1) << L2XTSLOTSIZE);
  1840. p->header.nextindex =
  1841.     cpu_to_le16(le16_to_cpu(p->header.nextindex) -
  1842. 1);
  1843. }
  1844. goto out;
  1845. } else if (xoff == nxoff)
  1846. goto out;
  1847. assert(xoff < nxoff);
  1848. /* #endif _JFS_WIP_COALESCE */
  1849. /*
  1850.  * split XAD into (lXAD, nXAD):
  1851.  *
  1852.  *          |---nXAD--->
  1853.  * --|----------XAD----------|--
  1854.  *   |-lXAD-|
  1855.  */
  1856.       updateRight: /* (xoff < nxoff) */
  1857. /* truncate old XAD as lXAD:not_recorded */
  1858. xad = &p->xad[index];
  1859. XADlength(xad, nxoff - xoff);
  1860. /* insert nXAD:recorded */
  1861. if (nextindex == le16_to_cpu(p->header.maxentry)) {
  1862. /*
  1863. printf("xtUpdate.updateRight.split p:0x%pn", p);
  1864. */
  1865. rootsplit = p->header.flag & BT_ROOT;
  1866. /* xtSpliUp() unpins leaf pages */
  1867. split.mp = mp;
  1868. split.index = newindex;
  1869. split.flag = xflag & ~XAD_NOTRECORDED;
  1870. split.off = nxoff;
  1871. split.len = nxlen;
  1872. split.addr = nxaddr;
  1873. split.pxdlist = NULL;
  1874. if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
  1875. return rc;
  1876. /*
  1877.  * if leaf root has been split, original root has been
  1878.  * copied to new child page, i.e., original entry now
  1879.  * resides on the new child page;
  1880.  */
  1881. if (rootsplit) {
  1882. if (p->header.nextindex ==
  1883.     cpu_to_le16(XTENTRYSTART + 1)) {
  1884. xad = &p->xad[XTENTRYSTART];
  1885. bn = addressXAD(xad);
  1886. /* get new child page */
  1887. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  1888. BT_MARK_DIRTY(mp, ip);
  1889. if (!test_cflag(COMMIT_Nolink, ip)) {
  1890. tlck = txLock(tid, ip, mp,
  1891.       tlckXTREE |
  1892.       tlckGROW);
  1893. xtlck = (struct xtlock *) & tlck->lock;
  1894. }
  1895. }
  1896. } else {
  1897. /* get back old page */
  1898. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  1899. /* is nXAD on new page ? */
  1900. if (newindex >
  1901.     (le16_to_cpu(p->header.maxentry) >> 1)) {
  1902. newindex =
  1903.     newindex -
  1904.     le16_to_cpu(p->header.nextindex) +
  1905.     XTENTRYSTART;
  1906. newpage = 1;
  1907. }
  1908. }
  1909. } else {
  1910. /* if insert into middle, shift right remaining entries */
  1911. if (newindex < nextindex)
  1912. memmove(&p->xad[newindex + 1], &p->xad[newindex],
  1913. (nextindex - newindex) << L2XTSLOTSIZE);
  1914. /* insert the entry */
  1915. xad = &p->xad[newindex];
  1916. *xad = *nxad;
  1917. xad->flag = xflag & ~XAD_NOTRECORDED;
  1918. /* advance next available entry index. */
  1919. p->header.nextindex =
  1920.     cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
  1921. }
  1922. /*
  1923.  * does nXAD force 3-way split ?
  1924.  *
  1925.  *          |---nXAD--->|
  1926.  * --|----------XAD-------------|--
  1927.  *   |-lXAD-|           |-rXAD -|
  1928.  */
  1929. if (nxoff + nxlen == xoff + xlen)
  1930. goto out;
  1931. /* reorient nXAD as XAD for further split XAD into (nXAD, rXAD) */
  1932. if (newpage) {
  1933. /* close out old page */
  1934. if (!test_cflag(COMMIT_Nolink, ip)) {
  1935. xtlck->lwm.offset = (xtlck->lwm.offset) ?
  1936.     min(index0, (int)xtlck->lwm.offset) : index0;
  1937. xtlck->lwm.length =
  1938.     le16_to_cpu(p->header.nextindex) -
  1939.     xtlck->lwm.offset;
  1940. }
  1941. bn = le64_to_cpu(p->header.next);
  1942. XT_PUTPAGE(mp);
  1943. /* get new right page */
  1944. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  1945. BT_MARK_DIRTY(mp, ip);
  1946. if (!test_cflag(COMMIT_Nolink, ip)) {
  1947. tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW);
  1948. xtlck = (struct xtlock *) & tlck->lock;
  1949. }
  1950. index0 = index = newindex;
  1951. } else
  1952. index++;
  1953. newindex = index + 1;
  1954. nextindex = le16_to_cpu(p->header.nextindex);
  1955. xlen = xlen - (nxoff - xoff);
  1956. xoff = nxoff;
  1957. xaddr = nxaddr;
  1958. /* recompute split pages */
  1959. if (nextindex == le16_to_cpu(p->header.maxentry)) {
  1960. /*
  1961. printf("xtUpdate: updateRight+Left recompute split pages: p:0x%pn", p);
  1962. */
  1963. XT_PUTPAGE(mp);
  1964. if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT)))
  1965. return rc;
  1966. assert(cmp == 0);
  1967. /* retrieve search result */
  1968. XT_GETSEARCH(ip, btstack.top, bn, mp, p, index0);
  1969. assert(index0 == index);
  1970. }
  1971. /*
  1972.  * split XAD into (nXAD, rXAD)
  1973.  *
  1974.  *          ---nXAD---|
  1975.  * --|----------XAD----------|--
  1976.  *                    |-rXAD-|
  1977.  */
  1978.       updateLeft: /* (nxoff == xoff) && (nxlen < xlen) */
  1979. /* update old XAD with nXAD:recorded */
  1980. xad = &p->xad[index];
  1981. *xad = *nxad;
  1982. xad->flag = xflag & ~XAD_NOTRECORDED;
  1983. /* insert rXAD:not_recorded */
  1984. xoff = xoff + nxlen;
  1985. xlen = xlen - nxlen;
  1986. xaddr = xaddr + nxlen;
  1987. if (nextindex == le16_to_cpu(p->header.maxentry)) {
  1988. rootsplit = p->header.flag & BT_ROOT;
  1989. /*
  1990. printf("xtUpdate.updateLeft.split p:0x%pn", p);
  1991. */
  1992. /* xtSpliUp() unpins leaf pages */
  1993. split.mp = mp;
  1994. split.index = newindex;
  1995. split.flag = xflag;
  1996. split.off = xoff;
  1997. split.len = xlen;
  1998. split.addr = xaddr;
  1999. split.pxdlist = NULL;
  2000. if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
  2001. return rc;
  2002. /*
  2003.  * if leaf root has been split, original root has been
  2004.  * copied to new child page, i.e., original entry now
  2005.  * resides on the new child page;
  2006.  */
  2007. if (rootsplit) {
  2008. if (p->header.nextindex ==
  2009.     cpu_to_le16(XTENTRYSTART + 1)) {
  2010. xad = &p->xad[XTENTRYSTART];
  2011. bn = addressXAD(xad);
  2012. /* get new child page */
  2013. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  2014. BT_MARK_DIRTY(mp, ip);
  2015. if (!test_cflag(COMMIT_Nolink, ip)) {
  2016. tlck = txLock(tid, ip, mp,
  2017.       tlckXTREE |
  2018.       tlckGROW);
  2019. xtlck = (struct xtlock *) & tlck->lock;
  2020. }
  2021. }
  2022. } else
  2023. /* get back old page */
  2024. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  2025. } else {
  2026. /* if insert into middle, shift right remaining entries */
  2027. if (newindex < nextindex)
  2028. memmove(&p->xad[newindex + 1], &p->xad[newindex],
  2029. (nextindex - newindex) << L2XTSLOTSIZE);
  2030. /* insert the entry */
  2031. xad = &p->xad[newindex];
  2032. XT_PUTENTRY(xad, xflag, xoff, xlen, xaddr);
  2033. /* advance next available entry index. */
  2034. p->header.nextindex =
  2035.     cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
  2036. }
  2037.       out:
  2038. if (!test_cflag(COMMIT_Nolink, ip)) {
  2039. xtlck->lwm.offset = (xtlck->lwm.offset) ?
  2040.     min(index0, (int)xtlck->lwm.offset) : index0;
  2041. xtlck->lwm.length = le16_to_cpu(p->header.nextindex) -
  2042.     xtlck->lwm.offset;
  2043. }
  2044. /* unpin the leaf page */
  2045. XT_PUTPAGE(mp);
  2046. return rc;
  2047. }
  2048. /*
  2049.  *      xtAppend()
  2050.  *
  2051.  * function: grow in append mode from contiguous region specified ;
  2052.  *
  2053.  * parameter:
  2054.  *      tid             - transaction id;
  2055.  *      ip              - file object;
  2056.  *      xflag           - extent flag:
  2057.  *      xoff            - extent offset;
  2058.  *      maxblocks       - max extent length;
  2059.  *      xlen            - extent length (in/out);
  2060.  *      xaddrp          - extent address pointer (in/out):
  2061.  *      flag            -
  2062.  *
  2063.  * return:
  2064.  */
  2065. int xtAppend(tid_t tid, /* transaction id */
  2066.      struct inode *ip, int xflag, s64 xoff, s32 maxblocks,
  2067.      s32 * xlenp, /* (in/out) */
  2068.      s64 * xaddrp, /* (in/out) */
  2069.      int flag)
  2070. {
  2071. int rc = 0;
  2072. struct metapage *mp; /* meta-page buffer */
  2073. xtpage_t *p; /* base B+-tree index page */
  2074. s64 bn, xaddr;
  2075. int index, nextindex;
  2076. struct btstack btstack; /* traverse stack */
  2077. struct xtsplit split; /* split information */
  2078. xad_t *xad;
  2079. int cmp;
  2080. struct tlock *tlck;
  2081. struct xtlock *xtlck;
  2082. int nsplit, nblocks, xlen;
  2083. struct pxdlist pxdlist;
  2084. pxd_t *pxd;
  2085. xaddr = *xaddrp;
  2086. xlen = *xlenp;
  2087. jEVENT(0,
  2088.        ("xtAppend: xoff:0x%lx maxblocks:%d xlen:%d xaddr:0x%lxn",
  2089. (ulong) xoff, maxblocks, xlen, (ulong) xaddr));
  2090. /*
  2091.  *      search for the entry location at which to insert:
  2092.  *
  2093.  * xtFastSearch() and xtSearch() both returns (leaf page
  2094.  * pinned, index at which to insert).
  2095.  * n.b. xtSearch() may return index of maxentry of
  2096.  * the full page.
  2097.  */
  2098. if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT)))
  2099. return rc;
  2100. /* retrieve search result */
  2101. XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
  2102. if (cmp == 0) {
  2103. rc = EEXIST;
  2104. goto out;
  2105. }
  2106. //insert:
  2107. /*
  2108.  *      insert entry for new extent
  2109.  */
  2110. xflag |= XAD_NEW;
  2111. /*
  2112.  *      if the leaf page is full, split the page and
  2113.  *      propagate up the router entry for the new page from split
  2114.  *
  2115.  * The xtSplitUp() will insert the entry and unpin the leaf page.
  2116.  */
  2117. nextindex = le16_to_cpu(p->header.nextindex);
  2118. if (nextindex < le16_to_cpu(p->header.maxentry))
  2119. goto insertLeaf;
  2120. /*
  2121.  * allocate new index blocks to cover index page split(s)
  2122.  */
  2123. nsplit = btstack.nsplit;
  2124. split.pxdlist = &pxdlist;
  2125. pxdlist.maxnpxd = pxdlist.npxd = 0;
  2126. pxd = &pxdlist.pxd[0];
  2127. nblocks = JFS_SBI(ip->i_sb)->nbperpage;
  2128. for (; nsplit > 0; nsplit--, pxd++, xaddr += nblocks, maxblocks -= nblocks) {
  2129. if ((rc = dbAllocBottomUp(ip, xaddr, (s64) nblocks)) == 0) {
  2130. PXDaddress(pxd, xaddr);
  2131. PXDlength(pxd, nblocks);
  2132. pxdlist.maxnpxd++;
  2133. continue;
  2134. }
  2135. /* undo allocation */
  2136. goto out;
  2137. }
  2138. xlen = min(xlen, maxblocks);
  2139. /*
  2140.  * allocate data extent requested
  2141.  */
  2142. if ((rc = dbAllocBottomUp(ip, xaddr, (s64) xlen)))
  2143. goto out;
  2144. split.mp = mp;
  2145. split.index = index;
  2146. split.flag = xflag;
  2147. split.off = xoff;
  2148. split.len = xlen;
  2149. split.addr = xaddr;
  2150. if ((rc = xtSplitUp(tid, ip, &split, &btstack))) {
  2151. /* undo data extent allocation */
  2152. dbFree(ip, *xaddrp, (s64) * xlenp);
  2153. return rc;
  2154. }
  2155. *xaddrp = xaddr;
  2156. *xlenp = xlen;
  2157. return 0;
  2158. /*
  2159.  *      insert the new entry into the leaf page
  2160.  */
  2161.       insertLeaf:
  2162. /*
  2163.  * allocate data extent requested
  2164.  */
  2165. if ((rc = dbAllocBottomUp(ip, xaddr, (s64) xlen)))
  2166. goto out;
  2167. BT_MARK_DIRTY(mp, ip);
  2168. /*
  2169.  * acquire a transaction lock on the leaf page;
  2170.  *
  2171.  * action: xad insertion/extension;
  2172.  */
  2173. tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW);
  2174. xtlck = (struct xtlock *) & tlck->lock;
  2175. /* insert the new entry: mark the entry NEW */
  2176. xad = &p->xad[index];
  2177. XT_PUTENTRY(xad, xflag, xoff, xlen, xaddr);
  2178. /* advance next available entry index */
  2179. p->header.nextindex =
  2180.     cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
  2181. xtlck->lwm.offset =
  2182.     (xtlck->lwm.offset) ? min(index,(int) xtlck->lwm.offset) : index;
  2183. xtlck->lwm.length = le16_to_cpu(p->header.nextindex) -
  2184.     xtlck->lwm.offset;
  2185. *xaddrp = xaddr;
  2186. *xlenp = xlen;
  2187.       out:
  2188. /* unpin the leaf page */
  2189. XT_PUTPAGE(mp);
  2190. return rc;
  2191. }
  2192. #ifdef _STILL_TO_PORT
  2193. /* - TBD for defragmentaion/reorganization -
  2194.  *
  2195.  *      xtDelete()
  2196.  *
  2197.  * function:
  2198.  *      delete the entry with the specified key.
  2199.  *
  2200.  *      N.B.: whole extent of the entry is assumed to be deleted.
  2201.  *
  2202.  * parameter:
  2203.  *
  2204.  * return:
  2205.  *       ENOENT: if the entry is not found.
  2206.  *
  2207.  * exception:
  2208.  */
  2209. int xtDelete(tid_t tid, struct inode *ip, s64 xoff, s32 xlen, int flag)
  2210. {
  2211. int rc = 0;
  2212. struct btstack btstack;
  2213. int cmp;
  2214. s64 bn;
  2215. struct metapage *mp;
  2216. xtpage_t *p;
  2217. int index, nextindex;
  2218. struct tlock *tlck;
  2219. struct xtlock *xtlck;
  2220. /*
  2221.  * find the matching entry; xtSearch() pins the page
  2222.  */
  2223. if ((rc = xtSearch(ip, xoff, &cmp, &btstack, 0)))
  2224. return rc;
  2225. XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
  2226. if (cmp) {
  2227. /* unpin the leaf page */
  2228. XT_PUTPAGE(mp);
  2229. return ENOENT;
  2230. }
  2231. /*
  2232.  * delete the entry from the leaf page
  2233.  */
  2234. nextindex = le16_to_cpu(p->header.nextindex);
  2235. p->header.nextindex =
  2236.     cpu_to_le16(le16_to_cpu(p->header.nextindex) - 1);
  2237. /*
  2238.  * if the leaf page bocome empty, free the page
  2239.  */
  2240. if (p->header.nextindex == cpu_to_le16(XTENTRYSTART))
  2241. return (xtDeleteUp(tid, ip, mp, p, &btstack));
  2242. BT_MARK_DIRTY(mp, ip);
  2243. /*
  2244.  * acquire a transaction lock on the leaf page;
  2245.  *
  2246.  * action:xad deletion;
  2247.  */
  2248. tlck = txLock(tid, ip, mp, tlckXTREE);
  2249. xtlck = (struct xtlock *) & tlck->lock;
  2250. xtlck->lwm.offset =
  2251.     (xtlck->lwm.offset) ? min(index, xtlck->lwm.offset) : index;
  2252. /* if delete from middle, shift left/compact the remaining entries */
  2253. if (index < nextindex - 1)
  2254. memmove(&p->xad[index], &p->xad[index + 1],
  2255. (nextindex - index - 1) * sizeof(xad_t));
  2256. XT_PUTPAGE(mp);
  2257. return 0;
  2258. }
  2259. /* - TBD for defragmentaion/reorganization -
  2260.  *
  2261.  *      xtDeleteUp()
  2262.  *
  2263.  * function:
  2264.  *      free empty pages as propagating deletion up the tree
  2265.  *
  2266.  * parameter:
  2267.  *
  2268.  * return:
  2269.  */
  2270. static int
  2271. xtDeleteUp(tid_t tid, struct inode *ip,
  2272.    struct metapage * fmp, xtpage_t * fp, struct btstack * btstack)
  2273. {
  2274. int rc = 0;
  2275. struct metapage *mp;
  2276. xtpage_t *p;
  2277. int index, nextindex;
  2278. s64 xaddr;
  2279. int xlen;
  2280. struct btframe *parent;
  2281. struct tlock *tlck;
  2282. struct xtlock *xtlck;
  2283. /*
  2284.  * keep root leaf page which has become empty
  2285.  */
  2286. if (fp->header.flag & BT_ROOT) {
  2287. /* keep the root page */
  2288. fp->header.flag &= ~BT_INTERNAL;
  2289. fp->header.flag |= BT_LEAF;
  2290. fp->header.nextindex = cpu_to_le16(XTENTRYSTART);
  2291. /* XT_PUTPAGE(fmp); */
  2292. return 0;
  2293. }
  2294. /*
  2295.  * free non-root leaf page
  2296.  */
  2297. if ((rc = xtRelink(tid, ip, fp)))
  2298. return rc;
  2299. xaddr = addressPXD(&fp->header.self);
  2300. xlen = lengthPXD(&fp->header.self);
  2301. /* free the page extent */
  2302. dbFree(ip, xaddr, (s64) xlen);
  2303. /* free the buffer page */
  2304. discard_metapage(fmp);
  2305. /*
  2306.  * propagate page deletion up the index tree
  2307.  *
  2308.  * If the delete from the parent page makes it empty,
  2309.  * continue all the way up the tree.
  2310.  * stop if the root page is reached (which is never deleted) or
  2311.  * if the entry deletion does not empty the page.
  2312.  */
  2313. while ((parent = BT_POP(btstack)) != NULL) {
  2314. /* get/pin the parent page <sp> */
  2315. XT_GETPAGE(ip, parent->bn, mp, PSIZE, p, rc);
  2316. if (rc)
  2317. return rc;
  2318. index = parent->index;
  2319. /* delete the entry for the freed child page from parent.
  2320.  */
  2321. nextindex = le16_to_cpu(p->header.nextindex);
  2322. /*
  2323.  * the parent has the single entry being deleted:
  2324.  * free the parent page which has become empty.
  2325.  */
  2326. if (nextindex == 1) {
  2327. if (p->header.flag & BT_ROOT) {
  2328. /* keep the root page */
  2329. p->header.flag &= ~BT_INTERNAL;
  2330. p->header.flag |= BT_LEAF;
  2331. p->header.nextindex =
  2332.     cpu_to_le16(XTENTRYSTART);
  2333. /* XT_PUTPAGE(fmp); */
  2334. break;
  2335. } else {
  2336. /* free the parent page */
  2337. if ((rc = xtRelink(tid, ip, p)))
  2338. return rc;
  2339. xaddr = addressPXD(&p->header.self);
  2340. /* free the page extent */
  2341. dbFree(ip, xaddr,
  2342.        (s64) JFS_SBI(ip->i_sb)->nbperpage);
  2343. /* unpin/free the buffer page */
  2344. discard_metapage(fmp);
  2345. /* propagate up */
  2346. continue;
  2347. }
  2348. }
  2349. /*
  2350.  * the parent has other entries remaining:
  2351.  * delete the router entry from the parent page.
  2352.  */
  2353. else {
  2354. BT_MARK_DIRTY(mp, ip);
  2355. /*
  2356.  * acquire a transaction lock on the leaf page;
  2357.  *
  2358.  * action:xad deletion;
  2359.  */
  2360. tlck = txLock(tid, ip, mp, tlckXTREE);
  2361. xtlck = (struct xtlock *) & tlck->lock;
  2362. xtlck->lwm.offset =
  2363.     (xtlck->lwm.offset) ? min(index,
  2364.       xtlck->lwm.
  2365.       offset) : index;
  2366. /* if delete from middle,
  2367.  * shift left/compact the remaining entries in the page
  2368.  */
  2369. if (index < nextindex - 1)
  2370. memmove(&p->xad[index], &p->xad[index + 1],
  2371. (nextindex - index -
  2372.  1) << L2XTSLOTSIZE);
  2373. p->header.nextindex =
  2374.     cpu_to_le16(le16_to_cpu(p->header.nextindex) -
  2375. 1);
  2376. jEVENT(0,
  2377.        ("xtDeleteUp(entry): 0x%lx[%d]n",
  2378. (ulong) parent->bn, index));
  2379. }
  2380. /* unpin the parent page */
  2381. XT_PUTPAGE(mp);
  2382. /* exit propagation up */
  2383. break;
  2384. }
  2385. return 0;
  2386. }
  2387. /*
  2388.  * NAME:        xtRelocate()
  2389.  *
  2390.  * FUNCTION:    relocate xtpage or data extent of regular file;
  2391.  *              This function is mainly used by defragfs utility.
  2392.  *
  2393.  * NOTE:        This routine does not have the logic to handle
  2394.  *              uncommitted allocated extent. The caller should call
  2395.  *              txCommit() to commit all the allocation before call
  2396.  *              this routine.
  2397.  */
  2398. xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
  2399.    s64 nxaddr, /* new xaddr */
  2400.    int xtype)
  2401. { /* extent type: XTPAGE or DATAEXT */
  2402. int rc = 0;
  2403. struct tblock *tblk;
  2404. struct tlock *tlck;
  2405. struct xtlock *xtlck;
  2406. struct metapage *mp, *pmp, *lmp, *rmp; /* meta-page buffer */
  2407. xtpage_t *p, *pp, *rp, *lp; /* base B+-tree index page */
  2408. xad_t *xad;
  2409. pxd_t *pxd;
  2410. s64 xoff, xsize;
  2411. int xlen;
  2412. s64 oxaddr, sxaddr, dxaddr, nextbn, prevbn;
  2413. cbuf_t *cp;
  2414. s64 offset, nbytes, nbrd, pno;
  2415. int nb, npages, nblks;
  2416. s64 bn;
  2417. int cmp;
  2418. int index;
  2419. struct pxd_lock *pxdlock;
  2420. struct btstack btstack; /* traverse stack */
  2421. xtype = xtype & EXTENT_TYPE;
  2422. xoff = offsetXAD(oxad);
  2423. oxaddr = addressXAD(oxad);
  2424. xlen = lengthXAD(oxad);
  2425. /* validate extent offset */
  2426. offset = xoff << JFS_SBI(ip->i_sb)->l2bsize;
  2427. if (offset >= ip->i_size)
  2428. return ESTALE; /* stale extent */
  2429. jEVENT(0,
  2430.        ("xtRelocate: xtype:%d xoff:0x%lx xlen:0x%x xaddr:0x%lx:0x%lxn",
  2431. xtype, (ulong) xoff, xlen, (ulong) oxaddr,
  2432. (ulong) nxaddr));
  2433. /*
  2434.  *      1. get and validate the parent xtpage/xad entry
  2435.  *      covering the source extent to be relocated;
  2436.  */
  2437. if (xtype == DATAEXT) {
  2438. /* search in leaf entry */
  2439. rc = xtSearch(ip, xoff, &cmp, &btstack, 0);
  2440. if (rc)
  2441. return rc;
  2442. if (cmp) {
  2443. XT_PUTPAGE(pmp);
  2444. return ESTALE;
  2445. }
  2446. /* retrieve search result */
  2447. XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
  2448. /* validate for exact match with a single entry */
  2449. xad = &pp->xad[index];
  2450. if (addressXAD(xad) != oxaddr || lengthXAD(xad) != xlen) {
  2451. XT_PUTPAGE(pmp);
  2452. return ESTALE;
  2453. }
  2454. } else { /* (xtype == XTPAGE) */
  2455. /* search in internal entry */
  2456. rc = xtSearchNode(ip, oxad, &cmp, &btstack, 0);
  2457. if (rc)
  2458. return rc;
  2459. if (cmp) {
  2460. XT_PUTPAGE(pmp);
  2461. return ESTALE;
  2462. }
  2463. /* retrieve search result */
  2464. XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
  2465. /* xtSearchNode() validated for exact match with a single entry
  2466.  */
  2467. xad = &pp->xad[index];
  2468. }
  2469. jEVENT(0, ("xtRelocate: parent xad entry validated.n"));
  2470. /*
  2471.  *      2. relocate the extent
  2472.  */
  2473. if (xtype == DATAEXT) {
  2474. /* if the extent is allocated-but-not-recorded
  2475.  * there is no real data to be moved in this extent,
  2476.  */
  2477. if (xad->flag & XAD_NOTRECORDED)
  2478. goto out;
  2479. else
  2480. /* release xtpage for cmRead()/xtLookup() */
  2481. XT_PUTPAGE(pmp);
  2482. /*
  2483.  *      cmRelocate()
  2484.  *
  2485.  * copy target data pages to be relocated;
  2486.  *
  2487.  * data extent must start at page boundary and
  2488.  * multiple of page size (except the last data extent);
  2489.  * read in each page of the source data extent into cbuf,
  2490.  * update the cbuf extent descriptor of the page to be
  2491.  * homeward bound to new dst data extent
  2492.  * copy the data from the old extent to new extent.
  2493.  * copy is essential for compressed files to avoid problems
  2494.  * that can arise if there was a change in compression
  2495.  * algorithms.
  2496.  * it is a good strategy because it may disrupt cache
  2497.  * policy to keep the pages in memory afterwards.
  2498.  */
  2499. offset = xoff << JFS_SBI(ip->i_sb)->l2bsize;
  2500. assert((offset & CM_OFFSET) == 0);
  2501. nbytes = xlen << JFS_SBI(ip->i_sb)->l2bsize;
  2502. pno = offset >> CM_L2BSIZE;
  2503. npages = (nbytes + (CM_BSIZE - 1)) >> CM_L2BSIZE;
  2504. /*
  2505.                 npages = ((offset + nbytes - 1) >> CM_L2BSIZE) -
  2506.                          (offset >> CM_L2BSIZE) + 1;
  2507. */
  2508. sxaddr = oxaddr;
  2509. dxaddr = nxaddr;
  2510. /* process the request one cache buffer at a time */
  2511. for (nbrd = 0; nbrd < nbytes; nbrd += nb,
  2512.      offset += nb, pno++, npages--) {
  2513. /* compute page size */
  2514. nb = min(nbytes - nbrd, CM_BSIZE);
  2515. /* get the cache buffer of the page */
  2516. if (rc = cmRead(ip, offset, npages, &cp))
  2517. break;
  2518. assert(addressPXD(&cp->cm_pxd) == sxaddr);
  2519. assert(!cp->cm_modified);
  2520. /* bind buffer with the new extent address */
  2521. nblks = nb >> JFS_IP(ip->i_sb)->l2bsize;
  2522. cmSetXD(ip, cp, pno, dxaddr, nblks);
  2523. /* release the cbuf, mark it as modified */
  2524. cmPut(cp, TRUE);
  2525. dxaddr += nblks;
  2526. sxaddr += nblks;
  2527. }
  2528. /* get back parent page */
  2529. rc = xtSearch(ip, xoff, &cmp, &btstack, 0);
  2530. XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
  2531. jEVENT(0, ("xtRelocate: target data extent relocated.n"));
  2532. } else { /* (xtype  == XTPAGE) */
  2533. /*
  2534.  * read in the target xtpage from the source extent;
  2535.  */
  2536. XT_GETPAGE(ip, oxaddr, mp, PSIZE, p, rc);
  2537. if (rc) {
  2538. XT_PUTPAGE(pmp);
  2539. return rc;
  2540. }
  2541. /*
  2542.  * read in sibling pages if any to update sibling pointers;
  2543.  */
  2544. rmp = NULL;
  2545. if (p->header.next) {
  2546. nextbn = le64_to_cpu(p->header.next);
  2547. XT_GETPAGE(ip, nextbn, rmp, PSIZE, rp, rc);
  2548. if (rc) {
  2549. XT_PUTPAGE(pmp);
  2550. XT_PUTPAGE(mp);
  2551. return (rc);
  2552. }
  2553. }
  2554. lmp = NULL;
  2555. if (p->header.prev) {
  2556. prevbn = le64_to_cpu(p->header.prev);
  2557. XT_GETPAGE(ip, prevbn, lmp, PSIZE, lp, rc);
  2558. if (rc) {
  2559. XT_PUTPAGE(pmp);
  2560. XT_PUTPAGE(mp);
  2561. if (rmp)
  2562. XT_PUTPAGE(rmp);
  2563. return (rc);
  2564. }
  2565. }
  2566. /* at this point, all xtpages to be updated are in memory */
  2567. /*
  2568.  * update sibling pointers of sibling xtpages if any;
  2569.  */
  2570. if (lmp) {
  2571. BT_MARK_DIRTY(lmp, ip);
  2572. tlck =
  2573.     txLock(tid, ip, lmp, tlckXTREE | tlckRELINK);
  2574. lp->header.next = cpu_to_le64(nxaddr);
  2575. XT_PUTPAGE(lmp);
  2576. }
  2577. if (rmp) {
  2578. BT_MARK_DIRTY(rmp, ip);
  2579. tlck =
  2580.     txLock(tid, ip, rmp, tlckXTREE | tlckRELINK);
  2581. rp->header.prev = cpu_to_le64(nxaddr);
  2582. XT_PUTPAGE(rmp);
  2583. }
  2584. /*
  2585.  * update the target xtpage to be relocated
  2586.  *
  2587.  * update the self address of the target page
  2588.  * and write to destination extent;
  2589.  * redo image covers the whole xtpage since it is new page
  2590.  * to the destination extent;
  2591.  * update of bmap for the free of source extent
  2592.  * of the target xtpage itself:
  2593.  * update of bmap for the allocation of destination extent
  2594.  * of the target xtpage itself:
  2595.  * update of bmap for the extents covered by xad entries in
  2596.  * the target xtpage is not necessary since they are not
  2597.  * updated;
  2598.  * if not committed before this relocation,
  2599.  * target page may contain XAD_NEW entries which must
  2600.  * be scanned for bmap update (logredo() always
  2601.  * scan xtpage REDOPAGE image for bmap update);
  2602.  * if committed before this relocation (tlckRELOCATE),
  2603.  * scan may be skipped by commit() and logredo();
  2604.  */
  2605. BT_MARK_DIRTY(mp, ip);
  2606. /* tlckNEW init  xtlck->lwm.offset = XTENTRYSTART; */
  2607. tlck = txLock(tid, ip, mp, tlckXTREE | tlckNEW);
  2608. xtlck = (struct xtlock *) & tlck->lock;
  2609. /* update the self address in the xtpage header */
  2610. pxd = &p->header.self;
  2611. PXDaddress(pxd, nxaddr);
  2612. /* linelock for the after image of the whole page */
  2613. xtlck->lwm.length =
  2614.     le16_to_cpu(p->header.nextindex) - xtlck->lwm.offset;
  2615. /* update the buffer extent descriptor of target xtpage */
  2616. xsize = xlen << JFS_SBI(ip->i_sb)->l2bsize;
  2617. bmSetXD(mp, nxaddr, xsize);
  2618. /* unpin the target page to new homeward bound */
  2619. XT_PUTPAGE(mp);
  2620. jEVENT(0, ("xtRelocate: target xtpage relocated.n"));
  2621. }
  2622. /*
  2623.  *      3. acquire maplock for the source extent to be freed;
  2624.  *
  2625.  * acquire a maplock saving the src relocated extent address;
  2626.  * to free of the extent at commit time;
  2627.  */
  2628.       out:
  2629. /* if DATAEXT relocation, write a LOG_UPDATEMAP record for
  2630.  * free PXD of the source data extent (logredo() will update
  2631.  * bmap for free of source data extent), and update bmap for
  2632.  * free of the source data extent;
  2633.  */
  2634. if (xtype == DATAEXT)
  2635. tlck = txMaplock(tid, ip, tlckMAP);
  2636. /* if XTPAGE relocation, write a LOG_NOREDOPAGE record
  2637.  * for the source xtpage (logredo() will init NoRedoPage
  2638.  * filter and will also update bmap for free of the source
  2639.  * xtpage), and update bmap for free of the source xtpage;
  2640.  * N.B. We use tlckMAP instead of tlkcXTREE because there
  2641.  *      is no buffer associated with this lock since the buffer
  2642.  *      has been redirected to the target location.
  2643.  */
  2644. else /* (xtype  == XTPAGE) */
  2645. tlck = txMaplock(tid, ip, tlckMAP | tlckRELOCATE);
  2646. pxdlock = (struct pxd_lock *) & tlck->lock;
  2647. pxdlock->flag = mlckFREEPXD;
  2648. PXDaddress(&pxdlock->pxd, oxaddr);
  2649. PXDlength(&pxdlock->pxd, xlen);
  2650. pxdlock->index = 1;
  2651. /*
  2652.  *      4. update the parent xad entry for relocation;
  2653.  *
  2654.  * acquire tlck for the parent entry with XAD_NEW as entry
  2655.  * update which will write LOG_REDOPAGE and update bmap for
  2656.  * allocation of XAD_NEW destination extent;
  2657.  */
  2658. jEVENT(0, ("xtRelocate: update parent xad entry.n"));
  2659. BT_MARK_DIRTY(pmp, ip);
  2660. tlck = txLock(tid, ip, pmp, tlckXTREE | tlckGROW);
  2661. xtlck = (struct xtlock *) & tlck->lock;
  2662. /* update the XAD with the new destination extent; */
  2663. xad = &pp->xad[index];
  2664. xad->flag |= XAD_NEW;
  2665. XADaddress(xad, nxaddr);
  2666. xtlck->lwm.offset = min(index, xtlck->lwm.offset);
  2667. xtlck->lwm.length = le16_to_cpu(pp->header.nextindex) -
  2668.     xtlck->lwm.offset;
  2669. /* unpin the parent xtpage */
  2670. XT_PUTPAGE(pmp);
  2671. return rc;
  2672. }
  2673. /*
  2674.  *      xtSearchNode()
  2675.  *
  2676.  * function:    search for the internal xad entry covering specified extent.
  2677.  *              This function is mainly used by defragfs utility.
  2678.  *
  2679.  * parameters:
  2680.  *      ip      - file object;
  2681.  *      xad     - extent to find;
  2682.  *      cmpp    - comparison result:
  2683.  *      btstack - traverse stack;
  2684.  *      flag    - search process flag;
  2685.  *
  2686.  * returns:
  2687.  *      btstack contains (bn, index) of search path traversed to the entry.
  2688.  *      *cmpp is set to result of comparison with the entry returned.
  2689.  *      the page containing the entry is pinned at exit.
  2690.  */
  2691. static int xtSearchNode(struct inode *ip, xad_t * xad, /* required XAD entry */
  2692. int *cmpp, struct btstack * btstack, int flag)
  2693. {
  2694. int rc = 0;
  2695. s64 xoff, xaddr;
  2696. int xlen;
  2697. int cmp = 1; /* init for empty page */
  2698. s64 bn; /* block number */
  2699. struct metapage *mp; /* meta-page buffer */
  2700. xtpage_t *p; /* page */
  2701. int base, index, lim;
  2702. struct btframe *btsp;
  2703. s64 t64;
  2704. BT_CLR(btstack);
  2705. xoff = offsetXAD(xad);
  2706. xlen = lengthXAD(xad);
  2707. xaddr = addressXAD(xad);
  2708. /*
  2709.  *      search down tree from root:
  2710.  *
  2711.  * between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
  2712.  * internal page, child page Pi contains entry with k, Ki <= K < Kj.
  2713.  *
  2714.  * if entry with search key K is not found
  2715.  * internal page search find the entry with largest key Ki
  2716.  * less than K which point to the child page to search;
  2717.  * leaf page search find the entry with smallest key Kj
  2718.  * greater than K so that the returned index is the position of
  2719.  * the entry to be shifted right for insertion of new entry.
  2720.  * for empty tree, search key is greater than any key of the tree.
  2721.  *
  2722.  * by convention, root bn = 0.
  2723.  */
  2724. for (bn = 0;;) {
  2725. /* get/pin the page to search */
  2726. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  2727. if (rc)
  2728. return rc;
  2729. if (p->header.flag & BT_LEAF)
  2730. return ESTALE;
  2731. lim = le16_to_cpu(p->header.nextindex) - XTENTRYSTART;
  2732. /*
  2733.  * binary search with search key K on the current page
  2734.  */
  2735. for (base = XTENTRYSTART; lim; lim >>= 1) {
  2736. index = base + (lim >> 1);
  2737. XT_CMP(cmp, xoff, &p->xad[index], t64);
  2738. if (cmp == 0) {
  2739. /*
  2740.  *      search hit
  2741.  *
  2742.  * verify for exact match;
  2743.  */
  2744. if (xaddr == addressXAD(&p->xad[index]) &&
  2745.     xoff == offsetXAD(&p->xad[index])) {
  2746. *cmpp = cmp;
  2747. /* save search result */
  2748. btsp = btstack->top;
  2749. btsp->bn = bn;
  2750. btsp->index = index;
  2751. btsp->mp = mp;
  2752. return 0;
  2753. }
  2754. /* descend/search its child page */
  2755. goto next;
  2756. }
  2757. if (cmp > 0) {
  2758. base = index + 1;
  2759. --lim;
  2760. }
  2761. }
  2762. /*
  2763.  *      search miss - non-leaf page:
  2764.  *
  2765.  * base is the smallest index with key (Kj) greater than
  2766.  * search key (K) and may be zero or maxentry index.
  2767.  * if base is non-zero, decrement base by one to get the parent
  2768.  * entry of the child page to search.
  2769.  */
  2770. index = base ? base - 1 : base;
  2771. /*
  2772.  * go down to child page
  2773.  */
  2774.       next:
  2775. /* get the child page block number */
  2776. bn = addressXAD(&p->xad[index]);
  2777. /* unpin the parent page */
  2778. XT_PUTPAGE(mp);
  2779. }
  2780. }
  2781. /*
  2782.  *      xtRelink()
  2783.  *
  2784.  * function:
  2785.  *      link around a freed page.
  2786.  *
  2787.  * Parameter:
  2788.  *      int           tid,
  2789.  *      struct inode    *ip,
  2790.  *      xtpage_t        *p)
  2791.  *
  2792.  * returns:
  2793.  */
  2794. static int xtRelink(tid_t tid, struct inode *ip, xtpage_t * p)
  2795. {
  2796. int rc = 0;
  2797. struct metapage *mp;
  2798. s64 nextbn, prevbn;
  2799. struct tlock *tlck;
  2800. nextbn = le64_to_cpu(p->header.next);
  2801. prevbn = le64_to_cpu(p->header.prev);
  2802. /* update prev pointer of the next page */
  2803. if (nextbn != 0) {
  2804. XT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);
  2805. if (rc)
  2806. return rc;
  2807. /*
  2808.  * acquire a transaction lock on the page;
  2809.  *
  2810.  * action: update prev pointer;
  2811.  */
  2812. BT_MARK_DIRTY(mp, ip);
  2813. tlck = txLock(tid, ip, mp, tlckXTREE | tlckRELINK);
  2814. /* the page may already have been tlock'd */
  2815. p->header.prev = cpu_to_le64(prevbn);
  2816. XT_PUTPAGE(mp);
  2817. }
  2818. /* update next pointer of the previous page */
  2819. if (prevbn != 0) {
  2820. XT_GETPAGE(ip, prevbn, mp, PSIZE, p, rc);
  2821. if (rc)
  2822. return rc;
  2823. /*
  2824.  * acquire a transaction lock on the page;
  2825.  *
  2826.  * action: update next pointer;
  2827.  */
  2828. BT_MARK_DIRTY(mp, ip);
  2829. tlck = txLock(tid, ip, mp, tlckXTREE | tlckRELINK);
  2830. /* the page may already have been tlock'd */
  2831. p->header.next = le64_to_cpu(nextbn);
  2832. XT_PUTPAGE(mp);
  2833. }
  2834. return 0;
  2835. }
  2836. #endif /*  _STILL_TO_PORT */
  2837. /*
  2838.  *      xtInitRoot()
  2839.  *
  2840.  * initialize file root (inline in inode)
  2841.  */
  2842. void xtInitRoot(tid_t tid, struct inode *ip)
  2843. {
  2844. xtpage_t *p;
  2845. struct tlock *tlck;
  2846. /*
  2847.  * acquire a transaction lock on the root
  2848.  *
  2849.  * action:
  2850.  */
  2851. tlck = txLock(tid, ip, (struct metapage *) &JFS_IP(ip)->bxflag,
  2852.       tlckXTREE | tlckNEW);
  2853. p = &JFS_IP(ip)->i_xtroot;
  2854. p->header.flag = DXD_INDEX | BT_ROOT | BT_LEAF;
  2855. p->header.nextindex = cpu_to_le16(XTENTRYSTART);
  2856. if (S_ISDIR(ip->i_mode))
  2857. p->header.maxentry = cpu_to_le16(XTROOTINITSLOT_DIR);
  2858. else {
  2859. p->header.maxentry = cpu_to_le16(XTROOTINITSLOT);
  2860. ip->i_size = 0;
  2861. }
  2862. return;
  2863. }
  2864. /*
  2865.  * We can run into a deadlock truncating a file with a large number of
  2866.  * xtree pages (large fragmented file).  A robust fix would entail a
  2867.  * reservation system where we would reserve a number of metadata pages
  2868.  * and tlocks which we would be guaranteed without a deadlock.  Without
  2869.  * this, a partial fix is to limit number of metadata pages we will lock
  2870.  * in a single transaction.  Currently we will truncate the file so that
  2871.  * no more than 50 leaf pages will be locked.  The caller of xtTruncate
  2872.  * will be responsible for ensuring that the current transaction gets
  2873.  * committed, and that subsequent transactions are created to truncate
  2874.  * the file further if needed.
  2875.  */
  2876. #define MAX_TRUNCATE_LEAVES 50
  2877. /*
  2878.  *      xtTruncate()
  2879.  *
  2880.  * function:
  2881.  *      traverse for truncation logging backward bottom up;
  2882.  *      terminate at the last extent entry at the current subtree
  2883.  *      root page covering new down size.
  2884.  *      truncation may occur within the last extent entry.
  2885.  *
  2886.  * parameter:
  2887.  *      int           tid,
  2888.  *      struct inode    *ip,
  2889.  *      s64           newsize,
  2890.  *      int           type)   {PWMAP, PMAP, WMAP; DELETE, TRUNCATE}
  2891.  *
  2892.  * return:
  2893.  *
  2894.  * note:
  2895.  *      PWMAP:
  2896.  *       1. truncate (non-COMMIT_NOLINK file)
  2897.  *          by jfs_truncate() or jfs_open(O_TRUNC):
  2898.  *          xtree is updated;
  2899.  *  2. truncate index table of directory when last entry removed
  2900.  *       map update via tlock at commit time;
  2901.  *      PMAP:
  2902.  *  Call xtTruncate_pmap instead
  2903.  *      WMAP:
  2904.  *       1. remove (free zero link count) on last reference release
  2905.  *          (pmap has been freed at commit zero link count);
  2906.  *       2. truncate (COMMIT_NOLINK file, i.e., tmp file):
  2907.  *          xtree is updated;
  2908.  *       map update directly at truncation time;
  2909.  *
  2910.  *      if (DELETE)
  2911.  *              no LOG_NOREDOPAGE is required (NOREDOFILE is sufficient);
  2912.  *      else if (TRUNCATE)
  2913.  *              must write LOG_NOREDOPAGE for deleted index page;
  2914.  *
  2915.  * pages may already have been tlocked by anonymous transactions
  2916.  * during file growth (i.e., write) before truncation;
  2917.  *
  2918.  * except last truncated entry, deleted entries remains as is
  2919.  * in the page (nextindex is updated) for other use
  2920.  * (e.g., log/update allocation map): this avoid copying the page
  2921.  * info but delay free of pages;
  2922.  *
  2923.  */
  2924. s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
  2925. {
  2926. int rc = 0;
  2927. s64 teof;
  2928. struct metapage *mp;
  2929. xtpage_t *p;
  2930. s64 bn;
  2931. int index, nextindex;
  2932. xad_t *xad;
  2933. s64 xoff, xaddr;
  2934. int xlen, len, freexlen;
  2935. struct btstack btstack;
  2936. struct btframe *parent;
  2937. struct tblock *tblk = 0;
  2938. struct tlock *tlck = 0;
  2939. struct xtlock *xtlck = 0;
  2940. struct xdlistlock xadlock; /* maplock for COMMIT_WMAP */
  2941. struct pxd_lock *pxdlock; /* maplock for COMMIT_WMAP */
  2942. s64 nfreed;
  2943. int freed, log;
  2944. int locked_leaves = 0;
  2945. /* save object truncation type */
  2946. if (tid) {
  2947. tblk = tid_to_tblock(tid);
  2948. tblk->xflag |= flag;
  2949. }
  2950. nfreed = 0;
  2951. flag &= COMMIT_MAP;
  2952. assert(flag != COMMIT_PMAP);
  2953. if (flag == COMMIT_PWMAP)
  2954. log = 1;
  2955. else {
  2956. log = 0;
  2957. xadlock.flag = mlckFREEXADLIST;
  2958. xadlock.index = 1;
  2959. }
  2960. /*
  2961.  * if the newsize is not an integral number of pages,
  2962.  * the file between newsize and next page boundary will
  2963.  * be cleared.
  2964.  * if truncating into a file hole, it will cause
  2965.  * a full block to be allocated for the logical block.
  2966.  */
  2967. /*
  2968.  * release page blocks of truncated region <teof, eof>
  2969.  *
  2970.  * free the data blocks from the leaf index blocks.
  2971.  * delete the parent index entries corresponding to
  2972.  * the freed child data/index blocks.
  2973.  * free the index blocks themselves which aren't needed
  2974.  * in new sized file.
  2975.  *
  2976.  * index blocks are updated only if the blocks are to be
  2977.  * retained in the new sized file.
  2978.  * if type is PMAP, the data and index pages are NOT
  2979.  * freed, and the data and index blocks are NOT freed
  2980.  * from  working map.
  2981.  * (this will allow continued access of data/index of
  2982.  * temporary file (zerolink count file truncated to zero-length)).
  2983.  */
  2984. teof = (newsize + (JFS_SBI(ip->i_sb)->bsize - 1)) >>
  2985.     JFS_SBI(ip->i_sb)->l2bsize;
  2986. /* clear stack */
  2987. BT_CLR(&btstack);
  2988. /*
  2989.  * start with root
  2990.  *
  2991.  * root resides in the inode
  2992.  */
  2993. bn = 0;
  2994. /*
  2995.  * first access of each page:
  2996.  */
  2997.       getPage:
  2998. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  2999. if (rc)
  3000. return -rc;
  3001. /* process entries backward from last index */
  3002. index = le16_to_cpu(p->header.nextindex) - 1;
  3003. if (p->header.flag & BT_INTERNAL)
  3004. goto getChild;
  3005. /*
  3006.  *      leaf page
  3007.  */
  3008. /* Since this is the rightmost leaf, and we may have already freed
  3009.  * a page that was formerly to the right, let's make sure that the
  3010.  * next pointer is zero.
  3011.  */
  3012. p->header.next = 0;
  3013. freed = 0;
  3014. /* does region covered by leaf page precede Teof ? */
  3015. xad = &p->xad[index];
  3016. xoff = offsetXAD(xad);
  3017. xlen = lengthXAD(xad);
  3018. if (teof >= xoff + xlen) {
  3019. XT_PUTPAGE(mp);
  3020. goto getParent;
  3021. }
  3022. /* (re)acquire tlock of the leaf page */
  3023. if (log) {
  3024. if (++locked_leaves > MAX_TRUNCATE_LEAVES) {
  3025. /*
  3026.  * We need to limit the size of the transaction
  3027.  * to avoid exhausting pagecache & tlocks
  3028.  */
  3029. XT_PUTPAGE(mp);
  3030. newsize = (xoff + xlen) << JFS_SBI(ip->i_sb)->l2bsize;
  3031. goto getParent;
  3032. }
  3033. tlck = txLock(tid, ip, mp, tlckXTREE);
  3034. tlck->type = tlckXTREE | tlckTRUNCATE;
  3035. xtlck = (struct xtlock *) & tlck->lock;
  3036. xtlck->hwm.offset = le16_to_cpu(p->header.nextindex) - 1;
  3037. }
  3038. BT_MARK_DIRTY(mp, ip);
  3039. /*
  3040.  * scan backward leaf page entries
  3041.  */
  3042. for (; index >= XTENTRYSTART; index--) {
  3043. xad = &p->xad[index];
  3044. xoff = offsetXAD(xad);
  3045. xlen = lengthXAD(xad);
  3046. xaddr = addressXAD(xad);
  3047. /*
  3048.  * entry beyond eof: continue scan of current page
  3049.  *          xad
  3050.  * ---|---=======------->
  3051.  *   eof
  3052.  */
  3053. if (teof < xoff) {
  3054. nfreed += xlen;
  3055. continue;
  3056. }
  3057. /*
  3058.  * (xoff <= teof): last entry to be deleted from page;
  3059.  * If other entries remain in page: keep and update the page.
  3060.  */
  3061. /*
  3062.  * eof == entry_start: delete the entry
  3063.  *           xad
  3064.  * -------|=======------->
  3065.  *       eof
  3066.  *
  3067.  */
  3068. if (teof == xoff) {
  3069. nfreed += xlen;
  3070. if (index == XTENTRYSTART)
  3071. break;
  3072. nextindex = index;
  3073. }
  3074. /*
  3075.  * eof within the entry: truncate the entry.
  3076.  *          xad
  3077.  * -------===|===------->
  3078.  *          eof
  3079.  */
  3080. else if (teof < xoff + xlen) {
  3081. /* update truncated entry */
  3082. len = teof - xoff;
  3083. freexlen = xlen - len;
  3084. XADlength(xad, len);
  3085. /* save pxd of truncated extent in tlck */
  3086. xaddr += len;
  3087. if (log) { /* COMMIT_PWMAP */
  3088. xtlck->lwm.offset = (xtlck->lwm.offset) ?
  3089.     min(index, (int)xtlck->lwm.offset) : index;
  3090. xtlck->lwm.length = index + 1 -
  3091.     xtlck->lwm.offset;
  3092. xtlck->twm.offset = index;
  3093. pxdlock = (struct pxd_lock *) & xtlck->pxdlock;
  3094. pxdlock->flag = mlckFREEPXD;
  3095. PXDaddress(&pxdlock->pxd, xaddr);
  3096. PXDlength(&pxdlock->pxd, freexlen);
  3097. }
  3098. /* free truncated extent */
  3099. else { /* COMMIT_WMAP */
  3100. pxdlock = (struct pxd_lock *) & xadlock;
  3101. pxdlock->flag = mlckFREEPXD;
  3102. PXDaddress(&pxdlock->pxd, xaddr);
  3103. PXDlength(&pxdlock->pxd, freexlen);
  3104. txFreeMap(ip, pxdlock, 0, COMMIT_WMAP);
  3105. /* reset map lock */
  3106. xadlock.flag = mlckFREEXADLIST;
  3107. }
  3108. /* current entry is new last entry; */
  3109. nextindex = index + 1;
  3110. nfreed += freexlen;
  3111. }
  3112. /*
  3113.  * eof beyond the entry:
  3114.  *          xad
  3115.  * -------=======---|--->
  3116.  *                 eof
  3117.  */
  3118. else { /* (xoff + xlen < teof) */
  3119. nextindex = index + 1;
  3120. }
  3121. if (nextindex < le16_to_cpu(p->header.nextindex)) {
  3122. if (!log) { /* COMMIT_WAMP */
  3123. xadlock.xdlist = &p->xad[nextindex];
  3124. xadlock.count =
  3125.     le16_to_cpu(p->header.nextindex) -
  3126.     nextindex;
  3127. txFreeMap(ip, (struct maplock *) & xadlock, 0,
  3128.   COMMIT_WMAP);
  3129. }
  3130. p->header.nextindex = cpu_to_le16(nextindex);
  3131. }
  3132. XT_PUTPAGE(mp);
  3133. /* assert(freed == 0); */
  3134. goto getParent;
  3135. } /* end scan of leaf page entries */
  3136. freed = 1;
  3137. /*
  3138.  * leaf page become empty: free the page if type != PMAP
  3139.  */
  3140. if (log) { /* COMMIT_PWMAP */
  3141. /* txCommit() with tlckFREE:
  3142.  * free data extents covered by leaf [XTENTRYSTART:hwm);
  3143.  * invalidate leaf if COMMIT_PWMAP;
  3144.  * if (TRUNCATE), will write LOG_NOREDOPAGE;
  3145.  */
  3146. tlck->type = tlckXTREE | tlckFREE;
  3147. } else { /* COMMIT_WAMP */
  3148. /* free data extents covered by leaf */
  3149. xadlock.xdlist = &p->xad[XTENTRYSTART];
  3150. xadlock.count =
  3151.     le16_to_cpu(p->header.nextindex) - XTENTRYSTART;
  3152. txFreeMap(ip, (struct maplock *) & xadlock, 0, COMMIT_WMAP);
  3153. }
  3154. if (p->header.flag & BT_ROOT) {
  3155. p->header.flag &= ~BT_INTERNAL;
  3156. p->header.flag |= BT_LEAF;
  3157. p->header.nextindex = cpu_to_le16(XTENTRYSTART);
  3158. XT_PUTPAGE(mp); /* debug */
  3159. goto out;
  3160. } else {
  3161. if (log) { /* COMMIT_PWMAP */
  3162. /* page will be invalidated at tx completion
  3163.  */
  3164. XT_PUTPAGE(mp);
  3165. } else { /* COMMIT_WMAP */
  3166. if (mp->lid)
  3167. lid_to_tlock(mp->lid)->flag |= tlckFREELOCK;
  3168. /* invalidate empty leaf page */
  3169. discard_metapage(mp);
  3170. }
  3171. }
  3172. /*
  3173.  * the leaf page become empty: delete the parent entry
  3174.  * for the leaf page if the parent page is to be kept
  3175.  * in the new sized file.
  3176.  */
  3177. /*
  3178.  * go back up to the parent page
  3179.  */
  3180.       getParent:
  3181. /* pop/restore parent entry for the current child page */
  3182. if ((parent = BT_POP(&btstack)) == NULL)
  3183. /* current page must have been root */
  3184. goto out;
  3185. /* get back the parent page */
  3186. bn = parent->bn;
  3187. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  3188. if (rc)
  3189. return -rc;
  3190. index = parent->index;
  3191. /*
  3192.  * child page was not empty:
  3193.  */
  3194. if (freed == 0) {
  3195. /* has any entry deleted from parent ? */
  3196. if (index < le16_to_cpu(p->header.nextindex) - 1) {
  3197. /* (re)acquire tlock on the parent page */
  3198. if (log) { /* COMMIT_PWMAP */
  3199. /* txCommit() with tlckTRUNCATE:
  3200.  * free child extents covered by parent [);
  3201.  */
  3202. tlck = txLock(tid, ip, mp, tlckXTREE);
  3203. xtlck = (struct xtlock *) & tlck->lock;
  3204. if (!(tlck->type & tlckTRUNCATE)) {
  3205. xtlck->hwm.offset =
  3206.     le16_to_cpu(p->header.
  3207. nextindex) - 1;
  3208. tlck->type =
  3209.     tlckXTREE | tlckTRUNCATE;
  3210. }
  3211. } else { /* COMMIT_WMAP */
  3212. /* free child extents covered by parent */
  3213. xadlock.xdlist = &p->xad[index + 1];
  3214. xadlock.count =
  3215.     le16_to_cpu(p->header.nextindex) -
  3216.     index - 1;
  3217. txFreeMap(ip, (struct maplock *) & xadlock, 0,
  3218.   COMMIT_WMAP);
  3219. }
  3220. BT_MARK_DIRTY(mp, ip);
  3221. p->header.nextindex = cpu_to_le16(index + 1);
  3222. }
  3223. XT_PUTPAGE(mp);
  3224. goto getParent;
  3225. }
  3226. /*
  3227.  * child page was empty:
  3228.  */
  3229. nfreed += lengthXAD(&p->xad[index]);
  3230. /*
  3231.  * During working map update, child page's tlock must be handled
  3232.  * before parent's.  This is because the parent's tlock will cause
  3233.  * the child's disk space to be marked available in the wmap, so
  3234.  * it's important that the child page be released by that time.
  3235.  *
  3236.  * ToDo:  tlocks should be on doubly-linked list, so we can
  3237.  * quickly remove it and add it to the end.
  3238.  */
  3239. /*
  3240.  * Move parent page's tlock to the end of the tid's tlock list
  3241.  */
  3242. if (log && mp->lid && (tblk->last != mp->lid) &&
  3243.     lid_to_tlock(mp->lid)->tid) {
  3244. lid_t lid = mp->lid;
  3245. struct tlock *prev;
  3246. tlck = lid_to_tlock(lid);
  3247. if (tblk->next == lid)
  3248. tblk->next = tlck->next;
  3249. else {
  3250. for (prev = lid_to_tlock(tblk->next);
  3251.      prev->next != lid;
  3252.      prev = lid_to_tlock(prev->next)) {
  3253. assert(prev->next);
  3254. }
  3255. prev->next = tlck->next;
  3256. }
  3257. lid_to_tlock(tblk->last)->next = lid;
  3258. tlck->next = 0;
  3259. tblk->last = lid;
  3260. }
  3261. /*
  3262.  * parent page become empty: free the page
  3263.  */
  3264. if (index == XTENTRYSTART) {
  3265. if (log) { /* COMMIT_PWMAP */
  3266. /* txCommit() with tlckFREE:
  3267.  * free child extents covered by parent;
  3268.  * invalidate parent if COMMIT_PWMAP;
  3269.  */
  3270. tlck = txLock(tid, ip, mp, tlckXTREE);
  3271. xtlck = (struct xtlock *) & tlck->lock;
  3272. xtlck->hwm.offset =
  3273.     le16_to_cpu(p->header.nextindex) - 1;
  3274. tlck->type = tlckXTREE | tlckFREE;
  3275. } else { /* COMMIT_WMAP */
  3276. /* free child extents covered by parent */
  3277. xadlock.xdlist = &p->xad[XTENTRYSTART];
  3278. xadlock.count =
  3279.     le16_to_cpu(p->header.nextindex) -
  3280.     XTENTRYSTART;
  3281. txFreeMap(ip, (struct maplock *) & xadlock, 0,
  3282.   COMMIT_WMAP);
  3283. }
  3284. BT_MARK_DIRTY(mp, ip);
  3285. if (p->header.flag & BT_ROOT) {
  3286. p->header.flag &= ~BT_INTERNAL;
  3287. p->header.flag |= BT_LEAF;
  3288. p->header.nextindex = cpu_to_le16(XTENTRYSTART);
  3289. if (le16_to_cpu(p->header.maxentry) == XTROOTMAXSLOT) {
  3290. /*
  3291.  * Shrink root down to allow inline
  3292.  * EA (otherwise fsck complains)
  3293.  */
  3294. p->header.maxentry =
  3295.     cpu_to_le16(XTROOTINITSLOT);
  3296. JFS_IP(ip)->mode2 |= INLINEEA;
  3297. }
  3298. XT_PUTPAGE(mp); /* debug */
  3299. goto out;
  3300. } else {
  3301. if (log) { /* COMMIT_PWMAP */
  3302. /* page will be invalidated at tx completion
  3303.  */
  3304. XT_PUTPAGE(mp);
  3305. } else { /* COMMIT_WMAP */
  3306. if (mp->lid)
  3307. lid_to_tlock(mp->lid)->flag |=
  3308. tlckFREELOCK;
  3309. /* invalidate parent page */
  3310. discard_metapage(mp);
  3311. }
  3312. /* parent has become empty and freed:
  3313.  * go back up to its parent page
  3314.  */
  3315. /* freed = 1; */
  3316. goto getParent;
  3317. }
  3318. }
  3319. /*
  3320.  * parent page still has entries for front region;
  3321.  */
  3322. else {
  3323. /* try truncate region covered by preceding entry
  3324.  * (process backward)
  3325.  */
  3326. index--;
  3327. /* go back down to the child page corresponding
  3328.  * to the entry
  3329.  */
  3330. goto getChild;
  3331. }
  3332. /*
  3333.  *      internal page: go down to child page of current entry
  3334.  */
  3335.       getChild:
  3336. /* save current parent entry for the child page */
  3337. BT_PUSH(&btstack, bn, index);
  3338. /* get child page */
  3339. xad = &p->xad[index];
  3340. bn = addressXAD(xad);
  3341. /*
  3342.  * first access of each internal entry:
  3343.  */
  3344. /* release parent page */
  3345. XT_PUTPAGE(mp);
  3346. /* process the child page */
  3347. goto getPage;
  3348.       out:
  3349. /*
  3350.  * update file resource stat
  3351.  */
  3352. /* set size
  3353.  */
  3354. if (S_ISDIR(ip->i_mode) && !newsize)
  3355. ip->i_size = 1; /* fsck hates zero-length directories */
  3356. else
  3357. ip->i_size = newsize;
  3358. /* update nblocks to reflect freed blocks */
  3359. ip->i_blocks -= LBLK2PBLK(ip->i_sb, nfreed);
  3360. /*
  3361.  * free tlock of invalidated pages
  3362.  */
  3363. if (flag == COMMIT_WMAP)
  3364. txFreelock(ip);
  3365. return newsize;
  3366. }
  3367. /*
  3368.  *      xtTruncate_pmap()
  3369.  *
  3370.  * function:
  3371.  * Perform truncate to zero lenghth for deleted file, leaving the
  3372.  * the xtree and working map untouched.  This allows the file to
  3373.  * be accessed via open file handles, while the delete of the file
  3374.  * is committed to disk.
  3375.  *
  3376.  * parameter:
  3377.  *      tid_t tid,
  3378.  *      struct inode *ip,
  3379.  *      s64 committed_size)
  3380.  *
  3381.  * return: new committed size
  3382.  *
  3383.  * note:
  3384.  *
  3385.  * To avoid deadlock by holding too many transaction locks, the
  3386.  * truncation may be broken up into multiple transactions.
  3387.  * The committed_size keeps track of part of the file has been
  3388.  * freed from the pmaps.
  3389.  */
  3390. s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
  3391. {
  3392. s64 bn;
  3393. struct btstack btstack;
  3394. int cmp;
  3395. int index;
  3396. int locked_leaves = 0;
  3397. struct metapage *mp;
  3398. xtpage_t *p;
  3399. struct btframe *parent;
  3400. int rc;
  3401. struct tblock *tblk;
  3402. struct tlock *tlck = 0;
  3403. xad_t *xad;
  3404. int xlen;
  3405. s64 xoff;
  3406. struct xtlock *xtlck = 0;
  3407. /* save object truncation type */
  3408. tblk = tid_to_tblock(tid);
  3409. tblk->xflag |= COMMIT_PMAP;
  3410. /* clear stack */
  3411. BT_CLR(&btstack);
  3412. if (committed_size) {
  3413. xoff = (committed_size >> JFS_SBI(ip->i_sb)->l2bsize) - 1;
  3414. rc = xtSearch(ip, xoff, &cmp, &btstack, 0);
  3415. if (rc)
  3416. return -rc;
  3417. assert(cmp == 0);
  3418. XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
  3419. } else {
  3420. /*
  3421.  * start with root
  3422.  *
  3423.  * root resides in the inode
  3424.  */
  3425. bn = 0;
  3426. /*
  3427.  * first access of each page:
  3428.  */
  3429.       getPage:
  3430. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  3431. if (rc)
  3432. return -rc;
  3433. /* process entries backward from last index */
  3434. index = le16_to_cpu(p->header.nextindex) - 1;
  3435. if (p->header.flag & BT_INTERNAL)
  3436. goto getChild;
  3437. }
  3438. /*
  3439.  *      leaf page
  3440.  */
  3441. if (++locked_leaves > MAX_TRUNCATE_LEAVES) {
  3442. /*
  3443.  * We need to limit the size of the transaction
  3444.  * to avoid exhausting pagecache & tlocks
  3445.  */
  3446. xad = &p->xad[index];
  3447. xoff = offsetXAD(xad);
  3448. xlen = lengthXAD(xad);
  3449. XT_PUTPAGE(mp);
  3450. return  (xoff + xlen) << JFS_SBI(ip->i_sb)->l2bsize;
  3451. }
  3452. tlck = txLock(tid, ip, mp, tlckXTREE);
  3453. tlck->type = tlckXTREE | tlckFREE;
  3454. xtlck = (struct xtlock *) & tlck->lock;
  3455. xtlck->hwm.offset = index;
  3456. XT_PUTPAGE(mp);
  3457. /*
  3458.  * go back up to the parent page
  3459.  */
  3460.       getParent:
  3461. /* pop/restore parent entry for the current child page */
  3462. if ((parent = BT_POP(&btstack)) == NULL)
  3463. /* current page must have been root */
  3464. goto out;
  3465. /* get back the parent page */
  3466. bn = parent->bn;
  3467. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  3468. if (rc)
  3469. return -rc;
  3470. index = parent->index;
  3471. /*
  3472.  * parent page become empty: free the page
  3473.  */
  3474. if (index == XTENTRYSTART) {
  3475. /* txCommit() with tlckFREE:
  3476.  * free child extents covered by parent;
  3477.  * invalidate parent if COMMIT_PWMAP;
  3478.  */
  3479. tlck = txLock(tid, ip, mp, tlckXTREE);
  3480. xtlck = (struct xtlock *) & tlck->lock;
  3481. xtlck->hwm.offset =
  3482.     le16_to_cpu(p->header.nextindex) - 1;
  3483. tlck->type = tlckXTREE | tlckFREE;
  3484. XT_PUTPAGE(mp);
  3485. if (p->header.flag & BT_ROOT) {
  3486. goto out;
  3487. } else {
  3488. goto getParent;
  3489. }
  3490. }
  3491. /*
  3492.  * parent page still has entries for front region;
  3493.  */
  3494. else
  3495. index--;
  3496. /*
  3497.  *      internal page: go down to child page of current entry
  3498.  */
  3499.       getChild:
  3500. /* save current parent entry for the child page */
  3501. BT_PUSH(&btstack, bn, index);
  3502. /* get child page */
  3503. xad = &p->xad[index];
  3504. bn = addressXAD(xad);
  3505. /*
  3506.  * first access of each internal entry:
  3507.  */
  3508. /* release parent page */
  3509. XT_PUTPAGE(mp);
  3510. /* process the child page */
  3511. goto getPage;
  3512.       out:
  3513. return 0;
  3514. }
  3515. #ifdef _JFS_DEBUG_XTREE
  3516. /*
  3517.  *      xtDisplayTree()
  3518.  *
  3519.  * function: traverse forward
  3520.  */
  3521. int xtDisplayTree(struct inode *ip)
  3522. {
  3523. int rc = 0;
  3524. struct metapage *mp;
  3525. xtpage_t *p;
  3526. s64 bn, pbn;
  3527. int index, lastindex, v, h;
  3528. xad_t *xad;
  3529. struct btstack btstack;
  3530. struct btframe *btsp;
  3531. struct btframe *parent;
  3532. printk("display B+-tree.n");
  3533. /* clear stack */
  3534. btsp = btstack.stack;
  3535. /*
  3536.  * start with root
  3537.  *
  3538.  * root resides in the inode
  3539.  */
  3540. bn = 0;
  3541. v = h = 0;
  3542. /*
  3543.  * first access of each page:
  3544.  */
  3545.       getPage:
  3546. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  3547. if (rc)
  3548. return rc;
  3549. /* process entries forward from first index */
  3550. index = XTENTRYSTART;
  3551. lastindex = le16_to_cpu(p->header.nextindex) - 1;
  3552. if (p->header.flag & BT_INTERNAL) {
  3553. /*
  3554.  * first access of each internal page
  3555.  */
  3556. goto getChild;
  3557. } else { /* (p->header.flag & BT_LEAF) */
  3558. /*
  3559.  * first access of each leaf page
  3560.  */
  3561. printf("leaf page ");
  3562. xtDisplayPage(ip, bn, p);
  3563. /* unpin the leaf page */
  3564. XT_PUTPAGE(mp);
  3565. }
  3566. /*
  3567.  * go back up to the parent page
  3568.  */
  3569.       getParent:
  3570. /* pop/restore parent entry for the current child page */
  3571. if ((parent = (btsp == btstack.stack ? NULL : --btsp)) == NULL)
  3572. /* current page must have been root */
  3573. return;
  3574. /*
  3575.  * parent page scan completed
  3576.  */
  3577. if ((index = parent->index) == (lastindex = parent->lastindex)) {
  3578. /* go back up to the parent page */
  3579. goto getParent;
  3580. }
  3581. /*
  3582.  * parent page has entries remaining
  3583.  */
  3584. /* get back the parent page */
  3585. bn = parent->bn;
  3586. /* v = parent->level; */
  3587. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  3588. if (rc)
  3589. return rc;
  3590. /* get next parent entry */
  3591. index++;
  3592. /*
  3593.  * internal page: go down to child page of current entry
  3594.  */
  3595.       getChild:
  3596. /* push/save current parent entry for the child page */
  3597. btsp->bn = pbn = bn;
  3598. btsp->index = index;
  3599. btsp->lastindex = lastindex;
  3600. /* btsp->level = v; */
  3601. /* btsp->node = h; */
  3602. ++btsp;
  3603. /* get child page */
  3604. xad = &p->xad[index];
  3605. bn = addressXAD(xad);
  3606. /*
  3607.  * first access of each internal entry:
  3608.  */
  3609. /* release parent page */
  3610. XT_PUTPAGE(mp);
  3611. printk("traverse down 0x%lx[%d]->0x%lxn", (ulong) pbn, index,
  3612.        (ulong) bn);
  3613. v++;
  3614. h = index;
  3615. /* process the child page */
  3616. goto getPage;
  3617. }
  3618. /*
  3619.  *      xtDisplayPage()
  3620.  *
  3621.  * function: display page
  3622.  */
  3623. int xtDisplayPage(struct inode *ip, s64 bn, xtpage_t * p)
  3624. {
  3625. int rc = 0;
  3626. struct metapage *mp;
  3627. xad_t *xad;
  3628. s64 xaddr, xoff;
  3629. int xlen, i, j;
  3630. if (p == NULL) {
  3631. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  3632. if (rc)
  3633. return rc;
  3634. }
  3635. /* display page control */
  3636. printf("bn:0x%lx flag:0x%x nextindex:%dn",
  3637.        (ulong) bn, p->header.flag,
  3638.        le16_to_cpu(p->header.nextindex));
  3639. /* display entries */
  3640. xad = &p->xad[XTENTRYSTART];
  3641. for (i = XTENTRYSTART, j = 1; i < le16_to_cpu(p->header.nextindex);
  3642.      i++, xad++, j++) {
  3643. xoff = offsetXAD(xad);
  3644. xaddr = addressXAD(xad);
  3645. xlen = lengthXAD(xad);
  3646. printf("t[%d] 0x%lx:0x%lx(0x%x)", i, (ulong) xoff,
  3647.        (ulong) xaddr, xlen);
  3648. if (j == 4) {
  3649. printf("n");
  3650. j = 0;
  3651. }
  3652. }
  3653. printf("n");
  3654. }
  3655. #endif /* _JFS_DEBUG_XTREE */
  3656. #ifdef _JFS_WIP
  3657. /*
  3658.  *      xtGather()
  3659.  *
  3660.  * function:
  3661.  *      traverse for allocation acquiring tlock at commit time
  3662.  *      (vs at the time of update) logging backward top down
  3663.  *
  3664.  * note:
  3665.  *      problem - establishing that all new allocation have been
  3666.  *      processed both for append and random write in sparse file
  3667.  *      at the current entry at the current subtree root page
  3668.  *
  3669.  */
  3670. int xtGather(t)
  3671. btree_t *t;
  3672. {
  3673. int rc = 0;
  3674. xtpage_t *p;
  3675. u64 bn;
  3676. int index;
  3677. btentry_t *e;
  3678. struct btstack btstack;
  3679. struct btsf *parent;
  3680. /* clear stack */
  3681. BT_CLR(&btstack);
  3682. /*
  3683.  * start with root
  3684.  *
  3685.  * root resides in the inode
  3686.  */
  3687. bn = 0;
  3688. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  3689. if (rc)
  3690. return rc;
  3691. /* new root is NOT pointed by a new entry
  3692.    if (p->header.flag & NEW)
  3693.    allocate new page lock;
  3694.    write a NEWPAGE log;
  3695.  */
  3696.       dopage:
  3697. /*
  3698.  * first access of each page:
  3699.  */
  3700. /* process entries backward from last index */
  3701. index = le16_to_cpu(p->header.nextindex) - 1;
  3702. if (p->header.flag & BT_LEAF) {
  3703. /*
  3704.  * first access of each leaf page
  3705.  */
  3706. /* process leaf page entries backward */
  3707. for (; index >= XTENTRYSTART; index--) {
  3708. e = &p->xad[index];
  3709. /*
  3710.  * if newpage, log NEWPAGE.
  3711.  *
  3712.  if (e->flag & XAD_NEW) {
  3713.  nfound =+ entry->length;
  3714.  update current page lock for the entry;
  3715.  newpage(entry);
  3716.  *
  3717.  * if moved, log move.
  3718.  *
  3719.  } else if (e->flag & XAD_MOVED) {
  3720.  reset flag;
  3721.  update current page lock for the entry;
  3722.  }
  3723.  */
  3724. }
  3725. /* unpin the leaf page */
  3726. XT_PUTPAGE(mp);
  3727. /*
  3728.  * go back up to the parent page
  3729.  */
  3730.       getParent:
  3731. /* restore parent entry for the current child page */
  3732. if ((parent = BT_POP(&btstack)) == NULL)
  3733. /* current page must have been root */
  3734. return 0;
  3735. if ((index = parent->index) == XTENTRYSTART) {
  3736. /*
  3737.  * parent page scan completed
  3738.  */
  3739. /* go back up to the parent page */
  3740. goto getParent;
  3741. } else {
  3742. /*
  3743.  * parent page has entries remaining
  3744.  */
  3745. /* get back the parent page */
  3746. bn = parent->bn;
  3747. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  3748. if (rc)
  3749. return EIO;
  3750. /* first subroot page which
  3751.  * covers all new allocated blocks
  3752.  * itself not new/modified.
  3753.  * (if modified from split of descendent,
  3754.  * go down path of split page)
  3755.  if (nfound == nnew &&
  3756.  !(p->header.flag & (NEW | MOD)))
  3757.  exit scan;
  3758.  */
  3759. /* process parent page entries backward */
  3760. index--;
  3761. }
  3762. } else {
  3763. /*
  3764.  * first access of each internal page
  3765.  */
  3766. }
  3767. /*
  3768.  * internal page: go down to child page of current entry
  3769.  */
  3770. /* save current parent entry for the child page */
  3771. BT_PUSH(&btstack, bn, index);
  3772. /* get current entry for the child page */
  3773. e = &p->xad[index];
  3774. /*
  3775.  * first access of each internal entry:
  3776.  */
  3777. /*
  3778.  * if new entry, log btree_tnewentry.
  3779.  *
  3780.  if (e->flag & XAD_NEW)
  3781.  update parent page lock for the entry;
  3782.  */
  3783. /* release parent page */
  3784. XT_PUTPAGE(mp);
  3785. /* get child page */
  3786. bn = e->bn;
  3787. XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
  3788. if (rc)
  3789. return rc;
  3790. /*
  3791.  * first access of each non-root page:
  3792.  */
  3793. /*
  3794.  * if new, log btree_newpage.
  3795.  *
  3796.  if (p->header.flag & NEW)
  3797.  allocate new page lock;
  3798.  write a NEWPAGE log (next, prev);
  3799.  */
  3800. /* process the child page */
  3801. goto dopage;
  3802.       out:
  3803. return 0;
  3804. }
  3805. #endif /* _JFS_WIP */
  3806. #ifdef CONFIG_JFS_STATISTICS
  3807. int jfs_xtstat_read(char *buffer, char **start, off_t offset, int length,
  3808.     int *eof, void *data)
  3809. {
  3810. int len = 0;
  3811. off_t begin;
  3812. len += sprintf(buffer,
  3813.        "JFS Xtree statisticsn"
  3814.        "====================n"
  3815.        "searches = %dn"
  3816.        "fast searches = %dn"
  3817.        "splits = %dn",
  3818.        xtStat.search,
  3819.        xtStat.fastSearch,
  3820.        xtStat.split);
  3821. begin = offset;
  3822. *start = buffer + begin;
  3823. len -= begin;
  3824. if (len > length)
  3825. len = length;
  3826. else
  3827. *eof = 1;
  3828. if (len < 0)
  3829. len = 0;
  3830. return len;
  3831. }
  3832. #endif