vserver 2.0 rc7
[linux-2.6.git] / fs / jfs / jfs_xtree.c
index 11c58c5..31b34db 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2004
+ *   Copyright (C) International Business Machines Corp., 2000-2005
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -111,8 +111,8 @@ static struct {
 /*
  * forward references
  */
-static int xtSearch(struct inode *ip,
-                   s64 xoff, int *cmpp, struct btstack * btstack, int flag);
+static int xtSearch(struct inode *ip, s64 xoff, s64 *next, int *cmpp,
+                   struct btstack * btstack, int flag);
 
 static int xtSplitUp(tid_t tid,
                     struct inode *ip,
@@ -159,11 +159,12 @@ int xtLookup(struct inode *ip, s64 lstart,
        xtpage_t *p;
        int index;
        xad_t *xad;
-       s64 size, xoff, xend;
+       s64 next, size, xoff, xend;
        int xlen;
        s64 xaddr;
 
-       *plen = 0;
+       *paddr = 0;
+       *plen = llen;
 
        if (!no_check) {
                /* is lookup offset beyond eof ? */
@@ -180,7 +181,7 @@ int xtLookup(struct inode *ip, s64 lstart,
         * search for the xad entry covering the logical extent
         */
 //search:
-       if ((rc = xtSearch(ip, lstart, &cmp, &btstack, 0))) {
+       if ((rc = xtSearch(ip, lstart, &next, &cmp, &btstack, 0))) {
                jfs_err("xtLookup: xtSearch returned %d", rc);
                return rc;
        }
@@ -198,8 +199,11 @@ int xtLookup(struct inode *ip, s64 lstart,
         * lstart is a page start address,
         * i.e., lstart cannot start in a hole;
         */
-       if (cmp)
+       if (cmp) {
+               if (next)
+                       *plen = min(next - lstart, llen);
                goto out;
+       }
 
        /*
         * lxd covered by xad
@@ -284,7 +288,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
        if (lstart >= size)
                return 0;
 
-       if ((rc = xtSearch(ip, lstart, &cmp, &btstack, 0)))
+       if ((rc = xtSearch(ip, lstart, NULL, &cmp, &btstack, 0)))
                return rc;
 
        /*
@@ -488,6 +492,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
  * parameters:
  *      ip      - file object;
  *      xoff    - extent offset;
+ *      nextp  - address of next extent (if any) for search miss
  *      cmpp    - comparison result:
  *      btstack - traverse stack;
  *      flag    - search process flag (XT_INSERT);
@@ -497,7 +502,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
  *      *cmpp is set to result of comparison with the entry returned.
  *      the page containing the entry is pinned at exit.
  */
-static int xtSearch(struct inode *ip, s64 xoff,        /* offset of extent */
+static int xtSearch(struct inode *ip, s64 xoff,        s64 *nextp,
                    int *cmpp, struct btstack * btstack, int flag)
 {
        struct jfs_inode_info *jfs_ip = JFS_IP(ip);
@@ -511,6 +516,7 @@ static int xtSearch(struct inode *ip, s64 xoff,     /* offset of extent */
        struct btframe *btsp;
        int nsplit = 0;         /* number of pages to split */
        s64 t64;
+       s64 next = 0;
 
        INCREMENT(xtStat.search);
 
@@ -579,6 +585,7 @@ static int xtSearch(struct inode *ip, s64 xoff,     /* offset of extent */
                                                 * previous and this entry
                                                 */
                                                *cmpp = 1;
+                                               next = t64;
                                                goto out;
                                        }
 
@@ -623,6 +630,9 @@ static int xtSearch(struct inode *ip, s64 xoff,     /* offset of extent */
                        /* update sequential access heuristics */
                        jfs_ip->btindex = index;
 
+                       if (nextp)
+                               *nextp = next;
+
                        INCREMENT(xtStat.fastSearch);
                        return 0;
                }
@@ -675,10 +685,11 @@ static int xtSearch(struct inode *ip, s64 xoff,   /* offset of extent */
 
                                        return 0;
                                }
-
                                /* search hit - internal page:
                                 * descend/search its child page
                                 */
+                               if (index < le16_to_cpu(p->header.nextindex)-1)
+                                       next = offsetXAD(&p->xad[index + 1]);
                                goto next;
                        }
 
@@ -694,6 +705,8 @@ static int xtSearch(struct inode *ip, s64 xoff,     /* offset of extent */
                 * base is the smallest index with key (Kj) greater than
                 * search key (K) and may be zero or maxentry index.
                 */
+               if (base < le16_to_cpu(p->header.nextindex))
+                       next = offsetXAD(&p->xad[base]);
                /*
                 * search miss - leaf page:
                 *
@@ -727,6 +740,9 @@ static int xtSearch(struct inode *ip, s64 xoff,     /* offset of extent */
                                jfs_ip->btorder = BT_RANDOM;
                        jfs_ip->btindex = base;
 
+                       if (nextp)
+                               *nextp = next;
+
                        return 0;
                }
 
@@ -793,6 +809,7 @@ int xtInsert(tid_t tid,             /* transaction id */
        struct xtsplit split;   /* split information */
        xad_t *xad;
        int cmp;
+       s64 next;
        struct tlock *tlck;
        struct xtlock *xtlck;
 
@@ -806,7 +823,7 @@ int xtInsert(tid_t tid,             /* transaction id */
         * n.b. xtSearch() may return index of maxentry of
         * the full page.
         */
-       if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT)))
+       if ((rc = xtSearch(ip, xoff, &next, &cmp, &btstack, XT_INSERT)))
                return rc;
 
        /* retrieve search result */
@@ -814,7 +831,7 @@ int xtInsert(tid_t tid,             /* transaction id */
 
        /* This test must follow XT_GETSEARCH since mp must be valid if
         * we branch to out: */
-       if (cmp == 0) {
+       if ((cmp == 0) || (next && (xlen > next - xoff))) {
                rc = -EEXIST;
                goto out;
        }
@@ -1626,7 +1643,7 @@ int xtExtend(tid_t tid,           /* transaction id */
        jfs_info("xtExtend: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen);
 
        /* there must exist extent to be extended */
-       if ((rc = xtSearch(ip, xoff - 1, &cmp, &btstack, XT_INSERT)))
+       if ((rc = xtSearch(ip, xoff - 1, NULL, &cmp, &btstack, XT_INSERT)))
                return rc;
 
        /* retrieve search result */
@@ -1794,7 +1811,7 @@ printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n",
 */
 
        /* there must exist extent to be tailgated */
-       if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT)))
+       if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, XT_INSERT)))
                return rc;
 
        /* retrieve search result */
@@ -1977,7 +1994,7 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
        nxlen = lengthXAD(nxad);
        nxaddr = addressXAD(nxad);
 
-       if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT)))
+       if ((rc = xtSearch(ip, nxoff, NULL, &cmp, &btstack, XT_INSERT)))
                return rc;
 
        /* retrieve search result */
@@ -2291,7 +2308,7 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
        if (nextindex == le16_to_cpu(p->header.maxentry)) {
                XT_PUTPAGE(mp);
 
-               if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT)))
+               if ((rc = xtSearch(ip, nxoff, NULL, &cmp, &btstack, XT_INSERT)))
                        return rc;
 
                /* retrieve search result */
@@ -2438,6 +2455,7 @@ int xtAppend(tid_t tid,           /* transaction id */
        int nsplit, nblocks, xlen;
        struct pxdlist pxdlist;
        pxd_t *pxd;
+       s64 next;
 
        xaddr = *xaddrp;
        xlen = *xlenp;
@@ -2452,7 +2470,7 @@ int xtAppend(tid_t tid,           /* transaction id */
         * n.b. xtSearch() may return index of maxentry of
         * the full page.
         */
-       if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT)))
+       if ((rc = xtSearch(ip, xoff, &next, &cmp, &btstack, XT_INSERT)))
                return rc;
 
        /* retrieve search result */
@@ -2462,6 +2480,9 @@ int xtAppend(tid_t tid,           /* transaction id */
                rc = -EEXIST;
                goto out;
        }
+
+       if (next)
+               xlen = min(xlen, (int)(next - xoff));
 //insert:
        /*
         *      insert entry for new extent
@@ -2600,7 +2621,7 @@ int xtDelete(tid_t tid, struct inode *ip, s64 xoff, s32 xlen, int flag)
        /*
         * find the matching entry; xtSearch() pins the page
         */
-       if ((rc = xtSearch(ip, xoff, &cmp, &btstack, 0)))
+       if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0)))
                return rc;
 
        XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
@@ -2852,7 +2873,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad,    /* old XAD */
         */
        if (xtype == DATAEXT) {
                /* search in leaf entry */
-               rc = xtSearch(ip, xoff, &cmp, &btstack, 0);
+               rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0);
                if (rc)
                        return rc;
 
@@ -2958,7 +2979,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad,    /* old XAD */
                }
 
                /* get back parent page */
-               if ((rc = xtSearch(ip, xoff, &cmp, &btstack, 0)))
+               if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0)))
                        return rc;
 
                XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
@@ -3991,7 +4012,7 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
 
        if (committed_size) {
                xoff = (committed_size >> JFS_SBI(ip->i_sb)->l2bsize) - 1;
-               rc = xtSearch(ip, xoff, &cmp, &btstack, 0);
+               rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0);
                if (rc)
                        return rc;