Skip to content

Commit 02c24a8

Browse files
Josef BacikAl Viro
Josef Bacik
authored and
Al Viro
committed
fs: push i_mutex and filemap_write_and_wait down into ->fsync() handlers
Btrfs needs to be able to control how filemap_write_and_wait_range() is called in fsync to make it less of a painful operation, so push down taking i_mutex and the calling of filemap_write_and_wait() down into the ->fsync() handlers. Some file systems can drop taking the i_mutex altogether it seems, like ext3 and ocfs2. For correctness sake I just pushed everything down in all cases to make sure that we keep the current behavior the same for everybody, and then each individual fs maintainer can make up their mind about what to do from there. Thanks, Acked-by: Jan Kara <[email protected]> Signed-off-by: Josef Bacik <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent 2273506 commit 02c24a8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+462
-164
lines changed

Documentation/filesystems/Locking

+2-4
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ prototypes:
412412
int (*open) (struct inode *, struct file *);
413413
int (*flush) (struct file *);
414414
int (*release) (struct inode *, struct file *);
415-
int (*fsync) (struct file *, int datasync);
415+
int (*fsync) (struct file *, loff_t start, loff_t end, int datasync);
416416
int (*aio_fsync) (struct kiocb *, int datasync);
417417
int (*fasync) (int, struct file *, int);
418418
int (*lock) (struct file *, int, struct file_lock *);
@@ -438,9 +438,7 @@ prototypes:
438438

439439
locking rules:
440440
All may block except for ->setlease.
441-
No VFS locks held on entry except for ->fsync and ->setlease.
442-
443-
->fsync() has i_mutex on inode.
441+
No VFS locks held on entry except for ->setlease.
444442

445443
->setlease has the file_list_lock held and must not sleep.
446444

Documentation/filesystems/porting

+7
Original file line numberDiff line numberDiff line change
@@ -421,3 +421,10 @@ data and there is a virtual hole at the end of the file. So if the provided
421421
offset is less than i_size and SEEK_DATA is specified, return the same offset.
422422
If the above is true for the offset and you are given SEEK_HOLE, return the end
423423
of the file. If the offset is i_size or greater return -ENXIO in either case.
424+
425+
[mandatory]
426+
If you have your own ->fsync() you must make sure to call
427+
filemap_write_and_wait_range() so that all dirty pages are synced out properly.
428+
You must also keep in mind that ->fsync() is not called with i_mutex held
429+
anymore, so if you require i_mutex locking you must make sure to take it and
430+
release it yourself.

Documentation/filesystems/vfs.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ struct file_operations {
777777
int (*open) (struct inode *, struct file *);
778778
int (*flush) (struct file *);
779779
int (*release) (struct inode *, struct file *);
780-
int (*fsync) (struct file *, int datasync);
780+
int (*fsync) (struct file *, loff_t, loff_t, int datasync);
781781
int (*aio_fsync) (struct kiocb *, int datasync);
782782
int (*fasync) (int, struct file *, int);
783783
int (*lock) (struct file *, int, struct file_lock *);

arch/powerpc/platforms/cell/spufs/file.c

+9-2
Original file line numberDiff line numberDiff line change
@@ -1850,9 +1850,16 @@ static int spufs_mfc_flush(struct file *file, fl_owner_t id)
18501850
return ret;
18511851
}
18521852

1853-
static int spufs_mfc_fsync(struct file *file, int datasync)
1853+
static int spufs_mfc_fsync(struct file *file, loff_t start, loff_t end, int datasync)
18541854
{
1855-
return spufs_mfc_flush(file, NULL);
1855+
struct inode *inode = file->f_path.dentry->d_inode;
1856+
int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
1857+
if (!err) {
1858+
mutex_lock(&inode->i_mutex);
1859+
err = spufs_mfc_flush(file, NULL);
1860+
mutex_unlock(&inode->i_mutex);
1861+
}
1862+
return err;
18561863
}
18571864

18581865
static int spufs_mfc_fasync(int fd, struct file *file, int on)

drivers/char/ps3flash.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -309,9 +309,14 @@ static int ps3flash_flush(struct file *file, fl_owner_t id)
309309
return ps3flash_writeback(ps3flash_dev);
310310
}
311311

312-
static int ps3flash_fsync(struct file *file, int datasync)
312+
static int ps3flash_fsync(struct file *file, loff_t start, loff_t end, int datasync)
313313
{
314-
return ps3flash_writeback(ps3flash_dev);
314+
struct inode *inode = file->f_path.dentry->d_inode;
315+
int err;
316+
mutex_lock(&inode->i_mutex);
317+
err = ps3flash_writeback(ps3flash_dev);
318+
mutex_unlock(&inode->i_mutex);
319+
return err;
315320
}
316321

317322
static irqreturn_t ps3flash_interrupt(int irq, void *data)

drivers/mtd/ubi/cdev.c

+7-3
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,16 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin)
189189
return new_offset;
190190
}
191191

192-
static int vol_cdev_fsync(struct file *file, int datasync)
192+
static int vol_cdev_fsync(struct file *file, loff_t start, loff_t end, int datasync)
193193
{
194194
struct ubi_volume_desc *desc = file->private_data;
195195
struct ubi_device *ubi = desc->vol->ubi;
196-
197-
return ubi_sync(ubi->ubi_num);
196+
struct inode *inode = file->f_path.dentry->d_inode;
197+
int err;
198+
mutex_lock(&inode->i_mutex);
199+
err = ubi_sync(ubi->ubi_num);
200+
mutex_unlock(&inode->i_mutex);
201+
return err;
198202
}
199203

200204

drivers/staging/pohmelfs/inode.c

+8-3
Original file line numberDiff line numberDiff line change
@@ -887,11 +887,16 @@ static struct inode *pohmelfs_alloc_inode(struct super_block *sb)
887887
/*
888888
* We want fsync() to work on POHMELFS.
889889
*/
890-
static int pohmelfs_fsync(struct file *file, int datasync)
890+
static int pohmelfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
891891
{
892892
struct inode *inode = file->f_mapping->host;
893-
894-
return sync_inode_metadata(inode, 1);
893+
int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
894+
if (!err) {
895+
mutex_lock(&inode->i_mutex);
896+
err = sync_inode_metadata(inode, 1);
897+
mutex_unlock(&inode->i_mutex);
898+
}
899+
return err;
895900
}
896901

897902
ssize_t pohmelfs_write(struct file *file, const char __user *buf,

drivers/usb/gadget/printer.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -795,12 +795,14 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
795795
}
796796

797797
static int
798-
printer_fsync(struct file *fd, int datasync)
798+
printer_fsync(struct file *fd, loff_t start, loff_t end, int datasync)
799799
{
800800
struct printer_dev *dev = fd->private_data;
801+
struct inode *inode = fd->f_path.dentry->d_inode;
801802
unsigned long flags;
802803
int tx_list_empty;
803804

805+
mutex_lock(&inode->i_mutex);
804806
spin_lock_irqsave(&dev->lock, flags);
805807
tx_list_empty = (likely(list_empty(&dev->tx_reqs)));
806808
spin_unlock_irqrestore(&dev->lock, flags);
@@ -810,6 +812,7 @@ printer_fsync(struct file *fd, int datasync)
810812
wait_event_interruptible(dev->tx_flush_wait,
811813
(likely(list_empty(&dev->tx_reqs_active))));
812814
}
815+
mutex_unlock(&inode->i_mutex);
813816

814817
return 0;
815818
}

drivers/video/fb_defio.c

+9-2
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,26 @@ static int fb_deferred_io_fault(struct vm_area_struct *vma,
6666
return 0;
6767
}
6868

69-
int fb_deferred_io_fsync(struct file *file, int datasync)
69+
int fb_deferred_io_fsync(struct file *file, loff_t start, loff_t end, int datasync)
7070
{
7171
struct fb_info *info = file->private_data;
72+
struct inode *inode = file->f_path.dentry->d_inode;
73+
int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
74+
if (err)
75+
return err;
7276

7377
/* Skip if deferred io is compiled-in but disabled on this fbdev */
7478
if (!info->fbdefio)
7579
return 0;
7680

81+
mutex_lock(&inode->i_mutex);
7782
/* Kill off the delayed work */
7883
cancel_delayed_work_sync(&info->deferred_work);
7984

8085
/* Run it immediately */
81-
return schedule_delayed_work(&info->deferred_work, 0);
86+
err = schedule_delayed_work(&info->deferred_work, 0);
87+
mutex_unlock(&inode->i_mutex);
88+
return err;
8289
}
8390
EXPORT_SYMBOL_GPL(fb_deferred_io_fsync);
8491

fs/9p/v9fs_vfs.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64);
7070
ssize_t v9fs_fid_readn(struct p9_fid *, char *, char __user *, u32, u64);
7171
void v9fs_blank_wstat(struct p9_wstat *wstat);
7272
int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *);
73-
int v9fs_file_fsync_dotl(struct file *filp, int datasync);
73+
int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end,
74+
int datasync);
7475
ssize_t v9fs_file_write_internal(struct inode *, struct p9_fid *,
7576
const char __user *, size_t, loff_t *, int);
7677
int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode);

fs/9p/vfs_file.c

+20-2
Original file line numberDiff line numberDiff line change
@@ -519,32 +519,50 @@ v9fs_file_write(struct file *filp, const char __user * data,
519519
}
520520

521521

522-
static int v9fs_file_fsync(struct file *filp, int datasync)
522+
static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end,
523+
int datasync)
523524
{
524525
struct p9_fid *fid;
526+
struct inode *inode = filp->f_mapping->host;
525527
struct p9_wstat wstat;
526528
int retval;
527529

530+
retval = filemap_write_and_wait_range(inode->i_mapping, start, end);
531+
if (retval)
532+
return retval;
533+
534+
mutex_lock(&inode->i_mutex);
528535
P9_DPRINTK(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync);
529536

530537
fid = filp->private_data;
531538
v9fs_blank_wstat(&wstat);
532539

533540
retval = p9_client_wstat(fid, &wstat);
541+
mutex_unlock(&inode->i_mutex);
542+
534543
return retval;
535544
}
536545

537-
int v9fs_file_fsync_dotl(struct file *filp, int datasync)
546+
int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end,
547+
int datasync)
538548
{
539549
struct p9_fid *fid;
550+
struct inode *inode = filp->f_mapping->host;
540551
int retval;
541552

553+
retval = filemap_write_and_wait_range(inode->i_mapping, start, end);
554+
if (retval)
555+
return retval;
556+
557+
mutex_lock(&inode->i_mutex);
542558
P9_DPRINTK(P9_DEBUG_VFS, "v9fs_file_fsync_dotl: filp %p datasync %x\n",
543559
filp, datasync);
544560

545561
fid = filp->private_data;
546562

547563
retval = p9_client_fsync(fid, datasync);
564+
mutex_unlock(&inode->i_mutex);
565+
548566
return retval;
549567
}
550568

fs/affs/affs.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ extern int affs_add_entry(struct inode *dir, struct inode *inode, struct dent
182182

183183
void affs_free_prealloc(struct inode *inode);
184184
extern void affs_truncate(struct inode *);
185-
int affs_file_fsync(struct file *, int);
185+
int affs_file_fsync(struct file *, loff_t, loff_t, int);
186186

187187
/* dir.c */
188188

fs/affs/file.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -923,14 +923,20 @@ affs_truncate(struct inode *inode)
923923
affs_free_prealloc(inode);
924924
}
925925

926-
int affs_file_fsync(struct file *filp, int datasync)
926+
int affs_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
927927
{
928928
struct inode *inode = filp->f_mapping->host;
929929
int ret, err;
930930

931+
err = filemap_write_and_wait_range(inode->i_mapping, start, end);
932+
if (err)
933+
return err;
934+
935+
mutex_lock(&inode->i_mutex);
931936
ret = write_inode_now(inode, 0);
932937
err = sync_blockdev(inode->i_sb->s_bdev);
933938
if (!ret)
934939
ret = err;
940+
mutex_unlock(&inode->i_mutex);
935941
return ret;
936942
}

fs/afs/internal.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,7 @@ extern void afs_pages_written_back(struct afs_vnode *, struct afs_call *);
750750
extern ssize_t afs_file_write(struct kiocb *, const struct iovec *,
751751
unsigned long, loff_t);
752752
extern int afs_writeback_all(struct afs_vnode *);
753-
extern int afs_fsync(struct file *, int);
753+
extern int afs_fsync(struct file *, loff_t, loff_t, int);
754754

755755

756756
/*****************************************************************************/

fs/afs/write.c

+14-4
Original file line numberDiff line numberDiff line change
@@ -681,9 +681,10 @@ int afs_writeback_all(struct afs_vnode *vnode)
681681
* - the return status from this call provides a reliable indication of
682682
* whether any write errors occurred for this process.
683683
*/
684-
int afs_fsync(struct file *file, int datasync)
684+
int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
685685
{
686686
struct dentry *dentry = file->f_path.dentry;
687+
struct inode *inode = file->f_mapping->host;
687688
struct afs_writeback *wb, *xwb;
688689
struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
689690
int ret;
@@ -692,12 +693,19 @@ int afs_fsync(struct file *file, int datasync)
692693
vnode->fid.vid, vnode->fid.vnode, dentry->d_name.name,
693694
datasync);
694695

696+
ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
697+
if (ret)
698+
return ret;
699+
mutex_lock(&inode->i_mutex);
700+
695701
/* use a writeback record as a marker in the queue - when this reaches
696702
* the front of the queue, all the outstanding writes are either
697703
* completed or rejected */
698704
wb = kzalloc(sizeof(*wb), GFP_KERNEL);
699-
if (!wb)
700-
return -ENOMEM;
705+
if (!wb) {
706+
ret = -ENOMEM;
707+
goto out;
708+
}
701709
wb->vnode = vnode;
702710
wb->first = 0;
703711
wb->last = -1;
@@ -720,7 +728,7 @@ int afs_fsync(struct file *file, int datasync)
720728
if (ret < 0) {
721729
afs_put_writeback(wb);
722730
_leave(" = %d [wb]", ret);
723-
return ret;
731+
goto out;
724732
}
725733

726734
/* wait for the preceding writes to actually complete */
@@ -729,6 +737,8 @@ int afs_fsync(struct file *file, int datasync)
729737
vnode->writebacks.next == &wb->link);
730738
afs_put_writeback(wb);
731739
_leave(" = %d", ret);
740+
out:
741+
mutex_unlock(&inode->i_mutex);
732742
return ret;
733743
}
734744

fs/bad_inode.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ static int bad_file_release(struct inode *inode, struct file *filp)
8787
return -EIO;
8888
}
8989

90-
static int bad_file_fsync(struct file *file, int datasync)
90+
static int bad_file_fsync(struct file *file, loff_t start, loff_t end,
91+
int datasync)
9192
{
9293
return -EIO;
9394
}

fs/block_dev.c

+1-5
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin)
378378
return retval;
379379
}
380380

381-
int blkdev_fsync(struct file *filp, int datasync)
381+
int blkdev_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
382382
{
383383
struct inode *bd_inode = filp->f_mapping->host;
384384
struct block_device *bdev = I_BDEV(bd_inode);
@@ -389,14 +389,10 @@ int blkdev_fsync(struct file *filp, int datasync)
389389
* i_mutex and doing so causes performance issues with concurrent
390390
* O_SYNC writers to a block device.
391391
*/
392-
mutex_unlock(&bd_inode->i_mutex);
393-
394392
error = blkdev_issue_flush(bdev, GFP_KERNEL, NULL);
395393
if (error == -EOPNOTSUPP)
396394
error = 0;
397395

398-
mutex_lock(&bd_inode->i_mutex);
399-
400396
return error;
401397
}
402398
EXPORT_SYMBOL(blkdev_fsync);

fs/btrfs/ctree.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -2605,7 +2605,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
26052605
int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
26062606
struct inode *inode);
26072607
int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info);
2608-
int btrfs_sync_file(struct file *file, int datasync);
2608+
int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync);
26092609
int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
26102610
int skip_pinned);
26112611
extern const struct file_operations btrfs_file_operations;

0 commit comments

Comments
 (0)