aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/linux-2.6/xfs_trace.h34
-rw-r--r--fs/xfs/xfs_inode.c163
-rw-r--r--fs/xfs/xfs_inode.h11
-rw-r--r--fs/xfs/xfs_vnodeops.c27
4 files changed, 4 insertions, 231 deletions
diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/linux-2.6/xfs_trace.h
index d48b7a579ae1..cac41e423451 100644
--- a/fs/xfs/linux-2.6/xfs_trace.h
+++ b/fs/xfs/linux-2.6/xfs_trace.h
@@ -1029,40 +1029,6 @@ DEFINE_SIMPLE_IO_EVENT(xfs_delalloc_enospc);
1029DEFINE_SIMPLE_IO_EVENT(xfs_unwritten_convert); 1029DEFINE_SIMPLE_IO_EVENT(xfs_unwritten_convert);
1030DEFINE_SIMPLE_IO_EVENT(xfs_get_blocks_notfound); 1030DEFINE_SIMPLE_IO_EVENT(xfs_get_blocks_notfound);
1031 1031
1032
1033TRACE_EVENT(xfs_itruncate_start,
1034 TP_PROTO(struct xfs_inode *ip, xfs_fsize_t new_size, int flag,
1035 xfs_off_t toss_start, xfs_off_t toss_finish),
1036 TP_ARGS(ip, new_size, flag, toss_start, toss_finish),
1037 TP_STRUCT__entry(
1038 __field(dev_t, dev)
1039 __field(xfs_ino_t, ino)
1040 __field(xfs_fsize_t, size)
1041 __field(xfs_fsize_t, new_size)
1042 __field(xfs_off_t, toss_start)
1043 __field(xfs_off_t, toss_finish)
1044 __field(int, flag)
1045 ),
1046 TP_fast_assign(
1047 __entry->dev = VFS_I(ip)->i_sb->s_dev;
1048 __entry->ino = ip->i_ino;
1049 __entry->size = ip->i_d.di_size;
1050 __entry->new_size = new_size;
1051 __entry->toss_start = toss_start;
1052 __entry->toss_finish = toss_finish;
1053 __entry->flag = flag;
1054 ),
1055 TP_printk("dev %d:%d ino 0x%llx %s size 0x%llx new_size 0x%llx "
1056 "toss start 0x%llx toss finish 0x%llx",
1057 MAJOR(__entry->dev), MINOR(__entry->dev),
1058 __entry->ino,
1059 __print_flags(__entry->flag, "|", XFS_ITRUNC_FLAGS),
1060 __entry->size,
1061 __entry->new_size,
1062 __entry->toss_start,
1063 __entry->toss_finish)
1064);
1065
1066DECLARE_EVENT_CLASS(xfs_itrunc_class, 1032DECLARE_EVENT_CLASS(xfs_itrunc_class,
1067 TP_PROTO(struct xfs_inode *ip, xfs_fsize_t new_size), 1033 TP_PROTO(struct xfs_inode *ip, xfs_fsize_t new_size),
1068 TP_ARGS(ip, new_size), 1034 TP_ARGS(ip, new_size),
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index a098a20ca63e..82a282ab63dc 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1217,165 +1217,8 @@ xfs_isize_check(
1217#endif /* DEBUG */ 1217#endif /* DEBUG */
1218 1218
1219/* 1219/*
1220 * Calculate the last possible buffered byte in a file. This must 1220 * Free up the underlying blocks past new_size. The new size must be
1221 * include data that was buffered beyond the EOF by the write code. 1221 * smaller than the current size.
1222 * This also needs to deal with overflowing the xfs_fsize_t type
1223 * which can happen for sizes near the limit.
1224 *
1225 * We also need to take into account any blocks beyond the EOF. It
1226 * may be the case that they were buffered by a write which failed.
1227 * In that case the pages will still be in memory, but the inode size
1228 * will never have been updated.
1229 */
1230STATIC xfs_fsize_t
1231xfs_file_last_byte(
1232 xfs_inode_t *ip)
1233{
1234 xfs_mount_t *mp;
1235 xfs_fsize_t last_byte;
1236 xfs_fileoff_t last_block;
1237 xfs_fileoff_t size_last_block;
1238 int error;
1239
1240 ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED));
1241
1242 mp = ip->i_mount;
1243 /*
1244 * Only check for blocks beyond the EOF if the extents have
1245 * been read in. This eliminates the need for the inode lock,
1246 * and it also saves us from looking when it really isn't
1247 * necessary.
1248 */
1249 if (ip->i_df.if_flags & XFS_IFEXTENTS) {
1250 xfs_ilock(ip, XFS_ILOCK_SHARED);
1251 error = xfs_bmap_last_offset(NULL, ip, &last_block,
1252 XFS_DATA_FORK);
1253 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1254 if (error) {
1255 last_block = 0;
1256 }
1257 } else {
1258 last_block = 0;
1259 }
1260 size_last_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)ip->i_size);
1261 last_block = XFS_FILEOFF_MAX(last_block, size_last_block);
1262
1263 last_byte = XFS_FSB_TO_B(mp, last_block);
1264 if (last_byte < 0) {
1265 return XFS_MAXIOFFSET(mp);
1266 }
1267 last_byte += (1 << mp->m_writeio_log);
1268 if (last_byte < 0) {
1269 return XFS_MAXIOFFSET(mp);
1270 }
1271 return last_byte;
1272}
1273
1274/*
1275 * Start the truncation of the file to new_size. The new size
1276 * must be smaller than the current size. This routine will
1277 * clear the buffer and page caches of file data in the removed
1278 * range, and xfs_itruncate_finish() will remove the underlying
1279 * disk blocks.
1280 *
1281 * The inode must have its I/O lock locked EXCLUSIVELY, and it
1282 * must NOT have the inode lock held at all. This is because we're
1283 * calling into the buffer/page cache code and we can't hold the
1284 * inode lock when we do so.
1285 *
1286 * We need to wait for any direct I/Os in flight to complete before we
1287 * proceed with the truncate. This is needed to prevent the extents
1288 * being read or written by the direct I/Os from being removed while the
1289 * I/O is in flight as there is no other method of synchronising
1290 * direct I/O with the truncate operation. Also, because we hold
1291 * the IOLOCK in exclusive mode, we prevent new direct I/Os from being
1292 * started until the truncate completes and drops the lock. Essentially,
1293 * the xfs_ioend_wait() call forms an I/O barrier that provides strict
1294 * ordering between direct I/Os and the truncate operation.
1295 *
1296 * The flags parameter can have either the value XFS_ITRUNC_DEFINITE
1297 * or XFS_ITRUNC_MAYBE. The XFS_ITRUNC_MAYBE value should be used
1298 * in the case that the caller is locking things out of order and
1299 * may not be able to call xfs_itruncate_finish() with the inode lock
1300 * held without dropping the I/O lock. If the caller must drop the
1301 * I/O lock before calling xfs_itruncate_finish(), then xfs_itruncate_start()
1302 * must be called again with all the same restrictions as the initial
1303 * call.
1304 */
1305int
1306xfs_itruncate_start(
1307 xfs_inode_t *ip,
1308 uint flags,
1309 xfs_fsize_t new_size)
1310{
1311 xfs_fsize_t last_byte;
1312 xfs_off_t toss_start;
1313 xfs_mount_t *mp;
1314 int error = 0;
1315
1316 ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
1317 ASSERT((new_size == 0) || (new_size <= ip->i_size));
1318 ASSERT((flags == XFS_ITRUNC_DEFINITE) ||
1319 (flags == XFS_ITRUNC_MAYBE));
1320
1321 mp = ip->i_mount;
1322
1323 /* wait for the completion of any pending DIOs */
1324 if (new_size == 0 || new_size < ip->i_size)
1325 xfs_ioend_wait(ip);
1326
1327 /*
1328 * Call toss_pages or flushinval_pages to get rid of pages
1329 * overlapping the region being removed. We have to use
1330 * the less efficient flushinval_pages in the case that the
1331 * caller may not be able to finish the truncate without
1332 * dropping the inode's I/O lock. Make sure
1333 * to catch any pages brought in by buffers overlapping
1334 * the EOF by searching out beyond the isize by our
1335 * block size. We round new_size up to a block boundary
1336 * so that we don't toss things on the same block as
1337 * new_size but before it.
1338 *
1339 * Before calling toss_page or flushinval_pages, make sure to
1340 * call remapf() over the same region if the file is mapped.
1341 * This frees up mapped file references to the pages in the
1342 * given range and for the flushinval_pages case it ensures
1343 * that we get the latest mapped changes flushed out.
1344 */
1345 toss_start = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size);
1346 toss_start = XFS_FSB_TO_B(mp, toss_start);
1347 if (toss_start < 0) {
1348 /*
1349 * The place to start tossing is beyond our maximum
1350 * file size, so there is no way that the data extended
1351 * out there.
1352 */
1353 return 0;
1354 }
1355 last_byte = xfs_file_last_byte(ip);
1356 trace_xfs_itruncate_start(ip, new_size, flags, toss_start, last_byte);
1357 if (last_byte > toss_start) {
1358 if (flags & XFS_ITRUNC_DEFINITE) {
1359 xfs_tosspages(ip, toss_start,
1360 -1, FI_REMAPF_LOCKED);
1361 } else {
1362 error = xfs_flushinval_pages(ip, toss_start,
1363 -1, FI_REMAPF_LOCKED);
1364 }
1365 }
1366
1367#ifdef DEBUG
1368 if (new_size == 0) {
1369 ASSERT(VN_CACHED(VFS_I(ip)) == 0);
1370 }
1371#endif
1372 return error;
1373}
1374
1375/*
1376 * Shrink the file to the given new_size. The new size must be smaller than
1377 * the current size. This will free up the underlying blocks in the removed
1378 * range after a call to xfs_itruncate_start() or xfs_atruncate_start().
1379 * 1222 *
1380 * The transaction passed to this routine must have made a permanent log 1223 * The transaction passed to this routine must have made a permanent log
1381 * reservation of at least XFS_ITRUNCATE_LOG_RES. This routine may commit the 1224 * reservation of at least XFS_ITRUNCATE_LOG_RES. This routine may commit the
@@ -1387,7 +1230,7 @@ xfs_itruncate_start(
1387 * will be "held" within the returned transaction. This routine does NOT 1230 * will be "held" within the returned transaction. This routine does NOT
1388 * require any disk space to be reserved for it within the transaction. 1231 * require any disk space to be reserved for it within the transaction.
1389 * 1232 *
1390 * The fork parameter must be either xfs_attr_fork or xfs_data_fork, and it 1233 * The fork parameter must be either XFS_ATTR_FORK or XFS_DATA_FORK, and it
1391 * indicates the fork which is to be truncated. For the attribute fork we only 1234 * indicates the fork which is to be truncated. For the attribute fork we only
1392 * support truncation to size 0. 1235 * support truncation to size 0.
1393 * 1236 *
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 964cfea77686..6efd471c8724 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -458,16 +458,6 @@ static inline void xfs_ifunlock(xfs_inode_t *ip)
458extern struct lock_class_key xfs_iolock_reclaimable; 458extern struct lock_class_key xfs_iolock_reclaimable;
459 459
460/* 460/*
461 * Flags for xfs_itruncate_start().
462 */
463#define XFS_ITRUNC_DEFINITE 0x1
464#define XFS_ITRUNC_MAYBE 0x2
465
466#define XFS_ITRUNC_FLAGS \
467 { XFS_ITRUNC_DEFINITE, "DEFINITE" }, \
468 { XFS_ITRUNC_MAYBE, "MAYBE" }
469
470/*
471 * For multiple groups support: if S_ISGID bit is set in the parent 461 * For multiple groups support: if S_ISGID bit is set in the parent
472 * directory, group of new file is set to that of the parent, and 462 * directory, group of new file is set to that of the parent, and
473 * new subdirectory gets S_ISGID bit from parent. 463 * new subdirectory gets S_ISGID bit from parent.
@@ -501,7 +491,6 @@ uint xfs_ip2xflags(struct xfs_inode *);
501uint xfs_dic2xflags(struct xfs_dinode *); 491uint xfs_dic2xflags(struct xfs_dinode *);
502int xfs_ifree(struct xfs_trans *, xfs_inode_t *, 492int xfs_ifree(struct xfs_trans *, xfs_inode_t *,
503 struct xfs_bmap_free *); 493 struct xfs_bmap_free *);
504int xfs_itruncate_start(xfs_inode_t *, uint, xfs_fsize_t);
505int xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *, 494int xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *,
506 xfs_fsize_t, int, int); 495 xfs_fsize_t, int, int);
507int xfs_iunlink(struct xfs_trans *, xfs_inode_t *); 496int xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index a4f56a42ef90..45b8ac662aee 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -197,13 +197,6 @@ xfs_free_eofblocks(
197 */ 197 */
198 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); 198 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
199 199
200 /*
201 * Do the xfs_itruncate_start() call before
202 * reserving any log space because
203 * itruncate_start will call into the buffer
204 * cache and we can't
205 * do that within a transaction.
206 */
207 if (flags & XFS_FREE_EOF_TRYLOCK) { 200 if (flags & XFS_FREE_EOF_TRYLOCK) {
208 if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) { 201 if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) {
209 xfs_trans_cancel(tp, 0); 202 xfs_trans_cancel(tp, 0);
@@ -212,13 +205,6 @@ xfs_free_eofblocks(
212 } else { 205 } else {
213 xfs_ilock(ip, XFS_IOLOCK_EXCL); 206 xfs_ilock(ip, XFS_IOLOCK_EXCL);
214 } 207 }
215 error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
216 ip->i_size);
217 if (error) {
218 xfs_trans_cancel(tp, 0);
219 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
220 return error;
221 }
222 208
223 error = xfs_trans_reserve(tp, 0, 209 error = xfs_trans_reserve(tp, 0,
224 XFS_ITRUNCATE_LOG_RES(mp), 210 XFS_ITRUNCATE_LOG_RES(mp),
@@ -660,20 +646,9 @@ xfs_inactive(
660 646
661 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); 647 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
662 if (truncate) { 648 if (truncate) {
663 /*
664 * Do the xfs_itruncate_start() call before
665 * reserving any log space because itruncate_start
666 * will call into the buffer cache and we can't
667 * do that within a transaction.
668 */
669 xfs_ilock(ip, XFS_IOLOCK_EXCL); 649 xfs_ilock(ip, XFS_IOLOCK_EXCL);
670 650
671 error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, 0); 651 xfs_ioend_wait(ip);
672 if (error) {
673 xfs_trans_cancel(tp, 0);
674 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
675 return VN_INACTIVE_CACHE;
676 }
677 652
678 error = xfs_trans_reserve(tp, 0, 653 error = xfs_trans_reserve(tp, 0,
679 XFS_ITRUNCATE_LOG_RES(mp), 654 XFS_ITRUNCATE_LOG_RES(mp),