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

Commit e09d3996 authored by Alex Elder's avatar Alex Elder
Browse files

Merge branch 'master' into for-linus

parents fdec29c5 d0800703
Loading
Loading
Loading
Loading
+28 −10
Original line number Diff line number Diff line
@@ -185,6 +185,24 @@ xfs_destroy_ioend(
	mempool_free(ioend, xfs_ioend_pool);
}

/*
 * If the end of the current ioend is beyond the current EOF,
 * return the new EOF value, otherwise zero.
 */
STATIC xfs_fsize_t
xfs_ioend_new_eof(
	xfs_ioend_t		*ioend)
{
	xfs_inode_t		*ip = XFS_I(ioend->io_inode);
	xfs_fsize_t		isize;
	xfs_fsize_t		bsize;

	bsize = ioend->io_offset + ioend->io_size;
	isize = MAX(ip->i_size, ip->i_new_size);
	isize = MIN(isize, bsize);
	return isize > ip->i_d.di_size ? isize : 0;
}

/*
 * Update on-disk file size now that data has been written to disk.
 * The current in-memory file size is i_size.  If a write is beyond
@@ -192,13 +210,13 @@ xfs_destroy_ioend(
 * updated.  If this write does not extend all the way to the valid
 * file size then restrict this update to the end of the write.
 */

STATIC void
xfs_setfilesize(
	xfs_ioend_t		*ioend)
{
	xfs_inode_t		*ip = XFS_I(ioend->io_inode);
	xfs_fsize_t		isize;
	xfs_fsize_t		bsize;

	ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
	ASSERT(ioend->io_type != IOMAP_READ);
@@ -206,16 +224,10 @@ xfs_setfilesize(
	if (unlikely(ioend->io_error))
		return;

	bsize = ioend->io_offset + ioend->io_size;

	xfs_ilock(ip, XFS_ILOCK_EXCL);

	isize = MAX(ip->i_size, ip->i_new_size);
	isize = MIN(isize, bsize);

	if (ip->i_d.di_size < isize) {
	isize = xfs_ioend_new_eof(ioend);
	if (isize) {
		ip->i_d.di_size = isize;
		ip->i_update_core = 1;
		xfs_mark_inode_dirty_sync(ip);
	}

@@ -404,10 +416,16 @@ xfs_submit_ioend_bio(
	struct bio	*bio)
{
	atomic_inc(&ioend->io_remaining);

	bio->bi_private = ioend;
	bio->bi_end_io = xfs_end_bio;

	/*
	 * If the I/O is beyond EOF we mark the inode dirty immediately
	 * but don't update the inode size until I/O completion.
	 */
	if (xfs_ioend_new_eof(ioend))
		xfs_mark_inode_dirty_sync(XFS_I(ioend->io_inode));

	submit_bio(WRITE, bio);
	ASSERT(!bio_flagged(bio, BIO_EOPNOTSUPP));
	bio_put(bio);
+1 −8
Original line number Diff line number Diff line
@@ -176,14 +176,7 @@ xfs_file_fsync(
	struct dentry		*dentry,
	int			datasync)
{
	struct inode		*inode = dentry->d_inode;
	struct xfs_inode	*ip = XFS_I(inode);
	int			error;

	/* capture size updates in I/O completion before writing the inode. */
	error = filemap_fdatawait(inode->i_mapping);
	if (error)
		return error;
	struct xfs_inode	*ip = XFS_I(dentry->d_inode);

	xfs_iflags_clear(ip, XFS_ITRUNCATED);
	return -xfs_fsync(ip);
+15 −26
Original line number Diff line number Diff line
@@ -57,19 +57,22 @@
#include <linux/fiemap.h>

/*
 * Bring the atime in the XFS inode uptodate.
 * Used before logging the inode to disk or when the Linux inode goes away.
 * Bring the timestamps in the XFS inode uptodate.
 *
 * Used before writing the inode to disk.
 */
void
xfs_synchronize_atime(
xfs_synchronize_times(
	xfs_inode_t	*ip)
{
	struct inode	*inode = VFS_I(ip);

	if (!(inode->i_state & I_CLEAR)) {
	ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
	ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
	}
	ip->i_d.di_ctime.t_sec = (__int32_t)inode->i_ctime.tv_sec;
	ip->i_d.di_ctime.t_nsec = (__int32_t)inode->i_ctime.tv_nsec;
	ip->i_d.di_mtime.t_sec = (__int32_t)inode->i_mtime.tv_sec;
	ip->i_d.di_mtime.t_nsec = (__int32_t)inode->i_mtime.tv_nsec;
}

/*
@@ -106,33 +109,21 @@ xfs_ichgtime(
	if ((flags & XFS_ICHGTIME_MOD) &&
	    !timespec_equal(&inode->i_mtime, &tv)) {
		inode->i_mtime = tv;
		ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec;
		ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec;
		sync_it = 1;
	}
	if ((flags & XFS_ICHGTIME_CHG) &&
	    !timespec_equal(&inode->i_ctime, &tv)) {
		inode->i_ctime = tv;
		ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec;
		ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec;
		sync_it = 1;
	}

	/*
	 * We update the i_update_core field _after_ changing
	 * the timestamps in order to coordinate properly with
	 * xfs_iflush() so that we don't lose timestamp updates.
	 * This keeps us from having to hold the inode lock
	 * while doing this.  We use the SYNCHRONIZE macro to
	 * ensure that the compiler does not reorder the update
	 * of i_update_core above the timestamp updates above.
	 * Update complete - now make sure everyone knows that the inode
	 * is dirty.
	 */
	if (sync_it) {
		SYNCHRONIZE();
		ip->i_update_core = 1;
	if (sync_it)
		xfs_mark_inode_dirty_sync(ip);
}
}

/*
 * Hook in SELinux.  This is not quite correct yet, what we really need
@@ -506,10 +497,8 @@ xfs_vn_getattr(
	stat->gid = ip->i_d.di_gid;
	stat->ino = ip->i_ino;
	stat->atime = inode->i_atime;
	stat->mtime.tv_sec = ip->i_d.di_mtime.t_sec;
	stat->mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
	stat->ctime.tv_sec = ip->i_d.di_ctime.t_sec;
	stat->ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;
	stat->mtime = inode->i_mtime;
	stat->ctime = inode->i_ctime;
	stat->blocks =
		XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);

+1 −1
Original line number Diff line number Diff line
@@ -667,7 +667,7 @@ start:
		xip->i_new_size = new_size;

	if (likely(!(ioflags & IO_INVIS)))
		xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
		file_update_time(file);

	/*
	 * If the offset is beyond the size of the file, we have a couple
+41 −18
Original line number Diff line number Diff line
@@ -976,6 +976,28 @@ xfs_fs_inode_init_once(
	mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
}

/*
 * Dirty the XFS inode when mark_inode_dirty_sync() is called so that
 * we catch unlogged VFS level updates to the inode. Care must be taken
 * here - the transaction code calls mark_inode_dirty_sync() to mark the
 * VFS inode dirty in a transaction and clears the i_update_core field;
 * it must clear the field after calling mark_inode_dirty_sync() to
 * correctly indicate that the dirty state has been propagated into the
 * inode log item.
 *
 * We need the barrier() to maintain correct ordering between unlogged
 * updates and the transaction commit code that clears the i_update_core
 * field. This requires all updates to be completed before marking the
 * inode dirty.
 */
STATIC void
xfs_fs_dirty_inode(
	struct inode	*inode)
{
	barrier();
	XFS_I(inode)->i_update_core = 1;
}

/*
 * Attempt to flush the inode, this will actually fail
 * if the inode is pinned, but we dirty the inode again
@@ -1126,7 +1148,7 @@ xfs_fs_put_super(
}

STATIC int
xfs_fs_sync_super(
xfs_fs_sync_fs(
	struct super_block	*sb,
	int			wait)
{
@@ -1134,23 +1156,23 @@ xfs_fs_sync_super(
	int			error;

	/*
	 * Treat a sync operation like a freeze.  This is to work
	 * around a race in sync_inodes() which works in two phases
	 * - an asynchronous flush, which can write out an inode
	 * without waiting for file size updates to complete, and a
	 * synchronous flush, which wont do anything because the
	 * async flush removed the inode's dirty flag.  Also
	 * sync_inodes() will not see any files that just have
	 * outstanding transactions to be flushed because we don't
	 * dirty the Linux inode until after the transaction I/O
	 * completes.
	 * Not much we can do for the first async pass.  Writing out the
	 * superblock would be counter-productive as we are going to redirty
	 * when writing out other data and metadata (and writing out a single
	 * block is quite fast anyway).
	 *
	 * Try to asynchronously kick off quota syncing at least.
	 */
	if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE))
	if (!wait) {
		xfs_qm_sync(mp, SYNC_TRYLOCK);
		return 0;
	}

	error = xfs_quiesce_data(mp);
	else
		error = xfs_sync_fsdata(mp, 0);
	if (error)
		return -error;

	if (unlikely(laptop_mode)) {
	if (laptop_mode) {
		int	prev_sync_seq = mp->m_sync_seq;

		/*
@@ -1169,7 +1191,7 @@ xfs_fs_sync_super(
				mp->m_sync_seq != prev_sync_seq);
	}

	return -error;
	return 0;
}

STATIC int
@@ -1539,10 +1561,11 @@ xfs_fs_get_sb(
static struct super_operations xfs_super_operations = {
	.alloc_inode		= xfs_fs_alloc_inode,
	.destroy_inode		= xfs_fs_destroy_inode,
	.dirty_inode		= xfs_fs_dirty_inode,
	.write_inode		= xfs_fs_write_inode,
	.clear_inode		= xfs_fs_clear_inode,
	.put_super		= xfs_fs_put_super,
	.sync_fs		= xfs_fs_sync_super,
	.sync_fs		= xfs_fs_sync_fs,
	.freeze_fs		= xfs_fs_freeze,
	.statfs			= xfs_fs_statfs,
	.remount_fs		= xfs_fs_remount,
Loading