--- loop.c 2006-05-04 18:48:34.000000000 -0700 +++ loop.c 2006-05-04 18:52:42.000000000 -0700 @@ -467,16 +467,53 @@ return ret; } +/* + * This is best effort. We really wouldn't know what to do with a returned + * error. This code is taken from the implementation of fsync. + */ +static void sync_file(struct file * file) +{ + struct address_space *mapping; + + if (!file->f_op || !file->f_op->fsync) + return; + + mapping = file->f_mapping; + + current->flags |= PF_SYNCWRITE; + filemap_fdatawrite(mapping); + + /* + * We need to protect against concurrent writers, + * which could cause livelocks in fsync_buffers_list + */ + mutex_lock(&mapping->host->i_mutex); + file->f_op->fsync(file, file->f_dentry, 1); + mutex_unlock(&mapping->host->i_mutex); + + filemap_fdatawait(mapping); + current->flags &= ~PF_SYNCWRITE; +} + static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) { loff_t pos; int ret; + int sync = bio_sync(bio); + int barrier = bio_barrier(bio); + + if (barrier) + sync_file(lo->lo_backing_file); pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset; if (bio_rw(bio) == WRITE) ret = lo_send(lo, bio, lo->lo_blocksize, pos); else ret = lo_receive(lo, bio, lo->lo_blocksize, pos); + + if (barrier || sync) + sync_file(lo->lo_backing_file); + return ret; }