* fs_sync() now holds the sVnodeMutex while iterating over the mount list.
* This has the advantage that we no longer need to call get_vnode(), and instead can use lookup_vnode(). * This means at least most of the "corrupted BFS inode" messages should be gone; they were produced when fs_sync() tried to get already deleted vnodes. This was actually harmless, but doesn't really help in trusting your system :-) * Also, it no longer tries to write back removed vnodes. * And finally, it now uses a marker vnode when iterating over the list, so that it doesn't need to break out of the loop anymore, and can always sync all willing vnodes. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28212 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c4b429ca1c
commit
552c8edcd1
@ -7142,50 +7142,62 @@ fs_sync(dev_t device)
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
struct vnode marker;
|
||||
marker.remove = true;
|
||||
|
||||
// First, synchronize all file caches
|
||||
|
||||
struct vnode *previousVnode = NULL;
|
||||
while (true) {
|
||||
MutexLocker locker(sVnodeMutex);
|
||||
|
||||
// synchronize access to vnode list
|
||||
recursive_lock_lock(&mount->rlock);
|
||||
|
||||
struct vnode *vnode = previousVnode;
|
||||
do {
|
||||
struct vnode *vnode;
|
||||
if (!marker.remove) {
|
||||
vnode = (struct vnode *)list_get_next_item(&mount->vnodes, &marker);
|
||||
list_remove_item(&mount->vnodes, &marker);
|
||||
marker.remove = true;
|
||||
} else
|
||||
vnode = (struct vnode *)list_get_first_item(&mount->vnodes);
|
||||
|
||||
while (vnode != NULL && (vnode->cache == NULL
|
||||
|| vnode->remove || vnode->busy)) {
|
||||
// TODO: we could track writes (and writable mapped vnodes)
|
||||
// and have a simple flag that we could test for here
|
||||
vnode = (struct vnode *)list_get_next_item(&mount->vnodes, vnode);
|
||||
} while (vnode != NULL && vnode->cache == NULL);
|
||||
}
|
||||
|
||||
ino_t id = -1;
|
||||
if (vnode != NULL)
|
||||
id = vnode->id;
|
||||
if (vnode != NULL) {
|
||||
// insert marker vnode again
|
||||
list_insert_item_before(&mount->vnodes,
|
||||
list_get_next_item(&mount->vnodes, vnode), &marker);
|
||||
marker.remove = false;
|
||||
}
|
||||
|
||||
recursive_lock_unlock(&mount->rlock);
|
||||
|
||||
if (vnode == NULL)
|
||||
break;
|
||||
|
||||
// acquire a reference to the vnode
|
||||
vnode = lookup_vnode(mount->id, vnode->id);
|
||||
if (vnode == NULL || vnode->busy)
|
||||
continue;
|
||||
|
||||
if (get_vnode(mount->id, id, &vnode, true, false) == B_OK) {
|
||||
if (previousVnode != NULL)
|
||||
put_vnode(previousVnode);
|
||||
if (vnode->ref_count == 0) {
|
||||
// this vnode has been unused before
|
||||
list_remove_item(&sUnusedVnodeList, vnode);
|
||||
sUnusedVnodes--;
|
||||
}
|
||||
inc_vnode_ref_count(vnode);
|
||||
|
||||
if (vnode->cache != NULL)
|
||||
locker.Unlock();
|
||||
|
||||
if (vnode->cache != NULL && !vnode->remove)
|
||||
vnode->cache->WriteModified();
|
||||
|
||||
// the next vnode might change until we lock the vnode list again,
|
||||
// but this vnode won't go away since we keep a reference to it.
|
||||
previousVnode = vnode;
|
||||
} else {
|
||||
dprintf("syncing of mount %ld stopped due to vnode %Ld.\n",
|
||||
mount->id, id);
|
||||
break;
|
||||
put_vnode(vnode);
|
||||
}
|
||||
}
|
||||
|
||||
if (previousVnode != NULL)
|
||||
put_vnode(previousVnode);
|
||||
|
||||
// And then, let the file systems do their synchronizing work
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user