aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2015-04-16 07:59:07 -0400
committerDave Chinner <david@fromorbit.com>2015-04-16 07:59:07 -0400
commitd5cc2e3f968ff60f247fdef15b04fac788ef46d2 (patch)
tree3fc9395d93bea2bddacdea465bef3fda76352a0a /fs/xfs
parent1fdca9c21198b2c2869086ac3629612492476f28 (diff)
xfs: DIO needs an ioend for writes
Currently we can only tell DIO completion that an IO requires unwritten extent completion. This is done by a hacky non-null private pointer passed to Io completion, but the private pointer does not actually contain any information that is used. We also need to pass to IO completion the fact that the IO may be beyond EOF and so a size update transaction needs to be done. This is currently determined by checks in the io completion, but we need to determine if this is necessary at block mapping time as we need to defer the size update transactions to a completion workqueue, just like unwritten extent conversion. To do this, first we need to allocate and pass an ioend to to IO completion. Add this for unwritten extent conversion; we'll do the EOF updates in the next commit. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_aops.c92
-rw-r--r--fs/xfs/xfs_trace.h3
2 files changed, 85 insertions, 10 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 4a29399ed549..60d6466d72f6 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1234,7 +1234,23 @@ xfs_vm_releasepage(
1234} 1234}
1235 1235
1236/* 1236/*
1237 * do all the direct IO specific mapping buffer manipulation here. 1237 * When we map a DIO buffer, we need to attach an ioend that describes the type
1238 * of write IO we are doing. This passes to the completion function the
1239 * operations it needs to perform.
1240 *
1241 * If we get multiple mappings in a single IO, we might be mapping different
1242 * types. But because the direct IO can only have a single private pointer, we
1243 * need to ensure that:
1244 *
1245 * a) the ioend spans the entire region of the IO; and
1246 * b) if it contains unwritten extents, it is *permanently* marked as such
1247 *
1248 * We could do this by chaining ioends like buffered IO does, but we only
1249 * actually get one IO completion callback from the direct IO, and that spans
1250 * the entire IO regardless of how many mappings and IOs are needed to complete
1251 * the DIO. There is only going to be one reference to the ioend and its life
1252 * cycle is constrained by the DIO completion code. hence we don't need
1253 * reference counting here.
1238 */ 1254 */
1239static void 1255static void
1240xfs_map_direct( 1256xfs_map_direct(
@@ -1243,10 +1259,42 @@ xfs_map_direct(
1243 struct xfs_bmbt_irec *imap, 1259 struct xfs_bmbt_irec *imap,
1244 xfs_off_t offset) 1260 xfs_off_t offset)
1245{ 1261{
1246 if (ISUNWRITTEN(imap)) { 1262 struct xfs_ioend *ioend;
1247 bh_result->b_private = inode; 1263 xfs_off_t size = bh_result->b_size;
1248 set_buffer_defer_completion(bh_result); 1264 int type;
1265
1266 if (ISUNWRITTEN(imap))
1267 type = XFS_IO_UNWRITTEN;
1268 else
1269 type = XFS_IO_OVERWRITE;
1270
1271 trace_xfs_gbmap_direct(XFS_I(inode), offset, size, type, imap);
1272
1273 if (bh_result->b_private) {
1274 ioend = bh_result->b_private;
1275 ASSERT(ioend->io_size > 0);
1276 ASSERT(offset >= ioend->io_offset);
1277 if (offset + size > ioend->io_offset + ioend->io_size)
1278 ioend->io_size = offset - ioend->io_offset + size;
1279
1280 if (type == XFS_IO_UNWRITTEN && type != ioend->io_type)
1281 ioend->io_type = XFS_IO_UNWRITTEN;
1282
1283 trace_xfs_gbmap_direct_update(XFS_I(inode), ioend->io_offset,
1284 ioend->io_size, ioend->io_type,
1285 imap);
1286 } else {
1287 ioend = xfs_alloc_ioend(inode, type);
1288 ioend->io_offset = offset;
1289 ioend->io_size = size;
1290 bh_result->b_private = ioend;
1291
1292 trace_xfs_gbmap_direct_new(XFS_I(inode), offset, size, type,
1293 imap);
1249 } 1294 }
1295
1296 if (ioend->io_type == XFS_IO_UNWRITTEN)
1297 set_buffer_defer_completion(bh_result);
1250} 1298}
1251 1299
1252 1300
@@ -1378,10 +1426,13 @@ __xfs_get_blocks(
1378 1426
1379 xfs_iunlock(ip, lockmode); 1427 xfs_iunlock(ip, lockmode);
1380 } 1428 }
1381 1429 trace_xfs_get_blocks_alloc(ip, offset, size,
1382 trace_xfs_get_blocks_alloc(ip, offset, size, 0, &imap); 1430 ISUNWRITTEN(&imap) ? XFS_IO_UNWRITTEN
1431 : XFS_IO_DELALLOC, &imap);
1383 } else if (nimaps) { 1432 } else if (nimaps) {
1384 trace_xfs_get_blocks_found(ip, offset, size, 0, &imap); 1433 trace_xfs_get_blocks_found(ip, offset, size,
1434 ISUNWRITTEN(&imap) ? XFS_IO_UNWRITTEN
1435 : XFS_IO_OVERWRITE, &imap);
1385 xfs_iunlock(ip, lockmode); 1436 xfs_iunlock(ip, lockmode);
1386 } else { 1437 } else {
1387 trace_xfs_get_blocks_notfound(ip, offset, size); 1438 trace_xfs_get_blocks_notfound(ip, offset, size);
@@ -1482,9 +1533,28 @@ xfs_end_io_direct_write(
1482 struct inode *inode = file_inode(iocb->ki_filp); 1533 struct inode *inode = file_inode(iocb->ki_filp);
1483 struct xfs_inode *ip = XFS_I(inode); 1534 struct xfs_inode *ip = XFS_I(inode);
1484 struct xfs_mount *mp = ip->i_mount; 1535 struct xfs_mount *mp = ip->i_mount;
1536 struct xfs_ioend *ioend = private;
1485 1537
1486 if (XFS_FORCED_SHUTDOWN(mp)) 1538 if (XFS_FORCED_SHUTDOWN(mp))
1487 return; 1539 goto out_destroy_ioend;
1540
1541 /*
1542 * dio completion end_io functions are only called on writes if more
1543 * than 0 bytes was written.
1544 */
1545 ASSERT(size > 0);
1546
1547 /*
1548 * The ioend only maps whole blocks, while the IO may be sector aligned.
1549 * Hence the ioend offset/size may not match the IO offset/size exactly,
1550 * but should span it completely. Write the IO sizes into the ioend so
1551 * that completion processing does the right thing.
1552 */
1553 ASSERT(size <= ioend->io_size);
1554 ASSERT(offset >= ioend->io_offset);
1555 ASSERT(offset + size <= ioend->io_offset + ioend->io_size);
1556 ioend->io_size = size;
1557 ioend->io_offset = offset;
1488 1558
1489 /* 1559 /*
1490 * While the generic direct I/O code updates the inode size, it does 1560 * While the generic direct I/O code updates the inode size, it does
@@ -1504,7 +1574,7 @@ xfs_end_io_direct_write(
1504 * we can pass the ioend to the direct IO allocation callbacks and 1574 * we can pass the ioend to the direct IO allocation callbacks and
1505 * avoid nesting that way. 1575 * avoid nesting that way.
1506 */ 1576 */
1507 if (private && size > 0) { 1577 if (ioend->io_type == XFS_IO_UNWRITTEN) {
1508 xfs_iomap_write_unwritten(ip, offset, size); 1578 xfs_iomap_write_unwritten(ip, offset, size);
1509 } else if (offset + size > ip->i_d.di_size) { 1579 } else if (offset + size > ip->i_d.di_size) {
1510 struct xfs_trans *tp; 1580 struct xfs_trans *tp;
@@ -1514,11 +1584,13 @@ xfs_end_io_direct_write(
1514 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_fsyncts, 0, 0); 1584 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_fsyncts, 0, 0);
1515 if (error) { 1585 if (error) {
1516 xfs_trans_cancel(tp, 0); 1586 xfs_trans_cancel(tp, 0);
1517 return; 1587 goto out_destroy_ioend;
1518 } 1588 }
1519 1589
1520 xfs_setfilesize(ip, tp, offset, size); 1590 xfs_setfilesize(ip, tp, offset, size);
1521 } 1591 }
1592out_destroy_ioend:
1593 xfs_destroy_ioend(ioend);
1522} 1594}
1523 1595
1524STATIC ssize_t 1596STATIC ssize_t
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 51372e34d988..2de8556ffac2 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -1217,6 +1217,9 @@ DEFINE_IOMAP_EVENT(xfs_map_blocks_found);
1217DEFINE_IOMAP_EVENT(xfs_map_blocks_alloc); 1217DEFINE_IOMAP_EVENT(xfs_map_blocks_alloc);
1218DEFINE_IOMAP_EVENT(xfs_get_blocks_found); 1218DEFINE_IOMAP_EVENT(xfs_get_blocks_found);
1219DEFINE_IOMAP_EVENT(xfs_get_blocks_alloc); 1219DEFINE_IOMAP_EVENT(xfs_get_blocks_alloc);
1220DEFINE_IOMAP_EVENT(xfs_gbmap_direct);
1221DEFINE_IOMAP_EVENT(xfs_gbmap_direct_new);
1222DEFINE_IOMAP_EVENT(xfs_gbmap_direct_update);
1220 1223
1221DECLARE_EVENT_CLASS(xfs_simple_io_class, 1224DECLARE_EVENT_CLASS(xfs_simple_io_class,
1222 TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count), 1225 TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count),