@@ -357,7 +357,7 @@ u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
357
357
358
358
struct fuse_writepage_args {
359
359
struct fuse_io_args ia ;
360
- struct list_head writepages_entry ;
360
+ struct rb_node writepages_entry ;
361
361
struct list_head queue_entry ;
362
362
struct fuse_writepage_args * next ;
363
363
struct inode * inode ;
@@ -366,17 +366,23 @@ struct fuse_writepage_args {
366
366
static struct fuse_writepage_args * fuse_find_writeback (struct fuse_inode * fi ,
367
367
pgoff_t idx_from , pgoff_t idx_to )
368
368
{
369
- struct fuse_writepage_args * wpa ;
369
+ struct rb_node * n ;
370
+
371
+ n = fi -> writepages .rb_node ;
370
372
371
- list_for_each_entry (wpa , & fi -> writepages , writepages_entry ) {
373
+ while (n ) {
374
+ struct fuse_writepage_args * wpa ;
372
375
pgoff_t curr_index ;
373
376
377
+ wpa = rb_entry (n , struct fuse_writepage_args , writepages_entry );
374
378
WARN_ON (get_fuse_inode (wpa -> inode ) != fi );
375
379
curr_index = wpa -> ia .write .in .offset >> PAGE_SHIFT ;
376
- if (idx_from < curr_index + wpa -> ia .ap .num_pages &&
377
- curr_index <= idx_to ) {
380
+ if (idx_from >= curr_index + wpa -> ia .ap .num_pages )
381
+ n = n -> rb_right ;
382
+ else if (idx_to < curr_index )
383
+ n = n -> rb_left ;
384
+ else
378
385
return wpa ;
379
- }
380
386
}
381
387
return NULL ;
382
388
}
@@ -445,9 +451,6 @@ static int fuse_flush(struct file *file, fl_owner_t id)
445
451
if (is_bad_inode (inode ))
446
452
return - EIO ;
447
453
448
- if (fc -> no_flush )
449
- return 0 ;
450
-
451
454
err = write_inode_now (inode , 1 );
452
455
if (err )
453
456
return err ;
@@ -460,6 +463,10 @@ static int fuse_flush(struct file *file, fl_owner_t id)
460
463
if (err )
461
464
return err ;
462
465
466
+ err = 0 ;
467
+ if (fc -> no_flush )
468
+ goto inval_attr_out ;
469
+
463
470
memset (& inarg , 0 , sizeof (inarg ));
464
471
inarg .fh = ff -> fh ;
465
472
inarg .lock_owner = fuse_lock_owner_id (fc , id );
@@ -475,6 +482,14 @@ static int fuse_flush(struct file *file, fl_owner_t id)
475
482
fc -> no_flush = 1 ;
476
483
err = 0 ;
477
484
}
485
+
486
+ inval_attr_out :
487
+ /*
488
+ * In memory i_blocks is not maintained by fuse, if writeback cache is
489
+ * enabled, i_blocks from cached attr may not be accurate.
490
+ */
491
+ if (!err && fc -> writeback_cache )
492
+ fuse_invalidate_attr (inode );
478
493
return err ;
479
494
}
480
495
@@ -712,6 +727,7 @@ static ssize_t fuse_async_req_send(struct fuse_conn *fc,
712
727
spin_unlock (& io -> lock );
713
728
714
729
ia -> ap .args .end = fuse_aio_complete_req ;
730
+ ia -> ap .args .may_block = io -> should_dirty ;
715
731
err = fuse_simple_background (fc , & ia -> ap .args , GFP_KERNEL );
716
732
if (err )
717
733
fuse_aio_complete_req (fc , & ia -> ap .args , err );
@@ -1570,7 +1586,7 @@ static void fuse_writepage_finish(struct fuse_conn *fc,
1570
1586
struct backing_dev_info * bdi = inode_to_bdi (inode );
1571
1587
int i ;
1572
1588
1573
- list_del (& wpa -> writepages_entry );
1589
+ rb_erase (& wpa -> writepages_entry , & fi -> writepages );
1574
1590
for (i = 0 ; i < ap -> num_pages ; i ++ ) {
1575
1591
dec_wb_stat (& bdi -> wb , WB_WRITEBACK );
1576
1592
dec_node_page_state (ap -> pages [i ], NR_WRITEBACK_TEMP );
@@ -1658,6 +1674,36 @@ __acquires(fi->lock)
1658
1674
}
1659
1675
}
1660
1676
1677
+ static void tree_insert (struct rb_root * root , struct fuse_writepage_args * wpa )
1678
+ {
1679
+ pgoff_t idx_from = wpa -> ia .write .in .offset >> PAGE_SHIFT ;
1680
+ pgoff_t idx_to = idx_from + wpa -> ia .ap .num_pages - 1 ;
1681
+ struct rb_node * * p = & root -> rb_node ;
1682
+ struct rb_node * parent = NULL ;
1683
+
1684
+ WARN_ON (!wpa -> ia .ap .num_pages );
1685
+ while (* p ) {
1686
+ struct fuse_writepage_args * curr ;
1687
+ pgoff_t curr_index ;
1688
+
1689
+ parent = * p ;
1690
+ curr = rb_entry (parent , struct fuse_writepage_args ,
1691
+ writepages_entry );
1692
+ WARN_ON (curr -> inode != wpa -> inode );
1693
+ curr_index = curr -> ia .write .in .offset >> PAGE_SHIFT ;
1694
+
1695
+ if (idx_from >= curr_index + curr -> ia .ap .num_pages )
1696
+ p = & (* p )-> rb_right ;
1697
+ else if (idx_to < curr_index )
1698
+ p = & (* p )-> rb_left ;
1699
+ else
1700
+ return (void ) WARN_ON (true);
1701
+ }
1702
+
1703
+ rb_link_node (& wpa -> writepages_entry , parent , p );
1704
+ rb_insert_color (& wpa -> writepages_entry , root );
1705
+ }
1706
+
1661
1707
static void fuse_writepage_end (struct fuse_conn * fc , struct fuse_args * args ,
1662
1708
int error )
1663
1709
{
@@ -1676,7 +1722,7 @@ static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_args *args,
1676
1722
wpa -> next = next -> next ;
1677
1723
next -> next = NULL ;
1678
1724
next -> ia .ff = fuse_file_get (wpa -> ia .ff );
1679
- list_add ( & next -> writepages_entry , & fi -> writepages );
1725
+ tree_insert ( & fi -> writepages , next );
1680
1726
1681
1727
/*
1682
1728
* Skip fuse_flush_writepages() to make it easy to crop requests
@@ -1811,7 +1857,7 @@ static int fuse_writepage_locked(struct page *page)
1811
1857
inc_node_page_state (tmp_page , NR_WRITEBACK_TEMP );
1812
1858
1813
1859
spin_lock (& fi -> lock );
1814
- list_add ( & wpa -> writepages_entry , & fi -> writepages );
1860
+ tree_insert ( & fi -> writepages , wpa );
1815
1861
list_add_tail (& wpa -> queue_entry , & fi -> queued_writes );
1816
1862
fuse_flush_writepages (inode );
1817
1863
spin_unlock (& fi -> lock );
@@ -1923,10 +1969,10 @@ static bool fuse_writepage_in_flight(struct fuse_writepage_args *new_wpa,
1923
1969
WARN_ON (new_ap -> num_pages != 0 );
1924
1970
1925
1971
spin_lock (& fi -> lock );
1926
- list_del (& new_wpa -> writepages_entry );
1972
+ rb_erase (& new_wpa -> writepages_entry , & fi -> writepages );
1927
1973
old_wpa = fuse_find_writeback (fi , page -> index , page -> index );
1928
1974
if (!old_wpa ) {
1929
- list_add ( & new_wpa -> writepages_entry , & fi -> writepages );
1975
+ tree_insert ( & fi -> writepages , new_wpa );
1930
1976
spin_unlock (& fi -> lock );
1931
1977
return false;
1932
1978
}
@@ -2041,7 +2087,7 @@ static int fuse_writepages_fill(struct page *page,
2041
2087
wpa -> inode = inode ;
2042
2088
2043
2089
spin_lock (& fi -> lock );
2044
- list_add ( & wpa -> writepages_entry , & fi -> writepages );
2090
+ tree_insert ( & fi -> writepages , wpa );
2045
2091
spin_unlock (& fi -> lock );
2046
2092
2047
2093
data -> wpa = wpa ;
@@ -3235,25 +3281,39 @@ static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in,
3235
3281
if (file_inode (file_in )-> i_sb != file_inode (file_out )-> i_sb )
3236
3282
return - EXDEV ;
3237
3283
3238
- if (fc -> writeback_cache ) {
3239
- inode_lock (inode_in );
3240
- err = fuse_writeback_range (inode_in , pos_in , pos_in + len );
3241
- inode_unlock (inode_in );
3242
- if (err )
3243
- return err ;
3244
- }
3284
+ inode_lock (inode_in );
3285
+ err = fuse_writeback_range (inode_in , pos_in , pos_in + len - 1 );
3286
+ inode_unlock (inode_in );
3287
+ if (err )
3288
+ return err ;
3245
3289
3246
3290
inode_lock (inode_out );
3247
3291
3248
3292
err = file_modified (file_out );
3249
3293
if (err )
3250
3294
goto out ;
3251
3295
3252
- if (fc -> writeback_cache ) {
3253
- err = fuse_writeback_range (inode_out , pos_out , pos_out + len );
3254
- if (err )
3255
- goto out ;
3256
- }
3296
+ /*
3297
+ * Write out dirty pages in the destination file before sending the COPY
3298
+ * request to userspace. After the request is completed, truncate off
3299
+ * pages (including partial ones) from the cache that have been copied,
3300
+ * since these contain stale data at that point.
3301
+ *
3302
+ * This should be mostly correct, but if the COPY writes to partial
3303
+ * pages (at the start or end) and the parts not covered by the COPY are
3304
+ * written through a memory map after calling fuse_writeback_range(),
3305
+ * then these partial page modifications will be lost on truncation.
3306
+ *
3307
+ * It is unlikely that someone would rely on such mixed style
3308
+ * modifications. Yet this does give less guarantees than if the
3309
+ * copying was performed with write(2).
3310
+ *
3311
+ * To fix this a i_mmap_sem style lock could be used to prevent new
3312
+ * faults while the copy is ongoing.
3313
+ */
3314
+ err = fuse_writeback_range (inode_out , pos_out , pos_out + len - 1 );
3315
+ if (err )
3316
+ goto out ;
3257
3317
3258
3318
if (is_unstable )
3259
3319
set_bit (FUSE_I_SIZE_UNSTABLE , & fi_out -> state );
@@ -3274,6 +3334,10 @@ static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in,
3274
3334
if (err )
3275
3335
goto out ;
3276
3336
3337
+ truncate_inode_pages_range (inode_out -> i_mapping ,
3338
+ ALIGN_DOWN (pos_out , PAGE_SIZE ),
3339
+ ALIGN (pos_out + outarg .size , PAGE_SIZE ) - 1 );
3340
+
3277
3341
if (fc -> writeback_cache ) {
3278
3342
fuse_write_update_size (inode_out , pos_out + outarg .size );
3279
3343
file_update_time (file_out );
@@ -3351,5 +3415,5 @@ void fuse_init_file_inode(struct inode *inode)
3351
3415
INIT_LIST_HEAD (& fi -> queued_writes );
3352
3416
fi -> writectr = 0 ;
3353
3417
init_waitqueue_head (& fi -> page_waitq );
3354
- INIT_LIST_HEAD ( & fi -> writepages ) ;
3418
+ fi -> writepages = RB_ROOT ;
3355
3419
}
0 commit comments