aboutsummaryrefslogtreecommitdiff
path: root/fs/jfs/jfs_dtree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jfs/jfs_dtree.c')
-rw-r--r--fs/jfs/jfs_dtree.c321
1 files changed, 168 insertions, 153 deletions
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index 404f33eae50..984c2bbf4f6 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -3,16 +3,16 @@
*
* 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
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -78,7 +78,7 @@
*
* case-insensitive search:
*
- * fold search key;
+ * fold search key;
*
* case-insensitive search of B-tree:
* for internal entry, router key is already folded;
@@ -93,7 +93,7 @@
* else
* return no match;
*
- * serialization:
+ * serialization:
* target directory inode lock is being held on entry/exit
* of all main directory service routines.
*
@@ -102,6 +102,7 @@
#include <linux/fs.h>
#include <linux/quotaops.h>
+#include <linux/slab.h>
#include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_filsys.h"
@@ -123,21 +124,21 @@ struct dtsplit {
#define DT_PAGE(IP, MP) BT_PAGE(IP, MP, dtpage_t, i_dtroot)
/* get page buffer for specified block address */
-#define DT_GETPAGE(IP, BN, MP, SIZE, P, RC)\
-{\
- BT_GETPAGE(IP, BN, MP, dtpage_t, SIZE, P, RC, i_dtroot)\
- if (!(RC))\
- {\
- if (((P)->header.nextindex > (((BN)==0)?DTROOTMAXSLOT:(P)->header.maxslot)) ||\
- ((BN) && ((P)->header.maxslot > DTPAGEMAXSLOT)))\
- {\
- BT_PUTPAGE(MP);\
- jfs_error((IP)->i_sb, "DT_GETPAGE: dtree page corrupt");\
- MP = NULL;\
- RC = -EIO;\
- }\
- }\
-}
+#define DT_GETPAGE(IP, BN, MP, SIZE, P, RC) \
+do { \
+ BT_GETPAGE(IP, BN, MP, dtpage_t, SIZE, P, RC, i_dtroot); \
+ if (!(RC)) { \
+ if (((P)->header.nextindex > \
+ (((BN) == 0) ? DTROOTMAXSLOT : (P)->header.maxslot)) || \
+ ((BN) && ((P)->header.maxslot > DTPAGEMAXSLOT))) { \
+ BT_PUTPAGE(MP); \
+ jfs_error((IP)->i_sb, \
+ "DT_GETPAGE: dtree page corrupt\n"); \
+ MP = NULL; \
+ RC = -EIO; \
+ } \
+ } \
+} while (0)
/* for consistency */
#define DT_PUTPAGE(MP) BT_PUTPAGE(MP)
@@ -284,11 +285,11 @@ static struct dir_table_slot *find_index(struct inode *ip, u32 index,
release_metapage(*mp);
*mp = NULL;
}
- if (*mp == 0) {
+ if (!(*mp)) {
*lblock = blkno;
*mp = read_index_page(ip, blkno);
}
- if (*mp == 0) {
+ if (!(*mp)) {
jfs_err("free_index: error reading directory table");
return NULL;
}
@@ -315,8 +316,8 @@ static inline void lock_index(tid_t tid, struct inode *ip, struct metapage * mp,
lv = &llck->lv[llck->index];
/*
- * Linelock slot size is twice the size of directory table
- * slot size. 512 entries per page.
+ * Linelock slot size is twice the size of directory table
+ * slot size. 512 entries per page.
*/
lv->offset = ((index - 2) & 511) >> 1;
lv->length = 1;
@@ -381,10 +382,10 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
* It's time to move the inline table to an external
* page and begin to build the xtree
*/
- if (DQUOT_ALLOC_BLOCK(ip, sbi->nbperpage))
+ if (dquot_alloc_block(ip, sbi->nbperpage))
goto clean_up;
if (dbAlloc(ip, 0, sbi->nbperpage, &xaddr)) {
- DQUOT_FREE_BLOCK(ip, sbi->nbperpage);
+ dquot_free_block(ip, sbi->nbperpage);
goto clean_up;
}
@@ -408,12 +409,13 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
memcpy(&jfs_ip->i_dirtable, temp_table,
sizeof (temp_table));
dbFree(ip, xaddr, sbi->nbperpage);
- DQUOT_FREE_BLOCK(ip, sbi->nbperpage);
+ dquot_free_block(ip, sbi->nbperpage);
goto clean_up;
}
ip->i_size = PSIZE;
- if ((mp = get_index_page(ip, 0)) == 0) {
+ mp = get_index_page(ip, 0);
+ if (!mp) {
jfs_err("add_index: get_metapage failed!");
xtTruncate(tid, ip, 0, COMMIT_PWMAP);
memcpy(&jfs_ip->i_dirtable, temp_table,
@@ -461,7 +463,7 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
} else
mp = read_index_page(ip, blkno);
- if (mp == 0) {
+ if (!mp) {
jfs_err("add_index: get/read_metapage failed!");
goto clean_up;
}
@@ -499,7 +501,7 @@ static void free_index(tid_t tid, struct inode *ip, u32 index, u32 next)
dirtab_slot = find_index(ip, index, &mp, &lblock);
- if (dirtab_slot == 0)
+ if (!dirtab_slot)
return;
dirtab_slot->flag = DIR_INDEX_FREE;
@@ -520,13 +522,13 @@ static void free_index(tid_t tid, struct inode *ip, u32 index, u32 next)
* Changes an entry in the directory index table
*/
static void modify_index(tid_t tid, struct inode *ip, u32 index, s64 bn,
- int slot, struct metapage ** mp, u64 *lblock)
+ int slot, struct metapage ** mp, s64 *lblock)
{
struct dir_table_slot *dirtab_slot;
dirtab_slot = find_index(ip, index, mp, lblock);
- if (dirtab_slot == 0)
+ if (!dirtab_slot)
return;
DTSaddress(dirtab_slot, bn);
@@ -552,7 +554,7 @@ static int read_index(struct inode *ip, u32 index,
struct dir_table_slot *slot;
slot = find_index(ip, index, &mp, &lblock);
- if (slot == 0) {
+ if (!slot) {
return -EIO;
}
@@ -592,10 +594,8 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
struct component_name ciKey;
struct super_block *sb = ip->i_sb;
- ciKey.name =
- (wchar_t *) kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
- GFP_NOFS);
- if (ciKey.name == 0) {
+ ciKey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t), GFP_NOFS);
+ if (!ciKey.name) {
rc = -ENOMEM;
goto dtSearch_Exit2;
}
@@ -615,7 +615,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
btstack->nsplit = 1;
/*
- * search down tree from root:
+ * search down tree from root:
*
* between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
* internal page, child page Pi contains entry with k, Ki <= K < Kj.
@@ -659,7 +659,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
}
if (cmp == 0) {
/*
- * search hit
+ * search hit
*/
/* search hit - leaf page:
* return the entry found
@@ -723,7 +723,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
}
/*
- * search miss
+ * search miss
*
* base is the smallest index with key (Kj) greater than
* search key (K) and may be zero or (maxindex + 1) index.
@@ -773,10 +773,10 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
getChild:
/* update max. number of pages to split */
if (BT_STACK_FULL(btstack)) {
- /* Something's corrupted, mark filesytem dirty so
+ /* Something's corrupted, mark filesystem dirty so
* chkdsk will fix it.
*/
- jfs_error(sb, "stack overrun in dtSearch!");
+ jfs_error(sb, "stack overrun!\n");
BT_STACK_DUMP(btstack);
rc = -EIO;
goto out;
@@ -834,7 +834,7 @@ int dtInsert(tid_t tid, struct inode *ip,
struct lv *lv;
/*
- * retrieve search result
+ * retrieve search result
*
* dtSearch() returns (leaf page pinned, index at which to insert).
* n.b. dtSearch() may return index of (maxindex + 1) of
@@ -843,7 +843,7 @@ int dtInsert(tid_t tid, struct inode *ip,
DT_GETSEARCH(ip, btstack->top, bn, mp, p, index);
/*
- * insert entry for new key
+ * insert entry for new key
*/
if (DO_INDEX(ip)) {
if (JFS_IP(ip)->next_index == DIREND) {
@@ -860,9 +860,9 @@ int dtInsert(tid_t tid, struct inode *ip,
data.leaf.ino = *fsn;
/*
- * leaf page does not have enough room for new entry:
+ * leaf page does not have enough room for new entry:
*
- * extend/split the leaf page;
+ * extend/split the leaf page;
*
* dtSplitUp() will insert the entry and unpin the leaf page.
*/
@@ -877,9 +877,9 @@ int dtInsert(tid_t tid, struct inode *ip,
}
/*
- * leaf page does have enough room for new entry:
+ * leaf page does have enough room for new entry:
*
- * insert the new data entry into the leaf page;
+ * insert the new data entry into the leaf page;
*/
BT_MARK_DIRTY(mp, ip);
/*
@@ -925,7 +925,7 @@ int dtInsert(tid_t tid, struct inode *ip,
*
* return: 0 - success;
* errno - failure;
- * leaf page unpinned;
+ * leaf page unpinned;
*/
static int dtSplitUp(tid_t tid,
struct inode *ip, struct dtsplit * split, struct btstack * btstack)
@@ -957,23 +957,21 @@ static int dtSplitUp(tid_t tid,
smp = split->mp;
sp = DT_PAGE(ip, smp);
- key.name =
- (wchar_t *) kmalloc((JFS_NAME_MAX + 2) * sizeof(wchar_t),
- GFP_NOFS);
- if (key.name == 0) {
+ key.name = kmalloc((JFS_NAME_MAX + 2) * sizeof(wchar_t), GFP_NOFS);
+ if (!key.name) {
DT_PUTPAGE(smp);
rc = -ENOMEM;
goto dtSplitUp_Exit;
}
/*
- * split leaf page
+ * split leaf page
*
* The split routines insert the new entry, and
* acquire txLock as appropriate.
*/
/*
- * split root leaf page:
+ * split root leaf page:
*/
if (sp->header.flag & BT_ROOT) {
/*
@@ -1005,11 +1003,14 @@ static int dtSplitUp(tid_t tid,
DT_PUTPAGE(smp);
+ if (!DO_INDEX(ip))
+ ip->i_size = xlen << sbi->l2bsize;
+
goto freeKeyName;
}
/*
- * extend first leaf page
+ * extend first leaf page
*
* extend the 1st extent if less than buffer page size
* (dtExtendPage() reurns leaf page unpinned)
@@ -1027,10 +1028,9 @@ static int dtSplitUp(tid_t tid,
n = xlen;
/* Allocate blocks to quota. */
- if (DQUOT_ALLOC_BLOCK(ip, n)) {
- rc = -EDQUOT;
+ rc = dquot_alloc_block(ip, n);
+ if (rc)
goto extendOut;
- }
quota_allocation += n;
if ((rc = dbReAlloc(sbi->ipbmap, xaddr, (s64) xlen,
@@ -1055,7 +1055,9 @@ static int dtSplitUp(tid_t tid,
xaddr = addressPXD(pxd) + xlen;
dbFree(ip, xaddr, (s64) n);
}
- }
+ } else if (!DO_INDEX(ip))
+ ip->i_size = lengthPXD(pxd) << sbi->l2bsize;
+
extendOut:
DT_PUTPAGE(smp);
@@ -1063,7 +1065,7 @@ static int dtSplitUp(tid_t tid,
}
/*
- * split leaf page <sp> into <sp> and a new right page <rp>.
+ * split leaf page <sp> into <sp> and a new right page <rp>.
*
* return <rp> pinned and its extent descriptor <rpxd>
*/
@@ -1098,6 +1100,9 @@ static int dtSplitUp(tid_t tid,
goto splitOut;
}
+ if (!DO_INDEX(ip))
+ ip->i_size += PSIZE;
+
/*
* propagate up the router entry for the leaf page just split
*
@@ -1303,7 +1308,7 @@ static int dtSplitUp(tid_t tid,
/* Rollback quota allocation */
if (rc && quota_allocation)
- DQUOT_FREE_BLOCK(ip, quota_allocation);
+ dquot_free_block(ip, quota_allocation);
dtSplitUp_Exit:
@@ -1364,9 +1369,10 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
return -EIO;
/* Allocate blocks to quota. */
- if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+ rc = dquot_alloc_block(ip, lengthPXD(pxd));
+ if (rc) {
release_metapage(rmp);
- return -EDQUOT;
+ return rc;
}
jfs_info("dtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp);
@@ -1425,7 +1431,7 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
rp->header.freecnt = rp->header.maxslot - fsi;
/*
- * sequential append at tail: append without split
+ * sequential append at tail: append without split
*
* If splitting the last page on a level because of appending
* a entry to it (skip is maxentry), it's likely that the access is
@@ -1459,7 +1465,7 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
}
/*
- * non-sequential insert (at possibly middle page)
+ * non-sequential insert (at possibly middle page)
*/
/*
@@ -1500,7 +1506,7 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
left = 0;
/*
- * compute fill factor for split pages
+ * compute fill factor for split pages
*
* <nxt> traces the next entry to move to rp
* <off> traces the next entry to stay in sp
@@ -1543,7 +1549,7 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
/* <nxt> poins to the 1st entry to move */
/*
- * move entries to right page
+ * move entries to right page
*
* dtMoveEntry() initializes rp and reserves entry for insertion
*
@@ -1669,7 +1675,7 @@ static int dtExtendPage(tid_t tid,
return (rc);
/*
- * extend the extent
+ * extend the extent
*/
pxdlist = split->pxdlist;
pxd = &pxdlist->pxd[pxdlist->npxd];
@@ -1714,7 +1720,7 @@ static int dtExtendPage(tid_t tid,
}
/*
- * extend the page
+ * extend the page
*/
sp->header.self = *pxd;
@@ -1731,9 +1737,6 @@ static int dtExtendPage(tid_t tid,
/* update buffer extent descriptor of extended page */
xlen = lengthPXD(pxd);
xsize = xlen << JFS_SBI(sb)->l2bsize;
-#ifdef _STILL_TO_PORT
- bmSetXD(smp, xaddr, xsize);
-#endif /* _STILL_TO_PORT */
/*
* copy old stbl to new stbl at start of extended area
@@ -1828,7 +1831,7 @@ static int dtExtendPage(tid_t tid,
}
/*
- * update parent entry on the parent/root page
+ * update parent entry on the parent/root page
*/
/*
* acquire a transaction lock on the parent/root page
@@ -1890,13 +1893,14 @@ static int dtSplitRoot(tid_t tid,
struct dt_lock *dtlck;
struct tlock *tlck;
struct lv *lv;
+ int rc;
/* get split root page */
smp = split->mp;
sp = &JFS_IP(ip)->i_dtroot;
/*
- * allocate/initialize a single (right) child page
+ * allocate/initialize a single (right) child page
*
* N.B. at first split, a one (or two) block to fit new entry
* is allocated; at subsequent split, a full page is allocated;
@@ -1914,9 +1918,10 @@ static int dtSplitRoot(tid_t tid,
rp = rmp->data;
/* Allocate blocks to quota. */
- if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+ rc = dquot_alloc_block(ip, lengthPXD(pxd));
+ if (rc) {
release_metapage(rmp);
- return -EDQUOT;
+ return rc;
}
BT_MARK_DIRTY(rmp, ip);
@@ -1935,7 +1940,7 @@ static int dtSplitRoot(tid_t tid,
rp->header.prev = 0;
/*
- * move in-line root page into new right page extent
+ * move in-line root page into new right page extent
*/
/* linelock header + copied entries + new stbl (1st slot) in new page */
ASSERT(dtlck->index == 0);
@@ -2008,7 +2013,7 @@ static int dtSplitRoot(tid_t tid,
dtInsertEntry(rp, split->index, split->key, split->data, &dtlck);
/*
- * reset parent/root page
+ * reset parent/root page
*
* set the 1st entry offset to 0, which force the left-most key
* at any level of the tree to be less than any search key.
@@ -2094,7 +2099,7 @@ int dtDelete(tid_t tid,
dtpage_t *np;
/*
- * search for the entry to delete:
+ * search for the entry to delete:
*
* dtSearch() returns (leaf page pinned, index at which to delete).
*/
@@ -2245,7 +2250,7 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
int i;
/*
- * keep the root leaf page which has become empty
+ * keep the root leaf page which has become empty
*/
if (BT_IS_ROOT(fmp)) {
/*
@@ -2261,7 +2266,7 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
}
/*
- * free the non-root leaf page
+ * free the non-root leaf page
*/
/*
* acquire a transaction lock on the page
@@ -2285,13 +2290,13 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
xlen = lengthPXD(&fp->header.self);
/* Free quota allocation. */
- DQUOT_FREE_BLOCK(ip, xlen);
+ dquot_free_block(ip, xlen);
/* free/invalidate its buffer page */
discard_metapage(fmp);
/*
- * propagate page deletion up the directory tree
+ * propagate page deletion up the directory tree
*
* If the delete from the parent page makes it empty,
* continue all the way up the tree.
@@ -2361,7 +2366,7 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
xlen = lengthPXD(&p->header.self);
/* Free quota allocation */
- DQUOT_FREE_BLOCK(ip, xlen);
+ dquot_free_block(ip, xlen);
/* free/invalidate its buffer page */
discard_metapage(mp);
@@ -2424,15 +2429,18 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
break;
}
+ if (!DO_INDEX(ip))
+ ip->i_size -= PSIZE;
+
return 0;
}
#ifdef _NOTYET
/*
- * NAME: dtRelocate()
+ * NAME: dtRelocate()
*
- * FUNCTION: relocate dtpage (internal or leaf) of directory;
- * This function is mainly used by defragfs utility.
+ * FUNCTION: relocate dtpage (internal or leaf) of directory;
+ * This function is mainly used by defragfs utility.
*/
int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
s64 nxaddr)
@@ -2460,8 +2468,8 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
xlen);
/*
- * 1. get the internal parent dtpage covering
- * router entry for the tartget page to be relocated;
+ * 1. get the internal parent dtpage covering
+ * router entry for the tartget page to be relocated;
*/
rc = dtSearchNode(ip, lmxaddr, opxd, &btstack);
if (rc)
@@ -2472,7 +2480,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
jfs_info("dtRelocate: parent router entry validated.");
/*
- * 2. relocate the target dtpage
+ * 2. relocate the target dtpage
*/
/* read in the target page from src extent */
DT_GETPAGE(ip, oxaddr, mp, PSIZE, p, rc);
@@ -2570,9 +2578,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
/* update the buffer extent descriptor of the dtpage */
xsize = xlen << JFS_SBI(ip->i_sb)->l2bsize;
-#ifdef _STILL_TO_PORT
- bmSetXD(mp, nxaddr, xsize);
-#endif /* _STILL_TO_PORT */
+
/* unpin the relocated page */
DT_PUTPAGE(mp);
jfs_info("dtRelocate: target dtpage relocated.");
@@ -2583,7 +2589,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
*/
/*
- * 3. acquire maplock for the source extent to be freed;
+ * 3. acquire maplock for the source extent to be freed;
*/
/* for dtpage relocation, write a LOG_NOREDOPAGE record
* for the source dtpage (logredo() will init NoRedoPage
@@ -2598,7 +2604,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
pxdlock->index = 1;
/*
- * 4. update the parent router entry for relocation;
+ * 4. update the parent router entry for relocation;
*
* acquire tlck for the parent entry covering the target dtpage;
* write LOG_REDOPAGE to apply after image only;
@@ -2626,7 +2632,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
* NAME: dtSearchNode()
*
* FUNCTION: Search for an dtpage containing a specified address
- * This function is mainly used by defragfs utility.
+ * This function is mainly used by defragfs utility.
*
* NOTE: Search result on stack, the found page is pinned at exit.
* The result page must be an internal dtpage.
@@ -2649,7 +2655,7 @@ static int dtSearchNode(struct inode *ip, s64 lmxaddr, pxd_t * kpxd,
BT_CLR(btstack); /* reset stack */
/*
- * descend tree to the level with specified leftmost page
+ * descend tree to the level with specified leftmost page
*
* by convention, root bn = 0.
*/
@@ -2688,7 +2694,7 @@ static int dtSearchNode(struct inode *ip, s64 lmxaddr, pxd_t * kpxd,
}
/*
- * search each page at the current levevl
+ * search each page at the current levevl
*/
loop:
stbl = DT_GETSTBL(p);
@@ -2996,9 +3002,9 @@ static inline struct jfs_dirent *next_jfs_dirent(struct jfs_dirent *dirent)
* return: offset = (pn, index) of start entry
* of next jfs_readdir()/dtRead()
*/
-int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+int jfs_readdir(struct file *file, struct dir_context *ctx)
{
- struct inode *ip = filp->f_dentry->d_inode;
+ struct inode *ip = file_inode(file);
struct nls_table *codepage = JFS_SBI(ip->i_sb)->nls_tab;
int rc = 0;
loff_t dtpos; /* legacy OS/2 style position */
@@ -3027,19 +3033,27 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
int overflow, fix_page, page_fixed = 0;
static int unique_pos = 2; /* If we can't fix broken index */
- if (filp->f_pos == DIREND)
+ if (ctx->pos == DIREND)
return 0;
if (DO_INDEX(ip)) {
/*
* persistent index is stored in directory entries.
- * Special cases: 0 = .
- * 1 = ..
- * -1 = End of directory
+ * Special cases: 0 = .
+ * 1 = ..
+ * -1 = End of directory
*/
do_index = 1;
- dir_index = (u32) filp->f_pos;
+ dir_index = (u32) ctx->pos;
+
+ /*
+ * NFSv4 reserves cookies 1 and 2 for . and .. so the value
+ * we return to the vfs is one greater than the one we use
+ * internally.
+ */
+ if (dir_index)
+ dir_index--;
if (dir_index > 1) {
struct dir_table_slot dirtab_slot;
@@ -3047,25 +3061,25 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (dtEmpty(ip) ||
(dir_index >= JFS_IP(ip)->next_index)) {
/* Stale position. Directory has shrunk */
- filp->f_pos = DIREND;
+ ctx->pos = DIREND;
return 0;
}
repeat:
rc = read_index(ip, dir_index, &dirtab_slot);
if (rc) {
- filp->f_pos = DIREND;
+ ctx->pos = DIREND;
return rc;
}
if (dirtab_slot.flag == DIR_INDEX_FREE) {
if (loop_count++ > JFS_IP(ip)->next_index) {
jfs_err("jfs_readdir detected "
"infinite loop!");
- filp->f_pos = DIREND;
+ ctx->pos = DIREND;
return 0;
}
dir_index = le32_to_cpu(dirtab_slot.addr2);
if (dir_index == -1) {
- filp->f_pos = DIREND;
+ ctx->pos = DIREND;
return 0;
}
goto repeat;
@@ -3074,13 +3088,13 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
index = dirtab_slot.slot;
DT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
if (rc) {
- filp->f_pos = DIREND;
+ ctx->pos = DIREND;
return 0;
}
if (p->header.flag & BT_INTERNAL) {
jfs_err("jfs_readdir: bad index table");
DT_PUTPAGE(mp);
- filp->f_pos = -1;
+ ctx->pos = DIREND;
return 0;
}
} else {
@@ -3088,23 +3102,22 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/*
* self "."
*/
- filp->f_pos = 0;
- if (filldir(dirent, ".", 1, 0, ip->i_ino,
- DT_DIR))
+ ctx->pos = 1;
+ if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR))
return 0;
}
/*
* parent ".."
*/
- filp->f_pos = 1;
- if (filldir(dirent, "..", 2, 1, PARENT(ip), DT_DIR))
+ ctx->pos = 2;
+ if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR))
return 0;
/*
* Find first entry of left-most leaf
*/
if (dtEmpty(ip)) {
- filp->f_pos = DIREND;
+ ctx->pos = DIREND;
return 0;
}
@@ -3117,28 +3130,25 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/*
* Legacy filesystem - OS/2 & Linux JFS < 0.3.6
*
- * pn = index = 0: First entry "."
- * pn = 0; index = 1: Second entry ".."
- * pn > 0: Real entries, pn=1 -> leftmost page
- * pn = index = -1: No more entries
+ * pn = 0; index = 1: First entry "."
+ * pn = 0; index = 2: Second entry ".."
+ * pn > 0: Real entries, pn=1 -> leftmost page
+ * pn = index = -1: No more entries
*/
- dtpos = filp->f_pos;
- if (dtpos == 0) {
+ dtpos = ctx->pos;
+ if (dtpos < 2) {
/* build "." entry */
-
- if (filldir(dirent, ".", 1, filp->f_pos, ip->i_ino,
- DT_DIR))
+ ctx->pos = 1;
+ if (!dir_emit(ctx, ".", 1, ip->i_ino, DT_DIR))
return 0;
- dtoffset->index = 1;
- filp->f_pos = dtpos;
+ dtoffset->index = 2;
+ ctx->pos = dtpos;
}
if (dtoffset->pn == 0) {
- if (dtoffset->index == 1) {
+ if (dtoffset->index == 2) {
/* build ".." entry */
-
- if (filldir(dirent, "..", 2, filp->f_pos,
- PARENT(ip), DT_DIR))
+ if (!dir_emit(ctx, "..", 2, PARENT(ip), DT_DIR))
return 0;
} else {
jfs_err("jfs_readdir called with "
@@ -3146,18 +3156,18 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
dtoffset->pn = 1;
dtoffset->index = 0;
- filp->f_pos = dtpos;
+ ctx->pos = dtpos;
}
if (dtEmpty(ip)) {
- filp->f_pos = DIREND;
+ ctx->pos = DIREND;
return 0;
}
- if ((rc = dtReadNext(ip, &filp->f_pos, &btstack))) {
+ if ((rc = dtReadNext(ip, &ctx->pos, &btstack))) {
jfs_err("jfs_readdir: unexpected rc = %d "
"from dtReadNext", rc);
- filp->f_pos = DIREND;
+ ctx->pos = DIREND;
return 0;
}
/* get start leaf page and index */
@@ -3165,7 +3175,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* offset beyond directory eof ? */
if (bn < 0) {
- filp->f_pos = DIREND;
+ ctx->pos = DIREND;
return 0;
}
}
@@ -3174,7 +3184,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (dirent_buf == 0) {
DT_PUTPAGE(mp);
jfs_warn("jfs_readdir: __get_free_page failed!");
- filp->f_pos = DIREND;
+ ctx->pos = DIREND;
return -ENOMEM;
}
@@ -3227,6 +3237,12 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
jfs_dirent->position = unique_pos++;
}
+ /*
+ * We add 1 to the index because we may
+ * use a value of 2 internally, and NFSv4
+ * doesn't like that.
+ */
+ jfs_dirent->position++;
} else {
jfs_dirent->position = dtpos;
len = min(d_namleft, DTLHDRDATALEN_LEGACY);
@@ -3246,8 +3262,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* Sanity Check */
if (d_namleft == 0) {
jfs_error(ip->i_sb,
- "JFS:Dtree error: ino = "
- "%ld, bn=%Ld, index = %d",
+ "JFS:Dtree error: ino = %ld, bn=%lld, index = %d\n",
(long)ip->i_ino,
(long long)bn,
i);
@@ -3289,9 +3304,9 @@ skip_one:
jfs_dirent = (struct jfs_dirent *) dirent_buf;
while (jfs_dirents--) {
- filp->f_pos = jfs_dirent->position;
- if (filldir(dirent, jfs_dirent->name,
- jfs_dirent->name_len, filp->f_pos,
+ ctx->pos = jfs_dirent->position;
+ if (!dir_emit(ctx, jfs_dirent->name,
+ jfs_dirent->name_len,
jfs_dirent->ino, DT_UNKNOWN))
goto out;
jfs_dirent = next_jfs_dirent(jfs_dirent);
@@ -3303,7 +3318,7 @@ skip_one:
}
if (!overflow && (bn == 0)) {
- filp->f_pos = DIREND;
+ ctx->pos = DIREND;
break;
}
@@ -3340,7 +3355,7 @@ static int dtReadFirst(struct inode *ip, struct btstack * btstack)
BT_CLR(btstack); /* reset stack */
/*
- * descend leftmost path of the tree
+ * descend leftmost path of the tree
*
* by convention, root bn = 0.
*/
@@ -3367,7 +3382,7 @@ static int dtReadFirst(struct inode *ip, struct btstack * btstack)
*/
if (BT_STACK_FULL(btstack)) {
DT_PUTPAGE(mp);
- jfs_error(ip->i_sb, "dtReadFirst: btstack overrun");
+ jfs_error(ip->i_sb, "btstack overrun\n");
BT_STACK_DUMP(btstack);
return -EIO;
}
@@ -3756,7 +3771,7 @@ static int ciCompare(struct component_name * key, /* search key */
* across page boundary
*
* return: non-zero on error
- *
+ *
*/
static int ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp,
int ri, struct component_name * key, int flag)
@@ -3766,16 +3781,16 @@ static int ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp,
struct component_name lkey;
struct component_name rkey;
- lkey.name = (wchar_t *) kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
+ lkey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
GFP_KERNEL);
if (lkey.name == NULL)
- return -ENOSPC;
+ return -ENOMEM;
- rkey.name = (wchar_t *) kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
+ rkey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
GFP_KERNEL);
if (rkey.name == NULL) {
kfree(lkey.name);
- return -ENOSPC;
+ return -ENOMEM;
}
/* get left and right key */
@@ -4520,7 +4535,7 @@ int dtModify(tid_t tid, struct inode *ip,
struct ldtentry *entry;
/*
- * search for the entry to modify:
+ * search for the entry to modify:
*
* dtSearch() returns (leaf page pinned, index at which to modify).
*/