scoutfs: wire up sop->dirty_inode

We're using the generic block buffer_head write_begin and write_end
functions.  They call sop->dirty_inode() to update the inode i_size.  We
didn't have that method wired up so updates to the inode in the write
path wasn't dirtying the inode item.  Lost i_size updates would
trivially lose data but we first noticed this when looking at inode item
sequence numbers while overwriting.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2016-10-24 18:06:08 -07:00
parent 165d833c46
commit 1cbd84eece
4 changed files with 35 additions and 0 deletions

View File

@@ -625,6 +625,11 @@ retry:
/* can't re-enter fs, have trans */
flags |= AOP_FLAG_NOFS;
/* generic write_end updates i_size and calls dirty_inode */
ret = scoutfs_dirty_inode_item(inode);
if (ret)
goto out;
/* make sure our get_block gets a chance to alloc */
clear_mapped_page_buffers(page);

View File

@@ -275,6 +275,34 @@ void scoutfs_update_inode_item(struct inode *inode)
trace_scoutfs_update_inode(inode);
}
/*
* sop->dirty_inode() can't return failure. Our use of it has to be
* careful to pin the inode during a transaction. The generic write
* paths pin the inode in write_begin and get called to update the inode
* in write_end.
*
* The caller should have a trans but it's cheap for us to grab it
* ourselves to make sure.
*
* This will holler at us if a caller didn't pin the inode and we
* couldn't dirty the inode ourselves.
*/
void scoutfs_dirty_inode(struct inode *inode, int flags)
{
struct super_block *sb = inode->i_sb;
int ret;
ret = scoutfs_hold_trans(sb);
if (ret == 0) {
ret = scoutfs_dirty_inode_item(inode);
if (ret == 0)
scoutfs_update_inode_item(inode);
scoutfs_release_trans(sb);
}
WARN_ON_ONCE(ret);
}
/*
* A quick atomic sample of the last inode number that's been allocated.
*/

View File

@@ -29,6 +29,7 @@ int scoutfs_orphan_inode(struct inode *inode);
struct inode *scoutfs_iget(struct super_block *sb, u64 ino);
int scoutfs_dirty_inode_item(struct inode *inode);
void scoutfs_dirty_inode(struct inode *inode, int flags);
void scoutfs_update_inode_item(struct inode *inode);
struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
umode_t mode, dev_t rdev);

View File

@@ -74,6 +74,7 @@ static int scoutfs_statfs(struct dentry *dentry, struct kstatfs *kst)
static const struct super_operations scoutfs_super_ops = {
.alloc_inode = scoutfs_alloc_inode,
.dirty_inode = scoutfs_dirty_inode,
.drop_inode = scoutfs_drop_inode,
.evict_inode = scoutfs_evict_inode,
.destroy_inode = scoutfs_destroy_inode,