Commit e09d3996 authored by Alex Elder's avatar Alex Elder

Merge branch 'master' into for-linus

parents fdec29c5 d0800703
...@@ -185,6 +185,24 @@ xfs_destroy_ioend( ...@@ -185,6 +185,24 @@ xfs_destroy_ioend(
mempool_free(ioend, xfs_ioend_pool); 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. * 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 * The current in-memory file size is i_size. If a write is beyond
...@@ -192,13 +210,13 @@ xfs_destroy_ioend( ...@@ -192,13 +210,13 @@ xfs_destroy_ioend(
* updated. If this write does not extend all the way to the valid * 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. * file size then restrict this update to the end of the write.
*/ */
STATIC void STATIC void
xfs_setfilesize( xfs_setfilesize(
xfs_ioend_t *ioend) xfs_ioend_t *ioend)
{ {
xfs_inode_t *ip = XFS_I(ioend->io_inode); xfs_inode_t *ip = XFS_I(ioend->io_inode);
xfs_fsize_t isize; xfs_fsize_t isize;
xfs_fsize_t bsize;
ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG); ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
ASSERT(ioend->io_type != IOMAP_READ); ASSERT(ioend->io_type != IOMAP_READ);
...@@ -206,16 +224,10 @@ xfs_setfilesize( ...@@ -206,16 +224,10 @@ xfs_setfilesize(
if (unlikely(ioend->io_error)) if (unlikely(ioend->io_error))
return; return;
bsize = ioend->io_offset + ioend->io_size;
xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_ilock(ip, XFS_ILOCK_EXCL);
isize = xfs_ioend_new_eof(ioend);
isize = MAX(ip->i_size, ip->i_new_size); if (isize) {
isize = MIN(isize, bsize);
if (ip->i_d.di_size < isize) {
ip->i_d.di_size = isize; ip->i_d.di_size = isize;
ip->i_update_core = 1;
xfs_mark_inode_dirty_sync(ip); xfs_mark_inode_dirty_sync(ip);
} }
...@@ -404,10 +416,16 @@ xfs_submit_ioend_bio( ...@@ -404,10 +416,16 @@ xfs_submit_ioend_bio(
struct bio *bio) struct bio *bio)
{ {
atomic_inc(&ioend->io_remaining); atomic_inc(&ioend->io_remaining);
bio->bi_private = ioend; bio->bi_private = ioend;
bio->bi_end_io = xfs_end_bio; 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); submit_bio(WRITE, bio);
ASSERT(!bio_flagged(bio, BIO_EOPNOTSUPP)); ASSERT(!bio_flagged(bio, BIO_EOPNOTSUPP));
bio_put(bio); bio_put(bio);
......
...@@ -176,14 +176,7 @@ xfs_file_fsync( ...@@ -176,14 +176,7 @@ xfs_file_fsync(
struct dentry *dentry, struct dentry *dentry,
int datasync) int datasync)
{ {
struct inode *inode = dentry->d_inode; struct xfs_inode *ip = XFS_I(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;
xfs_iflags_clear(ip, XFS_ITRUNCATED); xfs_iflags_clear(ip, XFS_ITRUNCATED);
return -xfs_fsync(ip); return -xfs_fsync(ip);
......
...@@ -57,19 +57,22 @@ ...@@ -57,19 +57,22 @@
#include <linux/fiemap.h> #include <linux/fiemap.h>
/* /*
* Bring the atime in the XFS inode uptodate. * Bring the timestamps in the XFS inode uptodate.
* Used before logging the inode to disk or when the Linux inode goes away. *
* Used before writing the inode to disk.
*/ */
void void
xfs_synchronize_atime( xfs_synchronize_times(
xfs_inode_t *ip) xfs_inode_t *ip)
{ {
struct inode *inode = VFS_I(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_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_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,32 +109,20 @@ xfs_ichgtime( ...@@ -106,32 +109,20 @@ xfs_ichgtime(
if ((flags & XFS_ICHGTIME_MOD) && if ((flags & XFS_ICHGTIME_MOD) &&
!timespec_equal(&inode->i_mtime, &tv)) { !timespec_equal(&inode->i_mtime, &tv)) {
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; sync_it = 1;
} }
if ((flags & XFS_ICHGTIME_CHG) && if ((flags & XFS_ICHGTIME_CHG) &&
!timespec_equal(&inode->i_ctime, &tv)) { !timespec_equal(&inode->i_ctime, &tv)) {
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; sync_it = 1;
} }
/* /*
* We update the i_update_core field _after_ changing * Update complete - now make sure everyone knows that the inode
* the timestamps in order to coordinate properly with * is dirty.
* 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.
*/ */
if (sync_it) { if (sync_it)
SYNCHRONIZE();
ip->i_update_core = 1;
xfs_mark_inode_dirty_sync(ip); xfs_mark_inode_dirty_sync(ip);
}
} }
/* /*
...@@ -506,10 +497,8 @@ xfs_vn_getattr( ...@@ -506,10 +497,8 @@ xfs_vn_getattr(
stat->gid = ip->i_d.di_gid; stat->gid = ip->i_d.di_gid;
stat->ino = ip->i_ino; stat->ino = ip->i_ino;
stat->atime = inode->i_atime; stat->atime = inode->i_atime;
stat->mtime.tv_sec = ip->i_d.di_mtime.t_sec; stat->mtime = inode->i_mtime;
stat->mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; stat->ctime = inode->i_ctime;
stat->ctime.tv_sec = ip->i_d.di_ctime.t_sec;
stat->ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;
stat->blocks = stat->blocks =
XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks); XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);
......
...@@ -667,7 +667,7 @@ xfs_write( ...@@ -667,7 +667,7 @@ xfs_write(
xip->i_new_size = new_size; xip->i_new_size = new_size;
if (likely(!(ioflags & IO_INVIS))) 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 * If the offset is beyond the size of the file, we have a couple
......
...@@ -976,6 +976,28 @@ xfs_fs_inode_init_once( ...@@ -976,6 +976,28 @@ xfs_fs_inode_init_once(
mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); 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 * Attempt to flush the inode, this will actually fail
* if the inode is pinned, but we dirty the inode again * if the inode is pinned, but we dirty the inode again
...@@ -1126,7 +1148,7 @@ xfs_fs_put_super( ...@@ -1126,7 +1148,7 @@ xfs_fs_put_super(
} }
STATIC int STATIC int
xfs_fs_sync_super( xfs_fs_sync_fs(
struct super_block *sb, struct super_block *sb,
int wait) int wait)
{ {
...@@ -1134,23 +1156,23 @@ xfs_fs_sync_super( ...@@ -1134,23 +1156,23 @@ xfs_fs_sync_super(
int error; int error;
/* /*
* Treat a sync operation like a freeze. This is to work * Not much we can do for the first async pass. Writing out the
* around a race in sync_inodes() which works in two phases * superblock would be counter-productive as we are going to redirty
* - an asynchronous flush, which can write out an inode * when writing out other data and metadata (and writing out a single
* without waiting for file size updates to complete, and a * block is quite fast anyway).
* synchronous flush, which wont do anything because the *
* async flush removed the inode's dirty flag. Also * Try to asynchronously kick off quota syncing at least.
* 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.
*/ */
if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE)) if (!wait) {
error = xfs_quiesce_data(mp); xfs_qm_sync(mp, SYNC_TRYLOCK);
else return 0;
error = xfs_sync_fsdata(mp, 0); }
error = xfs_quiesce_data(mp);
if (error)
return -error;
if (unlikely(laptop_mode)) { if (laptop_mode) {
int prev_sync_seq = mp->m_sync_seq; int prev_sync_seq = mp->m_sync_seq;
/* /*
...@@ -1169,7 +1191,7 @@ xfs_fs_sync_super( ...@@ -1169,7 +1191,7 @@ xfs_fs_sync_super(
mp->m_sync_seq != prev_sync_seq); mp->m_sync_seq != prev_sync_seq);
} }
return -error; return 0;
} }
STATIC int STATIC int
...@@ -1539,10 +1561,11 @@ xfs_fs_get_sb( ...@@ -1539,10 +1561,11 @@ xfs_fs_get_sb(
static struct super_operations xfs_super_operations = { static struct super_operations xfs_super_operations = {
.alloc_inode = xfs_fs_alloc_inode, .alloc_inode = xfs_fs_alloc_inode,
.destroy_inode = xfs_fs_destroy_inode, .destroy_inode = xfs_fs_destroy_inode,
.dirty_inode = xfs_fs_dirty_inode,
.write_inode = xfs_fs_write_inode, .write_inode = xfs_fs_write_inode,
.clear_inode = xfs_fs_clear_inode, .clear_inode = xfs_fs_clear_inode,
.put_super = xfs_fs_put_super, .put_super = xfs_fs_put_super,
.sync_fs = xfs_fs_sync_super, .sync_fs = xfs_fs_sync_fs,
.freeze_fs = xfs_fs_freeze, .freeze_fs = xfs_fs_freeze,
.statfs = xfs_fs_statfs, .statfs = xfs_fs_statfs,
.remount_fs = xfs_fs_remount, .remount_fs = xfs_fs_remount,
......
...@@ -309,11 +309,15 @@ xfs_sync_attr( ...@@ -309,11 +309,15 @@ xfs_sync_attr(
STATIC int STATIC int
xfs_commit_dummy_trans( xfs_commit_dummy_trans(
struct xfs_mount *mp, struct xfs_mount *mp,
uint log_flags) uint flags)
{ {
struct xfs_inode *ip = mp->m_rootip; struct xfs_inode *ip = mp->m_rootip;
struct xfs_trans *tp; struct xfs_trans *tp;
int error; int error;
int log_flags = XFS_LOG_FORCE;
if (flags & SYNC_WAIT)
log_flags |= XFS_LOG_SYNC;
/* /*
* Put a dummy transaction in the log to tell recovery * Put a dummy transaction in the log to tell recovery
...@@ -331,13 +335,12 @@ xfs_commit_dummy_trans( ...@@ -331,13 +335,12 @@ xfs_commit_dummy_trans(
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
xfs_trans_ihold(tp, ip); xfs_trans_ihold(tp, ip);
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
/* XXX(hch): ignoring the error here.. */
error = xfs_trans_commit(tp, 0); error = xfs_trans_commit(tp, 0);
xfs_iunlock(ip, XFS_ILOCK_EXCL); xfs_iunlock(ip, XFS_ILOCK_EXCL);
/* the log force ensures this transaction is pushed to disk */
xfs_log_force(mp, 0, log_flags); xfs_log_force(mp, 0, log_flags);
return 0; return error;
} }
int int
...@@ -385,7 +388,20 @@ xfs_sync_fsdata( ...@@ -385,7 +388,20 @@ xfs_sync_fsdata(
else else
XFS_BUF_ASYNC(bp); XFS_BUF_ASYNC(bp);
return xfs_bwrite(mp, bp); error = xfs_bwrite(mp, bp);
if (error)
return error;
/*
* If this is a data integrity sync make sure all pending buffers
* are flushed out for the log coverage check below.
*/
if (flags & SYNC_WAIT)
xfs_flush_buftarg(mp->m_ddev_targp, 1);
if (xfs_log_need_covered(mp))
error = xfs_commit_dummy_trans(mp, flags);
return error;
out_brelse: out_brelse:
xfs_buf_relse(bp); xfs_buf_relse(bp);
...@@ -419,14 +435,16 @@ xfs_quiesce_data( ...@@ -419,14 +435,16 @@ xfs_quiesce_data(
/* push non-blocking */ /* push non-blocking */
xfs_sync_data(mp, 0); xfs_sync_data(mp, 0);
xfs_qm_sync(mp, SYNC_TRYLOCK); xfs_qm_sync(mp, SYNC_TRYLOCK);
xfs_filestream_flush(mp);
/* push and block */ /* push and block till complete */
xfs_sync_data(mp, SYNC_WAIT); xfs_sync_data(mp, SYNC_WAIT);
xfs_qm_sync(mp, SYNC_WAIT); xfs_qm_sync(mp, SYNC_WAIT);
/* drop inode references pinned by filestreams */
xfs_filestream_flush(mp);
/* write superblock and hoover up shutdown errors */ /* write superblock and hoover up shutdown errors */
error = xfs_sync_fsdata(mp, 0); error = xfs_sync_fsdata(mp, SYNC_WAIT);
/* flush data-only devices */ /* flush data-only devices */
if (mp->m_rtdev_targp) if (mp->m_rtdev_targp)
...@@ -570,8 +588,6 @@ xfs_sync_worker( ...@@ -570,8 +588,6 @@ xfs_sync_worker(
/* dgc: errors ignored here */ /* dgc: errors ignored here */
error = xfs_qm_sync(mp, SYNC_TRYLOCK); error = xfs_qm_sync(mp, SYNC_TRYLOCK);
error = xfs_sync_fsdata(mp, SYNC_TRYLOCK); error = xfs_sync_fsdata(mp, SYNC_TRYLOCK);
if (xfs_log_need_covered(mp))
error = xfs_commit_dummy_trans(mp, XFS_LOG_FORCE);
} }
mp->m_sync_seq++; mp->m_sync_seq++;
wake_up(&mp->m_wait_single_sync_task); wake_up(&mp->m_wait_single_sync_task);
......
...@@ -206,10 +206,10 @@ xfs_swap_extents( ...@@ -206,10 +206,10 @@ xfs_swap_extents(
* process that the file was not changed out from * process that the file was not changed out from
* under it. * under it.
*/ */
if ((sbp->bs_ctime.tv_sec != ip->i_d.di_ctime.t_sec) || if ((sbp->bs_ctime.tv_sec != VFS_I(ip)->i_ctime.tv_sec) ||
(sbp->bs_ctime.tv_nsec != ip->i_d.di_ctime.t_nsec) || (sbp->bs_ctime.tv_nsec != VFS_I(ip)->i_ctime.tv_nsec) ||
(sbp->bs_mtime.tv_sec != ip->i_d.di_mtime.t_sec) || (sbp->bs_mtime.tv_sec != VFS_I(ip)->i_mtime.tv_sec) ||
(sbp->bs_mtime.tv_nsec != ip->i_d.di_mtime.t_nsec)) { (sbp->bs_mtime.tv_nsec != VFS_I(ip)->i_mtime.tv_nsec)) {
error = XFS_ERROR(EBUSY); error = XFS_ERROR(EBUSY);
goto out_unlock; goto out_unlock;
} }
......
...@@ -854,6 +854,7 @@ xfs_dir2_leaf_getdents( ...@@ -854,6 +854,7 @@ xfs_dir2_leaf_getdents(
*/ */
ra_want = howmany(bufsize + mp->m_dirblksize, ra_want = howmany(bufsize + mp->m_dirblksize,
mp->m_sb.sb_blocksize) - 1; mp->m_sb.sb_blocksize) - 1;
ASSERT(ra_want >= 0);
/* /*
* If we don't have as many as we want, and we haven't * If we don't have as many as we want, and we haven't
...@@ -1088,7 +1089,8 @@ xfs_dir2_leaf_getdents( ...@@ -1088,7 +1089,8 @@ xfs_dir2_leaf_getdents(
*/ */
ptr += length; ptr += length;
curoff += length; curoff += length;
bufsize -= length; /* bufsize may have just been a guess; don't go negative */
bufsize = bufsize > length ? bufsize - length : 0;
} }
/* /*
......
...@@ -3068,9 +3068,9 @@ xfs_iflush_int( ...@@ -3068,9 +3068,9 @@ xfs_iflush_int(
SYNCHRONIZE(); SYNCHRONIZE();
/* /*
* Make sure to get the latest atime from the Linux inode. * Make sure to get the latest timestamps from the Linux inode.
*/ */
xfs_synchronize_atime(ip); xfs_synchronize_times(ip);
if (XFS_TEST_ERROR(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC, if (XFS_TEST_ERROR(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC,
mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) { mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) {
......
...@@ -504,7 +504,7 @@ void xfs_ichgtime(xfs_inode_t *, int); ...@@ -504,7 +504,7 @@ void xfs_ichgtime(xfs_inode_t *, int);
void xfs_lock_inodes(xfs_inode_t **, int, uint); void xfs_lock_inodes(xfs_inode_t **, int, uint);
void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint); void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint);
void xfs_synchronize_atime(xfs_inode_t *); void xfs_synchronize_times(xfs_inode_t *);
void xfs_mark_inode_dirty_sync(xfs_inode_t *); void xfs_mark_inode_dirty_sync(xfs_inode_t *);
#if defined(XFS_INODE_TRACE) #if defined(XFS_INODE_TRACE)
......
...@@ -231,6 +231,15 @@ xfs_inode_item_format( ...@@ -231,6 +231,15 @@ xfs_inode_item_format(
vecp++; vecp++;
nvecs = 1; nvecs = 1;
/*
* Make sure the linux inode is dirty. We do this before
* clearing i_update_core as the VFS will call back into
* XFS here and set i_update_core, so we need to dirty the
* inode first so that the ordering of i_update_core and
* unlogged modifications still works as described below.
*/
xfs_mark_inode_dirty_sync(ip);
/* /*
* Clear i_update_core if the timestamps (or any other * Clear i_update_core if the timestamps (or any other
* non-transactional modification) need flushing/logging * non-transactional modification) need flushing/logging
...@@ -263,14 +272,9 @@ xfs_inode_item_format( ...@@ -263,14 +272,9 @@ xfs_inode_item_format(
} }
/* /*
* Make sure to get the latest atime from the Linux inode. * Make sure to get the latest timestamps from the Linux inode.
*/ */
xfs_synchronize_atime(ip); xfs_synchronize_times(ip);
/*
* make sure the linux inode is dirty
*/
xfs_mark_inode_dirty_sync(ip);
vecp->i_addr = (xfs_caddr_t)&ip->i_d; vecp->i_addr = (xfs_caddr_t)&ip->i_d;
vecp->i_len = sizeof(struct xfs_icdinode); vecp->i_len = sizeof(struct xfs_icdinode);
......
...@@ -59,6 +59,7 @@ xfs_bulkstat_one_iget( ...@@ -59,6 +59,7 @@ xfs_bulkstat_one_iget(
{ {
xfs_icdinode_t *dic; /* dinode core info pointer */ xfs_icdinode_t *dic; /* dinode core info pointer */
xfs_inode_t *ip; /* incore inode pointer */ xfs_inode_t *ip; /* incore inode pointer */
struct inode *inode;
int error; int error;
error = xfs_iget(mp, NULL, ino, error = xfs_iget(mp, NULL, ino,
...@@ -72,6 +73,7 @@ xfs_bulkstat_one_iget( ...@@ -72,6 +73,7 @@ xfs_bulkstat_one_iget(
ASSERT(ip->i_imap.im_blkno != 0); ASSERT(ip->i_imap.im_blkno != 0);
dic = &ip->i_d; dic = &ip->i_d;
inode = VFS_I(ip);
/* xfs_iget returns the following without needing /* xfs_iget returns the following without needing
* further change. * further change.
...@@ -83,16 +85,19 @@ xfs_bulkstat_one_iget( ...@@ -83,16 +85,19 @@ xfs_bulkstat_one_iget(
buf->bs_uid = dic->di_uid; buf->bs_uid = dic->di_uid;
buf->bs_gid = dic->di_gid; buf->bs_gid = dic->di_gid;
buf->bs_size = dic->di_size; buf->bs_size = dic->di_size;
/* /*
* We are reading the atime from the Linux inode because the * We need to read the timestamps from the Linux inode because
* dinode might not be uptodate. * the VFS keeps writing directly into the inode structure instead
* of telling us about the updates.
*/ */
buf->bs_atime.tv_sec = VFS_I(ip)->i_atime.tv_sec; buf->bs_atime.tv_sec = inode->i_atime.tv_sec;
buf->bs_atime.tv_nsec = VFS_I(ip)->i_atime.tv_nsec; buf->bs_atime.tv_nsec = inode->i_atime.tv_nsec;
buf->bs_mtime.tv_sec = dic->di_mtime.t_sec; buf->bs_mtime.tv_sec = inode->i_mtime.tv_sec;
buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec; buf->bs_mtime.tv_nsec = inode->i_mtime.tv_nsec;
buf->bs_ctime.tv_sec = dic->di_ctime.t_sec; buf->bs_ctime.tv_sec = inode->i_ctime.tv_sec;
buf->bs_ctime.tv_nsec = dic->di_ctime.t_nsec; buf->bs_ctime.tv_nsec = inode->i_ctime.tv_nsec;
buf->bs_xflags = xfs_ip2xflags(ip); buf->bs_xflags = xfs_ip2xflags(ip);
buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog; buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog;
buf->bs_extents = dic->di_nextents; buf->bs_extents = dic->di_nextents;
......
...@@ -2475,12 +2475,6 @@ xfs_reclaim( ...@@ -2475,12 +2475,6 @@ xfs_reclaim(
ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
/*
* Make sure the atime in the XFS inode is correct before freeing the
* Linux inode.
*/
xfs_synchronize_atime(ip);
/* /*
* If we have nothing to flush with this inode then complete the * If we have nothing to flush with this inode then complete the
* teardown now, otherwise break the link between the xfs inode and the * teardown now, otherwise break the link between the xfs inode and the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment