Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf2fd1f9 authored by Theodore Ts'o's avatar Theodore Ts'o Committed by Greg Kroah-Hartman
Browse files

ext4: force inode writes when nfsd calls commit_metadata()



commit fde872682e175743e0c3ef939c89e3c6008a1529 upstream.

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: default avatarTheodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 26366388
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -1202,6 +1202,16 @@ static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid,
				    ext4_nfs_get_inode);
				    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
 * Try to release metadata pages (indirect blocks, directories) which are
 * mapped via the block device.  Since these pages could have journal heads
 * 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_dentry = ext4_fh_to_dentry,
	.fh_to_parent = ext4_fh_to_parent,
	.fh_to_parent = ext4_fh_to_parent,
	.get_parent = ext4_get_parent,
	.get_parent = ext4_get_parent,
	.commit_metadata = ext4_nfs_commit_metadata,
};
};


enum {
enum {
+20 −0
Original line number Original line Diff line number Diff line
@@ -225,6 +225,26 @@ TRACE_EVENT(ext4_drop_inode,
		  (unsigned long) __entry->ino, __entry->drop)
		  (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,
TRACE_EVENT(ext4_mark_inode_dirty,
	TP_PROTO(struct inode *inode, unsigned long IP),
	TP_PROTO(struct inode *inode, unsigned long IP),