diff -urpNX dontdiff linux-2.5.24/fs/buffer.c linux-2.5.24-flock/fs/buffer.c --- linux-2.5.24/fs/buffer.c Thu Jun 20 16:53:42 2002 +++ linux-2.5.24-flock/fs/buffer.c Wed Jul 3 13:45:49 2002 @@ -685,8 +685,7 @@ void buffer_insert_list(spinlock_t *lock struct buffer_head *bh, struct list_head *list) { spin_lock(lock); - list_del(&bh->b_assoc_buffers); - list_add(&bh->b_assoc_buffers, list); + list_move(&bh->b_assoc_buffers, list); spin_unlock(lock); } @@ -864,12 +863,12 @@ EXPORT_SYMBOL(mark_buffer_dirty_inode); * dirtied buffers don't. After all, we don't want fsync to last * forever if somebody is actively writing to the file. * - * Do this in two main stages: first we copy dirty buffers to a - * temporary inode list, queueing the writes as we go. Then we clean - * up, waiting for those writes to complete. + * Do this in three stages: first we copy dirty buffers to a + * temporary inode list, second we queue the writes. Then we wait + * for those writes to complete. * - * During this second stage, any subsequent updates to the file may end - * up refiling the buffer on the original inode's dirty list again, so + * During the second or third stage, any subsequent updates to the file may + * end up refiling the buffer on the original inode's dirty list again, so * there is a chance we will end up with a buffer queued for write but * not yet completed on that list. So, as a final cleanup we go through * the osync code to catch these locked, dirty buffers without requeuing @@ -878,29 +877,32 @@ EXPORT_SYMBOL(mark_buffer_dirty_inode); int fsync_buffers_list(spinlock_t *lock, struct list_head *list) { struct buffer_head *bh; - struct list_head tmp; + LIST_HEAD(wait); + struct list_head *entry; int err = 0, err2; - INIT_LIST_HEAD(&tmp); - spin_lock(lock); while (!list_empty(list)) { bh = BH_ENTRY(list->next); list_del_init(&bh->b_assoc_buffers); if (buffer_dirty(bh) || buffer_locked(bh)) { - list_add(&bh->b_assoc_buffers, &tmp); - if (buffer_dirty(bh)) { - get_bh(bh); - spin_unlock(lock); - ll_rw_block(WRITE, 1, &bh); - brelse(bh); - spin_lock(lock); - } + list_add(&bh->b_assoc_buffers, &wait); + } + } + + list_for_each(entry, &wait) { + bh = BH_ENTRY(entry); + if (buffer_dirty(bh)) { + get_bh(bh); + spin_unlock(lock); + ll_rw_block(WRITE, 1, &bh); + brelse(bh); + spin_lock(lock); } } - while (!list_empty(&tmp)) { - bh = BH_ENTRY(tmp.prev); + while (!list_empty(&wait)) { + bh = BH_ENTRY(wait.prev); __remove_assoc_queue(bh); get_bh(bh); spin_unlock(lock); .