summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext2fs/inode.c53
1 files changed, 37 insertions, 16 deletions
diff --git a/ext2fs/inode.c b/ext2fs/inode.c
index 730b4e60..2d650b2e 100644
--- a/ext2fs/inode.c
+++ b/ext2fs/inode.c
@@ -193,7 +193,7 @@ diskfs_lost_hardrefs (struct node *np)
p = np->dn->fileinfo->p;
np->dn->fileinfo = 0;
diskfs_nref (np);
- pager_unreference (p);
+ ports_port_deref (p);
assert (np->references == 1 && np->light_references == 0);
@@ -370,12 +370,15 @@ write_node (struct node *np)
return NULL;
}
-/* Write all active disknodes into the ext2_inode pager. */
-void
-write_all_disknodes ()
+/* For each active node, call FUN. The node is to be locked around the call
+ to FUN. If FUN returns non-zero for any node, then immediately stop, and
+ return that value. */
+error_t
+diskfs_node_iterate (error_t (*fun)(struct node *))
{
+ error_t err = 0;
int n, num_nodes = 0;
- struct node *np, **node_list, **p;
+ struct node *node, **node_list, **p;
spin_lock (&diskfs_node_refcnt_lock);
@@ -386,16 +389,16 @@ write_all_disknodes ()
individual node locks). */
for (n = 0; n < INOHSZ; n++)
- for (np = nodehash[n]; np; np = np->dn->hnext)
+ for (node = nodehash[n]; node; node = node->dn->hnext)
num_nodes++;
node_list = alloca (num_nodes * sizeof (struct node *));
p = node_list;
for (n = 0; n < INOHSZ; n++)
- for (np = nodehash[n]; np; np = np->dn->hnext)
+ for (node = nodehash[n]; node; node = node->dn->hnext)
{
- *p++ = np;
- np->references++;
+ *p++ = node;
+ node->references++;
}
spin_unlock (&diskfs_node_refcnt_lock);
@@ -403,24 +406,42 @@ write_all_disknodes ()
p = node_list;
while (num_nodes-- > 0)
{
- struct ext2_inode *di;
+ node = *p++;
+ if (!err)
+ {
+ mutex_lock (&node->lock);
+ err = (*fun)(node);
+ mutex_unlock (&node->lock);
+ }
+ diskfs_nrele (node);
+ }
+
+ return err;
+}
- np = *p++;
- mutex_lock (&np->lock);
+/* Write all active disknodes into the ext2_inode pager. */
+void
+write_all_disknodes ()
+{
+ error_t write_one_disknode (struct node *node)
+ {
+ struct ext2_inode *di;
- diskfs_set_node_times (np);
+ diskfs_set_node_times (node);
/* Sync the indirect blocks here; they'll all be done before any
inodes. Waiting for them shouldn't be too bad. */
- pokel_sync (&np->dn->indir_pokel, 1);
+ pokel_sync (&node->dn->indir_pokel, 1);
/* Update the inode image. */
- di = write_node (np);
+ di = write_node (node);
if (di)
record_global_poke (di);
- diskfs_nput (np);
+ return 0;
}
+
+ diskfs_node_iterate (write_one_disknode);
}
/* Sync the info in NP->dn_stat and any associated format-specific