diff options
author | Christoph Hellwig <hch@infradead.org> | 2010-12-10 03:42:20 -0500 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2010-12-16 17:05:51 -0500 |
commit | a206c817c864583c44e2f418db8e6c7a000fbc38 (patch) | |
tree | 71c7327482299de93b4183c23d118939e8bd30fc /fs/xfs/linux-2.6/xfs_aops.c | |
parent | 405f80429436d38ab4e6b4c0d99861a1f00648fd (diff) |
xfs: kill xfs_iomap
Opencode the xfs_iomap code in it's two callers. The overlap of
passed flags already was minimal and will be further reduced in the
next patch.
As a side effect the BMAPI_* flags for xfs_bmapi and the IO_* flags
for I/O end processing are merged into a single set of flags, which
should be a bit more descriptive of the operation we perform.
Also improve the tracing by giving each caller it's own type set of
tracepoints.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_aops.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 211 |
1 files changed, 151 insertions, 60 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 1ace78bfbea7..365040f61d89 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -38,15 +38,6 @@ | |||
38 | #include <linux/pagevec.h> | 38 | #include <linux/pagevec.h> |
39 | #include <linux/writeback.h> | 39 | #include <linux/writeback.h> |
40 | 40 | ||
41 | /* | ||
42 | * Types of I/O for bmap clustering and I/O completion tracking. | ||
43 | */ | ||
44 | enum { | ||
45 | IO_READ, /* mapping for a read */ | ||
46 | IO_DELAY, /* mapping covers delalloc region */ | ||
47 | IO_UNWRITTEN, /* mapping covers allocated but uninitialized data */ | ||
48 | IO_NEW /* just allocated */ | ||
49 | }; | ||
50 | 41 | ||
51 | /* | 42 | /* |
52 | * Prime number of hash buckets since address is used as the key. | 43 | * Prime number of hash buckets since address is used as the key. |
@@ -182,9 +173,6 @@ xfs_setfilesize( | |||
182 | xfs_inode_t *ip = XFS_I(ioend->io_inode); | 173 | xfs_inode_t *ip = XFS_I(ioend->io_inode); |
183 | xfs_fsize_t isize; | 174 | xfs_fsize_t isize; |
184 | 175 | ||
185 | ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG); | ||
186 | ASSERT(ioend->io_type != IO_READ); | ||
187 | |||
188 | if (unlikely(ioend->io_error)) | 176 | if (unlikely(ioend->io_error)) |
189 | return 0; | 177 | return 0; |
190 | 178 | ||
@@ -244,10 +232,8 @@ xfs_end_io( | |||
244 | * We might have to update the on-disk file size after extending | 232 | * We might have to update the on-disk file size after extending |
245 | * writes. | 233 | * writes. |
246 | */ | 234 | */ |
247 | if (ioend->io_type != IO_READ) { | 235 | error = xfs_setfilesize(ioend); |
248 | error = xfs_setfilesize(ioend); | 236 | ASSERT(!error || error == EAGAIN); |
249 | ASSERT(!error || error == EAGAIN); | ||
250 | } | ||
251 | 237 | ||
252 | /* | 238 | /* |
253 | * If we didn't complete processing of the ioend, requeue it to the | 239 | * If we didn't complete processing of the ioend, requeue it to the |
@@ -320,12 +306,88 @@ xfs_map_blocks( | |||
320 | loff_t offset, | 306 | loff_t offset, |
321 | ssize_t count, | 307 | ssize_t count, |
322 | struct xfs_bmbt_irec *imap, | 308 | struct xfs_bmbt_irec *imap, |
323 | int flags) | 309 | int type, |
310 | int nonblocking) | ||
324 | { | 311 | { |
325 | int nmaps = 1; | 312 | struct xfs_inode *ip = XFS_I(inode); |
326 | int new = 0; | 313 | struct xfs_mount *mp = ip->i_mount; |
314 | xfs_fileoff_t offset_fsb, end_fsb; | ||
315 | int error = 0; | ||
316 | int lockmode = 0; | ||
317 | int bmapi_flags = XFS_BMAPI_ENTIRE; | ||
318 | int nimaps = 1; | ||
319 | |||
320 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
321 | return -XFS_ERROR(EIO); | ||
322 | |||
323 | switch (type) { | ||
324 | case IO_OVERWRITE: | ||
325 | lockmode = xfs_ilock_map_shared(ip); | ||
326 | break; | ||
327 | case IO_UNWRITTEN: | ||
328 | lockmode = XFS_ILOCK_EXCL; | ||
329 | bmapi_flags |= XFS_BMAPI_IGSTATE; | ||
330 | xfs_ilock(ip, lockmode); | ||
331 | break; | ||
332 | case IO_DELALLOC: | ||
333 | lockmode = XFS_ILOCK_SHARED; | ||
334 | |||
335 | if (!xfs_ilock_nowait(ip, lockmode)) { | ||
336 | if (nonblocking) | ||
337 | return -XFS_ERROR(EAGAIN); | ||
338 | xfs_ilock(ip, lockmode); | ||
339 | } | ||
340 | break; | ||
341 | } | ||
342 | |||
343 | ASSERT(offset <= mp->m_maxioffset); | ||
344 | if (offset + count > mp->m_maxioffset) | ||
345 | count = mp->m_maxioffset - offset; | ||
346 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); | ||
347 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | ||
348 | |||
349 | error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb, | ||
350 | bmapi_flags, NULL, 0, imap, &nimaps, NULL); | ||
351 | if (error) | ||
352 | goto out; | ||
353 | |||
354 | switch (type) { | ||
355 | case IO_UNWRITTEN: | ||
356 | /* If we found an extent, return it */ | ||
357 | if (nimaps && | ||
358 | (imap->br_startblock != HOLESTARTBLOCK) && | ||
359 | (imap->br_startblock != DELAYSTARTBLOCK)) { | ||
360 | trace_xfs_map_blocks_found(ip, offset, count, type, imap); | ||
361 | break; | ||
362 | } | ||
363 | |||
364 | error = xfs_iomap_write_delay(ip, offset, count, imap); | ||
365 | if (!error) | ||
366 | trace_xfs_map_blocks_alloc(ip, offset, count, type, imap); | ||
367 | break; | ||
368 | case IO_DELALLOC: | ||
369 | /* If we found an extent, return it */ | ||
370 | xfs_iunlock(ip, lockmode); | ||
371 | lockmode = 0; | ||
372 | |||
373 | if (nimaps && !isnullstartblock(imap->br_startblock)) { | ||
374 | trace_xfs_map_blocks_found(ip, offset, count, type, imap); | ||
375 | break; | ||
376 | } | ||
377 | |||
378 | error = xfs_iomap_write_allocate(ip, offset, count, imap); | ||
379 | if (!error) | ||
380 | trace_xfs_map_blocks_alloc(ip, offset, count, type, imap); | ||
381 | break; | ||
382 | default: | ||
383 | if (nimaps) | ||
384 | trace_xfs_map_blocks_found(ip, offset, count, type, imap); | ||
385 | } | ||
327 | 386 | ||
328 | return -xfs_iomap(XFS_I(inode), offset, count, flags, imap, &nmaps, &new); | 387 | out: |
388 | if (lockmode) | ||
389 | xfs_iunlock(ip, lockmode); | ||
390 | return -XFS_ERROR(error); | ||
329 | } | 391 | } |
330 | 392 | ||
331 | STATIC int | 393 | STATIC int |
@@ -722,9 +784,9 @@ xfs_is_delayed_page( | |||
722 | if (buffer_unwritten(bh)) | 784 | if (buffer_unwritten(bh)) |
723 | acceptable = (type == IO_UNWRITTEN); | 785 | acceptable = (type == IO_UNWRITTEN); |
724 | else if (buffer_delay(bh)) | 786 | else if (buffer_delay(bh)) |
725 | acceptable = (type == IO_DELAY); | 787 | acceptable = (type == IO_DELALLOC); |
726 | else if (buffer_dirty(bh) && buffer_mapped(bh)) | 788 | else if (buffer_dirty(bh) && buffer_mapped(bh)) |
727 | acceptable = (type == IO_NEW); | 789 | acceptable = (type == IO_OVERWRITE); |
728 | else | 790 | else |
729 | break; | 791 | break; |
730 | } while ((bh = bh->b_this_page) != head); | 792 | } while ((bh = bh->b_this_page) != head); |
@@ -809,7 +871,7 @@ xfs_convert_page( | |||
809 | if (buffer_unwritten(bh)) | 871 | if (buffer_unwritten(bh)) |
810 | type = IO_UNWRITTEN; | 872 | type = IO_UNWRITTEN; |
811 | else | 873 | else |
812 | type = IO_DELAY; | 874 | type = IO_DELALLOC; |
813 | 875 | ||
814 | if (!xfs_imap_valid(inode, imap, offset)) { | 876 | if (!xfs_imap_valid(inode, imap, offset)) { |
815 | done = 1; | 877 | done = 1; |
@@ -826,7 +888,7 @@ xfs_convert_page( | |||
826 | page_dirty--; | 888 | page_dirty--; |
827 | count++; | 889 | count++; |
828 | } else { | 890 | } else { |
829 | type = IO_NEW; | 891 | type = IO_OVERWRITE; |
830 | if (buffer_mapped(bh) && all_bh) { | 892 | if (buffer_mapped(bh) && all_bh) { |
831 | lock_buffer(bh); | 893 | lock_buffer(bh); |
832 | xfs_add_to_ioend(inode, bh, offset, | 894 | xfs_add_to_ioend(inode, bh, offset, |
@@ -926,7 +988,7 @@ xfs_aops_discard_page( | |||
926 | struct buffer_head *bh, *head; | 988 | struct buffer_head *bh, *head; |
927 | loff_t offset = page_offset(page); | 989 | loff_t offset = page_offset(page); |
928 | 990 | ||
929 | if (!xfs_is_delayed_page(page, IO_DELAY)) | 991 | if (!xfs_is_delayed_page(page, IO_DELALLOC)) |
930 | goto out_invalidate; | 992 | goto out_invalidate; |
931 | 993 | ||
932 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | 994 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) |
@@ -994,9 +1056,10 @@ xfs_vm_writepage( | |||
994 | __uint64_t end_offset; | 1056 | __uint64_t end_offset; |
995 | pgoff_t end_index, last_index; | 1057 | pgoff_t end_index, last_index; |
996 | ssize_t size, len; | 1058 | ssize_t size, len; |
997 | int flags, err, imap_valid = 0, uptodate = 1; | 1059 | int err, imap_valid = 0, uptodate = 1; |
998 | int count = 0; | 1060 | int count = 0; |
999 | int all_bh = 0; | 1061 | int all_bh = 0; |
1062 | int nonblocking = 0; | ||
1000 | 1063 | ||
1001 | trace_xfs_writepage(inode, page, 0); | 1064 | trace_xfs_writepage(inode, page, 0); |
1002 | 1065 | ||
@@ -1047,8 +1110,10 @@ xfs_vm_writepage( | |||
1047 | 1110 | ||
1048 | bh = head = page_buffers(page); | 1111 | bh = head = page_buffers(page); |
1049 | offset = page_offset(page); | 1112 | offset = page_offset(page); |
1050 | flags = BMAPI_READ; | 1113 | type = IO_OVERWRITE; |
1051 | type = IO_NEW; | 1114 | |
1115 | if (wbc->sync_mode == WB_SYNC_NONE && wbc->nonblocking) | ||
1116 | nonblocking = 1; | ||
1052 | 1117 | ||
1053 | do { | 1118 | do { |
1054 | int new_ioend = 0; | 1119 | int new_ioend = 0; |
@@ -1078,16 +1143,11 @@ xfs_vm_writepage( | |||
1078 | type = IO_UNWRITTEN; | 1143 | type = IO_UNWRITTEN; |
1079 | imap_valid = 0; | 1144 | imap_valid = 0; |
1080 | } | 1145 | } |
1081 | flags = BMAPI_WRITE | BMAPI_IGNSTATE; | ||
1082 | } else if (buffer_delay(bh)) { | 1146 | } else if (buffer_delay(bh)) { |
1083 | if (type != IO_DELAY) { | 1147 | if (type != IO_DELALLOC) { |
1084 | type = IO_DELAY; | 1148 | type = IO_DELALLOC; |
1085 | imap_valid = 0; | 1149 | imap_valid = 0; |
1086 | } | 1150 | } |
1087 | flags = BMAPI_ALLOCATE; | ||
1088 | |||
1089 | if (wbc->sync_mode == WB_SYNC_NONE) | ||
1090 | flags |= BMAPI_TRYLOCK; | ||
1091 | } | 1151 | } |
1092 | 1152 | ||
1093 | if (!imap_valid) { | 1153 | if (!imap_valid) { |
@@ -1100,8 +1160,8 @@ xfs_vm_writepage( | |||
1100 | * for unwritten extent conversion. | 1160 | * for unwritten extent conversion. |
1101 | */ | 1161 | */ |
1102 | new_ioend = 1; | 1162 | new_ioend = 1; |
1103 | err = xfs_map_blocks(inode, offset, len, | 1163 | err = xfs_map_blocks(inode, offset, len, &imap, |
1104 | &imap, flags); | 1164 | type, nonblocking); |
1105 | if (err) | 1165 | if (err) |
1106 | goto error; | 1166 | goto error; |
1107 | imap_valid = xfs_imap_valid(inode, &imap, | 1167 | imap_valid = xfs_imap_valid(inode, &imap, |
@@ -1119,30 +1179,21 @@ xfs_vm_writepage( | |||
1119 | * That means it must already have extents allocated | 1179 | * That means it must already have extents allocated |
1120 | * underneath it. Map the extent by reading it. | 1180 | * underneath it. Map the extent by reading it. |
1121 | */ | 1181 | */ |
1122 | if (flags != BMAPI_READ) { | 1182 | if (type != IO_OVERWRITE) { |
1123 | flags = BMAPI_READ; | 1183 | type = IO_OVERWRITE; |
1124 | imap_valid = 0; | 1184 | imap_valid = 0; |
1125 | } | 1185 | } |
1126 | if (!imap_valid) { | 1186 | if (!imap_valid) { |
1127 | new_ioend = 1; | 1187 | new_ioend = 1; |
1128 | size = xfs_probe_cluster(inode, page, bh, head); | 1188 | size = xfs_probe_cluster(inode, page, bh, head); |
1129 | err = xfs_map_blocks(inode, offset, size, | 1189 | err = xfs_map_blocks(inode, offset, size, |
1130 | &imap, flags); | 1190 | &imap, type, nonblocking); |
1131 | if (err) | 1191 | if (err) |
1132 | goto error; | 1192 | goto error; |
1133 | imap_valid = xfs_imap_valid(inode, &imap, | 1193 | imap_valid = xfs_imap_valid(inode, &imap, |
1134 | offset); | 1194 | offset); |
1135 | } | 1195 | } |
1136 | 1196 | ||
1137 | /* | ||
1138 | * We set the type to IO_NEW in case we are doing a | ||
1139 | * small write at EOF that is extending the file but | ||
1140 | * without needing an allocation. We need to update the | ||
1141 | * file size on I/O completion in this case so it is | ||
1142 | * the same case as having just allocated a new extent | ||
1143 | * that we are writing into for the first time. | ||
1144 | */ | ||
1145 | type = IO_NEW; | ||
1146 | if (imap_valid) { | 1197 | if (imap_valid) { |
1147 | all_bh = 1; | 1198 | all_bh = 1; |
1148 | lock_buffer(bh); | 1199 | lock_buffer(bh); |
@@ -1250,13 +1301,19 @@ __xfs_get_blocks( | |||
1250 | int create, | 1301 | int create, |
1251 | int direct) | 1302 | int direct) |
1252 | { | 1303 | { |
1253 | int flags = create ? BMAPI_WRITE : BMAPI_READ; | 1304 | struct xfs_inode *ip = XFS_I(inode); |
1305 | struct xfs_mount *mp = ip->i_mount; | ||
1306 | xfs_fileoff_t offset_fsb, end_fsb; | ||
1307 | int error = 0; | ||
1308 | int lockmode = 0; | ||
1254 | struct xfs_bmbt_irec imap; | 1309 | struct xfs_bmbt_irec imap; |
1310 | int nimaps = 1; | ||
1255 | xfs_off_t offset; | 1311 | xfs_off_t offset; |
1256 | ssize_t size; | 1312 | ssize_t size; |
1257 | int nimap = 1; | ||
1258 | int new = 0; | 1313 | int new = 0; |
1259 | int error; | 1314 | |
1315 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
1316 | return -XFS_ERROR(EIO); | ||
1260 | 1317 | ||
1261 | offset = (xfs_off_t)iblock << inode->i_blkbits; | 1318 | offset = (xfs_off_t)iblock << inode->i_blkbits; |
1262 | ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); | 1319 | ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); |
@@ -1265,15 +1322,45 @@ __xfs_get_blocks( | |||
1265 | if (!create && direct && offset >= i_size_read(inode)) | 1322 | if (!create && direct && offset >= i_size_read(inode)) |
1266 | return 0; | 1323 | return 0; |
1267 | 1324 | ||
1268 | if (direct && create) | 1325 | if (create) { |
1269 | flags |= BMAPI_DIRECT; | 1326 | lockmode = XFS_ILOCK_EXCL; |
1327 | xfs_ilock(ip, lockmode); | ||
1328 | } else { | ||
1329 | lockmode = xfs_ilock_map_shared(ip); | ||
1330 | } | ||
1331 | |||
1332 | ASSERT(offset <= mp->m_maxioffset); | ||
1333 | if (offset + size > mp->m_maxioffset) | ||
1334 | size = mp->m_maxioffset - offset; | ||
1335 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size); | ||
1336 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | ||
1270 | 1337 | ||
1271 | error = xfs_iomap(XFS_I(inode), offset, size, flags, &imap, &nimap, | 1338 | error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb, |
1272 | &new); | 1339 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, &nimaps, NULL); |
1273 | if (error) | 1340 | if (error) |
1274 | return -error; | 1341 | goto out_unlock; |
1275 | if (nimap == 0) | 1342 | |
1276 | return 0; | 1343 | if (create && |
1344 | (!nimaps || | ||
1345 | (imap.br_startblock == HOLESTARTBLOCK || | ||
1346 | imap.br_startblock == DELAYSTARTBLOCK))) { | ||
1347 | if (direct) { | ||
1348 | error = xfs_iomap_write_direct(ip, offset, size, | ||
1349 | &imap, nimaps); | ||
1350 | } else { | ||
1351 | error = xfs_iomap_write_delay(ip, offset, size, &imap); | ||
1352 | } | ||
1353 | if (error) | ||
1354 | goto out_unlock; | ||
1355 | |||
1356 | trace_xfs_get_blocks_alloc(ip, offset, size, 0, &imap); | ||
1357 | } else if (nimaps) { | ||
1358 | trace_xfs_get_blocks_found(ip, offset, size, 0, &imap); | ||
1359 | } else { | ||
1360 | trace_xfs_get_blocks_notfound(ip, offset, size); | ||
1361 | goto out_unlock; | ||
1362 | } | ||
1363 | xfs_iunlock(ip, lockmode); | ||
1277 | 1364 | ||
1278 | if (imap.br_startblock != HOLESTARTBLOCK && | 1365 | if (imap.br_startblock != HOLESTARTBLOCK && |
1279 | imap.br_startblock != DELAYSTARTBLOCK) { | 1366 | imap.br_startblock != DELAYSTARTBLOCK) { |
@@ -1340,6 +1427,10 @@ __xfs_get_blocks( | |||
1340 | } | 1427 | } |
1341 | 1428 | ||
1342 | return 0; | 1429 | return 0; |
1430 | |||
1431 | out_unlock: | ||
1432 | xfs_iunlock(ip, lockmode); | ||
1433 | return -error; | ||
1343 | } | 1434 | } |
1344 | 1435 | ||
1345 | int | 1436 | int |
@@ -1427,7 +1518,7 @@ xfs_vm_direct_IO( | |||
1427 | ssize_t ret; | 1518 | ssize_t ret; |
1428 | 1519 | ||
1429 | if (rw & WRITE) { | 1520 | if (rw & WRITE) { |
1430 | iocb->private = xfs_alloc_ioend(inode, IO_NEW); | 1521 | iocb->private = xfs_alloc_ioend(inode, IO_DIRECT); |
1431 | 1522 | ||
1432 | ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov, | 1523 | ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov, |
1433 | offset, nr_segs, | 1524 | offset, nr_segs, |