aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_attr.c4
-rw-r--r--fs/xfs/xfs_inode.c124
-rw-r--r--fs/xfs/xfs_inode.h2
-rw-r--r--fs/xfs/xfs_iops.c47
-rw-r--r--fs/xfs/xfs_qm_syscalls.c9
-rw-r--r--fs/xfs/xfs_trace.h4
-rw-r--r--fs/xfs/xfs_vnodeops.c17
7 files changed, 65 insertions, 142 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 1e5d97f86ea8..08b9ac644c31 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -827,10 +827,6 @@ xfs_attr_inactive(xfs_inode_t *dp)
827 if (error) 827 if (error)
828 goto out; 828 goto out;
829 829
830 /*
831 * Commit the last in the sequence of transactions.
832 */
833 xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE);
834 error = xfs_trans_commit(trans, XFS_TRANS_RELEASE_LOG_RES); 830 error = xfs_trans_commit(trans, XFS_TRANS_RELEASE_LOG_RES);
835 xfs_iunlock(dp, XFS_ILOCK_EXCL); 831 xfs_iunlock(dp, XFS_ILOCK_EXCL);
836 832
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 9dda7cc32848..ccd619a993f6 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1166,52 +1166,6 @@ xfs_ialloc(
1166} 1166}
1167 1167
1168/* 1168/*
1169 * Check to make sure that there are no blocks allocated to the
1170 * file beyond the size of the file. We don't check this for
1171 * files with fixed size extents or real time extents, but we
1172 * at least do it for regular files.
1173 */
1174#ifdef DEBUG
1175STATIC void
1176xfs_isize_check(
1177 struct xfs_inode *ip,
1178 xfs_fsize_t isize)
1179{
1180 struct xfs_mount *mp = ip->i_mount;
1181 xfs_fileoff_t map_first;
1182 int nimaps;
1183 xfs_bmbt_irec_t imaps[2];
1184 int error;
1185
1186 if (!S_ISREG(ip->i_d.di_mode))
1187 return;
1188
1189 if (XFS_IS_REALTIME_INODE(ip))
1190 return;
1191
1192 if (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
1193 return;
1194
1195 nimaps = 2;
1196 map_first = XFS_B_TO_FSB(mp, (xfs_ufsize_t)isize);
1197 /*
1198 * The filesystem could be shutting down, so bmapi may return
1199 * an error.
1200 */
1201 error = xfs_bmapi_read(ip, map_first,
1202 (XFS_B_TO_FSB(mp,
1203 (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) - map_first),
1204 imaps, &nimaps, XFS_BMAPI_ENTIRE);
1205 if (error)
1206 return;
1207 ASSERT(nimaps == 1);
1208 ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK);
1209}
1210#else /* DEBUG */
1211#define xfs_isize_check(ip, isize)
1212#endif /* DEBUG */
1213
1214/*
1215 * Free up the underlying blocks past new_size. The new size must be smaller 1169 * Free up the underlying blocks past new_size. The new size must be smaller
1216 * than the current size. This routine can be used both for the attribute and 1170 * than the current size. This routine can be used both for the attribute and
1217 * data fork, and does not modify the inode size, which is left to the caller. 1171 * data fork, and does not modify the inode size, which is left to the caller.
@@ -1258,6 +1212,8 @@ xfs_itruncate_extents(
1258 ASSERT(ip->i_itemp->ili_lock_flags == 0); 1212 ASSERT(ip->i_itemp->ili_lock_flags == 0);
1259 ASSERT(!XFS_NOT_DQATTACHED(mp, ip)); 1213 ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
1260 1214
1215 trace_xfs_itruncate_extents_start(ip, new_size);
1216
1261 /* 1217 /*
1262 * Since it is possible for space to become allocated beyond 1218 * Since it is possible for space to become allocated beyond
1263 * the end of the file (in a crash where the space is allocated 1219 * the end of the file (in a crash where the space is allocated
@@ -1325,6 +1281,14 @@ xfs_itruncate_extents(
1325 goto out; 1281 goto out;
1326 } 1282 }
1327 1283
1284 /*
1285 * Always re-log the inode so that our permanent transaction can keep
1286 * on rolling it forward in the log.
1287 */
1288 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1289
1290 trace_xfs_itruncate_extents_end(ip, new_size);
1291
1328out: 1292out:
1329 *tpp = tp; 1293 *tpp = tp;
1330 return error; 1294 return error;
@@ -1338,74 +1302,6 @@ out_bmap_cancel:
1338 goto out; 1302 goto out;
1339} 1303}
1340 1304
1341int
1342xfs_itruncate_data(
1343 struct xfs_trans **tpp,
1344 struct xfs_inode *ip,
1345 xfs_fsize_t new_size)
1346{
1347 int error;
1348
1349 trace_xfs_itruncate_data_start(ip, new_size);
1350
1351 /*
1352 * The first thing we do is set the size to new_size permanently on
1353 * disk. This way we don't have to worry about anyone ever being able
1354 * to look at the data being freed even in the face of a crash.
1355 * What we're getting around here is the case where we free a block, it
1356 * is allocated to another file, it is written to, and then we crash.
1357 * If the new data gets written to the file but the log buffers
1358 * containing the free and reallocation don't, then we'd end up with
1359 * garbage in the blocks being freed. As long as we make the new_size
1360 * permanent before actually freeing any blocks it doesn't matter if
1361 * they get written to.
1362 */
1363 if (ip->i_d.di_nextents > 0) {
1364 /*
1365 * If we are not changing the file size then do not update
1366 * the on-disk file size - we may be called from
1367 * xfs_inactive_free_eofblocks(). If we update the on-disk
1368 * file size and then the system crashes before the contents
1369 * of the file are flushed to disk then the files may be
1370 * full of holes (ie NULL files bug).
1371 */
1372 if (ip->i_size != new_size) {
1373 ip->i_d.di_size = new_size;
1374 ip->i_size = new_size;
1375 xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE);
1376 }
1377 }
1378
1379 error = xfs_itruncate_extents(tpp, ip, XFS_DATA_FORK, new_size);
1380 if (error)
1381 return error;
1382
1383 /*
1384 * If we are not changing the file size then do not update the on-disk
1385 * file size - we may be called from xfs_inactive_free_eofblocks().
1386 * If we update the on-disk file size and then the system crashes
1387 * before the contents of the file are flushed to disk then the files
1388 * may be full of holes (ie NULL files bug).
1389 */
1390 xfs_isize_check(ip, new_size);
1391 if (ip->i_size != new_size) {
1392 ip->i_d.di_size = new_size;
1393 ip->i_size = new_size;
1394 }
1395
1396 ASSERT(new_size != 0 || ip->i_delayed_blks == 0);
1397 ASSERT(new_size != 0 || ip->i_d.di_nextents == 0);
1398
1399 /*
1400 * Always re-log the inode so that our permanent transaction can keep
1401 * on rolling it forward in the log.
1402 */
1403 xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE);
1404
1405 trace_xfs_itruncate_data_end(ip, new_size);
1406 return 0;
1407}
1408
1409/* 1305/*
1410 * This is called when the inode's link count goes to 0. 1306 * This is called when the inode's link count goes to 0.
1411 * We place the on-disk inode on a list in the AGI. It 1307 * We place the on-disk inode on a list in the AGI. It
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index f0e6b151ba37..440f2acebfa8 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -491,8 +491,6 @@ int xfs_ifree(struct xfs_trans *, xfs_inode_t *,
491 struct xfs_bmap_free *); 491 struct xfs_bmap_free *);
492int xfs_itruncate_extents(struct xfs_trans **, struct xfs_inode *, 492int xfs_itruncate_extents(struct xfs_trans **, struct xfs_inode *,
493 int, xfs_fsize_t); 493 int, xfs_fsize_t);
494int xfs_itruncate_data(struct xfs_trans **, struct xfs_inode *,
495 xfs_fsize_t);
496int xfs_iunlink(struct xfs_trans *, xfs_inode_t *); 494int xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
497 495
498void xfs_iext_realloc(xfs_inode_t *, int, int); 496void xfs_iext_realloc(xfs_inode_t *, int, int);
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index f9babd179223..f02eaa298d3c 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -750,6 +750,7 @@ xfs_setattr_size(
750 struct xfs_mount *mp = ip->i_mount; 750 struct xfs_mount *mp = ip->i_mount;
751 struct inode *inode = VFS_I(ip); 751 struct inode *inode = VFS_I(ip);
752 int mask = iattr->ia_valid; 752 int mask = iattr->ia_valid;
753 xfs_off_t oldsize, newsize;
753 struct xfs_trans *tp; 754 struct xfs_trans *tp;
754 int error; 755 int error;
755 uint lock_flags; 756 uint lock_flags;
@@ -777,11 +778,13 @@ xfs_setattr_size(
777 lock_flags |= XFS_IOLOCK_EXCL; 778 lock_flags |= XFS_IOLOCK_EXCL;
778 xfs_ilock(ip, lock_flags); 779 xfs_ilock(ip, lock_flags);
779 780
781 oldsize = ip->i_size;
782 newsize = iattr->ia_size;
783
780 /* 784 /*
781 * Short circuit the truncate case for zero length files. 785 * Short circuit the truncate case for zero length files.
782 */ 786 */
783 if (iattr->ia_size == 0 && 787 if (newsize == 0 && oldsize == 0 && ip->i_d.di_nextents == 0) {
784 ip->i_size == 0 && ip->i_d.di_nextents == 0) {
785 if (!(mask & (ATTR_CTIME|ATTR_MTIME))) 788 if (!(mask & (ATTR_CTIME|ATTR_MTIME)))
786 goto out_unlock; 789 goto out_unlock;
787 790
@@ -807,14 +810,14 @@ xfs_setattr_size(
807 * the inode to the transaction, because the inode cannot be unlocked 810 * the inode to the transaction, because the inode cannot be unlocked
808 * once it is a part of the transaction. 811 * once it is a part of the transaction.
809 */ 812 */
810 if (iattr->ia_size > ip->i_size) { 813 if (newsize > oldsize) {
811 /* 814 /*
812 * Do the first part of growing a file: zero any data in the 815 * Do the first part of growing a file: zero any data in the
813 * last block that is beyond the old EOF. We need to do this 816 * last block that is beyond the old EOF. We need to do this
814 * before the inode is joined to the transaction to modify 817 * before the inode is joined to the transaction to modify
815 * i_size. 818 * i_size.
816 */ 819 */
817 error = xfs_zero_eof(ip, iattr->ia_size, ip->i_size); 820 error = xfs_zero_eof(ip, newsize, oldsize);
818 if (error) 821 if (error)
819 goto out_unlock; 822 goto out_unlock;
820 } 823 }
@@ -833,8 +836,8 @@ xfs_setattr_size(
833 * here and prevents waiting for other data not within the range we 836 * here and prevents waiting for other data not within the range we
834 * care about here. 837 * care about here.
835 */ 838 */
836 if (ip->i_size != ip->i_d.di_size && iattr->ia_size > ip->i_d.di_size) { 839 if (oldsize != ip->i_d.di_size && newsize > ip->i_d.di_size) {
837 error = xfs_flush_pages(ip, ip->i_d.di_size, iattr->ia_size, 0, 840 error = xfs_flush_pages(ip, ip->i_d.di_size, newsize, 0,
838 FI_NONE); 841 FI_NONE);
839 if (error) 842 if (error)
840 goto out_unlock; 843 goto out_unlock;
@@ -845,8 +848,7 @@ xfs_setattr_size(
845 */ 848 */
846 inode_dio_wait(inode); 849 inode_dio_wait(inode);
847 850
848 error = -block_truncate_page(inode->i_mapping, iattr->ia_size, 851 error = -block_truncate_page(inode->i_mapping, newsize, xfs_get_blocks);
849 xfs_get_blocks);
850 if (error) 852 if (error)
851 goto out_unlock; 853 goto out_unlock;
852 854
@@ -857,7 +859,7 @@ xfs_setattr_size(
857 if (error) 859 if (error)
858 goto out_trans_cancel; 860 goto out_trans_cancel;
859 861
860 truncate_setsize(inode, iattr->ia_size); 862 truncate_setsize(inode, newsize);
861 863
862 commit_flags = XFS_TRANS_RELEASE_LOG_RES; 864 commit_flags = XFS_TRANS_RELEASE_LOG_RES;
863 lock_flags |= XFS_ILOCK_EXCL; 865 lock_flags |= XFS_ILOCK_EXCL;
@@ -876,19 +878,30 @@ xfs_setattr_size(
876 * these flags set. For all other operations the VFS set these flags 878 * these flags set. For all other operations the VFS set these flags
877 * explicitly if it wants a timestamp update. 879 * explicitly if it wants a timestamp update.
878 */ 880 */
879 if (iattr->ia_size != ip->i_size && 881 if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME)))) {
880 (!(mask & (ATTR_CTIME | ATTR_MTIME)))) {
881 iattr->ia_ctime = iattr->ia_mtime = 882 iattr->ia_ctime = iattr->ia_mtime =
882 current_fs_time(inode->i_sb); 883 current_fs_time(inode->i_sb);
883 mask |= ATTR_CTIME | ATTR_MTIME; 884 mask |= ATTR_CTIME | ATTR_MTIME;
884 } 885 }
885 886
886 if (iattr->ia_size > ip->i_size) { 887 /*
887 ip->i_d.di_size = iattr->ia_size; 888 * The first thing we do is set the size to new_size permanently on
888 ip->i_size = iattr->ia_size; 889 * disk. This way we don't have to worry about anyone ever being able
889 } else if (iattr->ia_size <= ip->i_size || 890 * to look at the data being freed even in the face of a crash.
890 (iattr->ia_size == 0 && ip->i_d.di_nextents)) { 891 * What we're getting around here is the case where we free a block, it
891 error = xfs_itruncate_data(&tp, ip, iattr->ia_size); 892 * is allocated to another file, it is written to, and then we crash.
893 * If the new data gets written to the file but the log buffers
894 * containing the free and reallocation don't, then we'd end up with
895 * garbage in the blocks being freed. As long as we make the new size
896 * permanent before actually freeing any blocks it doesn't matter if
897 * they get written to.
898 */
899 ip->i_d.di_size = newsize;
900 ip->i_size = newsize;
901 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
902
903 if (newsize <= oldsize) {
904 error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, newsize);
892 if (error) 905 if (error)
893 goto out_trans_abort; 906 goto out_trans_abort;
894 907
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 5cc3dde1bc90..27378650b5cb 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -31,6 +31,7 @@
31#include "xfs_mount.h" 31#include "xfs_mount.h"
32#include "xfs_bmap_btree.h" 32#include "xfs_bmap_btree.h"
33#include "xfs_inode.h" 33#include "xfs_inode.h"
34#include "xfs_inode_item.h"
34#include "xfs_itable.h" 35#include "xfs_itable.h"
35#include "xfs_bmap.h" 36#include "xfs_bmap.h"
36#include "xfs_rtalloc.h" 37#include "xfs_rtalloc.h"
@@ -263,13 +264,19 @@ xfs_qm_scall_trunc_qfile(
263 xfs_ilock(ip, XFS_ILOCK_EXCL); 264 xfs_ilock(ip, XFS_ILOCK_EXCL);
264 xfs_trans_ijoin(tp, ip, 0); 265 xfs_trans_ijoin(tp, ip, 0);
265 266
266 error = xfs_itruncate_data(&tp, ip, 0); 267 ip->i_d.di_size = 0;
268 ip->i_size = 0;
269 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
270
271 error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
267 if (error) { 272 if (error) {
268 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | 273 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
269 XFS_TRANS_ABORT); 274 XFS_TRANS_ABORT);
270 goto out_unlock; 275 goto out_unlock;
271 } 276 }
272 277
278 ASSERT(ip->i_d.di_nextents == 0);
279
273 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 280 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
274 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); 281 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
275 282
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index a9d5b1e06efe..297f9fa6fb64 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -1090,8 +1090,8 @@ DECLARE_EVENT_CLASS(xfs_itrunc_class,
1090DEFINE_EVENT(xfs_itrunc_class, name, \ 1090DEFINE_EVENT(xfs_itrunc_class, name, \
1091 TP_PROTO(struct xfs_inode *ip, xfs_fsize_t new_size), \ 1091 TP_PROTO(struct xfs_inode *ip, xfs_fsize_t new_size), \
1092 TP_ARGS(ip, new_size)) 1092 TP_ARGS(ip, new_size))
1093DEFINE_ITRUNC_EVENT(xfs_itruncate_data_start); 1093DEFINE_ITRUNC_EVENT(xfs_itruncate_extents_start);
1094DEFINE_ITRUNC_EVENT(xfs_itruncate_data_end); 1094DEFINE_ITRUNC_EVENT(xfs_itruncate_extents_end);
1095 1095
1096TRACE_EVENT(xfs_pagecache_inval, 1096TRACE_EVENT(xfs_pagecache_inval,
1097 TP_PROTO(struct xfs_inode *ip, xfs_off_t start, xfs_off_t finish), 1097 TP_PROTO(struct xfs_inode *ip, xfs_off_t start, xfs_off_t finish),
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index f2fea868d4db..96ff03421753 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -226,7 +226,14 @@ xfs_free_eofblocks(
226 xfs_ilock(ip, XFS_ILOCK_EXCL); 226 xfs_ilock(ip, XFS_ILOCK_EXCL);
227 xfs_trans_ijoin(tp, ip, 0); 227 xfs_trans_ijoin(tp, ip, 0);
228 228
229 error = xfs_itruncate_data(&tp, ip, ip->i_size); 229 /*
230 * Do not update the on-disk file size. If we update the
231 * on-disk file size and then the system crashes before the
232 * contents of the file are flushed to disk then the files
233 * may be full of holes (ie NULL files bug).
234 */
235 error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK,
236 ip->i_size);
230 if (error) { 237 if (error) {
231 /* 238 /*
232 * If we get an error at this point we simply don't 239 * If we get an error at this point we simply don't
@@ -670,13 +677,19 @@ xfs_inactive(
670 xfs_ilock(ip, XFS_ILOCK_EXCL); 677 xfs_ilock(ip, XFS_ILOCK_EXCL);
671 xfs_trans_ijoin(tp, ip, 0); 678 xfs_trans_ijoin(tp, ip, 0);
672 679
673 error = xfs_itruncate_data(&tp, ip, 0); 680 ip->i_d.di_size = 0;
681 ip->i_size = 0;
682 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
683
684 error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
674 if (error) { 685 if (error) {
675 xfs_trans_cancel(tp, 686 xfs_trans_cancel(tp,
676 XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); 687 XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
677 xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); 688 xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
678 return VN_INACTIVE_CACHE; 689 return VN_INACTIVE_CACHE;
679 } 690 }
691
692 ASSERT(ip->i_d.di_nextents == 0);
680 } else if (S_ISLNK(ip->i_d.di_mode)) { 693 } else if (S_ISLNK(ip->i_d.di_mode)) {
681 694
682 /* 695 /*