ext4: force inode writes when nfsd calls commit_metadata()
Some time back, nfsd switched from calling vfs_fsync() to using a new commit_metadata() hook in export_operations(). If the file system did not provide a commit_metadata() hook, it fell back to using sync_inode_metadata(). Unfortunately doesn't work on all file systems. In particular, it doesn't work on ext4 due to how the inode gets journalled --- the VFS writeback code will not always call ext4_write_inode(). So we need to provide our own ext4_nfs_commit_metdata() method which calls ext4_write_inode() directly. Google-Bug-Id: 121195940 Signed-off-by: Theodore Ts'o <tytso@mit.edu> Cc: stable@kernel.org
This commit is contained in:
Родитель
8a363970d1
Коммит
fde872682e
|
@ -1202,6 +1202,16 @@ static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid,
|
|||
ext4_nfs_get_inode);
|
||||
}
|
||||
|
||||
static int ext4_nfs_commit_metadata(struct inode *inode)
|
||||
{
|
||||
struct writeback_control wbc = {
|
||||
.sync_mode = WB_SYNC_ALL
|
||||
};
|
||||
|
||||
trace_ext4_nfs_commit_metadata(inode);
|
||||
return ext4_write_inode(inode, &wbc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to release metadata pages (indirect blocks, directories) which are
|
||||
* mapped via the block device. Since these pages could have journal heads
|
||||
|
@ -1406,6 +1416,7 @@ static const struct export_operations ext4_export_ops = {
|
|||
.fh_to_dentry = ext4_fh_to_dentry,
|
||||
.fh_to_parent = ext4_fh_to_parent,
|
||||
.get_parent = ext4_get_parent,
|
||||
.commit_metadata = ext4_nfs_commit_metadata,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
@ -226,6 +226,26 @@ TRACE_EVENT(ext4_drop_inode,
|
|||
(unsigned long) __entry->ino, __entry->drop)
|
||||
);
|
||||
|
||||
TRACE_EVENT(ext4_nfs_commit_metadata,
|
||||
TP_PROTO(struct inode *inode),
|
||||
|
||||
TP_ARGS(inode),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( dev_t, dev )
|
||||
__field( ino_t, ino )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->dev = inode->i_sb->s_dev;
|
||||
__entry->ino = inode->i_ino;
|
||||
),
|
||||
|
||||
TP_printk("dev %d,%d ino %lu",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
(unsigned long) __entry->ino)
|
||||
);
|
||||
|
||||
TRACE_EVENT(ext4_mark_inode_dirty,
|
||||
TP_PROTO(struct inode *inode, unsigned long IP),
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче