···186186}187187188188/*189189+ * If the end of the current ioend is beyond the current EOF,190190+ * return the new EOF value, otherwise zero.191191+ */192192+STATIC xfs_fsize_t193193+xfs_ioend_new_eof(194194+ xfs_ioend_t *ioend)195195+{196196+ xfs_inode_t *ip = XFS_I(ioend->io_inode);197197+ xfs_fsize_t isize;198198+ xfs_fsize_t bsize;199199+200200+ bsize = ioend->io_offset + ioend->io_size;201201+ isize = MAX(ip->i_size, ip->i_new_size);202202+ isize = MIN(isize, bsize);203203+ return isize > ip->i_d.di_size ? isize : 0;204204+}205205+206206+/*189207 * Update on-disk file size now that data has been written to disk.190208 * The current in-memory file size is i_size. If a write is beyond191209 * eof i_new_size will be the intended file size until i_size is192210 * updated. If this write does not extend all the way to the valid193211 * file size then restrict this update to the end of the write.194212 */213213+195214STATIC void196215xfs_setfilesize(197216 xfs_ioend_t *ioend)198217{199218 xfs_inode_t *ip = XFS_I(ioend->io_inode);200219 xfs_fsize_t isize;201201- xfs_fsize_t bsize;202220203221 ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);204222 ASSERT(ioend->io_type != IOMAP_READ);···224206 if (unlikely(ioend->io_error))225207 return;226208227227- bsize = ioend->io_offset + ioend->io_size;228228-229209 xfs_ilock(ip, XFS_ILOCK_EXCL);230230-231231- isize = MAX(ip->i_size, ip->i_new_size);232232- isize = MIN(isize, bsize);233233-234234- if (ip->i_d.di_size < isize) {210210+ isize = xfs_ioend_new_eof(ioend);211211+ if (isize) {235212 ip->i_d.di_size = isize;236236- ip->i_update_core = 1;237213 xfs_mark_inode_dirty_sync(ip);238214 }239215···416404 struct bio *bio)417405{418406 atomic_inc(&ioend->io_remaining);419419-420407 bio->bi_private = ioend;421408 bio->bi_end_io = xfs_end_bio;409409+410410+ /*411411+ * If the I/O is beyond EOF we mark the inode dirty immediately412412+ * but don't update the inode size until I/O completion.413413+ */414414+ if (xfs_ioend_new_eof(ioend))415415+ xfs_mark_inode_dirty_sync(XFS_I(ioend->io_inode));422416423417 submit_bio(WRITE, bio);424418 ASSERT(!bio_flagged(bio, BIO_EOPNOTSUPP));
+1-8
fs/xfs/linux-2.6/xfs_file.c
···176176 struct dentry *dentry,177177 int datasync)178178{179179- struct inode *inode = dentry->d_inode;180180- struct xfs_inode *ip = XFS_I(inode);181181- int error;182182-183183- /* capture size updates in I/O completion before writing the inode. */184184- error = filemap_fdatawait(inode->i_mapping);185185- if (error)186186- return error;179179+ struct xfs_inode *ip = XFS_I(dentry->d_inode);187180188181 xfs_iflags_clear(ip, XFS_ITRUNCATED);189182 return -xfs_fsync(ip);
+15-26
fs/xfs/linux-2.6/xfs_iops.c
···5757#include <linux/fiemap.h>58585959/*6060- * Bring the atime in the XFS inode uptodate.6161- * Used before logging the inode to disk or when the Linux inode goes away.6060+ * Bring the timestamps in the XFS inode uptodate.6161+ *6262+ * Used before writing the inode to disk.6263 */6364void6464-xfs_synchronize_atime(6565+xfs_synchronize_times(6566 xfs_inode_t *ip)6667{6768 struct inode *inode = VFS_I(ip);68696969- if (!(inode->i_state & I_CLEAR)) {7070- ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;7171- ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;7272- }7070+ ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;7171+ ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;7272+ ip->i_d.di_ctime.t_sec = (__int32_t)inode->i_ctime.tv_sec;7373+ ip->i_d.di_ctime.t_nsec = (__int32_t)inode->i_ctime.tv_nsec;7474+ ip->i_d.di_mtime.t_sec = (__int32_t)inode->i_mtime.tv_sec;7575+ ip->i_d.di_mtime.t_nsec = (__int32_t)inode->i_mtime.tv_nsec;7376}74777578/*···109106 if ((flags & XFS_ICHGTIME_MOD) &&110107 !timespec_equal(&inode->i_mtime, &tv)) {111108 inode->i_mtime = tv;112112- ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec;113113- ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec;114109 sync_it = 1;115110 }116111 if ((flags & XFS_ICHGTIME_CHG) &&117112 !timespec_equal(&inode->i_ctime, &tv)) {118113 inode->i_ctime = tv;119119- ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec;120120- ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec;121114 sync_it = 1;122115 }123116124117 /*125125- * We update the i_update_core field _after_ changing126126- * the timestamps in order to coordinate properly with127127- * xfs_iflush() so that we don't lose timestamp updates.128128- * This keeps us from having to hold the inode lock129129- * while doing this. We use the SYNCHRONIZE macro to130130- * ensure that the compiler does not reorder the update131131- * of i_update_core above the timestamp updates above.118118+ * Update complete - now make sure everyone knows that the inode119119+ * is dirty.132120 */133133- if (sync_it) {134134- SYNCHRONIZE();135135- ip->i_update_core = 1;121121+ if (sync_it)136122 xfs_mark_inode_dirty_sync(ip);137137- }138123}139124140125/*···497506 stat->gid = ip->i_d.di_gid;498507 stat->ino = ip->i_ino;499508 stat->atime = inode->i_atime;500500- stat->mtime.tv_sec = ip->i_d.di_mtime.t_sec;501501- stat->mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;502502- stat->ctime.tv_sec = ip->i_d.di_ctime.t_sec;503503- stat->ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;509509+ stat->mtime = inode->i_mtime;510510+ stat->ctime = inode->i_ctime;504511 stat->blocks =505512 XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);506513
+1-1
fs/xfs/linux-2.6/xfs_lrw.c
···667667 xip->i_new_size = new_size;668668669669 if (likely(!(ioflags & IO_INVIS)))670670- xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);670670+ file_update_time(file);671671672672 /*673673 * If the offset is beyond the size of the file, we have a couple
+41-18
fs/xfs/linux-2.6/xfs_super.c
···977977}978978979979/*980980+ * Dirty the XFS inode when mark_inode_dirty_sync() is called so that981981+ * we catch unlogged VFS level updates to the inode. Care must be taken982982+ * here - the transaction code calls mark_inode_dirty_sync() to mark the983983+ * VFS inode dirty in a transaction and clears the i_update_core field;984984+ * it must clear the field after calling mark_inode_dirty_sync() to985985+ * correctly indicate that the dirty state has been propagated into the986986+ * inode log item.987987+ *988988+ * We need the barrier() to maintain correct ordering between unlogged989989+ * updates and the transaction commit code that clears the i_update_core990990+ * field. This requires all updates to be completed before marking the991991+ * inode dirty.992992+ */993993+STATIC void994994+xfs_fs_dirty_inode(995995+ struct inode *inode)996996+{997997+ barrier();998998+ XFS_I(inode)->i_update_core = 1;999999+}10001000+10011001+/*9801002 * Attempt to flush the inode, this will actually fail9811003 * if the inode is pinned, but we dirty the inode again9821004 * at the point when it is unpinned after a log write,···11481126}1149112711501128STATIC int11511151-xfs_fs_sync_super(11291129+xfs_fs_sync_fs(11521130 struct super_block *sb,11531131 int wait)11541132{···11561134 int error;1157113511581136 /*11591159- * Treat a sync operation like a freeze. This is to work11601160- * around a race in sync_inodes() which works in two phases11611161- * - an asynchronous flush, which can write out an inode11621162- * without waiting for file size updates to complete, and a11631163- * synchronous flush, which wont do anything because the11641164- * async flush removed the inode's dirty flag. Also11651165- * sync_inodes() will not see any files that just have11661166- * outstanding transactions to be flushed because we don't11671167- * dirty the Linux inode until after the transaction I/O11681168- * completes.11371137+ * Not much we can do for the first async pass. Writing out the11381138+ * superblock would be counter-productive as we are going to redirty11391139+ * when writing out other data and metadata (and writing out a single11401140+ * block is quite fast anyway).11411141+ *11421142+ * Try to asynchronously kick off quota syncing at least.11691143 */11701170- if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE))11711171- error = xfs_quiesce_data(mp);11721172- else11731173- error = xfs_sync_fsdata(mp, 0);11441144+ if (!wait) {11451145+ xfs_qm_sync(mp, SYNC_TRYLOCK);11461146+ return 0;11471147+ }1174114811751175- if (unlikely(laptop_mode)) {11491149+ error = xfs_quiesce_data(mp);11501150+ if (error)11511151+ return -error;11521152+11531153+ if (laptop_mode) {11761154 int prev_sync_seq = mp->m_sync_seq;1177115511781156 /*···11911169 mp->m_sync_seq != prev_sync_seq);11921170 }1193117111941194- return -error;11721172+ return 0;11951173}1196117411971175STATIC int···15611539static struct super_operations xfs_super_operations = {15621540 .alloc_inode = xfs_fs_alloc_inode,15631541 .destroy_inode = xfs_fs_destroy_inode,15421542+ .dirty_inode = xfs_fs_dirty_inode,15641543 .write_inode = xfs_fs_write_inode,15651544 .clear_inode = xfs_fs_clear_inode,15661545 .put_super = xfs_fs_put_super,15671567- .sync_fs = xfs_fs_sync_super,15461546+ .sync_fs = xfs_fs_sync_fs,15681547 .freeze_fs = xfs_fs_freeze,15691548 .statfs = xfs_fs_statfs,15701549 .remount_fs = xfs_fs_remount,
+26-10
fs/xfs/linux-2.6/xfs_sync.c
···309309STATIC int310310xfs_commit_dummy_trans(311311 struct xfs_mount *mp,312312- uint log_flags)312312+ uint flags)313313{314314 struct xfs_inode *ip = mp->m_rootip;315315 struct xfs_trans *tp;316316 int error;317317+ int log_flags = XFS_LOG_FORCE;318318+319319+ if (flags & SYNC_WAIT)320320+ log_flags |= XFS_LOG_SYNC;317321318322 /*319323 * Put a dummy transaction in the log to tell recovery···335331 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);336332 xfs_trans_ihold(tp, ip);337333 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);338338- /* XXX(hch): ignoring the error here.. */339334 error = xfs_trans_commit(tp, 0);340340-341335 xfs_iunlock(ip, XFS_ILOCK_EXCL);342336337337+ /* the log force ensures this transaction is pushed to disk */343338 xfs_log_force(mp, 0, log_flags);344344- return 0;339339+ return error;345340}346341347342int···388385 else389386 XFS_BUF_ASYNC(bp);390387391391- return xfs_bwrite(mp, bp);388388+ error = xfs_bwrite(mp, bp);389389+ if (error)390390+ return error;391391+392392+ /*393393+ * If this is a data integrity sync make sure all pending buffers394394+ * are flushed out for the log coverage check below.395395+ */396396+ if (flags & SYNC_WAIT)397397+ xfs_flush_buftarg(mp->m_ddev_targp, 1);398398+399399+ if (xfs_log_need_covered(mp))400400+ error = xfs_commit_dummy_trans(mp, flags);401401+ return error;392402393403 out_brelse:394404 xfs_buf_relse(bp);···435419 /* push non-blocking */436420 xfs_sync_data(mp, 0);437421 xfs_qm_sync(mp, SYNC_TRYLOCK);438438- xfs_filestream_flush(mp);439422440440- /* push and block */423423+ /* push and block till complete */441424 xfs_sync_data(mp, SYNC_WAIT);442425 xfs_qm_sync(mp, SYNC_WAIT);443426427427+ /* drop inode references pinned by filestreams */428428+ xfs_filestream_flush(mp);429429+444430 /* write superblock and hoover up shutdown errors */445445- error = xfs_sync_fsdata(mp, 0);431431+ error = xfs_sync_fsdata(mp, SYNC_WAIT);446432447433 /* flush data-only devices */448434 if (mp->m_rtdev_targp)···588570 /* dgc: errors ignored here */589571 error = xfs_qm_sync(mp, SYNC_TRYLOCK);590572 error = xfs_sync_fsdata(mp, SYNC_TRYLOCK);591591- if (xfs_log_need_covered(mp))592592- error = xfs_commit_dummy_trans(mp, XFS_LOG_FORCE);593573 }594574 mp->m_sync_seq++;595575 wake_up(&mp->m_wait_single_sync_task);
+4-4
fs/xfs/xfs_dfrag.c
···206206 * process that the file was not changed out from207207 * under it.208208 */209209- if ((sbp->bs_ctime.tv_sec != ip->i_d.di_ctime.t_sec) ||210210- (sbp->bs_ctime.tv_nsec != ip->i_d.di_ctime.t_nsec) ||211211- (sbp->bs_mtime.tv_sec != ip->i_d.di_mtime.t_sec) ||212212- (sbp->bs_mtime.tv_nsec != ip->i_d.di_mtime.t_nsec)) {209209+ if ((sbp->bs_ctime.tv_sec != VFS_I(ip)->i_ctime.tv_sec) ||210210+ (sbp->bs_ctime.tv_nsec != VFS_I(ip)->i_ctime.tv_nsec) ||211211+ (sbp->bs_mtime.tv_sec != VFS_I(ip)->i_mtime.tv_sec) ||212212+ (sbp->bs_mtime.tv_nsec != VFS_I(ip)->i_mtime.tv_nsec)) {213213 error = XFS_ERROR(EBUSY);214214 goto out_unlock;215215 }
+3-1
fs/xfs/xfs_dir2_leaf.c
···854854 */855855 ra_want = howmany(bufsize + mp->m_dirblksize,856856 mp->m_sb.sb_blocksize) - 1;857857+ ASSERT(ra_want >= 0);857858858859 /*859860 * If we don't have as many as we want, and we haven't···10891088 */10901089 ptr += length;10911090 curoff += length;10921092- bufsize -= length;10911091+ /* bufsize may have just been a guess; don't go negative */10921092+ bufsize = bufsize > length ? bufsize - length : 0;10931093 }1094109410951095 /*
+2-2
fs/xfs/xfs_inode.c
···30683068 SYNCHRONIZE();3069306930703070 /*30713071- * Make sure to get the latest atime from the Linux inode.30713071+ * Make sure to get the latest timestamps from the Linux inode.30723072 */30733073- xfs_synchronize_atime(ip);30733073+ xfs_synchronize_times(ip);3074307430753075 if (XFS_TEST_ERROR(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC,30763076 mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) {
···232232 nvecs = 1;233233234234 /*235235+ * Make sure the linux inode is dirty. We do this before236236+ * clearing i_update_core as the VFS will call back into237237+ * XFS here and set i_update_core, so we need to dirty the238238+ * inode first so that the ordering of i_update_core and239239+ * unlogged modifications still works as described below.240240+ */241241+ xfs_mark_inode_dirty_sync(ip);242242+243243+ /*235244 * Clear i_update_core if the timestamps (or any other236245 * non-transactional modification) need flushing/logging237246 * and we're about to log them with the rest of the core.···272263 }273264274265 /*275275- * Make sure to get the latest atime from the Linux inode.266266+ * Make sure to get the latest timestamps from the Linux inode.276267 */277277- xfs_synchronize_atime(ip);278278-279279- /*280280- * make sure the linux inode is dirty281281- */282282- xfs_mark_inode_dirty_sync(ip);268268+ xfs_synchronize_times(ip);283269284270 vecp->i_addr = (xfs_caddr_t)&ip->i_d;285271 vecp->i_len = sizeof(struct xfs_icdinode);
+13-8
fs/xfs/xfs_itable.c
···5959{6060 xfs_icdinode_t *dic; /* dinode core info pointer */6161 xfs_inode_t *ip; /* incore inode pointer */6262+ struct inode *inode;6263 int error;63646465 error = xfs_iget(mp, NULL, ino,···7372 ASSERT(ip->i_imap.im_blkno != 0);74737574 dic = &ip->i_d;7575+ inode = VFS_I(ip);76767777 /* xfs_iget returns the following without needing7878 * further change.···8583 buf->bs_uid = dic->di_uid;8684 buf->bs_gid = dic->di_gid;8785 buf->bs_size = dic->di_size;8686+8887 /*8989- * We are reading the atime from the Linux inode because the9090- * dinode might not be uptodate.8888+ * We need to read the timestamps from the Linux inode because8989+ * the VFS keeps writing directly into the inode structure instead9090+ * of telling us about the updates.9191 */9292- buf->bs_atime.tv_sec = VFS_I(ip)->i_atime.tv_sec;9393- buf->bs_atime.tv_nsec = VFS_I(ip)->i_atime.tv_nsec;9494- buf->bs_mtime.tv_sec = dic->di_mtime.t_sec;9595- buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec;9696- buf->bs_ctime.tv_sec = dic->di_ctime.t_sec;9797- buf->bs_ctime.tv_nsec = dic->di_ctime.t_nsec;9292+ buf->bs_atime.tv_sec = inode->i_atime.tv_sec;9393+ buf->bs_atime.tv_nsec = inode->i_atime.tv_nsec;9494+ buf->bs_mtime.tv_sec = inode->i_mtime.tv_sec;9595+ buf->bs_mtime.tv_nsec = inode->i_mtime.tv_nsec;9696+ buf->bs_ctime.tv_sec = inode->i_ctime.tv_sec;9797+ buf->bs_ctime.tv_nsec = inode->i_ctime.tv_nsec;9898+9899 buf->bs_xflags = xfs_ip2xflags(ip);99100 buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog;100101 buf->bs_extents = dic->di_nextents;
-6
fs/xfs/xfs_vnodeops.c
···24762476 ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);2477247724782478 /*24792479- * Make sure the atime in the XFS inode is correct before freeing the24802480- * Linux inode.24812481- */24822482- xfs_synchronize_atime(ip);24832483-24842484- /*24852479 * If we have nothing to flush with this inode then complete the24862480 * teardown now, otherwise break the link between the xfs inode and the24872481 * linux inode and clean up the xfs inode later. This avoids flushing