Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 213263
b: refs/heads/master
c: 78ae525
h: refs/heads/master
i:
  213261: b70b3eb
  213259: 93e1918
  213255: c4a14f0
  213247: bf2821d
v: v3
  • Loading branch information
Dave Chinner authored and Alex Elder committed Oct 18, 2010
1 parent d3afa15 commit b44cf95
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 24 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e13de955ca67b0bd1cec9a2f9352a3053065bf7f
refs/heads/master: 78ae5256768b91f25ce7a4eb9f56d563e302cc10
66 changes: 44 additions & 22 deletions trunk/fs/xfs/linux-2.6/xfs_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@
#include <linux/kthread.h>
#include <linux/freezer.h>

/*
* The inode lookup is done in batches to keep the amount of lock traffic and
* radix tree lookups to a minimum. The batch size is a trade off between
* lookup reduction and stack usage. This is in the reclaim path, so we can't
* be too greedy.
*/
#define XFS_LOOKUP_BATCH 32

STATIC int
xfs_inode_ag_walk_grab(
struct xfs_inode *ip)
Expand Down Expand Up @@ -66,7 +74,6 @@ xfs_inode_ag_walk_grab(
return 0;
}


STATIC int
xfs_inode_ag_walk(
struct xfs_mount *mp,
Expand All @@ -79,54 +86,69 @@ xfs_inode_ag_walk(
int last_error = 0;
int skipped;
int done;
int nr_found;

restart:
done = 0;
skipped = 0;
first_index = 0;
nr_found = 0;
do {
struct xfs_inode *batch[XFS_LOOKUP_BATCH];
int error = 0;
int nr_found;
xfs_inode_t *ip;
int i;

read_lock(&pag->pag_ici_lock);
nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
(void **)&ip, first_index, 1);
(void **)batch, first_index,
XFS_LOOKUP_BATCH);
if (!nr_found) {
read_unlock(&pag->pag_ici_lock);
break;
}

/*
* Update the index for the next lookup. Catch overflows
* into the next AG range which can occur if we have inodes
* in the last block of the AG and we are currently
* pointing to the last inode.
* Grab the inodes before we drop the lock. if we found
* nothing, nr == 0 and the loop will be skipped.
*/
first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
done = 1;
for (i = 0; i < nr_found; i++) {
struct xfs_inode *ip = batch[i];

if (xfs_inode_ag_walk_grab(ip)) {
read_unlock(&pag->pag_ici_lock);
continue;
if (done || xfs_inode_ag_walk_grab(ip))
batch[i] = NULL;

/*
* Update the index for the next lookup. Catch overflows
* into the next AG range which can occur if we have inodes
* in the last block of the AG and we are currently
* pointing to the last inode.
*/
first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino))
done = 1;
}

/* unlock now we've grabbed the inodes. */
read_unlock(&pag->pag_ici_lock);

error = execute(ip, pag, flags);
IRELE(ip);
if (error == EAGAIN) {
skipped++;
continue;
for (i = 0; i < nr_found; i++) {
if (!batch[i])
continue;
error = execute(batch[i], pag, flags);
IRELE(batch[i]);
if (error == EAGAIN) {
skipped++;
continue;
}
if (error && last_error != EFSCORRUPTED)
last_error = error;
}
if (error)
last_error = error;

/* bail out if the filesystem is corrupted. */
if (error == EFSCORRUPTED)
break;

} while (!done);
} while (nr_found && !done);

if (skipped) {
delay(1);
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/xfs/linux-2.6/xfs_sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip);
void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag,
struct xfs_inode *ip);

int xfs_sync_inode_valid(struct xfs_inode *ip, struct xfs_perag *pag);
int xfs_sync_inode_grab(struct xfs_inode *ip);
int xfs_inode_ag_iterator(struct xfs_mount *mp,
int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags),
int flags);
Expand Down

0 comments on commit b44cf95

Please sign in to comment.