The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/jfs/jfs_dtree.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 /*
   20  *      jfs_dtree.c: directory B+-tree manager
   21  *
   22  * B+-tree with variable length key directory:
   23  *
   24  * each directory page is structured as an array of 32-byte
   25  * directory entry slots initialized as a freelist
   26  * to avoid search/compaction of free space at insertion.
   27  * when an entry is inserted, a number of slots are allocated
   28  * from the freelist as required to store variable length data
   29  * of the entry; when the entry is deleted, slots of the entry
   30  * are returned to freelist.
   31  *
   32  * leaf entry stores full name as key and file serial number
   33  * (aka inode number) as data.
   34  * internal/router entry stores sufffix compressed name
   35  * as key and simple extent descriptor as data.
   36  *
   37  * each directory page maintains a sorted entry index table
   38  * which stores the start slot index of sorted entries
   39  * to allow binary search on the table.
   40  *
   41  * directory starts as a root/leaf page in on-disk inode
   42  * inline data area.
   43  * when it becomes full, it starts a leaf of a external extent
   44  * of length of 1 block. each time the first leaf becomes full,
   45  * it is extended rather than split (its size is doubled),
   46  * until its length becoms 4 KBytes, from then the extent is split
   47  * with new 4 Kbyte extent when it becomes full
   48  * to reduce external fragmentation of small directories.
   49  *
   50  * blah, blah, blah, for linear scan of directory in pieces by
   51  * readdir().
   52  *
   53  *
   54  *      case-insensitive directory file system
   55  *
   56  * names are stored in case-sensitive way in leaf entry.
   57  * but stored, searched and compared in case-insensitive (uppercase) order
   58  * (i.e., both search key and entry key are folded for search/compare):
   59  * (note that case-sensitive order is BROKEN in storage, e.g.,
   60  *  sensitive: Ad, aB, aC, aD -> insensitive: aB, aC, aD, Ad
   61  *
   62  *  entries which folds to the same key makes up a equivalent class
   63  *  whose members are stored as contiguous cluster (may cross page boundary)
   64  *  but whose order is arbitrary and acts as duplicate, e.g.,
   65  *  abc, Abc, aBc, abC)
   66  *
   67  * once match is found at leaf, requires scan forward/backward
   68  * either for, in case-insensitive search, duplicate
   69  * or for, in case-sensitive search, for exact match
   70  *
   71  * router entry must be created/stored in case-insensitive way
   72  * in internal entry:
   73  * (right most key of left page and left most key of right page
   74  * are folded, and its suffix compression is propagated as router
   75  * key in parent)
   76  * (e.g., if split occurs <abc> and <aBd>, <ABD> trather than <aB>
   77  * should be made the router key for the split)
   78  *
   79  * case-insensitive search:
   80  *
   81  *      fold search key;
   82  *
   83  *      case-insensitive search of B-tree:
   84  *      for internal entry, router key is already folded;
   85  *      for leaf entry, fold the entry key before comparison.
   86  *
   87  *      if (leaf entry case-insensitive match found)
   88  *              if (next entry satisfies case-insensitive match)
   89  *                      return EDUPLICATE;
   90  *              if (prev entry satisfies case-insensitive match)
   91  *                      return EDUPLICATE;
   92  *              return match;
   93  *      else
   94  *              return no match;
   95  *
   96  *      serialization:
   97  * target directory inode lock is being held on entry/exit
   98  * of all main directory service routines.
   99  *
  100  *      log based recovery:
  101  */
  102 
  103 #include <linux/fs.h>
  104 #include "jfs_incore.h"
  105 #include "jfs_superblock.h"
  106 #include "jfs_filsys.h"
  107 #include "jfs_metapage.h"
  108 #include "jfs_dmap.h"
  109 #include "jfs_unicode.h"
  110 #include "jfs_debug.h"
  111 
  112 /* dtree split parameter */
  113 struct dtsplit {
  114         struct metapage *mp;
  115         s16 index;
  116         s16 nslot;
  117         struct component_name *key;
  118         ddata_t *data;
  119         struct pxdlist *pxdlist;
  120 };
  121 
  122 #define DT_PAGE(IP, MP) BT_PAGE(IP, MP, dtpage_t, i_dtroot)
  123 
  124 /* get page buffer for specified block address */
  125 #define DT_GETPAGE(IP, BN, MP, SIZE, P, RC)\
  126 {\
  127         BT_GETPAGE(IP, BN, MP, dtpage_t, SIZE, P, RC, i_dtroot)\
  128         if (!(RC))\
  129         {\
  130                 if (((P)->header.nextindex > (((BN)==0)?DTROOTMAXSLOT:(P)->header.maxslot)) ||\
  131                     ((BN) && ((P)->header.maxslot > DTPAGEMAXSLOT)))\
  132                 {\
  133                         jfs_err("DT_GETPAGE: dtree page corrupt");\
  134                         BT_PUTPAGE(MP);\
  135                         updateSuper((IP)->i_sb, FM_DIRTY);\
  136                         MP = NULL;\
  137                         RC = EIO;\
  138                 }\
  139         }\
  140 }
  141 
  142 /* for consistency */
  143 #define DT_PUTPAGE(MP) BT_PUTPAGE(MP)
  144 
  145 #define DT_GETSEARCH(IP, LEAF, BN, MP, P, INDEX) \
  146         BT_GETSEARCH(IP, LEAF, BN, MP, dtpage_t, P, INDEX, i_dtroot)
  147 
  148 /*
  149  * forward references
  150  */
  151 static int dtSplitUp(tid_t tid, struct inode *ip,
  152                      struct dtsplit * split, struct btstack * btstack);
  153 
  154 static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
  155                        struct metapage ** rmpp, dtpage_t ** rpp, pxd_t * rxdp);
  156 
  157 static int dtExtendPage(tid_t tid, struct inode *ip,
  158                         struct dtsplit * split, struct btstack * btstack);
  159 
  160 static int dtSplitRoot(tid_t tid, struct inode *ip,
  161                        struct dtsplit * split, struct metapage ** rmpp);
  162 
  163 static int dtDeleteUp(tid_t tid, struct inode *ip, struct metapage * fmp,
  164                       dtpage_t * fp, struct btstack * btstack);
  165 
  166 static int dtSearchNode(struct inode *ip,
  167                         s64 lmxaddr, pxd_t * kpxd, struct btstack * btstack);
  168 
  169 static int dtRelink(tid_t tid, struct inode *ip, dtpage_t * p);
  170 
  171 static int dtReadFirst(struct inode *ip, struct btstack * btstack);
  172 
  173 static int dtReadNext(struct inode *ip,
  174                       loff_t * offset, struct btstack * btstack);
  175 
  176 static int dtCompare(struct component_name * key, dtpage_t * p, int si);
  177 
  178 static int ciCompare(struct component_name * key, dtpage_t * p, int si,
  179                      int flag);
  180 
  181 static void dtGetKey(dtpage_t * p, int i, struct component_name * key,
  182                      int flag);
  183 
  184 static void ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp,
  185                                int ri, struct component_name * key, int flag);
  186 
  187 static void dtInsertEntry(dtpage_t * p, int index, struct component_name * key,
  188                           ddata_t * data, struct dt_lock **);
  189 
  190 static void dtMoveEntry(dtpage_t * sp, int si, dtpage_t * dp,
  191                         struct dt_lock ** sdtlock, struct dt_lock ** ddtlock,
  192                         int do_index);
  193 
  194 static void dtDeleteEntry(dtpage_t * p, int fi, struct dt_lock ** dtlock);
  195 
  196 static void dtTruncateEntry(dtpage_t * p, int ti, struct dt_lock ** dtlock);
  197 
  198 static void dtLinelockFreelist(dtpage_t * p, int m, struct dt_lock ** dtlock);
  199 
  200 #define ciToUpper(c)    UniStrupr((c)->name)
  201 
  202 /*
  203  *      read_index_page()
  204  *
  205  *      Reads a page of a directory's index table.
  206  *      Having metadata mapped into the directory inode's address space
  207  *      presents a multitude of problems.  We avoid this by mapping to
  208  *      the absolute address space outside of the *_metapage routines
  209  */
  210 static struct metapage *read_index_page(struct inode *inode, s64 blkno)
  211 {
  212         int rc;
  213         s64 xaddr;
  214         int xflag;
  215         s32 xlen;
  216 
  217         rc = xtLookup(inode, blkno, 1, &xflag, &xaddr, &xlen, 1);
  218         if (rc || (xlen == 0))
  219                 return NULL;
  220 
  221         return read_metapage(inode, xaddr, PSIZE, 1);
  222 }
  223 
  224 /*
  225  *      get_index_page()
  226  *
  227  *      Same as get_index_page(), but get's a new page without reading
  228  */
  229 static struct metapage *get_index_page(struct inode *inode, s64 blkno)
  230 {
  231         int rc;
  232         s64 xaddr;
  233         int xflag;
  234         s32 xlen;
  235 
  236         rc = xtLookup(inode, blkno, 1, &xflag, &xaddr, &xlen, 1);
  237         if (rc || (xlen == 0))
  238                 return NULL;
  239 
  240         return get_metapage(inode, xaddr, PSIZE, 1);
  241 }
  242 
  243 /*
  244  *      find_index()
  245  *
  246  *      Returns dtree page containing directory table entry for specified
  247  *      index and pointer to its entry.
  248  *
  249  *      mp must be released by caller.
  250  */
  251 static struct dir_table_slot *find_index(struct inode *ip, u32 index,
  252                                          struct metapage ** mp, s64 *lblock)
  253 {
  254         struct jfs_inode_info *jfs_ip = JFS_IP(ip);
  255         s64 blkno;
  256         s64 offset;
  257         int page_offset;
  258         struct dir_table_slot *slot;
  259         static int maxWarnings = 10;
  260 
  261         if (index < 2) {
  262                 if (maxWarnings) {
  263                         jfs_warn("find_entry called with index = %d", index);
  264                         maxWarnings--;
  265                 }
  266                 return 0;
  267         }
  268 
  269         if (index >= jfs_ip->next_index) {
  270                 jfs_warn("find_entry called with index >= next_index");
  271                 return 0;
  272         }
  273 
  274         if (jfs_ip->next_index <= (MAX_INLINE_DIRTABLE_ENTRY + 1)) {
  275                 /*
  276                  * Inline directory table
  277                  */
  278                 *mp = 0;
  279                 slot = &jfs_ip->i_dirtable[index - 2];
  280         } else {
  281                 offset = (index - 2) * sizeof(struct dir_table_slot);
  282                 page_offset = offset & (PSIZE - 1);
  283                 blkno = ((offset + 1) >> L2PSIZE) <<
  284                     JFS_SBI(ip->i_sb)->l2nbperpage;
  285 
  286                 if (*mp && (*lblock != blkno)) {
  287                         release_metapage(*mp);
  288                         *mp = 0;
  289                 }
  290                 if (*mp == 0) {
  291                         *lblock = blkno;
  292                         *mp = read_index_page(ip, blkno);
  293                 }
  294                 if (*mp == 0) {
  295                         jfs_err("free_index: error reading directory table");
  296                         return 0;
  297                 }
  298 
  299                 slot =
  300                     (struct dir_table_slot *) ((char *) (*mp)->data +
  301                                                page_offset);
  302         }
  303         return slot;
  304 }
  305 
  306 static inline void lock_index(tid_t tid, struct inode *ip, struct metapage * mp,
  307                               u32 index)
  308 {
  309         struct tlock *tlck;
  310         struct linelock *llck;
  311         struct lv *lv;
  312 
  313         tlck = txLock(tid, ip, mp, tlckDATA);
  314         llck = (struct linelock *) tlck->lock;
  315 
  316         if (llck->index >= llck->maxcnt)
  317                 llck = txLinelock(llck);
  318         lv = &llck->lv[llck->index];
  319 
  320         /*
  321          *      Linelock slot size is twice the size of directory table
  322          *      slot size.  512 entries per page.
  323          */
  324         lv->offset = ((index - 2) & 511) >> 1;
  325         lv->length = 1;
  326         llck->index++;
  327 }
  328 
  329 /*
  330  *      add_index()
  331  *
  332  *      Adds an entry to the directory index table.  This is used to provide
  333  *      each directory entry with a persistent index in which to resume
  334  *      directory traversals
  335  */
  336 static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
  337 {
  338         struct super_block *sb = ip->i_sb;
  339         struct jfs_sb_info *sbi = JFS_SBI(sb);
  340         struct jfs_inode_info *jfs_ip = JFS_IP(ip);
  341         u64 blkno;
  342         struct dir_table_slot *dirtab_slot;
  343         u32 index;
  344         struct linelock *llck;
  345         struct lv *lv;
  346         struct metapage *mp;
  347         s64 offset;
  348         uint page_offset;
  349         int rc;
  350         struct tlock *tlck;
  351         s64 xaddr;
  352 
  353         ASSERT(DO_INDEX(ip));
  354 
  355         if (jfs_ip->next_index < 2) {
  356                 jfs_warn("add_index: next_index = %d.  Resetting!",
  357                            jfs_ip->next_index);
  358                 jfs_ip->next_index = 2;
  359         }
  360 
  361         index = jfs_ip->next_index++;
  362 
  363         if (index <= MAX_INLINE_DIRTABLE_ENTRY) {
  364                 /*
  365                  * i_size reflects size of index table, or 8 bytes per entry.
  366                  */
  367                 ip->i_size = (loff_t) (index - 1) << 3;
  368 
  369                 /*
  370                  * dir table fits inline within inode
  371                  */
  372                 dirtab_slot = &jfs_ip->i_dirtable[index-2];
  373                 dirtab_slot->flag = DIR_INDEX_VALID;
  374                 dirtab_slot->slot = slot;
  375                 DTSaddress(dirtab_slot, bn);
  376 
  377                 set_cflag(COMMIT_Dirtable, ip);
  378 
  379                 return index;
  380         }
  381         if (index == (MAX_INLINE_DIRTABLE_ENTRY + 1)) {
  382                 /*
  383                  * It's time to move the inline table to an external
  384                  * page and begin to build the xtree
  385                  */
  386 
  387                 /*
  388                  * Save the table, we're going to overwrite it with the
  389                  * xtree root
  390                  */
  391                 struct dir_table_slot temp_table[12];
  392                 memcpy(temp_table, &jfs_ip->i_dirtable, sizeof(temp_table));
  393 
  394                 /*
  395                  * Initialize empty x-tree
  396                  */
  397                 xtInitRoot(tid, ip);
  398 
  399                 /*
  400                  * Allocate the first block & add it to the xtree
  401                  */
  402                 xaddr = 0;
  403                 if ((rc =
  404                      xtInsert(tid, ip, 0, 0, sbi->nbperpage,
  405                               &xaddr, 0))) {
  406                         jfs_warn("add_index: xtInsert failed!");
  407                         return -1;
  408                 }
  409                 ip->i_size = PSIZE;
  410                 ip->i_blocks += LBLK2PBLK(sb, sbi->nbperpage);
  411 
  412                 if ((mp = get_index_page(ip, 0)) == 0) {
  413                         jfs_err("add_index: get_metapage failed!");
  414                         xtTruncate(tid, ip, 0, COMMIT_PWMAP);
  415                         return -1;
  416                 }
  417                 tlck = txLock(tid, ip, mp, tlckDATA);
  418                 llck = (struct linelock *) & tlck->lock;
  419                 ASSERT(llck->index == 0);
  420                 lv = &llck->lv[0];
  421 
  422                 lv->offset = 0;
  423                 lv->length = 6; /* tlckDATA slot size is 16 bytes */
  424                 llck->index++;
  425 
  426                 memcpy(mp->data, temp_table, sizeof(temp_table));
  427 
  428                 mark_metapage_dirty(mp);
  429                 release_metapage(mp);
  430 
  431                 /*
  432                  * Logging is now directed by xtree tlocks
  433                  */
  434                 clear_cflag(COMMIT_Dirtable, ip);
  435         }
  436 
  437         offset = (index - 2) * sizeof(struct dir_table_slot);
  438         page_offset = offset & (PSIZE - 1);
  439         blkno = ((offset + 1) >> L2PSIZE) << sbi->l2nbperpage;
  440         if (page_offset == 0) {
  441                 /*
  442                  * This will be the beginning of a new page
  443                  */
  444                 xaddr = 0;
  445                 if ((rc =
  446                      xtInsert(tid, ip, 0, blkno, sbi->nbperpage,
  447                               &xaddr, 0))) {
  448                         jfs_warn("add_index: xtInsert failed!");
  449                         jfs_ip->next_index--;
  450                         return -1;
  451                 }
  452                 ip->i_size += PSIZE;
  453                 ip->i_blocks += LBLK2PBLK(sb, sbi->nbperpage);
  454 
  455                 if ((mp = get_index_page(ip, blkno)))
  456                         memset(mp->data, 0, PSIZE);     /* Just looks better */
  457                 else
  458                         xtTruncate(tid, ip, offset, COMMIT_PWMAP);
  459         } else
  460                 mp = read_index_page(ip, blkno);
  461 
  462         if (mp == 0) {
  463                 jfs_err("add_index: get/read_metapage failed!");
  464                 return -1;
  465         }
  466 
  467         lock_index(tid, ip, mp, index);
  468 
  469         dirtab_slot =
  470             (struct dir_table_slot *) ((char *) mp->data + page_offset);
  471         dirtab_slot->flag = DIR_INDEX_VALID;
  472         dirtab_slot->slot = slot;
  473         DTSaddress(dirtab_slot, bn);
  474 
  475         mark_metapage_dirty(mp);
  476         release_metapage(mp);
  477 
  478         return index;
  479 }
  480 
  481 /*
  482  *      free_index()
  483  *
  484  *      Marks an entry to the directory index table as free.
  485  */
  486 static void free_index(tid_t tid, struct inode *ip, u32 index, u32 next)
  487 {
  488         struct dir_table_slot *dirtab_slot;
  489         s64 lblock;
  490         struct metapage *mp = 0;
  491 
  492         dirtab_slot = find_index(ip, index, &mp, &lblock);
  493 
  494         if (dirtab_slot == 0)
  495                 return;
  496 
  497         dirtab_slot->flag = DIR_INDEX_FREE;
  498         dirtab_slot->slot = dirtab_slot->addr1 = 0;
  499         dirtab_slot->addr2 = cpu_to_le32(next);
  500 
  501         if (mp) {
  502                 lock_index(tid, ip, mp, index);
  503                 mark_metapage_dirty(mp);
  504                 release_metapage(mp);
  505         } else
  506                 set_cflag(COMMIT_Dirtable, ip);
  507 }
  508 
  509 /*
  510  *      modify_index()
  511  *
  512  *      Changes an entry in the directory index table
  513  */
  514 static void modify_index(tid_t tid, struct inode *ip, u32 index, s64 bn,
  515                          int slot, struct metapage ** mp, u64 *lblock)
  516 {
  517         struct dir_table_slot *dirtab_slot;
  518 
  519         dirtab_slot = find_index(ip, index, mp, lblock);
  520 
  521         if (dirtab_slot == 0)
  522                 return;
  523 
  524         DTSaddress(dirtab_slot, bn);
  525         dirtab_slot->slot = slot;
  526 
  527         if (*mp) {
  528                 lock_index(tid, ip, *mp, index);
  529                 mark_metapage_dirty(*mp);
  530         } else
  531                 set_cflag(COMMIT_Dirtable, ip);
  532 }
  533 
  534 /*
  535  *      read_index()
  536  *
  537  *      reads a directory table slot
  538  */
  539 static int read_index(struct inode *ip, u32 index,
  540                      struct dir_table_slot * dirtab_slot)
  541 {
  542         s64 lblock;
  543         struct metapage *mp = 0;
  544         struct dir_table_slot *slot;
  545 
  546         slot = find_index(ip, index, &mp, &lblock);
  547         if (slot == 0) {
  548                 return -EIO;
  549         }
  550 
  551         memcpy(dirtab_slot, slot, sizeof(struct dir_table_slot));
  552 
  553         if (mp)
  554                 release_metapage(mp);
  555 
  556         return 0;
  557 }
  558 
  559 /*
  560  *      dtSearch()
  561  *
  562  * function:
  563  *      Search for the entry with specified key
  564  *
  565  * parameter:
  566  *
  567  * return: 0 - search result on stack, leaf page pinned;
  568  *         errno - I/O error
  569  */
  570 int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
  571              struct btstack * btstack, int flag)
  572 {
  573         int rc = 0;
  574         int cmp = 1;            /* init for empty page */
  575         s64 bn;
  576         struct metapage *mp;
  577         dtpage_t *p;
  578         s8 *stbl;
  579         int base, index, lim;
  580         struct btframe *btsp;
  581         pxd_t *pxd;
  582         int psize = 288;        /* initial in-line directory */
  583         ino_t inumber;
  584         struct component_name ciKey;
  585         struct super_block *sb = ip->i_sb;
  586 
  587         ciKey.name =
  588             (wchar_t *) kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
  589                                 GFP_NOFS);
  590         if (ciKey.name == 0) {
  591                 rc = ENOMEM;
  592                 goto dtSearch_Exit2;
  593         }
  594 
  595 
  596         /* uppercase search key for c-i directory */
  597         UniStrcpy(ciKey.name, key->name);
  598         ciKey.namlen = key->namlen;
  599 
  600         /* only uppercase if case-insensitive support is on */
  601         if ((JFS_SBI(sb)->mntflag & JFS_OS2) == JFS_OS2) {
  602                 ciToUpper(&ciKey);
  603         }
  604         BT_CLR(btstack);        /* reset stack */
  605 
  606         /* init level count for max pages to split */
  607         btstack->nsplit = 1;
  608 
  609         /*
  610          *      search down tree from root:
  611          *
  612          * between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
  613          * internal page, child page Pi contains entry with k, Ki <= K < Kj.
  614          *
  615          * if entry with search key K is not found
  616          * internal page search find the entry with largest key Ki
  617          * less than K which point to the child page to search;
  618          * leaf page search find the entry with smallest key Kj
  619          * greater than K so that the returned index is the position of
  620          * the entry to be shifted right for insertion of new entry.
  621          * for empty tree, search key is greater than any key of the tree.
  622          *
  623          * by convention, root bn = 0.
  624          */
  625         for (bn = 0;;) {
  626                 /* get/pin the page to search */
  627                 DT_GETPAGE(ip, bn, mp, psize, p, rc);
  628                 if (rc)
  629                         goto dtSearch_Exit1;
  630 
  631                 /* get sorted entry table of the page */
  632                 stbl = DT_GETSTBL(p);
  633 
  634                 /*
  635                  * binary search with search key K on the current page.
  636                  */
  637                 for (base = 0, lim = p->header.nextindex; lim; lim >>= 1) {
  638                         index = base + (lim >> 1);
  639 
  640                         if (p->header.flag & BT_LEAF) {
  641                                 /* uppercase leaf name to compare */
  642                                 cmp =
  643                                     ciCompare(&ciKey, p, stbl[index],
  644                                               JFS_SBI(sb)->mntflag);
  645                         } else {
  646                                 /* router key is in uppercase */
  647 
  648                                 cmp = dtCompare(&ciKey, p, stbl[index]);
  649 
  650 
  651                         }
  652                         if (cmp == 0) {
  653                                 /*
  654                                  *      search hit
  655                                  */
  656                                 /* search hit - leaf page:
  657                                  * return the entry found
  658                                  */
  659                                 if (p->header.flag & BT_LEAF) {
  660                                         inumber = le32_to_cpu(
  661                         ((struct ldtentry *) & p->slot[stbl[index]])->inumber);
  662 
  663                                         /*
  664                                          * search for JFS_LOOKUP
  665                                          */
  666                                         if (flag == JFS_LOOKUP) {
  667                                                 *data = inumber;
  668                                                 rc = 0;
  669                                                 goto out;
  670                                         }
  671 
  672                                         /*
  673                                          * search for JFS_CREATE
  674                                          */
  675                                         if (flag == JFS_CREATE) {
  676                                                 *data = inumber;
  677                                                 rc = EEXIST;
  678                                                 goto out;
  679                                         }
  680 
  681                                         /*
  682                                          * search for JFS_REMOVE or JFS_RENAME
  683                                          */
  684                                         if ((flag == JFS_REMOVE ||
  685                                              flag == JFS_RENAME) &&
  686                                             *data != inumber) {
  687                                                 rc = ESTALE;
  688                                                 goto out;
  689                                         }
  690 
  691                                         /*
  692                                          * JFS_REMOVE|JFS_FINDDIR|JFS_RENAME
  693                                          */
  694                                         /* save search result */
  695                                         *data = inumber;
  696                                         btsp = btstack->top;
  697                                         btsp->bn = bn;
  698                                         btsp->index = index;
  699                                         btsp->mp = mp;
  700 
  701                                         rc = 0;
  702                                         goto dtSearch_Exit1;
  703                                 }
  704 
  705                                 /* search hit - internal page:
  706                                  * descend/search its child page
  707                                  */
  708                                 goto getChild;
  709                         }
  710 
  711                         if (cmp > 0) {
  712                                 base = index + 1;
  713                                 --lim;
  714                         }
  715                 }
  716 
  717                 /*
  718                  *      search miss
  719                  *
  720                  * base is the smallest index with key (Kj) greater than
  721                  * search key (K) and may be zero or (maxindex + 1) index.
  722                  */
  723                 /*
  724                  * search miss - leaf page
  725                  *
  726                  * return location of entry (base) where new entry with
  727                  * search key K is to be inserted.
  728                  */
  729                 if (p->header.flag & BT_LEAF) {
  730                         /*
  731                          * search for JFS_LOOKUP, JFS_REMOVE, or JFS_RENAME
  732                          */
  733                         if (flag == JFS_LOOKUP || flag == JFS_REMOVE ||
  734                             flag == JFS_RENAME) {
  735                                 rc = ENOENT;
  736                                 goto out;
  737                         }
  738 
  739                         /*
  740                          * search for JFS_CREATE|JFS_FINDDIR:
  741                          *
  742                          * save search result
  743                          */
  744                         *data = 0;
  745                         btsp = btstack->top;
  746                         btsp->bn = bn;
  747                         btsp->index = base;
  748                         btsp->mp = mp;
  749 
  750                         rc = 0;
  751                         goto dtSearch_Exit1;
  752                 }
  753 
  754                 /*
  755                  * search miss - internal page
  756                  *
  757                  * if base is non-zero, decrement base by one to get the parent
  758                  * entry of the child page to search.
  759                  */
  760                 index = base ? base - 1 : base;
  761 
  762                 /*
  763                  * go down to child page
  764                  */
  765               getChild:
  766                 /* update max. number of pages to split */
  767                 if (btstack->nsplit >= 8) {
  768                         /* Something's corrupted, mark filesytem dirty so
  769                          * chkdsk will fix it.
  770                          */
  771                         jfs_err("stack overrun in dtSearch!");
  772                         updateSuper(sb, FM_DIRTY);
  773                         rc = EIO;
  774                         goto out;
  775                 }
  776                 btstack->nsplit++;
  777 
  778                 /* push (bn, index) of the parent page/entry */
  779                 BT_PUSH(btstack, bn, index);
  780 
  781                 /* get the child page block number */
  782                 pxd = (pxd_t *) & p->slot[stbl[index]];
  783                 bn = addressPXD(pxd);
  784                 psize = lengthPXD(pxd) << JFS_SBI(ip->i_sb)->l2bsize;
  785 
  786                 /* unpin the parent page */
  787                 DT_PUTPAGE(mp);
  788         }
  789 
  790       out:
  791         DT_PUTPAGE(mp);
  792 
  793       dtSearch_Exit1:
  794 
  795         kfree(ciKey.name);
  796 
  797       dtSearch_Exit2:
  798 
  799         return rc;
  800 }
  801 
  802 
  803 /*
  804  *      dtInsert()
  805  *
  806  * function: insert an entry to directory tree
  807  *
  808  * parameter:
  809  *
  810  * return: 0 - success;
  811  *         errno - failure;
  812  */
  813 int dtInsert(tid_t tid, struct inode *ip,
  814          struct component_name * name, ino_t * fsn, struct btstack * btstack)
  815 {
  816         int rc = 0;
  817         struct metapage *mp;    /* meta-page buffer */
  818         dtpage_t *p;            /* base B+-tree index page */
  819         s64 bn;
  820         int index;
  821         struct dtsplit split;   /* split information */
  822         ddata_t data;
  823         struct dt_lock *dtlck;
  824         int n;
  825         struct tlock *tlck;
  826         struct lv *lv;
  827 
  828         /*
  829          *      retrieve search result
  830          *
  831          * dtSearch() returns (leaf page pinned, index at which to insert).
  832          * n.b. dtSearch() may return index of (maxindex + 1) of
  833          * the full page.
  834          */
  835         DT_GETSEARCH(ip, btstack->top, bn, mp, p, index);
  836 
  837         /*
  838          *      insert entry for new key
  839          */
  840         if (DO_INDEX(ip)) {
  841                 if (JFS_IP(ip)->next_index == DIREND) {
  842                         DT_PUTPAGE(mp);
  843                         return EMLINK;
  844                 }
  845                 n = NDTLEAF(name->namlen);
  846                 data.leaf.tid = tid;
  847                 data.leaf.ip = ip;
  848         } else {
  849                 n = NDTLEAF_LEGACY(name->namlen);
  850                 data.leaf.ip = 0;       /* signifies legacy directory format */
  851         }
  852         data.leaf.ino = cpu_to_le32(*fsn);
  853 
  854         /*
  855          *      leaf page does not have enough room for new entry:
  856          *
  857          *      extend/split the leaf page;
  858          *
  859          * dtSplitUp() will insert the entry and unpin the leaf page.
  860          */
  861         if (n > p->header.freecnt) {
  862                 split.mp = mp;
  863                 split.index = index;
  864                 split.nslot = n;
  865                 split.key = name;
  866                 split.data = &data;
  867                 rc = dtSplitUp(tid, ip, &split, btstack);
  868                 return rc;
  869         }
  870 
  871         /*
  872          *      leaf page does have enough room for new entry:
  873          *
  874          *      insert the new data entry into the leaf page;
  875          */
  876         BT_MARK_DIRTY(mp, ip);
  877         /*
  878          * acquire a transaction lock on the leaf page
  879          */
  880         tlck = txLock(tid, ip, mp, tlckDTREE | tlckENTRY);
  881         dtlck = (struct dt_lock *) & tlck->lock;
  882         ASSERT(dtlck->index == 0);
  883         lv = & dtlck->lv[0];
  884 
  885         /* linelock header */
  886         lv->offset = 0;
  887         lv->length = 1;
  888         dtlck->index++;
  889 
  890         dtInsertEntry(p, index, name, &data, &dtlck);
  891 
  892         /* linelock stbl of non-root leaf page */
  893         if (!(p->header.flag & BT_ROOT)) {
  894                 if (dtlck->index >= dtlck->maxcnt)
  895                         dtlck = (struct dt_lock *) txLinelock(dtlck);
  896                 lv = & dtlck->lv[dtlck->index];
  897                 n = index >> L2DTSLOTSIZE;
  898                 lv->offset = p->header.stblindex + n;
  899                 lv->length =
  900                     ((p->header.nextindex - 1) >> L2DTSLOTSIZE) - n + 1;
  901                 dtlck->index++;
  902         }
  903 
  904         /* unpin the leaf page */
  905         DT_PUTPAGE(mp);
  906 
  907         return 0;
  908 }
  909 
  910 
  911 /*
  912  *      dtSplitUp()
  913  *
  914  * function: propagate insertion bottom up;
  915  *
  916  * parameter:
  917  *
  918  * return: 0 - success;
  919  *         errno - failure;
  920  *      leaf page unpinned;
  921  */
  922 static int dtSplitUp(tid_t tid,
  923           struct inode *ip, struct dtsplit * split, struct btstack * btstack)
  924 {
  925         struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
  926         int rc = 0;
  927         struct metapage *smp;
  928         dtpage_t *sp;           /* split page */
  929         struct metapage *rmp;
  930         dtpage_t *rp;           /* new right page split from sp */
  931         pxd_t rpxd;             /* new right page extent descriptor */
  932         struct metapage *lmp;
  933         dtpage_t *lp;           /* left child page */
  934         int skip;               /* index of entry of insertion */
  935         struct btframe *parent; /* parent page entry on traverse stack */
  936         s64 xaddr, nxaddr;
  937         int xlen, xsize;
  938         struct pxdlist pxdlist;
  939         pxd_t *pxd;
  940         struct component_name key = { 0, 0 };
  941         ddata_t *data = split->data;
  942         int n;
  943         struct dt_lock *dtlck;
  944         struct tlock *tlck;
  945         struct lv *lv;
  946 
  947         /* get split page */
  948         smp = split->mp;
  949         sp = DT_PAGE(ip, smp);
  950 
  951         key.name =
  952             (wchar_t *) kmalloc((JFS_NAME_MAX + 2) * sizeof(wchar_t),
  953                                 GFP_NOFS);
  954         if (key.name == 0) {
  955                 DT_PUTPAGE(smp);
  956                 rc = ENOMEM;
  957                 goto dtSplitUp_Exit;
  958         }
  959 
  960         /*
  961          *      split leaf page
  962          *
  963          * The split routines insert the new entry, and
  964          * acquire txLock as appropriate.
  965          */
  966         /*
  967          *      split root leaf page:
  968          */
  969         if (sp->header.flag & BT_ROOT) {
  970                 /*
  971                  * allocate a single extent child page
  972                  */
  973                 xlen = 1;
  974                 n = sbi->bsize >> L2DTSLOTSIZE;
  975                 n -= (n + 31) >> L2DTSLOTSIZE;  /* stbl size */
  976                 n -= DTROOTMAXSLOT - sp->header.freecnt; /* header + entries */
  977                 if (n <= split->nslot)
  978                         xlen++;
  979                 if ((rc = dbAlloc(ip, 0, (s64) xlen, &xaddr)))
  980                         goto freeKeyName;
  981 
  982                 pxdlist.maxnpxd = 1;
  983                 pxdlist.npxd = 0;
  984                 pxd = &pxdlist.pxd[0];
  985                 PXDaddress(pxd, xaddr);
  986                 PXDlength(pxd, xlen);
  987                 split->pxdlist = &pxdlist;
  988                 rc = dtSplitRoot(tid, ip, split, &rmp);
  989 
  990                 DT_PUTPAGE(rmp);
  991                 DT_PUTPAGE(smp);
  992 
  993                 goto freeKeyName;
  994         }
  995 
  996         /*
  997          *      extend first leaf page
  998          *
  999          * extend the 1st extent if less than buffer page size
 1000          * (dtExtendPage() reurns leaf page unpinned)
 1001          */
 1002         pxd = &sp->header.self;
 1003         xlen = lengthPXD(pxd);
 1004         xsize = xlen << sbi->l2bsize;
 1005         if (xsize < PSIZE) {
 1006                 xaddr = addressPXD(pxd);
 1007                 n = xsize >> L2DTSLOTSIZE;
 1008                 n -= (n + 31) >> L2DTSLOTSIZE;  /* stbl size */
 1009                 if ((n + sp->header.freecnt) <= split->nslot)
 1010                         n = xlen + (xlen << 1);
 1011                 else
 1012                         n = xlen;
 1013                 if ((rc = dbReAlloc(sbi->ipbmap, xaddr, (s64) xlen,
 1014                                     (s64) n, &nxaddr)))
 1015                         goto extendOut;
 1016 
 1017                 pxdlist.maxnpxd = 1;
 1018                 pxdlist.npxd = 0;
 1019                 pxd = &pxdlist.pxd[0];
 1020                 PXDaddress(pxd, nxaddr)
 1021                     PXDlength(pxd, xlen + n);
 1022                 split->pxdlist = &pxdlist;
 1023                 if ((rc = dtExtendPage(tid, ip, split, btstack))) {
 1024                         nxaddr = addressPXD(pxd);
 1025                         if (xaddr != nxaddr) {
 1026                                 /* free relocated extent */
 1027                                 xlen = lengthPXD(pxd);
 1028                                 dbFree(ip, nxaddr, (s64) xlen);
 1029                         } else {
 1030                                 /* free extended delta */
 1031                                 xlen = lengthPXD(pxd) - n;
 1032                                 xaddr = addressPXD(pxd) + xlen;
 1033                                 dbFree(ip, xaddr, (s64) n);
 1034                         }
 1035                 }
 1036 
 1037               extendOut:
 1038                 DT_PUTPAGE(smp);
 1039                 goto freeKeyName;
 1040         }
 1041 
 1042         /*
 1043          *      split leaf page <sp> into <sp> and a new right page <rp>.
 1044          *
 1045          * return <rp> pinned and its extent descriptor <rpxd>
 1046          */
 1047         /*
 1048          * allocate new directory page extent and
 1049          * new index page(s) to cover page split(s)
 1050          *
 1051          * allocation hint: ?
 1052          */
 1053         n = btstack->nsplit;
 1054         pxdlist.maxnpxd = pxdlist.npxd = 0;
 1055         xlen = sbi->nbperpage;
 1056         for (pxd = pxdlist.pxd; n > 0; n--, pxd++) {
 1057                 if ((rc = dbAlloc(ip, 0, (s64) xlen, &xaddr)) == 0) {
 1058                         PXDaddress(pxd, xaddr);
 1059                         PXDlength(pxd, xlen);
 1060                         pxdlist.maxnpxd++;
 1061                         continue;
 1062                 }
 1063 
 1064                 DT_PUTPAGE(smp);
 1065 
 1066                 /* undo allocation */
 1067                 goto splitOut;
 1068         }
 1069 
 1070         split->pxdlist = &pxdlist;
 1071         if ((rc = dtSplitPage(tid, ip, split, &rmp, &rp, &rpxd))) {
 1072                 DT_PUTPAGE(smp);
 1073 
 1074                 /* undo allocation */
 1075                 goto splitOut;
 1076         }
 1077 
 1078         /*
 1079          * propagate up the router entry for the leaf page just split
 1080          *
 1081          * insert a router entry for the new page into the parent page,
 1082          * propagate the insert/split up the tree by walking back the stack
 1083          * of (bn of parent page, index of child page entry in parent page)
 1084          * that were traversed during the search for the page that split.
 1085          *
 1086          * the propagation of insert/split up the tree stops if the root
 1087          * splits or the page inserted into doesn't have to split to hold
 1088          * the new entry.
 1089          *
 1090          * the parent entry for the split page remains the same, and
 1091          * a new entry is inserted at its right with the first key and
 1092          * block number of the new right page.
 1093          *
 1094          * There are a maximum of 4 pages pinned at any time:
 1095          * two children, left parent and right parent (when the parent splits).
 1096          * keep the child pages pinned while working on the parent.
 1097          * make sure that all pins are released at exit.
 1098          */
 1099         while ((parent = BT_POP(btstack)) != NULL) {
 1100                 /* parent page specified by stack frame <parent> */
 1101 
 1102                 /* keep current child pages (<lp>, <rp>) pinned */
 1103                 lmp = smp;
 1104                 lp = sp;
 1105 
 1106                 /*
 1107                  * insert router entry in parent for new right child page <rp>
 1108                  */
 1109                 /* get the parent page <sp> */
 1110                 DT_GETPAGE(ip, parent->bn, smp, PSIZE, sp, rc);
 1111                 if (rc) {
 1112                         DT_PUTPAGE(lmp);
 1113                         DT_PUTPAGE(rmp);
 1114                         goto splitOut;
 1115                 }
 1116 
 1117                 /*
 1118                  * The new key entry goes ONE AFTER the index of parent entry,
 1119                  * because the split was to the right.
 1120                  */
 1121                 skip = parent->index + 1;
 1122 
 1123                 /*
 1124                  * compute the key for the router entry
 1125                  *
 1126                  * key suffix compression:
 1127                  * for internal pages that have leaf pages as children,
 1128                  * retain only what's needed to distinguish between
 1129                  * the new entry and the entry on the page to its left.
 1130                  * If the keys compare equal, retain the entire key.
 1131                  *
 1132                  * note that compression is performed only at computing
 1133                  * router key at the lowest internal level.
 1134                  * further compression of the key between pairs of higher
 1135                  * level internal pages loses too much information and
 1136                  * the search may fail.
 1137                  * (e.g., two adjacent leaf pages of {a, ..., x} {xx, ...,}
 1138                  * results in two adjacent parent entries (a)(xx).
 1139                  * if split occurs between these two entries, and
 1140                  * if compression is applied, the router key of parent entry
 1141                  * of right page (x) will divert search for x into right
 1142                  * subtree and miss x in the left subtree.)
 1143                  *
 1144                  * the entire key must be retained for the next-to-leftmost
 1145                  * internal key at any level of the tree, or search may fail
 1146                  * (e.g., ?)
 1147                  */
 1148                 switch (rp->header.flag & BT_TYPE) {
 1149                 case BT_LEAF:
 1150                         /*
 1151                          * compute the length of prefix for suffix compression
 1152                          * between last entry of left page and first entry
 1153                          * of right page
 1154                          */
 1155                         if ((sp->header.flag & BT_ROOT && skip > 1) ||
 1156                             sp->header.prev != 0 || skip > 1) {
 1157                                 /* compute uppercase router prefix key */
 1158                                 ciGetLeafPrefixKey(lp,
 1159                                                    lp->header.nextindex - 1,
 1160                                                    rp, 0, &key, sbi->mntflag);
 1161                         } else {
 1162                                 /* next to leftmost entry of
 1163                                    lowest internal level */
 1164 
 1165                                 /* compute uppercase router key */
 1166                                 dtGetKey(rp, 0, &key, sbi->mntflag);
 1167                                 key.name[key.namlen] = 0;
 1168 
 1169                                 if ((sbi->mntflag & JFS_OS2) == JFS_OS2)
 1170                                         ciToUpper(&key);
 1171                         }
 1172 
 1173                         n = NDTINTERNAL(key.namlen);
 1174                         break;
 1175 
 1176                 case BT_INTERNAL:
 1177                         dtGetKey(rp, 0, &key, sbi->mntflag);
 1178                         n = NDTINTERNAL(key.namlen);
 1179                         break;
 1180 
 1181                 default:
 1182                         jfs_err("dtSplitUp(): UFO!");
 1183                         break;
 1184                 }
 1185 
 1186                 /* unpin left child page */
 1187                 DT_PUTPAGE(lmp);
 1188 
 1189                 /*
 1190                  * compute the data for the router entry
 1191                  */
 1192                 data->xd = rpxd;        /* child page xd */
 1193 
 1194                 /*
 1195                  * parent page is full - split the parent page
 1196                  */
 1197                 if (n > sp->header.freecnt) {
 1198                         /* init for parent page split */
 1199                         split->mp = smp;
 1200                         split->index = skip;    /* index at insert */
 1201                         split->nslot = n;
 1202                         split->key = &key;
 1203                         /* split->data = data; */
 1204 
 1205                         /* unpin right child page */
 1206                         DT_PUTPAGE(rmp);
 1207 
 1208                         /* The split routines insert the new entry,
 1209                          * acquire txLock as appropriate.
 1210                          * return <rp> pinned and its block number <rbn>.
 1211                          */
 1212                         rc = (sp->header.flag & BT_ROOT) ?
 1213                             dtSplitRoot(tid, ip, split, &rmp) :
 1214                             dtSplitPage(tid, ip, split, &rmp, &rp, &rpxd);
 1215                         if (rc) {
 1216                                 DT_PUTPAGE(smp);
 1217                                 goto splitOut;
 1218                         }
 1219 
 1220                         /* smp and rmp are pinned */
 1221                 }
 1222                 /*
 1223                  * parent page is not full - insert router entry in parent page
 1224                  */
 1225                 else {
 1226                         BT_MARK_DIRTY(smp, ip);
 1227                         /*
 1228                          * acquire a transaction lock on the parent page
 1229                          */
 1230                         tlck = txLock(tid, ip, smp, tlckDTREE | tlckENTRY);
 1231                         dtlck = (struct dt_lock *) & tlck->lock;
 1232                         ASSERT(dtlck->index == 0);
 1233                         lv = & dtlck->lv[0];
 1234 
 1235                         /* linelock header */
 1236                         lv->offset = 0;
 1237                         lv->length = 1;
 1238                         dtlck->index++;
 1239 
 1240                         /* linelock stbl of non-root parent page */
 1241                         if (!(sp->header.flag & BT_ROOT)) {
 1242                                 lv++;
 1243                                 n = skip >> L2DTSLOTSIZE;
 1244                                 lv->offset = sp->header.stblindex + n;
 1245                                 lv->length =
 1246                                     ((sp->header.nextindex -
 1247                                       1) >> L2DTSLOTSIZE) - n + 1;
 1248                                 dtlck->index++;
 1249                         }
 1250 
 1251                         dtInsertEntry(sp, skip, &key, data, &dtlck);
 1252 
 1253                         /* exit propagate up */
 1254                         break;
 1255                 }
 1256         }
 1257 
 1258         /* unpin current split and its right page */
 1259         DT_PUTPAGE(smp);
 1260         DT_PUTPAGE(rmp);
 1261 
 1262         /*
 1263          * free remaining extents allocated for split
 1264          */
 1265       splitOut:
 1266         n = pxdlist.npxd;
 1267         pxd = &pxdlist.pxd[n];
 1268         for (; n < pxdlist.maxnpxd; n++, pxd++)
 1269                 dbFree(ip, addressPXD(pxd), (s64) lengthPXD(pxd));
 1270 
 1271       freeKeyName:
 1272         kfree(key.name);
 1273 
 1274       dtSplitUp_Exit:
 1275 
 1276         return rc;
 1277 }
 1278 
 1279 
 1280 /*
 1281  *      dtSplitPage()
 1282  *
 1283  * function: Split a non-root page of a btree.
 1284  *
 1285  * parameter:
 1286  *
 1287  * return: 0 - success;
 1288  *         errno - failure;
 1289  *      return split and new page pinned;
 1290  */
 1291 static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
 1292             struct metapage ** rmpp, dtpage_t ** rpp, pxd_t * rpxdp)
 1293 {
 1294         struct super_block *sb = ip->i_sb;
 1295         int rc = 0;
 1296         struct metapage *smp;
 1297         dtpage_t *sp;
 1298         struct metapage *rmp;
 1299         dtpage_t *rp;           /* new right page allocated */
 1300         s64 rbn;                /* new right page block number */
 1301         struct metapage *mp;
 1302         dtpage_t *p;
 1303         s64 nextbn;
 1304         struct pxdlist *pxdlist;
 1305         pxd_t *pxd;
 1306         int skip, nextindex, half, left, nxt, off, si;
 1307         struct ldtentry *ldtentry;
 1308         struct idtentry *idtentry;
 1309         u8 *stbl;
 1310         struct dtslot *f;
 1311         int fsi, stblsize;
 1312         int n;
 1313         struct dt_lock *sdtlck, *rdtlck;
 1314         struct tlock *tlck;
 1315         struct dt_lock *dtlck;
 1316         struct lv *slv, *rlv, *lv;
 1317 
 1318         /* get split page */
 1319         smp = split->mp;
 1320         sp = DT_PAGE(ip, smp);
 1321 
 1322         /*
 1323          * allocate the new right page for the split
 1324          */
 1325         pxdlist = split->pxdlist;
 1326         pxd = &pxdlist->pxd[pxdlist->npxd];
 1327         pxdlist->npxd++;
 1328         rbn = addressPXD(pxd);
 1329         rmp = get_metapage(ip, rbn, PSIZE, 1);
 1330         if (rmp == NULL)
 1331                 return EIO;
 1332 
 1333         jfs_info("dtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp);
 1334 
 1335         BT_MARK_DIRTY(rmp, ip);
 1336         /*
 1337          * acquire a transaction lock on the new right page
 1338          */
 1339         tlck = txLock(tid, ip, rmp, tlckDTREE | tlckNEW);
 1340         rdtlck = (struct dt_lock *) & tlck->lock;
 1341 
 1342         rp = (dtpage_t *) rmp->data;
 1343         *rpp = rp;
 1344         rp->header.self = *pxd;
 1345 
 1346         BT_MARK_DIRTY(smp, ip);
 1347         /*
 1348          * acquire a transaction lock on the split page
 1349          *
 1350          * action:
 1351          */
 1352         tlck = txLock(tid, ip, smp, tlckDTREE | tlckENTRY);
 1353         sdtlck = (struct dt_lock *) & tlck->lock;
 1354 
 1355         /* linelock header of split page */
 1356         ASSERT(sdtlck->index == 0);
 1357         slv = & sdtlck->lv[0];
 1358         slv->offset = 0;
 1359         slv->length = 1;
 1360         sdtlck->index++;
 1361 
 1362         /*
 1363          * initialize/update sibling pointers between sp and rp
 1364          */
 1365         nextbn = le64_to_cpu(sp->header.next);
 1366         rp->header.next = cpu_to_le64(nextbn);
 1367         rp->header.prev = cpu_to_le64(addressPXD(&sp->header.self));
 1368         sp->header.next = cpu_to_le64(rbn);
 1369 
 1370         /*
 1371          * initialize new right page
 1372          */
 1373         rp->header.flag = sp->header.flag;
 1374 
 1375         /* compute sorted entry table at start of extent data area */
 1376         rp->header.nextindex = 0;
 1377         rp->header.stblindex = 1;
 1378 
 1379         n = PSIZE >> L2DTSLOTSIZE;
 1380         rp->header.maxslot = n;
 1381         stblsize = (n + 31) >> L2DTSLOTSIZE;    /* in unit of slot */
 1382 
 1383         /* init freelist */
 1384         fsi = rp->header.stblindex + stblsize;
 1385         rp->header.freelist = fsi;
 1386         rp->header.freecnt = rp->header.maxslot - fsi;
 1387 
 1388         /*
 1389          *      sequential append at tail: append without split
 1390          *
 1391          * If splitting the last page on a level because of appending
 1392          * a entry to it (skip is maxentry), it's likely that the access is
 1393          * sequential. Adding an empty page on the side of the level is less
 1394          * work and can push the fill factor much higher than normal.
 1395          * If we're wrong it's no big deal, we'll just do the split the right
 1396          * way next time.
 1397          * (It may look like it's equally easy to do a similar hack for
 1398          * reverse sorted data, that is, split the tree left,
 1399          * but it's not. Be my guest.)
 1400          */
 1401         if (nextbn == 0 && split->index == sp->header.nextindex) {
 1402                 /* linelock header + stbl (first slot) of new page */
 1403                 rlv = & rdtlck->lv[rdtlck->index];
 1404                 rlv->offset = 0;
 1405                 rlv->length = 2;
 1406                 rdtlck->index++;
 1407 
 1408                 /*
 1409                  * initialize freelist of new right page
 1410                  */
 1411                 f = &rp->slot[fsi];
 1412                 for (fsi++; fsi < rp->header.maxslot; f++, fsi++)
 1413                         f->next = fsi;
 1414                 f->next = -1;
 1415 
 1416                 /* insert entry at the first entry of the new right page */
 1417                 dtInsertEntry(rp, 0, split->key, split->data, &rdtlck);
 1418 
 1419                 goto out;
 1420         }
 1421 
 1422         /*
 1423          *      non-sequential insert (at possibly middle page)
 1424          */
 1425 
 1426         /*
 1427          * update prev pointer of previous right sibling page;
 1428          */
 1429         if (nextbn != 0) {
 1430                 DT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);
 1431                 if (rc)
 1432                         return rc;
 1433 
 1434                 BT_MARK_DIRTY(mp, ip);
 1435                 /*
 1436                  * acquire a transaction lock on the next page
 1437                  */
 1438                 tlck = txLock(tid, ip, mp, tlckDTREE | tlckRELINK);
 1439                 jfs_info("dtSplitPage: tlck = 0x%p, ip = 0x%p, mp=0x%p",
 1440                         tlck, ip, mp);
 1441                 dtlck = (struct dt_lock *) & tlck->lock;
 1442 
 1443                 /* linelock header of previous right sibling page */
 1444                 lv = & dtlck->lv[dtlck->index];
 1445                 lv->offset = 0;
 1446                 lv->length = 1;
 1447                 dtlck->index++;
 1448 
 1449                 p->header.prev = cpu_to_le64(rbn);
 1450 
 1451                 DT_PUTPAGE(mp);
 1452         }
 1453 
 1454         /*
 1455          * split the data between the split and right pages.
 1456          */
 1457         skip = split->index;
 1458         half = (PSIZE >> L2DTSLOTSIZE) >> 1;    /* swag */
 1459         left = 0;
 1460 
 1461         /*
 1462          *      compute fill factor for split pages
 1463          *
 1464          * <nxt> traces the next entry to move to rp
 1465          * <off> traces the next entry to stay in sp
 1466          */
 1467         stbl = (u8 *) & sp->slot[sp->header.stblindex];
 1468         nextindex = sp->header.nextindex;
 1469         for (nxt = off = 0; nxt < nextindex; ++off) {
 1470                 if (off == skip)
 1471                         /* check for fill factor with new entry size */
 1472                         n = split->nslot;
 1473                 else {
 1474                         si = stbl[nxt];
 1475                         switch (sp->header.flag & BT_TYPE) {
 1476                         case BT_LEAF:
 1477                                 ldtentry = (struct ldtentry *) & sp->slot[si];
 1478                                 if (DO_INDEX(ip))
 1479                                         n = NDTLEAF(ldtentry->namlen);
 1480                                 else
 1481                                         n = NDTLEAF_LEGACY(ldtentry->
 1482                                                            namlen);
 1483                                 break;
 1484 
 1485                         case BT_INTERNAL:
 1486                                 idtentry = (struct idtentry *) & sp->slot[si];
 1487                                 n = NDTINTERNAL(idtentry->namlen);
 1488                                 break;
 1489 
 1490                         default:
 1491                                 break;
 1492                         }
 1493 
 1494                         ++nxt;  /* advance to next entry to move in sp */
 1495                 }
 1496 
 1497                 left += n;
 1498                 if (left >= half)
 1499                         break;
 1500         }
 1501 
 1502         /* <nxt> poins to the 1st entry to move */
 1503 
 1504         /*
 1505          *      move entries to right page
 1506          *
 1507          * dtMoveEntry() initializes rp and reserves entry for insertion
 1508          *
 1509          * split page moved out entries are linelocked;
 1510          * new/right page moved in entries are linelocked;
 1511          */
 1512         /* linelock header + stbl of new right page */
 1513         rlv = & rdtlck->lv[rdtlck->index];
 1514         rlv->offset = 0;
 1515         rlv->length = 5;
 1516         rdtlck->index++;
 1517 
 1518         dtMoveEntry(sp, nxt, rp, &sdtlck, &rdtlck, DO_INDEX(ip));
 1519 
 1520         sp->header.nextindex = nxt;
 1521 
 1522         /*
 1523          * finalize freelist of new right page
 1524          */
 1525         fsi = rp->header.freelist;
 1526         f = &rp->slot[fsi];
 1527         for (fsi++; fsi < rp->header.maxslot; f++, fsi++)
 1528                 f->next = fsi;
 1529         f->next = -1;
 1530 
 1531         /*
 1532          * Update directory index table for entries now in right page
 1533          */
 1534         if ((rp->header.flag & BT_LEAF) && DO_INDEX(ip)) {
 1535                 s64 lblock;
 1536 
 1537                 mp = 0;
 1538                 stbl = DT_GETSTBL(rp);
 1539                 for (n = 0; n < rp->header.nextindex; n++) {
 1540                         ldtentry = (struct ldtentry *) & rp->slot[stbl[n]];
 1541                         modify_index(tid, ip, le32_to_cpu(ldtentry->index),
 1542                                      rbn, n, &mp, &lblock);
 1543                 }
 1544                 if (mp)
 1545                         release_metapage(mp);
 1546         }
 1547 
 1548         /*
 1549          * the skipped index was on the left page,
 1550          */
 1551         if (skip <= off) {
 1552                 /* insert the new entry in the split page */
 1553                 dtInsertEntry(sp, skip, split->key, split->data, &sdtlck);
 1554 
 1555                 /* linelock stbl of split page */
 1556                 if (sdtlck->index >= sdtlck->maxcnt)
 1557                         sdtlck = (struct dt_lock *) txLinelock(sdtlck);
 1558                 slv = & sdtlck->lv[sdtlck->index];
 1559                 n = skip >> L2DTSLOTSIZE;
 1560                 slv->offset = sp->header.stblindex + n;
 1561                 slv->length =
 1562                     ((sp->header.nextindex - 1) >> L2DTSLOTSIZE) - n + 1;
 1563                 sdtlck->index++;
 1564         }
 1565         /*
 1566          * the skipped index was on the right page,
 1567          */
 1568         else {
 1569                 /* adjust the skip index to reflect the new position */
 1570                 skip -= nxt;
 1571 
 1572                 /* insert the new entry in the right page */
 1573                 dtInsertEntry(rp, skip, split->key, split->data, &rdtlck);
 1574         }
 1575 
 1576       out:
 1577         *rmpp = rmp;
 1578         *rpxdp = *pxd;
 1579 
 1580         ip->i_blocks += LBLK2PBLK(sb, lengthPXD(pxd));
 1581 
 1582         return 0;
 1583 }
 1584 
 1585 
 1586 /*
 1587  *      dtExtendPage()
 1588  *
 1589  * function: extend 1st/only directory leaf page
 1590  *
 1591  * parameter:
 1592  *
 1593  * return: 0 - success;
 1594  *         errno - failure;
 1595  *      return extended page pinned;
 1596  */
 1597 static int dtExtendPage(tid_t tid,
 1598              struct inode *ip, struct dtsplit * split, struct btstack * btstack)
 1599 {
 1600         struct super_block *sb = ip->i_sb;
 1601         int rc;
 1602         struct metapage *smp, *pmp, *mp;
 1603         dtpage_t *sp, *pp;
 1604         struct pxdlist *pxdlist;
 1605         pxd_t *pxd, *tpxd;
 1606         int xlen, xsize;
 1607         int newstblindex, newstblsize;
 1608         int oldstblindex, oldstblsize;
 1609         int fsi, last;
 1610         struct dtslot *f;
 1611         struct btframe *parent;
 1612         int n;
 1613         struct dt_lock *dtlck;
 1614         s64 xaddr, txaddr;
 1615         struct tlock *tlck;
 1616         struct pxd_lock *pxdlock;
 1617         struct lv *lv;
 1618         uint type;
 1619         struct ldtentry *ldtentry;
 1620         u8 *stbl;
 1621 
 1622         /* get page to extend */
 1623         smp = split->mp;
 1624         sp = DT_PAGE(ip, smp);
 1625 
 1626         /* get parent/root page */
 1627         parent = BT_POP(btstack);
 1628         DT_GETPAGE(ip, parent->bn, pmp, PSIZE, pp, rc);
 1629         if (rc)
 1630                 return (rc);
 1631 
 1632         /*
 1633          *      extend the extent
 1634          */
 1635         pxdlist = split->pxdlist;
 1636         pxd = &pxdlist->pxd[pxdlist->npxd];
 1637         pxdlist->npxd++;
 1638 
 1639         xaddr = addressPXD(pxd);
 1640         tpxd = &sp->header.self;
 1641         txaddr = addressPXD(tpxd);
 1642         /* in-place extension */
 1643         if (xaddr == txaddr) {
 1644                 type = tlckEXTEND;
 1645         }
 1646         /* relocation */
 1647         else {
 1648                 type = tlckNEW;
 1649 
 1650                 /* save moved extent descriptor for later free */
 1651                 tlck = txMaplock(tid, ip, tlckDTREE | tlckRELOCATE);
 1652                 pxdlock = (struct pxd_lock *) & tlck->lock;
 1653                 pxdlock->flag = mlckFREEPXD;
 1654                 pxdlock->pxd = sp->header.self;
 1655                 pxdlock->index = 1;
 1656 
 1657                 /*
 1658                  * Update directory index table to reflect new page address
 1659                  */
 1660                 if (DO_INDEX(ip)) {
 1661                         s64 lblock;
 1662 
 1663                         mp = 0;
 1664                         stbl = DT_GETSTBL(sp);
 1665                         for (n = 0; n < sp->header.nextindex; n++) {
 1666                                 ldtentry =
 1667                                     (struct ldtentry *) & sp->slot[stbl[n]];
 1668                                 modify_index(tid, ip,
 1669                                              le32_to_cpu(ldtentry->index),
 1670                                              xaddr, n, &mp, &lblock);
 1671                         }
 1672                         if (mp)
 1673                                 release_metapage(mp);
 1674                 }
 1675         }
 1676 
 1677         /*
 1678          *      extend the page
 1679          */
 1680         sp->header.self = *pxd;
 1681 
 1682         jfs_info("dtExtendPage: ip:0x%p smp:0x%p sp:0x%p", ip, smp, sp);
 1683 
 1684         BT_MARK_DIRTY(smp, ip);
 1685         /*
 1686          * acquire a transaction lock on the extended/leaf page
 1687          */
 1688         tlck = txLock(tid, ip, smp, tlckDTREE | type);
 1689         dtlck = (struct dt_lock *) & tlck->lock;
 1690         lv = & dtlck->lv[0];
 1691 
 1692         /* update buffer extent descriptor of extended page */
 1693         xlen = lengthPXD(pxd);
 1694         xsize = xlen << JFS_SBI(sb)->l2bsize;
 1695 #ifdef _STILL_TO_PORT
 1696         bmSetXD(smp, xaddr, xsize);
 1697 #endif                          /*  _STILL_TO_PORT */
 1698 
 1699         /*
 1700          * copy old stbl to new stbl at start of extended area
 1701          */
 1702         oldstblindex = sp->header.stblindex;
 1703         oldstblsize = (sp->header.maxslot + 31) >> L2DTSLOTSIZE;
 1704         newstblindex = sp->header.maxslot;
 1705         n = xsize >> L2DTSLOTSIZE;
 1706         newstblsize = (n + 31) >> L2DTSLOTSIZE;
 1707         memcpy(&sp->slot[newstblindex], &sp->slot[oldstblindex],
 1708                sp->header.nextindex);
 1709 
 1710         /*
 1711          * in-line extension: linelock old area of extended page
 1712          */
 1713         if (type == tlckEXTEND) {
 1714                 /* linelock header */
 1715                 lv->offset = 0;
 1716                 lv->length = 1;
 1717                 dtlck->index++;
 1718                 lv++;
 1719 
 1720                 /* linelock new stbl of extended page */
 1721                 lv->offset = newstblindex;
 1722                 lv->length = newstblsize;
 1723         }
 1724         /*
 1725          * relocation: linelock whole relocated area
 1726          */
 1727         else {
 1728                 lv->offset = 0;
 1729                 lv->length = sp->header.maxslot + newstblsize;
 1730         }
 1731 
 1732         dtlck->index++;
 1733 
 1734         sp->header.maxslot = n;
 1735         sp->header.stblindex = newstblindex;
 1736         /* sp->header.nextindex remains the same */
 1737 
 1738         /*
 1739          * add old stbl region at head of freelist
 1740          */
 1741         fsi = oldstblindex;
 1742         f = &sp->slot[fsi];
 1743         last = sp->header.freelist;
 1744         for (n = 0; n < oldstblsize; n++, fsi++, f++) {
 1745                 f->next = last;
 1746                 last = fsi;
 1747         }
 1748         sp->header.freelist = last;
 1749         sp->header.freecnt += oldstblsize;
 1750 
 1751         /*
 1752          * append free region of newly extended area at tail of freelist
 1753          */
 1754         /* init free region of newly extended area */
 1755         fsi = n = newstblindex + newstblsize;
 1756         f = &sp->slot[fsi];
 1757         for (fsi++; fsi < sp->header.maxslot; f++, fsi++)
 1758                 f->next = fsi;
 1759         f->next = -1;
 1760 
 1761         /* append new free region at tail of old freelist */
 1762         fsi = sp->header.freelist;
 1763         if (fsi == -1)
 1764                 sp->header.freelist = n;
 1765         else {
 1766                 do {
 1767                         f = &sp->slot[fsi];
 1768                         fsi = f->next;
 1769                 } while (fsi != -1);
 1770 
 1771                 f->next = n;
 1772         }
 1773 
 1774         sp->header.freecnt += sp->header.maxslot - n;
 1775 
 1776         /*
 1777          * insert the new entry
 1778          */
 1779         dtInsertEntry(sp, split->index, split->key, split->data, &dtlck);
 1780 
 1781         BT_MARK_DIRTY(pmp, ip);
 1782         /*
 1783          * linelock any freeslots residing in old extent
 1784          */
 1785         if (type == tlckEXTEND) {
 1786                 n = sp->header.maxslot >> 2;
 1787                 if (sp->header.freelist < n)
 1788                         dtLinelockFreelist(sp, n, &dtlck);
 1789         }
 1790 
 1791         /*
 1792          *      update parent entry on the parent/root page
 1793          */
 1794         /*
 1795          * acquire a transaction lock on the parent/root page
 1796          */
 1797         tlck = txLock(tid, ip, pmp, tlckDTREE | tlckENTRY);
 1798         dtlck = (struct dt_lock *) & tlck->lock;
 1799         lv = & dtlck->lv[dtlck->index];
 1800 
 1801         /* linelock parent entry - 1st slot */
 1802         lv->offset = 1;
 1803         lv->length = 1;
 1804         dtlck->index++;
 1805 
 1806         /* update the parent pxd for page extension */
 1807         tpxd = (pxd_t *) & pp->slot[1];
 1808         *tpxd = *pxd;
 1809 
 1810         /* Since the directory might have an EA and/or ACL associated with it
 1811          * we need to make sure we take that into account when setting the
 1812          * i_nblocks
 1813          */
 1814         ip->i_blocks = LBLK2PBLK(ip->i_sb, xlen +
 1815                                  ((JFS_IP(ip)->ea.flag & DXD_EXTENT) ?
 1816                                   lengthDXD(&JFS_IP(ip)->ea) : 0) +
 1817                                  ((JFS_IP(ip)->acl.flag & DXD_EXTENT) ?
 1818                                   lengthDXD(&JFS_IP(ip)->acl) : 0));
 1819 
 1820         DT_PUTPAGE(pmp);
 1821         return 0;
 1822 }
 1823 
 1824 
 1825 /*
 1826  *      dtSplitRoot()
 1827  *
 1828  * function:
 1829  *      split the full root page into
 1830  *      original/root/split page and new right page
 1831  *      i.e., root remains fixed in tree anchor (inode) and
 1832  *      the root is copied to a single new right child page
 1833  *      since root page << non-root page, and
 1834  *      the split root page contains a single entry for the
 1835  *      new right child page.
 1836  *
 1837  * parameter:
 1838  *
 1839  * return: 0 - success;
 1840  *         errno - failure;
 1841  *      return new page pinned;
 1842  */
 1843 static int dtSplitRoot(tid_t tid,
 1844             struct inode *ip, struct dtsplit * split, struct metapage ** rmpp)
 1845 {
 1846         struct super_block *sb = ip->i_sb;
 1847         struct metapage *smp;
 1848         dtroot_t *sp;
 1849         struct metapage *rmp;
 1850         dtpage_t *rp;
 1851         s64 rbn;
 1852         int xlen;
 1853         int xsize;
 1854         struct dtslot *f;
 1855         s8 *stbl;
 1856         int fsi, stblsize, n;
 1857         struct idtentry *s;
 1858         pxd_t *ppxd;
 1859         struct pxdlist *pxdlist;
 1860         pxd_t *pxd;
 1861         struct dt_lock *dtlck;
 1862         struct tlock *tlck;
 1863         struct lv *lv;
 1864 
 1865         /* get split root page */
 1866         smp = split->mp;
 1867         sp = &JFS_IP(ip)->i_dtroot;
 1868 
 1869         /*
 1870          *      allocate/initialize a single (right) child page
 1871          *
 1872          * N.B. at first split, a one (or two) block to fit new entry
 1873          * is allocated; at subsequent split, a full page is allocated;
 1874          */
 1875         pxdlist = split->pxdlist;
 1876         pxd = &pxdlist->pxd[pxdlist->npxd];
 1877         pxdlist->npxd++;
 1878         rbn = addressPXD(pxd);
 1879         xlen = lengthPXD(pxd);
 1880         xsize = xlen << JFS_SBI(sb)->l2bsize;
 1881         rmp = get_metapage(ip, rbn, xsize, 1);
 1882         rp = rmp->data;
 1883 
 1884         BT_MARK_DIRTY(rmp, ip);
 1885         /*
 1886          * acquire a transaction lock on the new right page
 1887          */
 1888         tlck = txLock(tid, ip, rmp, tlckDTREE | tlckNEW);
 1889         dtlck = (struct dt_lock *) & tlck->lock;
 1890 
 1891         rp->header.flag =
 1892             (sp->header.flag & BT_LEAF) ? BT_LEAF : BT_INTERNAL;
 1893         rp->header.self = *pxd;
 1894 
 1895         /* initialize sibling pointers */
 1896         rp->header.next = 0;
 1897         rp->header.prev = 0;
 1898 
 1899         /*
 1900          *      move in-line root page into new right page extent
 1901          */
 1902         /* linelock header + copied entries + new stbl (1st slot) in new page */
 1903         ASSERT(dtlck->index == 0);
 1904         lv = & dtlck->lv[0];
 1905         lv->offset = 0;
 1906         lv->length = 10;        /* 1 + 8 + 1 */
 1907         dtlck->index++;
 1908 
 1909         n = xsize >> L2DTSLOTSIZE;
 1910         rp->header.maxslot = n;
 1911         stblsize = (n + 31) >> L2DTSLOTSIZE;
 1912 
 1913         /* copy old stbl to new stbl at start of extended area */
 1914         rp->header.stblindex = DTROOTMAXSLOT;
 1915         stbl = (s8 *) & rp->slot[DTROOTMAXSLOT];
 1916         memcpy(stbl, sp->header.stbl, sp->header.nextindex);
 1917         rp->header.nextindex = sp->header.nextindex;
 1918 
 1919         /* copy old data area to start of new data area */
 1920         memcpy(&rp->slot[1], &sp->slot[1], IDATASIZE);
 1921 
 1922         /*
 1923          * append free region of newly extended area at tail of freelist
 1924          */
 1925         /* init free region of newly extended area */
 1926         fsi = n = DTROOTMAXSLOT + stblsize;
 1927         f = &rp->slot[fsi];
 1928         for (fsi++; fsi < rp->header.maxslot; f++, fsi++)
 1929                 f->next = fsi;
 1930         f->next = -1;
 1931 
 1932         /* append new free region at tail of old freelist */
 1933         fsi = sp->header.freelist;
 1934         if (fsi == -1)
 1935                 rp->header.freelist = n;
 1936         else {
 1937                 rp->header.freelist = fsi;
 1938 
 1939                 do {
 1940                         f = &rp->slot[fsi];
 1941                         fsi = f->next;
 1942                 } while (fsi != -1);
 1943 
 1944                 f->next = n;
 1945         }
 1946 
 1947         rp->header.freecnt = sp->header.freecnt + rp->header.maxslot - n;
 1948 
 1949         /*
 1950          * Update directory index table for entries now in right page
 1951          */
 1952         if ((rp->header.flag & BT_LEAF) && DO_INDEX(ip)) {
 1953                 s64 lblock;
 1954                 struct metapage *mp = 0;
 1955                 struct ldtentry *ldtentry;
 1956 
 1957                 stbl = DT_GETSTBL(rp);
 1958                 for (n = 0; n < rp->header.nextindex; n++) {
 1959                         ldtentry = (struct ldtentry *) & rp->slot[stbl[n]];
 1960                         modify_index(tid, ip, le32_to_cpu(ldtentry->index),
 1961                                      rbn, n, &mp, &lblock);
 1962                 }
 1963                 if (mp)
 1964                         release_metapage(mp);
 1965         }
 1966         /*
 1967          * insert the new entry into the new right/child page
 1968          * (skip index in the new right page will not change)
 1969          */
 1970         dtInsertEntry(rp, split->index, split->key, split->data, &dtlck);
 1971 
 1972         /*
 1973          *      reset parent/root page
 1974          *
 1975          * set the 1st entry offset to 0, which force the left-most key
 1976          * at any level of the tree to be less than any search key.
 1977          *
 1978          * The btree comparison code guarantees that the left-most key on any
 1979          * level of the tree is never used, so it doesn't need to be filled in.
 1980          */
 1981         BT_MARK_DIRTY(smp, ip);
 1982         /*
 1983          * acquire a transaction lock on the root page (in-memory inode)
 1984          */
 1985         tlck = txLock(tid, ip, smp, tlckDTREE | tlckNEW | tlckBTROOT);
 1986         dtlck = (struct dt_lock *) & tlck->lock;
 1987 
 1988         /* linelock root */
 1989         ASSERT(dtlck->index == 0);
 1990         lv = & dtlck->lv[0];
 1991         lv->offset = 0;
 1992         lv->length = DTROOTMAXSLOT;
 1993         dtlck->index++;
 1994 
 1995         /* update page header of root */
 1996         if (sp->header.flag & BT_LEAF) {
 1997                 sp->header.flag &= ~BT_LEAF;
 1998                 sp->header.flag |= BT_INTERNAL;
 1999         }
 2000 
 2001         /* init the first entry */
 2002         s = (struct idtentry *) & sp->slot[DTENTRYSTART];
 2003         ppxd = (pxd_t *) s;
 2004         *ppxd = *pxd;
 2005         s->next = -1;
 2006         s->namlen = 0;
 2007 
 2008         stbl = sp->header.stbl;
 2009         stbl[0] = DTENTRYSTART;
 2010         sp->header.nextindex = 1;
 2011 
 2012         /* init freelist */
 2013         fsi = DTENTRYSTART + 1;
 2014         f = &sp->slot[fsi];
 2015 
 2016         /* init free region of remaining area */
 2017         for (fsi++; fsi < DTROOTMAXSLOT; f++, fsi++)
 2018                 f->next = fsi;
 2019         f->next = -1;
 2020 
 2021         sp->header.freelist = DTENTRYSTART + 1;
 2022         sp->header.freecnt = DTROOTMAXSLOT - (DTENTRYSTART + 1);
 2023 
 2024         *rmpp = rmp;
 2025 
 2026         ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
 2027         return 0;
 2028 }
 2029 
 2030 
 2031 /*
 2032  *      dtDelete()
 2033  *
 2034  * function: delete the entry(s) referenced by a key.
 2035  *
 2036  * parameter:
 2037  *
 2038  * return:
 2039  */
 2040 int dtDelete(tid_t tid,
 2041          struct inode *ip, struct component_name * key, ino_t * ino, int flag)
 2042 {
 2043         int rc = 0;
 2044         s64 bn;
 2045         struct metapage *mp, *imp;
 2046         dtpage_t *p;
 2047         int index;
 2048         struct btstack btstack;
 2049         struct dt_lock *dtlck;
 2050         struct tlock *tlck;
 2051         struct lv *lv;
 2052         int i;
 2053         struct ldtentry *ldtentry;
 2054         u8 *stbl;
 2055         u32 table_index, next_index;
 2056         struct metapage *nmp;
 2057         dtpage_t *np;
 2058 
 2059         /*
 2060          *      search for the entry to delete:
 2061          *
 2062          * dtSearch() returns (leaf page pinned, index at which to delete).
 2063          */
 2064         if ((rc = dtSearch(ip, key, ino, &btstack, flag)))
 2065                 return rc;
 2066 
 2067         /* retrieve search result */
 2068         DT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
 2069 
 2070         /*
 2071          * We need to find put the index of the next entry into the
 2072          * directory index table in order to resume a readdir from this
 2073          * entry.
 2074          */
 2075         if (DO_INDEX(ip)) {
 2076                 stbl = DT_GETSTBL(p);
 2077                 ldtentry = (struct ldtentry *) & p->slot[stbl[index]];
 2078                 table_index = le32_to_cpu(ldtentry->index);
 2079                 if (index == (p->header.nextindex - 1)) {
 2080                         /*
 2081                          * Last entry in this leaf page
 2082                          */
 2083                         if ((p->header.flag & BT_ROOT)
 2084                             || (p->header.next == 0))
 2085                                 next_index = -1;
 2086                         else {
 2087                                 /* Read next leaf page */
 2088                                 DT_GETPAGE(ip, le64_to_cpu(p->header.next),
 2089                                            nmp, PSIZE, np, rc);
 2090                                 if (rc)
 2091                                         next_index = -1;
 2092                                 else {
 2093                                         stbl = DT_GETSTBL(np);
 2094                                         ldtentry =
 2095                                             (struct ldtentry *) & np->
 2096                                             slot[stbl[0]];
 2097                                         next_index =
 2098                                             le32_to_cpu(ldtentry->index);
 2099                                         DT_PUTPAGE(nmp);
 2100                                 }
 2101                         }
 2102                 } else {
 2103                         ldtentry =
 2104                             (struct ldtentry *) & p->slot[stbl[index + 1]];
 2105                         next_index = le32_to_cpu(ldtentry->index);
 2106                 }
 2107                 free_index(tid, ip, table_index, next_index);
 2108         }
 2109         /*
 2110          * the leaf page becomes empty, delete the page
 2111          */
 2112         if (p->header.nextindex == 1) {
 2113                 /* delete empty page */
 2114                 rc = dtDeleteUp(tid, ip, mp, p, &btstack);
 2115         }
 2116         /*
 2117          * the leaf page has other entries remaining:
 2118          *
 2119          * delete the entry from the leaf page.
 2120          */
 2121         else {
 2122                 BT_MARK_DIRTY(mp, ip);
 2123                 /*
 2124                  * acquire a transaction lock on the leaf page
 2125                  */
 2126                 tlck = txLock(tid, ip, mp, tlckDTREE | tlckENTRY);
 2127                 dtlck = (struct dt_lock *) & tlck->lock;
 2128 
 2129                 /*
 2130                  * Do not assume that dtlck->index will be zero.  During a
 2131                  * rename within a directory, this transaction may have
 2132                  * modified this page already when adding the new entry.
 2133                  */
 2134 
 2135                 /* linelock header */
 2136                 if (dtlck->index >= dtlck->maxcnt)
 2137                         dtlck = (struct dt_lock *) txLinelock(dtlck);
 2138                 lv = & dtlck->lv[dtlck->index];
 2139                 lv->offset = 0;
 2140                 lv->length = 1;
 2141                 dtlck->index++;
 2142 
 2143                 /* linelock stbl of non-root leaf page */
 2144                 if (!(p->header.flag & BT_ROOT)) {
 2145                         if (dtlck->index >= dtlck->maxcnt)
 2146                                 dtlck = (struct dt_lock *) txLinelock(dtlck);
 2147                         lv = & dtlck->lv[dtlck->index];
 2148                         i = index >> L2DTSLOTSIZE;
 2149                         lv->offset = p->header.stblindex + i;
 2150                         lv->length =
 2151                             ((p->header.nextindex - 1) >> L2DTSLOTSIZE) -
 2152                             i + 1;
 2153                         dtlck->index++;
 2154                 }
 2155 
 2156                 /* free the leaf entry */
 2157                 dtDeleteEntry(p, index, &dtlck);
 2158 
 2159                 /*
 2160                  * Update directory index table for entries moved in stbl
 2161                  */
 2162                 if (DO_INDEX(ip) && index < p->header.nextindex) {
 2163                         s64 lblock;
 2164 
 2165                         imp = 0;
 2166                         stbl = DT_GETSTBL(p);
 2167                         for (i = index; i < p->header.nextindex; i++) {
 2168                                 ldtentry =
 2169                                     (struct ldtentry *) & p->slot[stbl[i]];
 2170                                 modify_index(tid, ip,
 2171                                              le32_to_cpu(ldtentry->index),
 2172                                              bn, i, &imp, &lblock);
 2173                         }
 2174                         if (imp)
 2175                                 release_metapage(imp);
 2176                 }
 2177 
 2178                 DT_PUTPAGE(mp);
 2179         }
 2180 
 2181         return rc;
 2182 }
 2183 
 2184 
 2185 /*
 2186  *      dtDeleteUp()
 2187  *
 2188  * function:
 2189  *      free empty pages as propagating deletion up the tree
 2190  *
 2191  * parameter:
 2192  *
 2193  * return:
 2194  */
 2195 static int dtDeleteUp(tid_t tid, struct inode *ip,
 2196            struct metapage * fmp, dtpage_t * fp, struct btstack * btstack)
 2197 {
 2198         int rc = 0;
 2199         struct metapage *mp;
 2200         dtpage_t *p;
 2201         int index, nextindex;
 2202         int xlen;
 2203         struct btframe *parent;
 2204         struct dt_lock *dtlck;
 2205         struct tlock *tlck;
 2206         struct lv *lv;
 2207         struct pxd_lock *pxdlock;
 2208         int i;
 2209 
 2210         /*
 2211          *      keep the root leaf page which has become empty
 2212          */
 2213         if (BT_IS_ROOT(fmp)) {
 2214                 /*
 2215                  * reset the root
 2216                  *
 2217                  * dtInitRoot() acquires txlock on the root
 2218                  */
 2219                 dtInitRoot(tid, ip, PARENT(ip));
 2220 
 2221                 DT_PUTPAGE(fmp);
 2222 
 2223                 return 0;
 2224         }
 2225 
 2226         /*
 2227          *      free the non-root leaf page
 2228          */
 2229         /*
 2230          * acquire a transaction lock on the page
 2231          *
 2232          * write FREEXTENT|NOREDOPAGE log record
 2233          * N.B. linelock is overlaid as freed extent descriptor, and
 2234          * the buffer page is freed;
 2235          */
 2236         tlck = txMaplock(tid, ip, tlckDTREE | tlckFREE);
 2237         pxdlock = (struct pxd_lock *) & tlck->lock;
 2238         pxdlock->flag = mlckFREEPXD;
 2239         pxdlock->pxd = fp->header.self;
 2240         pxdlock->index = 1;
 2241 
 2242         /* update sibling pointers */
 2243         if ((rc = dtRelink(tid, ip, fp)))
 2244                 return rc;
 2245 
 2246         xlen = lengthPXD(&fp->header.self);
 2247         ip->i_blocks -= LBLK2PBLK(ip->i_sb, xlen);
 2248 
 2249         /* free/invalidate its buffer page */
 2250         discard_metapage(fmp);
 2251 
 2252         /*
 2253          *      propagate page deletion up the directory tree
 2254          *
 2255          * If the delete from the parent page makes it empty,
 2256          * continue all the way up the tree.
 2257          * stop if the root page is reached (which is never deleted) or
 2258          * if the entry deletion does not empty the page.
 2259          */
 2260         while ((parent = BT_POP(btstack)) != NULL) {
 2261                 /* pin the parent page <sp> */
 2262                 DT_GETPAGE(ip, parent->bn, mp, PSIZE, p, rc);
 2263                 if (rc)
 2264                         return rc;
 2265 
 2266                 /*
 2267                  * free the extent of the child page deleted
 2268                  */
 2269                 index = parent->index;
 2270 
 2271                 /*
 2272                  * delete the entry for the child page from parent
 2273                  */
 2274                 nextindex = p->header.nextindex;
 2275 
 2276                 /*
 2277                  * the parent has the single entry being deleted:
 2278                  *
 2279                  * free the parent page which has become empty.
 2280                  */
 2281                 if (nextindex == 1) {
 2282                         /*
 2283                          * keep the root internal page which has become empty
 2284                          */
 2285                         if (p->header.flag & BT_ROOT) {
 2286                                 /*
 2287                                  * reset the root
 2288                                  *
 2289                                  * dtInitRoot() acquires txlock on the root
 2290                                  */
 2291                                 dtInitRoot(tid, ip, PARENT(ip));
 2292 
 2293                                 DT_PUTPAGE(mp);
 2294 
 2295                                 return 0;
 2296                         }
 2297                         /*
 2298                          * free the parent page
 2299                          */
 2300                         else {
 2301                                 /*
 2302                                  * acquire a transaction lock on the page
 2303                                  *
 2304                                  * write FREEXTENT|NOREDOPAGE log record
 2305                                  */
 2306                                 tlck =
 2307                                     txMaplock(tid, ip,
 2308                                               tlckDTREE | tlckFREE);
 2309                                 pxdlock = (struct pxd_lock *) & tlck->lock;
 2310                                 pxdlock->flag = mlckFREEPXD;
 2311                                 pxdlock->pxd = p->header.self;
 2312                                 pxdlock->index = 1;
 2313 
 2314                                 /* update sibling pointers */
 2315                                 if ((rc = dtRelink(tid, ip, p)))
 2316                                         return rc;
 2317 
 2318                                 xlen = lengthPXD(&p->header.self);
 2319                                 ip->i_blocks -= LBLK2PBLK(ip->i_sb, xlen);
 2320 
 2321                                 /* free/invalidate its buffer page */
 2322                                 discard_metapage(mp);
 2323 
 2324                                 /* propagate up */
 2325                                 continue;
 2326                         }
 2327                 }
 2328 
 2329                 /*
 2330                  * the parent has other entries remaining:
 2331                  *
 2332                  * delete the router entry from the parent page.
 2333                  */
 2334                 BT_MARK_DIRTY(mp, ip);
 2335                 /*
 2336                  * acquire a transaction lock on the page
 2337                  *
 2338                  * action: router entry deletion
 2339                  */
 2340                 tlck = txLock(tid, ip, mp, tlckDTREE | tlckENTRY);
 2341                 dtlck = (struct dt_lock *) & tlck->lock;
 2342 
 2343                 /* linelock header */
 2344                 if (dtlck->index >= dtlck->maxcnt)
 2345                         dtlck = (struct dt_lock *) txLinelock(dtlck);
 2346                 lv = & dtlck->lv[dtlck->index];
 2347                 lv->offset = 0;
 2348                 lv->length = 1;
 2349                 dtlck->index++;
 2350 
 2351                 /* linelock stbl of non-root leaf page */
 2352                 if (!(p->header.flag & BT_ROOT)) {
 2353                         if (dtlck->index < dtlck->maxcnt)
 2354                                 lv++;
 2355                         else {
 2356                                 dtlck = (struct dt_lock *) txLinelock(dtlck);
 2357                                 lv = & dtlck->lv[0];
 2358                         }
 2359                         i = index >> L2DTSLOTSIZE;
 2360                         lv->offset = p->header.stblindex + i;
 2361                         lv->length =
 2362                             ((p->header.nextindex - 1) >> L2DTSLOTSIZE) -
 2363                             i + 1;
 2364                         dtlck->index++;
 2365                 }
 2366 
 2367                 /* free the router entry */
 2368                 dtDeleteEntry(p, index, &dtlck);
 2369 
 2370                 /* reset key of new leftmost entry of level (for consistency) */
 2371                 if (index == 0 &&
 2372                     ((p->header.flag & BT_ROOT) || p->header.prev == 0))
 2373                         dtTruncateEntry(p, 0, &dtlck);
 2374 
 2375                 /* unpin the parent page */
 2376                 DT_PUTPAGE(mp);
 2377 
 2378                 /* exit propagation up */
 2379                 break;
 2380         }
 2381 
 2382         return 0;
 2383 }
 2384 
 2385 
 2386 /*
 2387  * NAME:        dtRelocate()
 2388  *
 2389  * FUNCTION:    relocate dtpage (internal or leaf) of directory;
 2390  *              This function is mainly used by defragfs utility.
 2391  */
 2392 int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
 2393                s64 nxaddr)
 2394 {
 2395         int rc = 0;
 2396         struct metapage *mp, *pmp, *lmp, *rmp;
 2397         dtpage_t *p, *pp, *rp = 0, *lp= 0;
 2398         s64 bn;
 2399         int index;
 2400         struct btstack btstack;
 2401         pxd_t *pxd;
 2402         s64 oxaddr, nextbn, prevbn;
 2403         int xlen, xsize;
 2404         struct tlock *tlck;
 2405         struct dt_lock *dtlck;
 2406         struct pxd_lock *pxdlock;
 2407         s8 *stbl;
 2408         struct lv *lv;
 2409 
 2410         oxaddr = addressPXD(opxd);
 2411         xlen = lengthPXD(opxd);
 2412 
 2413         jfs_info("dtRelocate: lmxaddr:%Ld xaddr:%Ld:%Ld xlen:%d",
 2414                    (long long)lmxaddr, (long long)oxaddr, (long long)nxaddr,
 2415                    xlen);
 2416 
 2417         /*
 2418          *      1. get the internal parent dtpage covering
 2419          *      router entry for the tartget page to be relocated;
 2420          */
 2421         rc = dtSearchNode(ip, lmxaddr, opxd, &btstack);
 2422         if (rc)
 2423                 return rc;
 2424 
 2425         /* retrieve search result */
 2426         DT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
 2427         jfs_info("dtRelocate: parent router entry validated.");
 2428 
 2429         /*
 2430          *      2. relocate the target dtpage
 2431          */
 2432         /* read in the target page from src extent */
 2433         DT_GETPAGE(ip, oxaddr, mp, PSIZE, p, rc);
 2434         if (rc) {
 2435                 /* release the pinned parent page */
 2436                 DT_PUTPAGE(pmp);
 2437                 return rc;
 2438         }
 2439 
 2440         /*
 2441          * read in sibling pages if any to update sibling pointers;
 2442          */
 2443         rmp = NULL;
 2444         if (p->header.next) {
 2445                 nextbn = le64_to_cpu(p->header.next);
 2446                 DT_GETPAGE(ip, nextbn, rmp, PSIZE, rp, rc);
 2447                 if (rc) {
 2448                         DT_PUTPAGE(mp);
 2449                         DT_PUTPAGE(pmp);
 2450                         return (rc);
 2451                 }
 2452         }
 2453 
 2454         lmp = NULL;
 2455         if (p->header.prev) {
 2456                 prevbn = le64_to_cpu(p->header.prev);
 2457                 DT_GETPAGE(ip, prevbn, lmp, PSIZE, lp, rc);
 2458                 if (rc) {
 2459                         DT_PUTPAGE(mp);
 2460                         DT_PUTPAGE(pmp);
 2461                         if (rmp)
 2462                                 DT_PUTPAGE(rmp);
 2463                         return (rc);
 2464                 }
 2465         }
 2466 
 2467         /* at this point, all xtpages to be updated are in memory */
 2468 
 2469         /*
 2470          * update sibling pointers of sibling dtpages if any;
 2471          */
 2472         if (lmp) {
 2473                 tlck = txLock(tid, ip, lmp, tlckDTREE | tlckRELINK);
 2474                 dtlck = (struct dt_lock *) & tlck->lock;
 2475                 /* linelock header */
 2476                 ASSERT(dtlck->index == 0);
 2477                 lv = & dtlck->lv[0];
 2478                 lv->offset = 0;
 2479                 lv->length = 1;
 2480                 dtlck->index++;
 2481 
 2482                 lp->header.next = cpu_to_le64(nxaddr);
 2483                 DT_PUTPAGE(lmp);
 2484         }
 2485 
 2486         if (rmp) {
 2487                 tlck = txLock(tid, ip, rmp, tlckDTREE | tlckRELINK);
 2488                 dtlck = (struct dt_lock *) & tlck->lock;
 2489                 /* linelock header */
 2490                 ASSERT(dtlck->index == 0);
 2491                 lv = & dtlck->lv[0];
 2492                 lv->offset = 0;
 2493                 lv->length = 1;
 2494                 dtlck->index++;
 2495 
 2496                 rp->header.prev = cpu_to_le64(nxaddr);
 2497                 DT_PUTPAGE(rmp);
 2498         }
 2499 
 2500         /*
 2501          * update the target dtpage to be relocated
 2502          *
 2503          * write LOG_REDOPAGE of LOG_NEW type for dst page
 2504          * for the whole target page (logredo() will apply
 2505          * after image and update bmap for allocation of the
 2506          * dst extent), and update bmap for allocation of
 2507          * the dst extent;
 2508          */
 2509         tlck = txLock(tid, ip, mp, tlckDTREE | tlckNEW);
 2510         dtlck = (struct dt_lock *) & tlck->lock;
 2511         /* linelock header */
 2512         ASSERT(dtlck->index == 0);
 2513         lv = & dtlck->lv[0];
 2514 
 2515         /* update the self address in the dtpage header */
 2516         pxd = &p->header.self;
 2517         PXDaddress(pxd, nxaddr);
 2518 
 2519         /* the dst page is the same as the src page, i.e.,
 2520          * linelock for afterimage of the whole page;
 2521          */
 2522         lv->offset = 0;
 2523         lv->length = p->header.maxslot;
 2524         dtlck->index++;
 2525 
 2526         /* update the buffer extent descriptor of the dtpage */
 2527         xsize = xlen << JFS_SBI(ip->i_sb)->l2bsize;
 2528 #ifdef _STILL_TO_PORT
 2529         bmSetXD(mp, nxaddr, xsize);
 2530 #endif /* _STILL_TO_PORT */
 2531         /* unpin the relocated page */
 2532         DT_PUTPAGE(mp);
 2533         jfs_info("dtRelocate: target dtpage relocated.");
 2534 
 2535         /* the moved extent is dtpage, then a LOG_NOREDOPAGE log rec
 2536          * needs to be written (in logredo(), the LOG_NOREDOPAGE log rec
 2537          * will also force a bmap update ).
 2538          */
 2539 
 2540         /*
 2541          *      3. acquire maplock for the source extent to be freed;
 2542          */
 2543         /* for dtpage relocation, write a LOG_NOREDOPAGE record
 2544          * for the source dtpage (logredo() will init NoRedoPage
 2545          * filter and will also update bmap for free of the source
 2546          * dtpage), and upadte bmap for free of the source dtpage;
 2547          */
 2548         tlck = txMaplock(tid, ip, tlckDTREE | tlckFREE);
 2549         pxdlock = (struct pxd_lock *) & tlck->lock;
 2550         pxdlock->flag = mlckFREEPXD;
 2551         PXDaddress(&pxdlock->pxd, oxaddr);
 2552         PXDlength(&pxdlock->pxd, xlen);
 2553         pxdlock->index = 1;
 2554 
 2555         /*
 2556          *      4. update the parent router entry for relocation;
 2557          *
 2558          * acquire tlck for the parent entry covering the target dtpage;
 2559          * write LOG_REDOPAGE to apply after image only;
 2560          */
 2561         jfs_info("dtRelocate: update parent router entry.");
 2562         tlck = txLock(tid, ip, pmp, tlckDTREE | tlckENTRY);
 2563         dtlck = (struct dt_lock *) & tlck->lock;
 2564         lv = & dtlck->lv[dtlck->index];
 2565 
 2566         /* update the PXD with the new address */
 2567         stbl = DT_GETSTBL(pp);
 2568         pxd = (pxd_t *) & pp->slot[stbl[index]];
 2569         PXDaddress(pxd, nxaddr);
 2570         lv->offset = stbl[index];
 2571         lv->length = 1;
 2572         dtlck->index++;
 2573 
 2574         /* unpin the parent dtpage */
 2575         DT_PUTPAGE(pmp);
 2576 
 2577         return rc;
 2578 }
 2579 
 2580 
 2581 /*
 2582  * NAME:        dtSearchNode()
 2583  *
 2584  * FUNCTION:    Search for an dtpage containing a specified address
 2585  *              This function is mainly used by defragfs utility.
 2586  *
 2587  * NOTE:        Search result on stack, the found page is pinned at exit.
 2588  *              The result page must be an internal dtpage.
 2589  *              lmxaddr give the address of the left most page of the
 2590  *              dtree level, in which the required dtpage resides.
 2591  */
 2592 static int dtSearchNode(struct inode *ip, s64 lmxaddr, pxd_t * kpxd,
 2593                         struct btstack * btstack)
 2594 {
 2595         int rc = 0;
 2596         s64 bn;
 2597         struct metapage *mp;
 2598         dtpage_t *p;
 2599         int psize = 288;        /* initial in-line directory */
 2600         s8 *stbl;
 2601         int i;
 2602         pxd_t *pxd;
 2603         struct btframe *btsp;
 2604 
 2605         BT_CLR(btstack);        /* reset stack */
 2606 
 2607         /*
 2608          *      descend tree to the level with specified leftmost page
 2609          *
 2610          *  by convention, root bn = 0.
 2611          */
 2612         for (bn = 0;;) {
 2613                 /* get/pin the page to search */
 2614                 DT_GETPAGE(ip, bn, mp, psize, p, rc);
 2615                 if (rc)
 2616                         return rc;
 2617 
 2618                 /* does the xaddr of leftmost page of the levevl
 2619                  * matches levevl search key ?
 2620                  */
 2621                 if (p->header.flag & BT_ROOT) {
 2622                         if (lmxaddr == 0)
 2623                                 break;
 2624                 } else if (addressPXD(&p->header.self) == lmxaddr)
 2625                         break;
 2626 
 2627                 /*
 2628                  * descend down to leftmost child page
 2629                  */
 2630                 if (p->header.flag & BT_LEAF)
 2631                         return ESTALE;
 2632 
 2633                 /* get the leftmost entry */
 2634                 stbl = DT_GETSTBL(p);
 2635                 pxd = (pxd_t *) & p->slot[stbl[0]];
 2636 
 2637                 /* get the child page block address */
 2638                 bn = addressPXD(pxd);
 2639                 psize = lengthPXD(pxd) << JFS_SBI(ip->i_sb)->l2bsize;
 2640                 /* unpin the parent page */
 2641                 DT_PUTPAGE(mp);
 2642         }
 2643 
 2644         /*
 2645          *      search each page at the current levevl
 2646          */
 2647       loop:
 2648         stbl = DT_GETSTBL(p);
 2649         for (i = 0; i < p->header.nextindex; i++) {
 2650                 pxd = (pxd_t *) & p->slot[stbl[i]];
 2651 
 2652                 /* found the specified router entry */
 2653                 if (addressPXD(pxd) == addressPXD(kpxd) &&
 2654                     lengthPXD(pxd) == lengthPXD(kpxd)) {
 2655                         btsp = btstack->top;
 2656                         btsp->bn = bn;
 2657                         btsp->index = i;
 2658                         btsp->mp = mp;
 2659 
 2660                         return 0;
 2661                 }
 2662         }
 2663 
 2664         /* get the right sibling page if any */
 2665         if (p->header.next)
 2666                 bn = le64_to_cpu(p->header.next);
 2667         else {
 2668                 DT_PUTPAGE(mp);
 2669                 return ESTALE;
 2670         }
 2671 
 2672         /* unpin current page */
 2673         DT_PUTPAGE(mp);
 2674 
 2675         /* get the right sibling page */
 2676         DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
 2677         if (rc)
 2678                 return rc;
 2679 
 2680         goto loop;
 2681 }
 2682 
 2683 
 2684 /*
 2685  *      dtRelink()
 2686  *
 2687  * function:
 2688  *      link around a freed page.
 2689  *
 2690  * parameter:
 2691  *      fp:     page to be freed
 2692  *
 2693  * return:
 2694  */
 2695 static int dtRelink(tid_t tid, struct inode *ip, dtpage_t * p)
 2696 {
 2697         int rc;
 2698         struct metapage *mp;
 2699         s64 nextbn, prevbn;
 2700         struct tlock *tlck;
 2701         struct dt_lock *dtlck;
 2702         struct lv *lv;
 2703 
 2704         nextbn = le64_to_cpu(p->header.next);
 2705         prevbn = le64_to_cpu(p->header.prev);
 2706 
 2707         /* update prev pointer of the next page */
 2708         if (nextbn != 0) {
 2709                 DT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);
 2710                 if (rc)
 2711                         return rc;
 2712 
 2713                 BT_MARK_DIRTY(mp, ip);
 2714                 /*
 2715                  * acquire a transaction lock on the next page
 2716                  *
 2717                  * action: update prev pointer;
 2718                  */
 2719                 tlck = txLock(tid, ip, mp, tlckDTREE | tlckRELINK);
 2720                 jfs_info("dtRelink nextbn: tlck = 0x%p, ip = 0x%p, mp=0x%p",
 2721                         tlck, ip, mp);
 2722                 dtlck = (struct dt_lock *) & tlck->lock;
 2723 
 2724                 /* linelock header */
 2725                 if (dtlck->index >= dtlck->maxcnt)
 2726                         dtlck = (struct dt_lock *) txLinelock(dtlck);
 2727                 lv = & dtlck->lv[dtlck->index];
 2728                 lv->offset = 0;
 2729                 lv->length = 1;
 2730                 dtlck->index++;
 2731 
 2732                 p->header.prev = cpu_to_le64(prevbn);
 2733                 DT_PUTPAGE(mp);
 2734         }
 2735 
 2736         /* update next pointer of the previous page */
 2737         if (prevbn != 0) {
 2738                 DT_GETPAGE(ip, prevbn, mp, PSIZE, p, rc);
 2739                 if (rc)
 2740                         return rc;
 2741 
 2742                 BT_MARK_DIRTY(mp, ip);
 2743                 /*
 2744                  * acquire a transaction lock on the prev page
 2745                  *
 2746                  * action: update next pointer;
 2747                  */
 2748                 tlck = txLock(tid, ip, mp, tlckDTREE | tlckRELINK);
 2749                 jfs_info("dtRelink prevbn: tlck = 0x%p, ip = 0x%p, mp=0x%p",
 2750                         tlck, ip, mp);
 2751                 dtlck = (struct dt_lock *) & tlck->lock;
 2752 
 2753                 /* linelock header */
 2754                 if (dtlck->index >= dtlck->maxcnt)
 2755                         dtlck = (struct dt_lock *) txLinelock(dtlck);
 2756                 lv = & dtlck->lv[dtlck->index];
 2757                 lv->offset = 0;
 2758                 lv->length = 1;
 2759                 dtlck->index++;
 2760 
 2761                 p->header.next = cpu_to_le64(nextbn);
 2762                 DT_PUTPAGE(mp);
 2763         }
 2764 
 2765         return 0;
 2766 }
 2767 
 2768 
 2769 /*
 2770  *      dtInitRoot()
 2771  *
 2772  * initialize directory root (inline in inode)
 2773  */
 2774 void dtInitRoot(tid_t tid, struct inode *ip, u32 idotdot)
 2775 {
 2776         struct jfs_inode_info *jfs_ip = JFS_IP(ip);
 2777         dtroot_t *p;
 2778         int fsi;
 2779         struct dtslot *f;
 2780         struct tlock *tlck;
 2781         struct dt_lock *dtlck;
 2782         struct lv *lv;
 2783         u16 xflag_save;
 2784 
 2785         /*
 2786          * If this was previously an non-empty directory, we need to remove
 2787          * the old directory table.
 2788          */
 2789         if (DO_INDEX(ip)) {
 2790                 if (jfs_ip->next_index > (MAX_INLINE_DIRTABLE_ENTRY + 1)) {
 2791                         struct tblock *tblk = tid_to_tblock(tid);
 2792                         /*
 2793                          * We're playing games with the tid's xflag.  If
 2794                          * we're removing a regular file, the file's xtree
 2795                          * is committed with COMMIT_PMAP, but we always
 2796                          * commit the directories xtree with COMMIT_PWMAP.
 2797                          */
 2798                         xflag_save = tblk->xflag;
 2799                         tblk->xflag = 0;
 2800                         /*
 2801                          * xtTruncate isn't guaranteed to fully truncate
 2802                          * the xtree.  The caller needs to check i_size
 2803                          * after committing the transaction to see if
 2804                          * additional truncation is needed.  The
 2805                          * COMMIT_Stale flag tells caller that we
 2806                          * initiated the truncation.
 2807                          */
 2808                         xtTruncate(tid, ip, 0, COMMIT_PWMAP);
 2809                         set_cflag(COMMIT_Stale, ip);
 2810 
 2811                         tblk->xflag = xflag_save;
 2812                 } else
 2813                         ip->i_size = 1;
 2814 
 2815                 jfs_ip->next_index = 2;
 2816         } else
 2817                 ip->i_size = IDATASIZE;
 2818 
 2819         /*
 2820          * acquire a transaction lock on the root
 2821          *
 2822          * action: directory initialization;
 2823          */
 2824         tlck = txLock(tid, ip, (struct metapage *) & jfs_ip->bxflag,
 2825                       tlckDTREE | tlckENTRY | tlckBTROOT);
 2826         dtlck = (struct dt_lock *) & tlck->lock;
 2827 
 2828         /* linelock root */
 2829         ASSERT(dtlck->index == 0);
 2830         lv = & dtlck->lv[0];
 2831         lv->offset = 0;
 2832         lv->length = DTROOTMAXSLOT;
 2833         dtlck->index++;
 2834 
 2835         p = &jfs_ip->i_dtroot;
 2836 
 2837         p->header.flag = DXD_INDEX | BT_ROOT | BT_LEAF;
 2838 
 2839         p->header.nextindex = 0;
 2840 
 2841         /* init freelist */
 2842         fsi = 1;
 2843         f = &p->slot[fsi];
 2844 
 2845         /* init data area of root */
 2846         for (fsi++; fsi < DTROOTMAXSLOT; f++, fsi++)
 2847                 f->next = fsi;
 2848         f->next = -1;
 2849 
 2850         p->header.freelist = 1;
 2851         p->header.freecnt = 8;
 2852 
 2853         /* init '..' entry */
 2854         p->header.idotdot = cpu_to_le32(idotdot);
 2855 
 2856 #if 0
 2857         ip->i_blocks = LBLK2PBLK(ip->i_sb,
 2858                                  ((jfs_ip->ea.flag & DXD_EXTENT) ?
 2859                                   lengthDXD(&jfs_ip->ea) : 0) +
 2860                                  ((jfs_ip->acl.flag & DXD_EXTENT) ?
 2861                                   lengthDXD(&jfs_ip->acl) : 0));
 2862 #endif
 2863 
 2864         return;
 2865 }
 2866 
 2867 /*
 2868  *      add_missing_indices()
 2869  *
 2870  * function: Fix dtree page in which one or more entries has an invalid index.
 2871  *           fsck.jfs should really fix this, but it currently does not.
 2872  *           Called from jfs_readdir when bad index is detected.
 2873  */
 2874 static void add_missing_indices(struct inode *inode, s64 bn)
 2875 {
 2876         struct ldtentry *d;
 2877         struct dt_lock *dtlck;
 2878         int i;
 2879         uint index;
 2880         struct lv *lv;
 2881         struct metapage *mp;
 2882         dtpage_t *p;
 2883         int rc;
 2884         s8 *stbl;
 2885         tid_t tid;
 2886         struct tlock *tlck;
 2887 
 2888         tid = txBegin(inode->i_sb, 0);
 2889 
 2890         DT_GETPAGE(inode, bn, mp, PSIZE, p, rc);
 2891 
 2892         if (rc) {
 2893                 printk(KERN_ERR "DT_GETPAGE failed!\n");
 2894                 goto end;
 2895         }
 2896         BT_MARK_DIRTY(mp, inode);
 2897 
 2898         ASSERT(p->header.flag & BT_LEAF);
 2899 
 2900         tlck = txLock(tid, inode, mp, tlckDTREE | tlckENTRY);
 2901         dtlck = (struct dt_lock *) &tlck->lock;
 2902 
 2903         stbl = DT_GETSTBL(p);
 2904         for (i = 0; i < p->header.nextindex; i++) {
 2905                 d = (struct ldtentry *) &p->slot[stbl[i]];
 2906                 index = le32_to_cpu(d->index);
 2907                 if ((index < 2) || (index >= JFS_IP(inode)->next_index)) {
 2908                         d->index = cpu_to_le32(add_index(tid, inode, bn, i));
 2909                         if (dtlck->index >= dtlck->maxcnt)
 2910                                 dtlck = (struct dt_lock *) txLinelock(dtlck);
 2911                         lv = &dtlck->lv[dtlck->index];
 2912                         lv->offset = stbl[i];
 2913                         lv->length = 1;
 2914                         dtlck->index++;
 2915                 }
 2916         }
 2917 
 2918         DT_PUTPAGE(mp);
 2919         (void) txCommit(tid, 1, &inode, 0);
 2920 end:
 2921         txEnd(tid);
 2922 }
 2923 
 2924 /*
 2925  * Buffer to hold directory entry info while traversing a dtree page
 2926  * before being fed to the filldir function
 2927  */
 2928 struct jfs_dirent {
 2929         loff_t position;
 2930         int ino;
 2931         u16 name_len;
 2932         char name[0];
 2933 };
 2934 
 2935 /*
 2936  * function to determine next variable-sized jfs_dirent in buffer
 2937  */
 2938 inline struct jfs_dirent *next_jfs_dirent(struct jfs_dirent *dirent)
 2939 {
 2940         return (struct jfs_dirent *)
 2941                 ((char *)dirent +
 2942                  ((sizeof (struct jfs_dirent) + dirent->name_len + 1 +
 2943                    sizeof (loff_t) - 1) &
 2944                   ~(sizeof (loff_t) - 1)));
 2945 }
 2946 
 2947 /*
 2948  *      jfs_readdir()
 2949  *
 2950  * function: read directory entries sequentially
 2951  *      from the specified entry offset
 2952  *
 2953  * parameter:
 2954  *
 2955  * return: offset = (pn, index) of start entry
 2956  *      of next jfs_readdir()/dtRead()
 2957  */
 2958 int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 2959 {
 2960         struct inode *ip = filp->f_dentry->d_inode;
 2961         struct nls_table *codepage = JFS_SBI(ip->i_sb)->nls_tab;
 2962         int rc = 0;
 2963         loff_t dtpos;   /* legacy OS/2 style position */
 2964         struct dtoffset {
 2965                 s16 pn;
 2966                 s16 index;
 2967                 s32 unused;
 2968         } *dtoffset = (struct dtoffset *) &dtpos;
 2969         s64 bn;
 2970         struct metapage *mp;
 2971         dtpage_t *p;
 2972         int index;
 2973         s8 *stbl;
 2974         struct btstack btstack;
 2975         int i, next;
 2976         struct ldtentry *d;
 2977         struct dtslot *t;
 2978         int d_namleft, len, outlen;
 2979         unsigned long dirent_buf;
 2980         char *name_ptr;
 2981         u32 dir_index;
 2982         int do_index = 0;
 2983         uint loop_count = 0;
 2984         struct jfs_dirent *jfs_dirent;
 2985         int jfs_dirents;
 2986         int overflow, fix_page, page_fixed = 0;
 2987         static int unique_pos = 2;      /* If we can't fix broken index */
 2988 
 2989         if (filp->f_pos == DIREND)
 2990                 return 0;
 2991 
 2992         if (DO_INDEX(ip)) {
 2993                 /*
 2994                  * persistent index is stored in directory entries.
 2995                  * Special cases:        0 = .
 2996                  *                       1 = ..
 2997                  *                      -1 = End of directory
 2998                  */
 2999                 do_index = 1;
 3000 
 3001                 dir_index = (u32) filp->f_pos;
 3002 
 3003                 if (dir_index > 1) {
 3004                         struct dir_table_slot dirtab_slot;
 3005 
 3006                         if (dtEmpty(ip) ||
 3007                             (dir_index >= JFS_IP(ip)->next_index)) {
 3008                                 /* Stale position.  Directory has shrunk */
 3009                                 filp->f_pos = DIREND;
 3010                                 return 0;
 3011                         }
 3012                       repeat:
 3013                         rc = read_index(ip, dir_index, &dirtab_slot);
 3014                         if (rc) {
 3015                                 filp->f_pos = DIREND;
 3016                                 return rc;
 3017                         }
 3018                         if (dirtab_slot.flag == DIR_INDEX_FREE) {
 3019                                 if (loop_count++ > JFS_IP(ip)->next_index) {
 3020                                         jfs_err("jfs_readdir detected "
 3021                                                    "infinite loop!");
 3022                                         filp->f_pos = DIREND;
 3023                                         return 0;
 3024                                 }
 3025                                 dir_index = le32_to_cpu(dirtab_slot.addr2);
 3026                                 if (dir_index == -1) {
 3027                                         filp->f_pos = DIREND;
 3028                                         return 0;
 3029                                 }
 3030                                 goto repeat;
 3031                         }
 3032                         bn = addressDTS(&dirtab_slot);
 3033                         index = dirtab_slot.slot;
 3034                         DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
 3035                         if (rc) {
 3036                                 filp->f_pos = DIREND;
 3037                                 return 0;
 3038                         }
 3039                         if (p->header.flag & BT_INTERNAL) {
 3040                                 jfs_err("jfs_readdir: bad index table");
 3041                                 DT_PUTPAGE(mp);
 3042                                 filp->f_pos = -1;
 3043                                 return 0;
 3044                         }
 3045                 } else {
 3046                         if (dir_index == 0) {
 3047                                 /*
 3048                                  * self "."
 3049                                  */
 3050                                 filp->f_pos = 0;
 3051                                 if (filldir(dirent, ".", 1, 0, ip->i_ino,
 3052                                             DT_DIR))
 3053                                         return 0;
 3054                         }
 3055                         /*
 3056                          * parent ".."
 3057                          */
 3058                         filp->f_pos = 1;
 3059                         if (filldir(dirent, "..", 2, 1, PARENT(ip), DT_DIR))
 3060                                 return 0;
 3061 
 3062                         /*
 3063                          * Find first entry of left-most leaf
 3064                          */
 3065                         if (dtEmpty(ip)) {
 3066                                 filp->f_pos = DIREND;
 3067                                 return 0;
 3068                         }
 3069 
 3070                         if ((rc = dtReadFirst(ip, &btstack)))
 3071                                 return -rc;
 3072 
 3073                         DT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
 3074                 }
 3075         } else {
 3076                 /*
 3077                  * Legacy filesystem - OS/2 & Linux JFS < 0.3.6
 3078                  *
 3079                  * pn = index = 0:      First entry "."
 3080                  * pn = 0; index = 1:   Second entry ".."
 3081                  * pn > 0:              Real entries, pn=1 -> leftmost page
 3082                  * pn = index = -1:     No more entries
 3083                  */
 3084                 dtpos = filp->f_pos;
 3085                 if (dtpos == 0) {
 3086                         /* build "." entry */
 3087 
 3088                         if (filldir(dirent, ".", 1, filp->f_pos, ip->i_ino,
 3089                                     DT_DIR))
 3090                                 return 0;
 3091                         dtoffset->index = 1;
 3092                         filp->f_pos = dtpos;
 3093                 }
 3094 
 3095                 if (dtoffset->pn == 0) {
 3096                         if (dtoffset->index == 1) {
 3097                                 /* build ".." entry */
 3098 
 3099                                 if (filldir(dirent, "..", 2, filp->f_pos,
 3100                                             PARENT(ip), DT_DIR))
 3101                                         return 0;
 3102                         } else {
 3103                                 jfs_err("jfs_readdir called with "
 3104                                         "invalid offset!");
 3105                         }
 3106                         dtoffset->pn = 1;
 3107                         dtoffset->index = 0;
 3108                         filp->f_pos = dtpos;
 3109                 }
 3110 
 3111                 if (dtEmpty(ip)) {
 3112                         filp->f_pos = DIREND;
 3113                         return 0;
 3114                 }
 3115 
 3116                 if ((rc = dtReadNext(ip, &filp->f_pos, &btstack))) {
 3117                         jfs_err("jfs_readdir: unexpected rc = %d "
 3118                                 "from dtReadNext", rc);
 3119                         filp->f_pos = DIREND;
 3120                         return 0;
 3121                 }
 3122                 /* get start leaf page and index */
 3123                 DT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
 3124 
 3125                 /* offset beyond directory eof ? */
 3126                 if (bn < 0) {
 3127                         filp->f_pos = DIREND;
 3128                         return 0;
 3129                 }
 3130         }
 3131 
 3132         dirent_buf = __get_free_page(GFP_KERNEL);
 3133         if (dirent_buf == 0) {
 3134                 DT_PUTPAGE(mp);
 3135                 jfs_warn("jfs_readdir: __get_free_page failed!");
 3136                 filp->f_pos = DIREND;
 3137                 return -ENOMEM;
 3138         }
 3139 
 3140         while (1) {
 3141                 jfs_dirent = (struct jfs_dirent *) dirent_buf;
 3142                 jfs_dirents = 0;
 3143                 overflow = fix_page = 0;
 3144 
 3145                 stbl = DT_GETSTBL(p);
 3146 
 3147                 for (i = index; i < p->header.nextindex; i++) {
 3148                         d = (struct ldtentry *) & p->slot[stbl[i]];
 3149 
 3150                         if (((long) jfs_dirent + d->namlen + 1) >
 3151                             (dirent_buf + PSIZE)) {
 3152                                 /* DBCS codepages could overrun dirent_buf */
 3153                                 index = i;
 3154                                 overflow = 1;
 3155                                 break;
 3156                         }
 3157 
 3158                         d_namleft = d->namlen;
 3159                         name_ptr = jfs_dirent->name;
 3160                         jfs_dirent->ino = le32_to_cpu(d->inumber);
 3161 
 3162                         if (do_index) {
 3163                                 len = min(d_namleft, DTLHDRDATALEN);
 3164                                 jfs_dirent->position = le32_to_cpu(d->index);
 3165                                 /*
 3166                                  * d->index should always be valid, but it
 3167                                  * isn't.  fsck.jfs doesn't create the
 3168                                  * directory index for the lost+found
 3169                                  * directory.  Rather than let it go,
 3170                                  * we can try to fix it.
 3171                                  */
 3172                                 if ((jfs_dirent->position < 2) ||
 3173                                     (jfs_dirent->position >=
 3174                                      JFS_IP(ip)->next_index)) {
 3175                                         if (!page_fixed && !isReadOnly(ip)) {
 3176                                                 fix_page = 1;
 3177                                                 /*
 3178                                                  * setting overflow and setting
 3179                                                  * index to i will cause the
 3180                                                  * same page to be processed
 3181                                                  * again starting here
 3182                                                  */
 3183                                                 overflow = 1;
 3184                                                 index = i;
 3185                                                 break;
 3186                                         }
 3187                                         jfs_dirent->position = unique_pos++;
 3188                                 }
 3189                         } else {
 3190                                 jfs_dirent->position = dtpos;
 3191                                 len = min(d_namleft, DTLHDRDATALEN_LEGACY);
 3192                         }
 3193 
 3194                         /* copy the name of head/only segment */
 3195                         outlen = jfs_strfromUCS_le(name_ptr, d->name, len,
 3196                                                    codepage);
 3197                         jfs_dirent->name_len = outlen;
 3198 
 3199                         /* copy name in the additional segment(s) */
 3200                         next = d->next;
 3201                         while (next >= 0) {
 3202                                 t = (struct dtslot *) & p->slot[next];
 3203                                 name_ptr += outlen;
 3204                                 d_namleft -= len;
 3205                                 /* Sanity Check */
 3206                                 if (d_namleft == 0) {
 3207                                         jfs_err("JFS:Dtree error: ino = "
 3208                                                 "%ld, bn=%Ld, index = %d",
 3209                                                 (long)ip->i_ino,(long long)bn,
 3210                                                 i);
 3211                                         updateSuper(ip->i_sb, FM_DIRTY);
 3212                                         goto skip_one;
 3213                                 }
 3214                                 len = min(d_namleft, DTSLOTDATALEN);
 3215                                 outlen = jfs_strfromUCS_le(name_ptr, t->name,
 3216                                                            len, codepage);
 3217                                 jfs_dirent->name_len += outlen;
 3218 
 3219                                 next = t->next;
 3220                         }
 3221 
 3222                         jfs_dirents++;
 3223                         jfs_dirent = next_jfs_dirent(jfs_dirent);
 3224 skip_one:
 3225                         if (!do_index)
 3226                                 dtoffset->index++;
 3227                 }
 3228 
 3229                 if (!overflow) {
 3230                         /* Point to next leaf page */
 3231                         if (p->header.flag & BT_ROOT)
 3232                                 bn = 0;
 3233                         else {
 3234                                 bn = le64_to_cpu(p->header.next);
 3235                                 index = 0;
 3236                                 /* update offset (pn:index) for new page */
 3237                                 if (!do_index) {
 3238                                         dtoffset->pn++;
 3239                                         dtoffset->index = 0;
 3240                                 }
 3241                         }
 3242                         page_fixed = 0;
 3243                 }
 3244 
 3245                 /* unpin previous leaf page */
 3246                 DT_PUTPAGE(mp);
 3247 
 3248                 jfs_dirent = (struct jfs_dirent *) dirent_buf;
 3249                 while (jfs_dirents--) {
 3250                         filp->f_pos = jfs_dirent->position;
 3251                         if (filldir(dirent, jfs_dirent->name,
 3252                                     jfs_dirent->name_len, filp->f_pos,
 3253                                     jfs_dirent->ino, DT_UNKNOWN))
 3254                                 goto out;
 3255                         jfs_dirent = next_jfs_dirent(jfs_dirent);
 3256                 }
 3257 
 3258                 if (fix_page) {
 3259                         add_missing_indices(ip, bn);
 3260                         page_fixed = 1;
 3261                 }
 3262 
 3263                 if (!overflow && (bn == 0)) {
 3264                         filp->f_pos = DIREND;
 3265                         break;
 3266                 }
 3267 
 3268                 DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
 3269                 if (rc) {
 3270                         free_page(dirent_buf);
 3271                         return -rc;
 3272                 }
 3273         }
 3274 
 3275       out:
 3276         free_page(dirent_buf);
 3277 
 3278         return rc;
 3279 }
 3280 
 3281 
 3282 /*
 3283  *      dtReadFirst()
 3284  *
 3285  * function: get the leftmost page of the directory
 3286  */
 3287 static int dtReadFirst(struct inode *ip, struct btstack * btstack)
 3288 {
 3289         int rc = 0;
 3290         s64 bn;
 3291         int psize = 288;        /* initial in-line directory */
 3292         struct metapage *mp;
 3293         dtpage_t *p;
 3294         s8 *stbl;
 3295         struct btframe *btsp;
 3296         pxd_t *xd;
 3297 
 3298         BT_CLR(btstack);        /* reset stack */
 3299 
 3300         /*
 3301          *      descend leftmost path of the tree
 3302          *
 3303          * by convention, root bn = 0.
 3304          */
 3305         for (bn = 0;;) {
 3306                 DT_GETPAGE(ip, bn, mp, psize, p, rc);
 3307                 if (rc)
 3308                         return rc;
 3309 
 3310                 /*
 3311                  * leftmost leaf page
 3312                  */
 3313                 if (p->header.flag & BT_LEAF) {
 3314                         /* return leftmost entry */
 3315                         btsp = btstack->top;
 3316                         btsp->bn = bn;
 3317                         btsp->index = 0;
 3318                         btsp->mp = mp;
 3319 
 3320                         return 0;
 3321                 }
 3322 
 3323                 /*
 3324                  * descend down to leftmost child page
 3325                  */
 3326                 /* push (bn, index) of the parent page/entry */
 3327                 BT_PUSH(btstack, bn, 0);
 3328 
 3329                 /* get the leftmost entry */
 3330                 stbl = DT_GETSTBL(p);
 3331                 xd = (pxd_t *) & p->slot[stbl[0]];
 3332 
 3333                 /* get the child page block address */
 3334                 bn = addressPXD(xd);
 3335                 psize = lengthPXD(xd) << JFS_SBI(ip->i_sb)->l2bsize;
 3336 
 3337                 /* unpin the parent page */
 3338                 DT_PUTPAGE(mp);
 3339         }
 3340 }
 3341 
 3342 
 3343 /*
 3344  *      dtReadNext()
 3345  *
 3346  * function: get the page of the specified offset (pn:index)
 3347  *
 3348  * return: if (offset > eof), bn = -1;
 3349  *
 3350  * note: if index > nextindex of the target leaf page,
 3351  * start with 1st entry of next leaf page;
 3352  */
 3353 static int dtReadNext(struct inode *ip, loff_t * offset,
 3354                       struct btstack * btstack)
 3355 {
 3356         int rc = 0;
 3357         struct dtoffset {
 3358                 s16 pn;
 3359                 s16 index;
 3360                 s32 unused;
 3361         } *dtoffset = (struct dtoffset *) offset;
 3362         s64 bn;
 3363         struct metapage *mp;
 3364         dtpage_t *p;
 3365         int index;
 3366         int pn;
 3367         s8 *stbl;
 3368         struct btframe *btsp, *parent;
 3369         pxd_t *xd;
 3370 
 3371         /*
 3372          * get leftmost leaf page pinned
 3373          */
 3374         if ((rc = dtReadFirst(ip, btstack)))
 3375                 return rc;
 3376 
 3377         /* get leaf page */
 3378         DT_GETSEARCH(ip, btstack->top, bn, mp, p, index);
 3379 
 3380         /* get the start offset (pn:index) */
 3381         pn = dtoffset->pn - 1;  /* Now pn = 0 represents leftmost leaf */
 3382         index = dtoffset->index;
 3383 
 3384         /* start at leftmost page ? */
 3385         if (pn == 0) {
 3386                 /* offset beyond eof ? */
 3387                 if (index < p->header.nextindex)
 3388                         goto out;
 3389 
 3390                 if (p->header.flag & BT_ROOT) {
 3391                         bn = -1;
 3392                         goto out;
 3393                 }
 3394 
 3395                 /* start with 1st entry of next leaf page */
 3396                 dtoffset->pn++;
 3397                 dtoffset->index = index = 0;
 3398                 goto a;
 3399         }
 3400 
 3401         /* start at non-leftmost page: scan parent pages for large pn */
 3402         if (p->header.flag & BT_ROOT) {
 3403                 bn = -1;
 3404                 goto out;
 3405         }
 3406 
 3407         /* start after next leaf page ? */
 3408         if (pn > 1)
 3409                 goto b;
 3410 
 3411         /* get leaf page pn = 1 */
 3412       a:
 3413         bn = le64_to_cpu(p->header.next);
 3414 
 3415         /* unpin leaf page */
 3416         DT_PUTPAGE(mp);
 3417 
 3418         /* offset beyond eof ? */
 3419         if (bn == 0) {
 3420                 bn = -1;
 3421                 goto out;
 3422         }
 3423 
 3424         goto c;
 3425 
 3426         /*
 3427          * scan last internal page level to get target leaf page
 3428          */
 3429       b:
 3430         /* unpin leftmost leaf page */
 3431         DT_PUTPAGE(mp);
 3432 
 3433         /* get left most parent page */
 3434         btsp = btstack->top;
 3435         parent = btsp - 1;
 3436         bn = parent->bn;
 3437         DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
 3438         if (rc)
 3439                 return rc;
 3440 
 3441         /* scan parent pages at last internal page level */
 3442         while (pn >= p->header.nextindex) {
 3443                 pn -= p->header.nextindex;
 3444 
 3445                 /* get next parent page address */
 3446                 bn = le64_to_cpu(p->header.next);
 3447 
 3448                 /* unpin current parent page */
 3449                 DT_PUTPAGE(mp);
 3450 
 3451                 /* offset beyond eof ? */
 3452                 if (bn == 0) {
 3453                         bn = -1;
 3454                         goto out;
 3455                 }
 3456 
 3457                 /* get next parent page */
 3458                 DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
 3459                 if (rc)
 3460                         return rc;
 3461 
 3462                 /* update parent page stack frame */
 3463                 parent->bn = bn;
 3464         }
 3465 
 3466         /* get leaf page address */
 3467         stbl = DT_GETSTBL(p);
 3468         xd = (pxd_t *) & p->slot[stbl[pn]];
 3469         bn = addressPXD(xd);
 3470 
 3471         /* unpin parent page */
 3472         DT_PUTPAGE(mp);
 3473 
 3474         /*
 3475          * get target leaf page
 3476          */
 3477       c:
 3478         DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
 3479         if (rc)
 3480                 return rc;
 3481 
 3482         /*
 3483          * leaf page has been completed:
 3484          * start with 1st entry of next leaf page
 3485          */
 3486         if (index >= p->header.nextindex) {
 3487                 bn = le64_to_cpu(p->header.next);
 3488 
 3489                 /* unpin leaf page */
 3490                 DT_PUTPAGE(mp);
 3491 
 3492                 /* offset beyond eof ? */
 3493                 if (bn == 0) {
 3494                         bn = -1;
 3495                         goto out;
 3496                 }
 3497 
 3498                 /* get next leaf page */
 3499                 DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
 3500                 if (rc)
 3501                         return rc;
 3502 
 3503                 /* start with 1st entry of next leaf page */
 3504                 dtoffset->pn++;
 3505                 dtoffset->index = 0;
 3506         }
 3507 
 3508       out:
 3509         /* return target leaf page pinned */
 3510         btsp = btstack->top;
 3511         btsp->bn = bn;
 3512         btsp->index = dtoffset->index;
 3513         btsp->mp = mp;
 3514 
 3515         return 0;
 3516 }
 3517 
 3518 
 3519 /*
 3520  *      dtCompare()
 3521  *
 3522  * function: compare search key with an internal entry
 3523  *
 3524  * return:
 3525  *      < 0 if k is < record
 3526  *      = 0 if k is = record
 3527  *      > 0 if k is > record
 3528  */
 3529 static int dtCompare(struct component_name * key,       /* search key */
 3530                      dtpage_t * p,      /* directory page */
 3531                      int si)
 3532 {                               /* entry slot index */
 3533         wchar_t *kname, *name;
 3534         int klen, namlen, len, rc;
 3535         struct idtentry *ih;
 3536         struct dtslot *t;
 3537 
 3538         /*
 3539          * force the left-most key on internal pages, at any level of
 3540          * the tree, to be less than any search key.
 3541          * this obviates having to update the leftmost key on an internal
 3542          * page when the user inserts a new key in the tree smaller than
 3543          * anything that has been stored.
 3544          *
 3545          * (? if/when dtSearch() narrows down to 1st entry (index = 0),
 3546          * at any internal page at any level of the tree,
 3547          * it descends to child of the entry anyway -
 3548          * ? make the entry as min size dummy entry)
 3549          *
 3550          * if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & BT_LEAF))
 3551          * return (1);
 3552          */
 3553 
 3554         kname = key->name;
 3555         klen = key->namlen;
 3556 
 3557         ih = (struct idtentry *) & p->slot[si];
 3558         si = ih->next;
 3559         name = ih->name;
 3560         namlen = ih->namlen;
 3561         len = min(namlen, DTIHDRDATALEN);
 3562 
 3563         /* compare with head/only segment */
 3564         len = min(klen, len);
 3565         if ((rc = UniStrncmp_le(kname, name, len)))
 3566                 return rc;
 3567 
 3568         klen -= len;
 3569         namlen -= len;
 3570 
 3571         /* compare with additional segment(s) */
 3572         kname += len;
 3573         while (klen > 0 && namlen > 0) {
 3574                 /* compare with next name segment */
 3575                 t = (struct dtslot *) & p->slot[si];
 3576                 len = min(namlen, DTSLOTDATALEN);
 3577                 len = min(klen, len);
 3578                 name = t->name;
 3579                 if ((rc = UniStrncmp_le(kname, name, len)))
 3580                         return rc;
 3581 
 3582                 klen -= len;
 3583                 namlen -= len;
 3584                 kname += len;
 3585                 si = t->next;
 3586         }
 3587 
 3588         return (klen - namlen);
 3589 }
 3590 
 3591 
 3592 
 3593 
 3594 /*
 3595  *      ciCompare()
 3596  *
 3597  * function: compare search key with an (leaf/internal) entry
 3598  *
 3599  * return:
 3600  *      < 0 if k is < record
 3601  *      = 0 if k is = record
 3602  *      > 0 if k is > record
 3603  */
 3604 static int ciCompare(struct component_name * key,       /* search key */
 3605                      dtpage_t * p,      /* directory page */
 3606                      int si,    /* entry slot index */
 3607                      int flag)
 3608 {
 3609         wchar_t *kname, *name, x;
 3610         int klen, namlen, len, rc;
 3611         struct ldtentry *lh;
 3612         struct idtentry *ih;
 3613         struct dtslot *t;
 3614         int i;
 3615 
 3616         /*
 3617          * force the left-most key on internal pages, at any level of
 3618          * the tree, to be less than any search key.
 3619          * this obviates having to update the leftmost key on an internal
 3620          * page when the user inserts a new key in the tree smaller than
 3621          * anything that has been stored.
 3622          *
 3623          * (? if/when dtSearch() narrows down to 1st entry (index = 0),
 3624          * at any internal page at any level of the tree,
 3625          * it descends to child of the entry anyway -
 3626          * ? make the entry as min size dummy entry)
 3627          *
 3628          * if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & BT_LEAF))
 3629          * return (1);
 3630          */
 3631 
 3632         kname = key->name;
 3633         klen = key->namlen;
 3634 
 3635         /*
 3636          * leaf page entry
 3637          */
 3638         if (p->header.flag & BT_LEAF) {
 3639                 lh = (struct ldtentry *) & p->slot[si];
 3640                 si = lh->next;
 3641                 name = lh->name;
 3642                 namlen = lh->namlen;
 3643                 if (flag & JFS_DIR_INDEX)
 3644                         len = min(namlen, DTLHDRDATALEN);
 3645                 else
 3646                         len = min(namlen, DTLHDRDATALEN_LEGACY);
 3647         }
 3648         /*
 3649          * internal page entry
 3650          */
 3651         else {
 3652                 ih = (struct idtentry *) & p->slot[si];
 3653                 si = ih->next;
 3654                 name = ih->name;
 3655                 namlen = ih->namlen;
 3656                 len = min(namlen, DTIHDRDATALEN);
 3657         }
 3658 
 3659         /* compare with head/only segment */
 3660         len = min(klen, len);
 3661         for (i = 0; i < len; i++, kname++, name++) {
 3662                 /* only uppercase if case-insensitive support is on */
 3663                 if ((flag & JFS_OS2) == JFS_OS2)
 3664                         x = UniToupper(le16_to_cpu(*name));
 3665                 else
 3666                         x = le16_to_cpu(*name);
 3667                 if ((rc = *kname - x))
 3668                         return rc;
 3669         }
 3670 
 3671         klen -= len;
 3672         namlen -= len;
 3673 
 3674         /* compare with additional segment(s) */
 3675         while (klen > 0 && namlen > 0) {
 3676                 /* compare with next name segment */
 3677                 t = (struct dtslot *) & p->slot[si];
 3678                 len = min(namlen, DTSLOTDATALEN);
 3679                 len = min(klen, len);
 3680                 name = t->name;
 3681                 for (i = 0; i < len; i++, kname++, name++) {
 3682                         /* only uppercase if case-insensitive support is on */
 3683                         if ((flag & JFS_OS2) == JFS_OS2)
 3684                                 x = UniToupper(le16_to_cpu(*name));
 3685                         else
 3686                                 x = le16_to_cpu(*name);
 3687 
 3688                         if ((rc = *kname - x))
 3689                                 return rc;
 3690                 }
 3691 
 3692                 klen -= len;
 3693                 namlen -= len;
 3694                 si = t->next;
 3695         }
 3696 
 3697         return (klen - namlen);
 3698 }
 3699 
 3700 
 3701 /*
 3702  *      ciGetLeafPrefixKey()
 3703  *
 3704  * function: compute prefix of suffix compression
 3705  *           from two adjacent leaf entries
 3706  *           across page boundary
 3707  *
 3708  * return:
 3709  *      Number of prefix bytes needed to distinguish b from a.
 3710  */
 3711 static void ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp,
 3712                                int ri, struct component_name * key, int flag)
 3713 {
 3714         int klen, namlen;
 3715         wchar_t *pl, *pr, *kname;
 3716         wchar_t lname[JFS_NAME_MAX + 1];
 3717         struct component_name lkey = { 0, lname };
 3718         wchar_t rname[JFS_NAME_MAX + 1];
 3719         struct component_name rkey = { 0, rname };
 3720 
 3721         /* get left and right key */
 3722         dtGetKey(lp, li, &lkey, flag);
 3723         lkey.name[lkey.namlen] = 0;
 3724 
 3725         if ((flag & JFS_OS2) == JFS_OS2)
 3726                 ciToUpper(&lkey);
 3727 
 3728         dtGetKey(rp, ri, &rkey, flag);
 3729         rkey.name[rkey.namlen] = 0;
 3730 
 3731 
 3732         if ((flag & JFS_OS2) == JFS_OS2)
 3733                 ciToUpper(&rkey);
 3734 
 3735         /* compute prefix */
 3736         klen = 0;
 3737         kname = key->name;
 3738         namlen = min(lkey.namlen, rkey.namlen);
 3739         for (pl = lkey.name, pr = rkey.name;
 3740              namlen; pl++, pr++, namlen--, klen++, kname++) {
 3741                 *kname = *pr;
 3742                 if (*pl != *pr) {
 3743                         key->namlen = klen + 1;
 3744                         return;
 3745                 }
 3746         }
 3747 
 3748         /* l->namlen <= r->namlen since l <= r */
 3749         if (lkey.namlen < rkey.namlen) {
 3750                 *kname = *pr;
 3751                 key->namlen = klen + 1;
 3752         } else                  /* l->namelen == r->namelen */
 3753                 key->namlen = klen;
 3754 
 3755         return;
 3756 }
 3757 
 3758 
 3759 
 3760 /*
 3761  *      dtGetKey()
 3762  *
 3763  * function: get key of the entry
 3764  */
 3765 static void dtGetKey(dtpage_t * p, int i,       /* entry index */
 3766                      struct component_name * key, int flag)
 3767 {
 3768         int si;
 3769         s8 *stbl;
 3770         struct ldtentry *lh;
 3771         struct idtentry *ih;
 3772         struct dtslot *t;
 3773         int namlen, len;
 3774         wchar_t *name, *kname;
 3775 
 3776         /* get entry */
 3777         stbl = DT_GETSTBL(p);
 3778         si = stbl[i];
 3779         if (p->header.flag & BT_LEAF) {
 3780                 lh = (struct ldtentry *) & p->slot[si];
 3781                 si = lh->next;
 3782                 namlen = lh->namlen;
 3783                 name = lh->name;
 3784                 if (flag & JFS_DIR_INDEX)
 3785                         len = min(namlen, DTLHDRDATALEN);
 3786                 else
 3787                         len = min(namlen, DTLHDRDATALEN_LEGACY);
 3788         } else {
 3789                 ih = (struct idtentry *) & p->slot[si];
 3790                 si = ih->next;
 3791                 namlen = ih->namlen;
 3792                 name = ih->name;
 3793                 len = min(namlen, DTIHDRDATALEN);
 3794         }
 3795 
 3796         key->namlen = namlen;
 3797         kname = key->name;
 3798 
 3799         /*
 3800          * move head/only segment
 3801          */
 3802         UniStrncpy_le(kname, name, len);
 3803 
 3804         /*
 3805          * move additional segment(s)
 3806          */
 3807         while (si >= 0) {
 3808                 /* get next segment */
 3809                 t = &p->slot[si];
 3810                 kname += len;
 3811                 namlen -= len;
 3812                 len = min(namlen, DTSLOTDATALEN);
 3813                 UniStrncpy_le(kname, t->name, len);
 3814 
 3815                 si = t->next;
 3816         }
 3817 }
 3818 
 3819 
 3820 /*
 3821  *      dtInsertEntry()
 3822  *
 3823  * function: allocate free slot(s) and
 3824  *           write a leaf/internal entry
 3825  *
 3826  * return: entry slot index
 3827  */
 3828 static void dtInsertEntry(dtpage_t * p, int index, struct component_name * key,
 3829                           ddata_t * data, struct dt_lock ** dtlock)
 3830 {
 3831         struct dtslot *h, *t;
 3832         struct ldtentry *lh = 0;
 3833         struct idtentry *ih = 0;
 3834         int hsi, fsi, klen, len, nextindex;
 3835         wchar_t *kname, *name;
 3836         s8 *stbl;
 3837         pxd_t *xd;
 3838         struct dt_lock *dtlck = *dtlock;
 3839         struct lv *lv;
 3840         int xsi, n;
 3841         s64 bn = 0;
 3842         struct metapage *mp = 0;
 3843 
 3844         klen = key->namlen;
 3845         kname = key->name;
 3846 
 3847         /* allocate a free slot */
 3848         hsi = fsi = p->header.freelist;
 3849         h = &p->slot[fsi];
 3850         p->header.freelist = h->next;
 3851         --p->header.freecnt;
 3852 
 3853         /* open new linelock */
 3854         if (dtlck->index >= dtlck->maxcnt)
 3855                 dtlck = (struct dt_lock *) txLinelock(dtlck);
 3856 
 3857         lv = & dtlck->lv[dtlck->index];
 3858         lv->offset = hsi;
 3859 
 3860         /* write head/only segment */
 3861         if (p->header.flag & BT_LEAF) {
 3862                 lh = (struct ldtentry *) h;
 3863                 lh->next = h->next;
 3864                 lh->inumber = data->leaf.ino;   /* little-endian */
 3865                 lh->namlen = klen;
 3866                 name = lh->name;
 3867                 if (data->leaf.ip) {
 3868                         len = min(klen, DTLHDRDATALEN);
 3869                         if (!(p->header.flag & BT_ROOT))
 3870                                 bn = addressPXD(&p->header.self);
 3871                         lh->index = cpu_to_le32(add_index(data->leaf.tid,
 3872                                                           data->leaf.ip,
 3873                                                           bn, index));
 3874                 } else
 3875                         len = min(klen, DTLHDRDATALEN_LEGACY);
 3876         } else {
 3877                 ih = (struct idtentry *) h;
 3878                 ih->next = h->next;
 3879                 xd = (pxd_t *) ih;
 3880                 *xd = data->xd;
 3881                 ih->namlen = klen;
 3882                 name = ih->name;
 3883                 len = min(klen, DTIHDRDATALEN);
 3884         }
 3885 
 3886         UniStrncpy_le(name, kname, len);
 3887 
 3888         n = 1;
 3889         xsi = hsi;
 3890 
 3891         /* write additional segment(s) */
 3892         t = h;
 3893         klen -= len;
 3894         while (klen) {
 3895                 /* get free slot */
 3896                 fsi = p->header.freelist;
 3897                 t = &p->slot[fsi];
 3898                 p->header.freelist = t->next;
 3899                 --p->header.freecnt;
 3900 
 3901                 /* is next slot contiguous ? */
 3902                 if (fsi != xsi + 1) {
 3903                         /* close current linelock */
 3904                         lv->length = n;
 3905                         dtlck->index++;
 3906 
 3907                         /* open new linelock */
 3908                         if (dtlck->index < dtlck->maxcnt)
 3909                                 lv++;
 3910                         else {
 3911                                 dtlck = (struct dt_lock *) txLinelock(dtlck);
 3912                                 lv = & dtlck->lv[0];
 3913                         }
 3914 
 3915                         lv->offset = fsi;
 3916                         n = 0;
 3917                 }
 3918 
 3919                 kname += len;
 3920                 len = min(klen, DTSLOTDATALEN);
 3921                 UniStrncpy_le(t->name, kname, len);
 3922 
 3923                 n++;
 3924                 xsi = fsi;
 3925                 klen -= len;
 3926         }
 3927 
 3928         /* close current linelock */
 3929         lv->length = n;
 3930         dtlck->index++;
 3931 
 3932         *dtlock = dtlck;
 3933 
 3934         /* terminate last/only segment */
 3935         if (h == t) {
 3936                 /* single segment entry */
 3937                 if (p->header.flag & BT_LEAF)
 3938                         lh->next = -1;
 3939                 else
 3940                         ih->next = -1;
 3941         } else
 3942                 /* multi-segment entry */
 3943                 t->next = -1;
 3944 
 3945         /* if insert into middle, shift right succeeding entries in stbl */
 3946         stbl = DT_GETSTBL(p);
 3947         nextindex = p->header.nextindex;
 3948         if (index < nextindex) {
 3949                 memmove(stbl + index + 1, stbl + index, nextindex - index);
 3950 
 3951                 if ((p->header.flag & BT_LEAF) && data->leaf.ip) {
 3952                         s64 lblock;
 3953 
 3954                         /*
 3955                          * Need to update slot number for entries that moved
 3956                          * in the stbl
 3957                          */
 3958                         mp = 0;
 3959                         for (n = index + 1; n <= nextindex; n++) {
 3960                                 lh = (struct ldtentry *) & (p->slot[stbl[n]]);
 3961                                 modify_index(data->leaf.tid, data->leaf.ip,
 3962                                              le32_to_cpu(lh->index), bn, n,
 3963                                              &mp, &lblock);
 3964                         }
 3965                         if (mp)
 3966                                 release_metapage(mp);
 3967                 }
 3968         }
 3969 
 3970         stbl[index] = hsi;
 3971 
 3972         /* advance next available entry index of stbl */
 3973         ++p->header.nextindex;
 3974 }
 3975 
 3976 
 3977 /*
 3978  *      dtMoveEntry()
 3979  *
 3980  * function: move entries from split/left page to new/right page
 3981  *
 3982  *      nextindex of dst page and freelist/freecnt of both pages
 3983  *      are updated.
 3984  */
 3985 static void dtMoveEntry(dtpage_t * sp, int si, dtpage_t * dp,
 3986                         struct dt_lock ** sdtlock, struct dt_lock ** ddtlock,
 3987                         int do_index)
 3988 {
 3989         int ssi, next;          /* src slot index */
 3990         int di;                 /* dst entry index */
 3991         int dsi;                /* dst slot index */
 3992         s8 *sstbl, *dstbl;      /* sorted entry table */
 3993         int snamlen, len;
 3994         struct ldtentry *slh, *dlh = 0;
 3995         struct idtentry *sih, *dih = 0;
 3996         struct dtslot *h, *s, *d;
 3997         struct dt_lock *sdtlck = *sdtlock, *ddtlck = *ddtlock;
 3998         struct lv *slv, *dlv;
 3999         int xssi, ns, nd;
 4000         int sfsi;
 4001 
 4002         sstbl = (s8 *) & sp->slot[sp->header.stblindex];
 4003         dstbl = (s8 *) & dp->slot[dp->header.stblindex];
 4004 
 4005         dsi = dp->header.freelist;      /* first (whole page) free slot */
 4006         sfsi = sp->header.freelist;
 4007 
 4008         /* linelock destination entry slot */
 4009         dlv = & ddtlck->lv[ddtlck->index];
 4010         dlv->offset = dsi;
 4011 
 4012         /* linelock source entry slot */
 4013         slv = & sdtlck->lv[sdtlck->index];
 4014         slv->offset = sstbl[si];
 4015         xssi = slv->offset - 1;
 4016 
 4017         /*
 4018          * move entries
 4019          */
 4020         ns = nd = 0;
 4021         for (di = 0; si < sp->header.nextindex; si++, di++) {
 4022                 ssi = sstbl[si];
 4023                 dstbl[di] = dsi;
 4024 
 4025                 /* is next slot contiguous ? */
 4026                 if (ssi != xssi + 1) {
 4027                         /* close current linelock */
 4028                         slv->length = ns;
 4029                         sdtlck->index++;
 4030 
 4031                         /* open new linelock */
 4032                         if (sdtlck->index < sdtlck->maxcnt)
 4033                                 slv++;
 4034                         else {
 4035                                 sdtlck = (struct dt_lock *) txLinelock(sdtlck);
 4036                                 slv = & sdtlck->lv[0];
 4037                         }
 4038 
 4039                         slv->offset = ssi;
 4040                         ns = 0;
 4041                 }
 4042 
 4043                 /*
 4044                  * move head/only segment of an entry
 4045                  */
 4046                 /* get dst slot */
 4047                 h = d = &dp->slot[dsi];
 4048 
 4049                 /* get src slot and move */
 4050                 s = &sp->slot[ssi];
 4051                 if (sp->header.flag & BT_LEAF) {
 4052                         /* get source entry */
 4053                         slh = (struct ldtentry *) s;
 4054                         dlh = (struct ldtentry *) h;
 4055                         snamlen = slh->namlen;
 4056 
 4057                         if (do_index) {
 4058                                 len = min(snamlen, DTLHDRDATALEN);
 4059                                 dlh->index = slh->index; /* little-endian */
 4060                         } else
 4061                                 len = min(snamlen, DTLHDRDATALEN_LEGACY);
 4062 
 4063                         memcpy(dlh, slh, 6 + len * 2);
 4064 
 4065                         next = slh->next;
 4066 
 4067                         /* update dst head/only segment next field */
 4068                         dsi++;
 4069                         dlh->next = dsi;
 4070                 } else {
 4071                         sih = (struct idtentry *) s;
 4072                         snamlen = sih->namlen;
 4073 
 4074                         len = min(snamlen, DTIHDRDATALEN);
 4075                         dih = (struct idtentry *) h;
 4076                         memcpy(dih, sih, 10 + len * 2);
 4077                         next = sih->next;
 4078 
 4079                         dsi++;
 4080                         dih->next = dsi;
 4081                 }
 4082 
 4083                 /* free src head/only segment */
 4084                 s->next = sfsi;
 4085                 s->cnt = 1;
 4086                 sfsi = ssi;
 4087 
 4088                 ns++;
 4089                 nd++;
 4090                 xssi = ssi;
 4091 
 4092                 /*
 4093                  * move additional segment(s) of the entry
 4094                  */
 4095                 snamlen -= len;
 4096                 while ((ssi = next) >= 0) {
 4097                         /* is next slot contiguous ? */
 4098                         if (ssi != xssi + 1) {
 4099                                 /* close current linelock */
 4100                                 slv->length = ns;
 4101                                 sdtlck->index++;
 4102 
 4103                                 /* open new linelock */
 4104                                 if (sdtlck->index < sdtlck->maxcnt)
 4105                                         slv++;
 4106                                 else {
 4107                                         sdtlck =
 4108                                             (struct dt_lock *)
 4109                                             txLinelock(sdtlck);
 4110                                         slv = & sdtlck->lv[0];
 4111                                 }
 4112 
 4113                                 slv->offset = ssi;
 4114                                 ns = 0;
 4115                         }
 4116 
 4117                         /* get next source segment */
 4118                         s = &sp->slot[ssi];
 4119 
 4120                         /* get next destination free slot */
 4121                         d++;
 4122 
 4123                         len = min(snamlen, DTSLOTDATALEN);
 4124                         UniStrncpy(d->name, s->name, len);
 4125 
 4126                         ns++;
 4127                         nd++;
 4128                         xssi = ssi;
 4129 
 4130                         dsi++;
 4131                         d->next = dsi;
 4132 
 4133                         /* free source segment */
 4134                         next = s->next;
 4135                         s->next = sfsi;
 4136                         s->cnt = 1;
 4137                         sfsi = ssi;
 4138 
 4139                         snamlen -= len;
 4140                 }               /* end while */
 4141 
 4142                 /* terminate dst last/only segment */
 4143                 if (h == d) {
 4144                         /* single segment entry */
 4145                         if (dp->header.flag & BT_LEAF)
 4146                                 dlh->next = -1;
 4147                         else
 4148                                 dih->next = -1;
 4149                 } else
 4150                         /* multi-segment entry */
 4151                         d->next = -1;
 4152         }                       /* end for */
 4153 
 4154         /* close current linelock */
 4155         slv->length = ns;
 4156         sdtlck->index++;
 4157         *sdtlock = sdtlck;
 4158 
 4159         dlv->length = nd;
 4160         ddtlck->index++;
 4161         *ddtlock = ddtlck;
 4162 
 4163         /* update source header */
 4164         sp->header.freelist = sfsi;
 4165         sp->header.freecnt += nd;
 4166 
 4167         /* update destination header */
 4168         dp->header.nextindex = di;
 4169 
 4170         dp->header.freelist = dsi;
 4171         dp->header.freecnt -= nd;
 4172 }
 4173 
 4174 
 4175 /*
 4176  *      dtDeleteEntry()
 4177  *
 4178  * function: free a (leaf/internal) entry
 4179  *
 4180  * log freelist header, stbl, and each segment slot of entry
 4181  * (even though last/only segment next field is modified,
 4182  * physical image logging requires all segment slots of
 4183  * the entry logged to avoid applying previous updates
 4184  * to the same slots)
 4185  */
 4186 static void dtDeleteEntry(dtpage_t * p, int fi, struct dt_lock ** dtlock)
 4187 {
 4188         int fsi;                /* free entry slot index */
 4189         s8 *stbl;
 4190         struct dtslot *t;
 4191         int si, freecnt;
 4192         struct dt_lock *dtlck = *dtlock;
 4193         struct lv *lv;
 4194         int xsi, n;
 4195 
 4196         /* get free entry slot index */
 4197         stbl = DT_GETSTBL(p);
 4198         fsi = stbl[fi];
 4199 
 4200         /* open new linelock */
 4201         if (dtlck->index >= dtlck->maxcnt)
 4202                 dtlck = (struct dt_lock *) txLinelock(dtlck);
 4203         lv = & dtlck->lv[dtlck->index];
 4204 
 4205         lv->offset = fsi;
 4206 
 4207         /* get the head/only segment */
 4208         t = &p->slot[fsi];
 4209         if (p->header.flag & BT_LEAF)
 4210                 si = ((struct ldtentry *) t)->next;
 4211         else
 4212                 si = ((struct idtentry *) t)->next;
 4213         t->next = si;
 4214         t->cnt = 1;
 4215 
 4216         n = freecnt = 1;
 4217         xsi = fsi;
 4218 
 4219         /* find the last/only segment */
 4220         while (si >= 0) {
 4221                 /* is next slot contiguous ? */
 4222                 if (si != xsi + 1) {
 4223                         /* close current linelock */
 4224                         lv->length = n;
 4225                         dtlck->index++;
 4226 
 4227                         /* open new linelock */
 4228                         if (dtlck->index < dtlck->maxcnt)
 4229                                 lv++;
 4230                         else {
 4231                                 dtlck = (struct dt_lock *) txLinelock(dtlck);
 4232                                 lv = & dtlck->lv[0];
 4233                         }
 4234 
 4235                         lv->offset = si;
 4236                         n = 0;
 4237                 }
 4238 
 4239                 n++;
 4240                 xsi = si;
 4241                 freecnt++;
 4242 
 4243                 t = &p->slot[si];
 4244                 t->cnt = 1;
 4245                 si = t->next;
 4246         }
 4247 
 4248         /* close current linelock */
 4249         lv->length = n;
 4250         dtlck->index++;
 4251 
 4252         *dtlock = dtlck;
 4253 
 4254         /* update freelist */
 4255         t->next = p->header.freelist;
 4256         p->header.freelist = fsi;
 4257         p->header.freecnt += freecnt;
 4258 
 4259         /* if delete from middle,
 4260          * shift left the succedding entries in the stbl
 4261          */
 4262         si = p->header.nextindex;
 4263         if (fi < si - 1)
 4264                 memmove(&stbl[fi], &stbl[fi + 1], si - fi - 1);
 4265 
 4266         p->header.nextindex--;
 4267 }
 4268 
 4269 
 4270 /*
 4271  *      dtTruncateEntry()
 4272  *
 4273  * function: truncate a (leaf/internal) entry
 4274  *
 4275  * log freelist header, stbl, and each segment slot of entry
 4276  * (even though last/only segment next field is modified,
 4277  * physical image logging requires all segment slots of
 4278  * the entry logged to avoid applying previous updates
 4279  * to the same slots)
 4280  */
 4281 static void dtTruncateEntry(dtpage_t * p, int ti, struct dt_lock ** dtlock)
 4282 {
 4283         int tsi;                /* truncate entry slot index */
 4284         s8 *stbl;
 4285         struct dtslot *t;
 4286         int si, freecnt;
 4287         struct dt_lock *dtlck = *dtlock;
 4288         struct lv *lv;
 4289         int fsi, xsi, n;
 4290 
 4291         /* get free entry slot index */
 4292         stbl = DT_GETSTBL(p);
 4293         tsi = stbl[ti];
 4294 
 4295         /* open new linelock */
 4296         if (dtlck->index >= dtlck->maxcnt)
 4297                 dtlck = (struct dt_lock *) txLinelock(dtlck);
 4298         lv = & dtlck->lv[dtlck->index];
 4299 
 4300         lv->offset = tsi;
 4301 
 4302         /* get the head/only segment */
 4303         t = &p->slot[tsi];
 4304         ASSERT(p->header.flag & BT_INTERNAL);
 4305         ((struct idtentry *) t)->namlen = 0;
 4306         si = ((struct idtentry *) t)->next;
 4307         ((struct idtentry *) t)->next = -1;
 4308 
 4309         n = 1;
 4310         freecnt = 0;
 4311         fsi = si;
 4312         xsi = tsi;
 4313 
 4314         /* find the last/only segment */
 4315         while (si >= 0) {
 4316                 /* is next slot contiguous ? */
 4317                 if (si != xsi + 1) {
 4318                         /* close current linelock */
 4319                         lv->length = n;
 4320                         dtlck->index++;
 4321 
 4322                         /* open new linelock */
 4323                         if (dtlck->index < dtlck->maxcnt)
 4324                                 lv++;
 4325                         else {
 4326                                 dtlck = (struct dt_lock *) txLinelock(dtlck);
 4327                                 lv = & dtlck->lv[0];
 4328                         }
 4329 
 4330                         lv->offset = si;
 4331                         n = 0;
 4332                 }
 4333 
 4334                 n++;
 4335                 xsi = si;
 4336                 freecnt++;
 4337 
 4338                 t = &p->slot[si];
 4339                 t->cnt = 1;
 4340                 si = t->next;
 4341         }
 4342 
 4343         /* close current linelock */
 4344         lv->length = n;
 4345         dtlck->index++;
 4346 
 4347         *dtlock = dtlck;
 4348 
 4349         /* update freelist */
 4350         if (freecnt == 0)
 4351                 return;
 4352         t->next = p->header.freelist;
 4353         p->header.freelist = fsi;
 4354         p->header.freecnt += freecnt;
 4355 }
 4356 
 4357 
 4358 /*
 4359  *      dtLinelockFreelist()
 4360  */
 4361 static void dtLinelockFreelist(dtpage_t * p,    /* directory page */
 4362                                int m,   /* max slot index */
 4363                                struct dt_lock ** dtlock)
 4364 {
 4365         int fsi;                /* free entry slot index */
 4366         struct dtslot *t;
 4367         int si;
 4368         struct dt_lock *dtlck = *dtlock;
 4369         struct lv *lv;
 4370         int xsi, n;
 4371 
 4372         /* get free entry slot index */
 4373         fsi = p->header.freelist;
 4374 
 4375         /* open new linelock */
 4376         if (dtlck->index >= dtlck->maxcnt)
 4377                 dtlck = (struct dt_lock *) txLinelock(dtlck);
 4378         lv = & dtlck->lv[dtlck->index];
 4379 
 4380         lv->offset = fsi;
 4381 
 4382         n = 1;
 4383         xsi = fsi;
 4384 
 4385         t = &p->slot[fsi];
 4386         si = t->next;
 4387 
 4388         /* find the last/only segment */
 4389         while (si < m && si >= 0) {
 4390                 /* is next slot contiguous ? */
 4391                 if (si != xsi + 1) {
 4392                         /* close current linelock */
 4393                         lv->length = n;
 4394                         dtlck->index++;
 4395 
 4396                         /* open new linelock */
 4397                         if (dtlck->index < dtlck->maxcnt)
 4398                                 lv++;
 4399                         else {
 4400                                 dtlck = (struct dt_lock *) txLinelock(dtlck);
 4401                                 lv = & dtlck->lv[0];
 4402                         }
 4403 
 4404                         lv->offset = si;
 4405                         n = 0;
 4406                 }
 4407 
 4408                 n++;
 4409                 xsi = si;
 4410 
 4411                 t = &p->slot[si];
 4412                 si = t->next;
 4413         }
 4414 
 4415         /* close current linelock */
 4416         lv->length = n;
 4417         dtlck->index++;
 4418 
 4419         *dtlock = dtlck;
 4420 }
 4421 
 4422 
 4423 /*
 4424  * NAME: dtModify
 4425  *
 4426  * FUNCTION: Modify the inode number part of a directory entry
 4427  *
 4428  * PARAMETERS:
 4429  *      tid     - Transaction id
 4430  *      ip      - Inode of parent directory
 4431  *      key     - Name of entry to be modified
 4432  *      orig_ino        - Original inode number expected in entry
 4433  *      new_ino - New inode number to put into entry
 4434  *      flag    - JFS_RENAME
 4435  *
 4436  * RETURNS:
 4437  *      ESTALE  - If entry found does not match orig_ino passed in
 4438  *      ENOENT  - If no entry can be found to match key
 4439  *      0       - If successfully modified entry
 4440  */
 4441 int dtModify(tid_t tid, struct inode *ip,
 4442          struct component_name * key, ino_t * orig_ino, ino_t new_ino, int flag)
 4443 {
 4444         int rc;
 4445         s64 bn;
 4446         struct metapage *mp;
 4447         dtpage_t *p;
 4448         int index;
 4449         struct btstack btstack;
 4450         struct tlock *tlck;
 4451         struct dt_lock *dtlck;
 4452         struct lv *lv;
 4453         s8 *stbl;
 4454         int entry_si;           /* entry slot index */
 4455         struct ldtentry *entry;
 4456 
 4457         /*
 4458          *      search for the entry to modify:
 4459          *
 4460          * dtSearch() returns (leaf page pinned, index at which to modify).
 4461          */
 4462         if ((rc = dtSearch(ip, key, orig_ino, &btstack, flag)))
 4463                 return rc;
 4464 
 4465         /* retrieve search result */
 4466         DT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
 4467 
 4468         BT_MARK_DIRTY(mp, ip);
 4469         /*
 4470          * acquire a transaction lock on the leaf page of named entry
 4471          */
 4472         tlck = txLock(tid, ip, mp, tlckDTREE | tlckENTRY);
 4473         dtlck = (struct dt_lock *) & tlck->lock;
 4474 
 4475         /* get slot index of the entry */
 4476         stbl = DT_GETSTBL(p);
 4477         entry_si = stbl[index];
 4478 
 4479         /* linelock entry */
 4480         ASSERT(dtlck->index == 0);
 4481         lv = & dtlck->lv[0];
 4482         lv->offset = entry_si;
 4483         lv->length = 1;
 4484         dtlck->index++;
 4485 
 4486         /* get the head/only segment */
 4487         entry = (struct ldtentry *) & p->slot[entry_si];
 4488 
 4489         /* substitute the inode number of the entry */
 4490         entry->inumber = cpu_to_le32(new_ino);
 4491 
 4492         /* unpin the leaf page */
 4493         DT_PUTPAGE(mp);
 4494 
 4495         return 0;
 4496 }
 4497 
 4498 #ifdef _JFS_DEBUG_DTREE
 4499 /*
 4500  *      dtDisplayTree()
 4501  *
 4502  * function: traverse forward
 4503  */
 4504 int dtDisplayTree(struct inode *ip)
 4505 {
 4506         int rc;
 4507         struct metapage *mp;
 4508         dtpage_t *p;
 4509         s64 bn, pbn;
 4510         int index, lastindex, v, h;
 4511         pxd_t *xd;
 4512         struct btstack btstack;
 4513         struct btframe *btsp;
 4514         struct btframe *parent;
 4515         u8 *stbl;
 4516         int psize = 256;
 4517 
 4518         printk("display B+-tree.\n");
 4519 
 4520         /* clear stack */
 4521         btsp = btstack.stack;
 4522 
 4523         /*
 4524          * start with root
 4525          *
 4526          * root resides in the inode
 4527          */
 4528         bn = 0;
 4529         v = h = 0;
 4530 
 4531         /*
 4532          * first access of each page:
 4533          */
 4534       newPage:
 4535         DT_GETPAGE(ip, bn, mp, psize, p, rc);
 4536         if (rc)
 4537                 return rc;
 4538 
 4539         /* process entries forward from first index */
 4540         index = 0;
 4541         lastindex = p->header.nextindex - 1;
 4542 
 4543         if (p->header.flag & BT_INTERNAL) {
 4544                 /*
 4545                  * first access of each internal page
 4546                  */
 4547                 printf("internal page ");
 4548                 dtDisplayPage(ip, bn, p);
 4549 
 4550                 goto getChild;
 4551         } else {                /* (p->header.flag & BT_LEAF) */
 4552 
 4553                 /*
 4554                  * first access of each leaf page
 4555                  */
 4556                 printf("leaf page ");
 4557                 dtDisplayPage(ip, bn, p);
 4558 
 4559                 /*
 4560                  * process leaf page entries
 4561                  *
 4562                  for ( ; index <= lastindex; index++)
 4563                  {
 4564                  }
 4565                  */
 4566 
 4567                 /* unpin the leaf page */
 4568                 DT_PUTPAGE(mp);
 4569         }
 4570 
 4571         /*
 4572          * go back up to the parent page
 4573          */
 4574       getParent:
 4575         /* pop/restore parent entry for the current child page */
 4576         if ((parent = (btsp == btstack.stack ? NULL : --btsp)) == NULL)
 4577                 /* current page must have been root */
 4578                 return;
 4579 
 4580         /*
 4581          * parent page scan completed
 4582          */
 4583         if ((index = parent->index) == (lastindex = parent->lastindex)) {
 4584                 /* go back up to the parent page */
 4585                 goto getParent;
 4586         }
 4587 
 4588         /*
 4589          * parent page has entries remaining
 4590          */
 4591         /* get back the parent page */
 4592         bn = parent->bn;
 4593         /* v = parent->level; */
 4594         DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
 4595         if (rc)
 4596                 return rc;
 4597 
 4598         /* get next parent entry */
 4599         index++;
 4600 
 4601         /*
 4602          * internal page: go down to child page of current entry
 4603          */
 4604       getChild:
 4605         /* push/save current parent entry for the child page */
 4606         btsp->bn = pbn = bn;
 4607         btsp->index = index;
 4608         btsp->lastindex = lastindex;
 4609         /* btsp->level = v; */
 4610         /* btsp->node = h; */
 4611         ++btsp;
 4612 
 4613         /* get current entry for the child page */
 4614         stbl = DT_GETSTBL(p);
 4615         xd = (pxd_t *) & p->slot[stbl[index]];
 4616 
 4617         /*
 4618          * first access of each internal entry:
 4619          */
 4620 
 4621         /* get child page */
 4622         bn = addressPXD(xd);
 4623         psize = lengthPXD(xd) << ip->i_ipmnt->i_l2bsize;
 4624 
 4625         printk("traverse down 0x%Lx[%d]->0x%Lx\n", pbn, index, bn);
 4626         v++;
 4627         h = index;
 4628 
 4629         /* release parent page */
 4630         DT_PUTPAGE(mp);
 4631 
 4632         /* process the child page */
 4633         goto newPage;
 4634 }
 4635 
 4636 
 4637 /*
 4638  *      dtDisplayPage()
 4639  *
 4640  * function: display page
 4641  */
 4642 int dtDisplayPage(struct inode *ip, s64 bn, dtpage_t * p)
 4643 {
 4644         int rc;
 4645         struct metapage *mp;
 4646         struct ldtentry *lh;
 4647         struct idtentry *ih;
 4648         pxd_t *xd;
 4649         int i, j;
 4650         u8 *stbl;
 4651         wchar_t name[JFS_NAME_MAX + 1];
 4652         struct component_name key = { 0, name };
 4653         int freepage = 0;
 4654 
 4655         if (p == NULL) {
 4656                 freepage = 1;
 4657                 DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
 4658                 if (rc)
 4659                         return rc;
 4660         }
 4661 
 4662         /* display page control */
 4663         printk("bn:0x%Lx flag:0x%08x nextindex:%d\n",
 4664                bn, p->header.flag, p->header.nextindex);
 4665 
 4666         /* display entries */
 4667         stbl = DT_GETSTBL(p);
 4668         for (i = 0, j = 1; i < p->header.nextindex; i++, j++) {
 4669                 dtGetKey(p, i, &key, JFS_SBI(ip->i_sb)->mntflag);
 4670                 key.name[key.namlen] = '\0';
 4671                 if (p->header.flag & BT_LEAF) {
 4672                         lh = (struct ldtentry *) & p->slot[stbl[i]];
 4673                         printf("\t[%d] %s:%d", i, key.name,
 4674                                le32_to_cpu(lh->inumber));
 4675                 } else {
 4676                         ih = (struct idtentry *) & p->slot[stbl[i]];
 4677                         xd = (pxd_t *) ih;
 4678                         bn = addressPXD(xd);
 4679                         printf("\t[%d] %s:0x%Lx", i, key.name, bn);
 4680                 }
 4681 
 4682                 if (j == 4) {
 4683                         printf("\n");
 4684                         j = 0;
 4685                 }
 4686         }
 4687 
 4688         printf("\n");
 4689 
 4690         if (freepage)
 4691                 DT_PUTPAGE(mp);
 4692 
 4693         return 0;
 4694 }
 4695 #endif                          /* _JFS_DEBUG_DTREE */

Cache object: 08ff73adcea9924c0173929ae8b22808


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.