diff options
Diffstat (limited to 'fs/xfs')
47 files changed, 2033 insertions, 2324 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index bdd9cb54d63b..ce84ffd0264c 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
@@ -452,7 +452,7 @@ xfs_alloc_read_agfl( | |||
452 | if (error) | 452 | if (error) |
453 | return error; | 453 | return error; |
454 | ASSERT(!xfs_buf_geterror(bp)); | 454 | ASSERT(!xfs_buf_geterror(bp)); |
455 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGFL, XFS_AGFL_REF); | 455 | xfs_buf_set_ref(bp, XFS_AGFL_REF); |
456 | *bpp = bp; | 456 | *bpp = bp; |
457 | return 0; | 457 | return 0; |
458 | } | 458 | } |
@@ -2139,7 +2139,7 @@ xfs_read_agf( | |||
2139 | xfs_trans_brelse(tp, *bpp); | 2139 | xfs_trans_brelse(tp, *bpp); |
2140 | return XFS_ERROR(EFSCORRUPTED); | 2140 | return XFS_ERROR(EFSCORRUPTED); |
2141 | } | 2141 | } |
2142 | XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_AGF, XFS_AGF_REF); | 2142 | xfs_buf_set_ref(*bpp, XFS_AGF_REF); |
2143 | return 0; | 2143 | return 0; |
2144 | } | 2144 | } |
2145 | 2145 | ||
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 8c37dde4c521..11b2aad982d4 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
@@ -38,40 +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 | /* | ||
43 | * Prime number of hash buckets since address is used as the key. | ||
44 | */ | ||
45 | #define NVSYNC 37 | ||
46 | #define to_ioend_wq(v) (&xfs_ioend_wq[((unsigned long)v) % NVSYNC]) | ||
47 | static wait_queue_head_t xfs_ioend_wq[NVSYNC]; | ||
48 | |||
49 | void __init | ||
50 | xfs_ioend_init(void) | ||
51 | { | ||
52 | int i; | ||
53 | |||
54 | for (i = 0; i < NVSYNC; i++) | ||
55 | init_waitqueue_head(&xfs_ioend_wq[i]); | ||
56 | } | ||
57 | |||
58 | void | ||
59 | xfs_ioend_wait( | ||
60 | xfs_inode_t *ip) | ||
61 | { | ||
62 | wait_queue_head_t *wq = to_ioend_wq(ip); | ||
63 | |||
64 | wait_event(*wq, (atomic_read(&ip->i_iocount) == 0)); | ||
65 | } | ||
66 | |||
67 | STATIC void | ||
68 | xfs_ioend_wake( | ||
69 | xfs_inode_t *ip) | ||
70 | { | ||
71 | if (atomic_dec_and_test(&ip->i_iocount)) | ||
72 | wake_up(to_ioend_wq(ip)); | ||
73 | } | ||
74 | |||
75 | void | 41 | void |
76 | xfs_count_page_state( | 42 | xfs_count_page_state( |
77 | struct page *page, | 43 | struct page *page, |
@@ -115,25 +81,20 @@ xfs_destroy_ioend( | |||
115 | xfs_ioend_t *ioend) | 81 | xfs_ioend_t *ioend) |
116 | { | 82 | { |
117 | struct buffer_head *bh, *next; | 83 | struct buffer_head *bh, *next; |
118 | struct xfs_inode *ip = XFS_I(ioend->io_inode); | ||
119 | 84 | ||
120 | for (bh = ioend->io_buffer_head; bh; bh = next) { | 85 | for (bh = ioend->io_buffer_head; bh; bh = next) { |
121 | next = bh->b_private; | 86 | next = bh->b_private; |
122 | bh->b_end_io(bh, !ioend->io_error); | 87 | bh->b_end_io(bh, !ioend->io_error); |
123 | } | 88 | } |
124 | 89 | ||
125 | /* | 90 | if (ioend->io_iocb) { |
126 | * Volume managers supporting multiple paths can send back ENODEV | 91 | if (ioend->io_isasync) { |
127 | * when the final path disappears. In this case continuing to fill | 92 | aio_complete(ioend->io_iocb, ioend->io_error ? |
128 | * the page cache with dirty data which cannot be written out is | 93 | ioend->io_error : ioend->io_result, 0); |
129 | * evil, so prevent that. | 94 | } |
130 | */ | 95 | inode_dio_done(ioend->io_inode); |
131 | if (unlikely(ioend->io_error == -ENODEV)) { | ||
132 | xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, | ||
133 | __FILE__, __LINE__); | ||
134 | } | 96 | } |
135 | 97 | ||
136 | xfs_ioend_wake(ip); | ||
137 | mempool_free(ioend, xfs_ioend_pool); | 98 | mempool_free(ioend, xfs_ioend_pool); |
138 | } | 99 | } |
139 | 100 | ||
@@ -156,6 +117,15 @@ xfs_ioend_new_eof( | |||
156 | } | 117 | } |
157 | 118 | ||
158 | /* | 119 | /* |
120 | * Fast and loose check if this write could update the on-disk inode size. | ||
121 | */ | ||
122 | static inline bool xfs_ioend_is_append(struct xfs_ioend *ioend) | ||
123 | { | ||
124 | return ioend->io_offset + ioend->io_size > | ||
125 | XFS_I(ioend->io_inode)->i_d.di_size; | ||
126 | } | ||
127 | |||
128 | /* | ||
159 | * Update on-disk file size now that data has been written to disk. The | 129 | * Update on-disk file size now that data has been written to disk. The |
160 | * current in-memory file size is i_size. If a write is beyond eof i_new_size | 130 | * current in-memory file size is i_size. If a write is beyond eof i_new_size |
161 | * will be the intended file size until i_size is updated. If this write does | 131 | * will be the intended file size until i_size is updated. If this write does |
@@ -173,9 +143,6 @@ xfs_setfilesize( | |||
173 | xfs_inode_t *ip = XFS_I(ioend->io_inode); | 143 | xfs_inode_t *ip = XFS_I(ioend->io_inode); |
174 | xfs_fsize_t isize; | 144 | xfs_fsize_t isize; |
175 | 145 | ||
176 | if (unlikely(ioend->io_error)) | ||
177 | return 0; | ||
178 | |||
179 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) | 146 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) |
180 | return EAGAIN; | 147 | return EAGAIN; |
181 | 148 | ||
@@ -192,6 +159,9 @@ xfs_setfilesize( | |||
192 | 159 | ||
193 | /* | 160 | /* |
194 | * Schedule IO completion handling on the final put of an ioend. | 161 | * Schedule IO completion handling on the final put of an ioend. |
162 | * | ||
163 | * If there is no work to do we might as well call it a day and free the | ||
164 | * ioend right now. | ||
195 | */ | 165 | */ |
196 | STATIC void | 166 | STATIC void |
197 | xfs_finish_ioend( | 167 | xfs_finish_ioend( |
@@ -200,8 +170,10 @@ xfs_finish_ioend( | |||
200 | if (atomic_dec_and_test(&ioend->io_remaining)) { | 170 | if (atomic_dec_and_test(&ioend->io_remaining)) { |
201 | if (ioend->io_type == IO_UNWRITTEN) | 171 | if (ioend->io_type == IO_UNWRITTEN) |
202 | queue_work(xfsconvertd_workqueue, &ioend->io_work); | 172 | queue_work(xfsconvertd_workqueue, &ioend->io_work); |
203 | else | 173 | else if (xfs_ioend_is_append(ioend)) |
204 | queue_work(xfsdatad_workqueue, &ioend->io_work); | 174 | queue_work(xfsdatad_workqueue, &ioend->io_work); |
175 | else | ||
176 | xfs_destroy_ioend(ioend); | ||
205 | } | 177 | } |
206 | } | 178 | } |
207 | 179 | ||
@@ -216,17 +188,24 @@ xfs_end_io( | |||
216 | struct xfs_inode *ip = XFS_I(ioend->io_inode); | 188 | struct xfs_inode *ip = XFS_I(ioend->io_inode); |
217 | int error = 0; | 189 | int error = 0; |
218 | 190 | ||
191 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { | ||
192 | error = -EIO; | ||
193 | goto done; | ||
194 | } | ||
195 | if (ioend->io_error) | ||
196 | goto done; | ||
197 | |||
219 | /* | 198 | /* |
220 | * For unwritten extents we need to issue transactions to convert a | 199 | * For unwritten extents we need to issue transactions to convert a |
221 | * range to normal written extens after the data I/O has finished. | 200 | * range to normal written extens after the data I/O has finished. |
222 | */ | 201 | */ |
223 | if (ioend->io_type == IO_UNWRITTEN && | 202 | if (ioend->io_type == IO_UNWRITTEN) { |
224 | likely(!ioend->io_error && !XFS_FORCED_SHUTDOWN(ip->i_mount))) { | ||
225 | |||
226 | error = xfs_iomap_write_unwritten(ip, ioend->io_offset, | 203 | error = xfs_iomap_write_unwritten(ip, ioend->io_offset, |
227 | ioend->io_size); | 204 | ioend->io_size); |
228 | if (error) | 205 | if (error) { |
229 | ioend->io_error = error; | 206 | ioend->io_error = -error; |
207 | goto done; | ||
208 | } | ||
230 | } | 209 | } |
231 | 210 | ||
232 | /* | 211 | /* |
@@ -236,6 +215,7 @@ xfs_end_io( | |||
236 | error = xfs_setfilesize(ioend); | 215 | error = xfs_setfilesize(ioend); |
237 | ASSERT(!error || error == EAGAIN); | 216 | ASSERT(!error || error == EAGAIN); |
238 | 217 | ||
218 | done: | ||
239 | /* | 219 | /* |
240 | * If we didn't complete processing of the ioend, requeue it to the | 220 | * If we didn't complete processing of the ioend, requeue it to the |
241 | * tail of the workqueue for another attempt later. Otherwise destroy | 221 | * tail of the workqueue for another attempt later. Otherwise destroy |
@@ -247,8 +227,6 @@ xfs_end_io( | |||
247 | /* ensure we don't spin on blocked ioends */ | 227 | /* ensure we don't spin on blocked ioends */ |
248 | delay(1); | 228 | delay(1); |
249 | } else { | 229 | } else { |
250 | if (ioend->io_iocb) | ||
251 | aio_complete(ioend->io_iocb, ioend->io_result, 0); | ||
252 | xfs_destroy_ioend(ioend); | 230 | xfs_destroy_ioend(ioend); |
253 | } | 231 | } |
254 | } | 232 | } |
@@ -285,13 +263,13 @@ xfs_alloc_ioend( | |||
285 | * all the I/O from calling the completion routine too early. | 263 | * all the I/O from calling the completion routine too early. |
286 | */ | 264 | */ |
287 | atomic_set(&ioend->io_remaining, 1); | 265 | atomic_set(&ioend->io_remaining, 1); |
266 | ioend->io_isasync = 0; | ||
288 | ioend->io_error = 0; | 267 | ioend->io_error = 0; |
289 | ioend->io_list = NULL; | 268 | ioend->io_list = NULL; |
290 | ioend->io_type = type; | 269 | ioend->io_type = type; |
291 | ioend->io_inode = inode; | 270 | ioend->io_inode = inode; |
292 | ioend->io_buffer_head = NULL; | 271 | ioend->io_buffer_head = NULL; |
293 | ioend->io_buffer_tail = NULL; | 272 | ioend->io_buffer_tail = NULL; |
294 | atomic_inc(&XFS_I(ioend->io_inode)->i_iocount); | ||
295 | ioend->io_offset = 0; | 273 | ioend->io_offset = 0; |
296 | ioend->io_size = 0; | 274 | ioend->io_size = 0; |
297 | ioend->io_iocb = NULL; | 275 | ioend->io_iocb = NULL; |
@@ -337,8 +315,8 @@ xfs_map_blocks( | |||
337 | count = mp->m_maxioffset - offset; | 315 | count = mp->m_maxioffset - offset; |
338 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); | 316 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); |
339 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 317 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
340 | error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb, | 318 | error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, |
341 | bmapi_flags, NULL, 0, imap, &nimaps, NULL); | 319 | imap, &nimaps, bmapi_flags); |
342 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 320 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
343 | 321 | ||
344 | if (error) | 322 | if (error) |
@@ -551,7 +529,6 @@ xfs_cancel_ioend( | |||
551 | unlock_buffer(bh); | 529 | unlock_buffer(bh); |
552 | } while ((bh = next_bh) != NULL); | 530 | } while ((bh = next_bh) != NULL); |
553 | 531 | ||
554 | xfs_ioend_wake(XFS_I(ioend->io_inode)); | ||
555 | mempool_free(ioend, xfs_ioend_pool); | 532 | mempool_free(ioend, xfs_ioend_pool); |
556 | } while ((ioend = next) != NULL); | 533 | } while ((ioend = next) != NULL); |
557 | } | 534 | } |
@@ -1161,8 +1138,8 @@ __xfs_get_blocks( | |||
1161 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size); | 1138 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size); |
1162 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 1139 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
1163 | 1140 | ||
1164 | error = xfs_bmapi(NULL, ip, offset_fsb, end_fsb - offset_fsb, | 1141 | error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, |
1165 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, &nimaps, NULL); | 1142 | &imap, &nimaps, XFS_BMAPI_ENTIRE); |
1166 | if (error) | 1143 | if (error) |
1167 | goto out_unlock; | 1144 | goto out_unlock; |
1168 | 1145 | ||
@@ -1300,7 +1277,6 @@ xfs_end_io_direct_write( | |||
1300 | bool is_async) | 1277 | bool is_async) |
1301 | { | 1278 | { |
1302 | struct xfs_ioend *ioend = iocb->private; | 1279 | struct xfs_ioend *ioend = iocb->private; |
1303 | struct inode *inode = ioend->io_inode; | ||
1304 | 1280 | ||
1305 | /* | 1281 | /* |
1306 | * blockdev_direct_IO can return an error even after the I/O | 1282 | * blockdev_direct_IO can return an error even after the I/O |
@@ -1311,28 +1287,17 @@ xfs_end_io_direct_write( | |||
1311 | 1287 | ||
1312 | ioend->io_offset = offset; | 1288 | ioend->io_offset = offset; |
1313 | ioend->io_size = size; | 1289 | ioend->io_size = size; |
1290 | ioend->io_iocb = iocb; | ||
1291 | ioend->io_result = ret; | ||
1314 | if (private && size > 0) | 1292 | if (private && size > 0) |
1315 | ioend->io_type = IO_UNWRITTEN; | 1293 | ioend->io_type = IO_UNWRITTEN; |
1316 | 1294 | ||
1317 | if (is_async) { | 1295 | if (is_async) { |
1318 | /* | 1296 | ioend->io_isasync = 1; |
1319 | * If we are converting an unwritten extent we need to delay | ||
1320 | * the AIO completion until after the unwrittent extent | ||
1321 | * conversion has completed, otherwise do it ASAP. | ||
1322 | */ | ||
1323 | if (ioend->io_type == IO_UNWRITTEN) { | ||
1324 | ioend->io_iocb = iocb; | ||
1325 | ioend->io_result = ret; | ||
1326 | } else { | ||
1327 | aio_complete(iocb, ret, 0); | ||
1328 | } | ||
1329 | xfs_finish_ioend(ioend); | 1297 | xfs_finish_ioend(ioend); |
1330 | } else { | 1298 | } else { |
1331 | xfs_finish_ioend_sync(ioend); | 1299 | xfs_finish_ioend_sync(ioend); |
1332 | } | 1300 | } |
1333 | |||
1334 | /* XXX: probably should move into the real I/O completion handler */ | ||
1335 | inode_dio_done(inode); | ||
1336 | } | 1301 | } |
1337 | 1302 | ||
1338 | STATIC ssize_t | 1303 | STATIC ssize_t |
diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h index 71f721e1a71f..116dd5c37034 100644 --- a/fs/xfs/xfs_aops.h +++ b/fs/xfs/xfs_aops.h | |||
@@ -47,6 +47,7 @@ typedef struct xfs_ioend { | |||
47 | unsigned int io_type; /* delalloc / unwritten */ | 47 | unsigned int io_type; /* delalloc / unwritten */ |
48 | int io_error; /* I/O error code */ | 48 | int io_error; /* I/O error code */ |
49 | atomic_t io_remaining; /* hold count */ | 49 | atomic_t io_remaining; /* hold count */ |
50 | unsigned int io_isasync : 1; /* needs aio_complete */ | ||
50 | struct inode *io_inode; /* file being written to */ | 51 | struct inode *io_inode; /* file being written to */ |
51 | struct buffer_head *io_buffer_head;/* buffer linked list head */ | 52 | struct buffer_head *io_buffer_head;/* buffer linked list head */ |
52 | struct buffer_head *io_buffer_tail;/* buffer linked list tail */ | 53 | struct buffer_head *io_buffer_tail;/* buffer linked list tail */ |
@@ -60,9 +61,6 @@ typedef struct xfs_ioend { | |||
60 | extern const struct address_space_operations xfs_address_space_operations; | 61 | extern const struct address_space_operations xfs_address_space_operations; |
61 | extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int); | 62 | extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int); |
62 | 63 | ||
63 | extern void xfs_ioend_init(void); | ||
64 | extern void xfs_ioend_wait(struct xfs_inode *); | ||
65 | |||
66 | extern void xfs_count_page_state(struct page *, int *, int *); | 64 | extern void xfs_count_page_state(struct page *, int *, int *); |
67 | 65 | ||
68 | #endif /* __XFS_AOPS_H__ */ | 66 | #endif /* __XFS_AOPS_H__ */ |
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 160bcdc34a6e..1e5d97f86ea8 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
@@ -319,7 +319,7 @@ xfs_attr_set_int( | |||
319 | return (error); | 319 | return (error); |
320 | } | 320 | } |
321 | 321 | ||
322 | xfs_trans_ijoin(args.trans, dp); | 322 | xfs_trans_ijoin(args.trans, dp, 0); |
323 | 323 | ||
324 | /* | 324 | /* |
325 | * If the attribute list is non-existent or a shortform list, | 325 | * If the attribute list is non-existent or a shortform list, |
@@ -389,7 +389,7 @@ xfs_attr_set_int( | |||
389 | * a new one. We need the inode to be in all transactions. | 389 | * a new one. We need the inode to be in all transactions. |
390 | */ | 390 | */ |
391 | if (committed) | 391 | if (committed) |
392 | xfs_trans_ijoin(args.trans, dp); | 392 | xfs_trans_ijoin(args.trans, dp, 0); |
393 | 393 | ||
394 | /* | 394 | /* |
395 | * Commit the leaf transformation. We'll need another (linked) | 395 | * Commit the leaf transformation. We'll need another (linked) |
@@ -537,7 +537,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | |||
537 | * No need to make quota reservations here. We expect to release some | 537 | * No need to make quota reservations here. We expect to release some |
538 | * blocks not allocate in the common case. | 538 | * blocks not allocate in the common case. |
539 | */ | 539 | */ |
540 | xfs_trans_ijoin(args.trans, dp); | 540 | xfs_trans_ijoin(args.trans, dp, 0); |
541 | 541 | ||
542 | /* | 542 | /* |
543 | * Decide on what work routines to call based on the inode size. | 543 | * Decide on what work routines to call based on the inode size. |
@@ -809,7 +809,7 @@ xfs_attr_inactive(xfs_inode_t *dp) | |||
809 | * No need to make quota reservations here. We expect to release some | 809 | * No need to make quota reservations here. We expect to release some |
810 | * blocks, not allocate, in the common case. | 810 | * blocks, not allocate, in the common case. |
811 | */ | 811 | */ |
812 | xfs_trans_ijoin(trans, dp); | 812 | xfs_trans_ijoin(trans, dp, 0); |
813 | 813 | ||
814 | /* | 814 | /* |
815 | * Decide on what work routines to call based on the inode size. | 815 | * Decide on what work routines to call based on the inode size. |
@@ -823,18 +823,6 @@ xfs_attr_inactive(xfs_inode_t *dp) | |||
823 | if (error) | 823 | if (error) |
824 | goto out; | 824 | goto out; |
825 | 825 | ||
826 | /* | ||
827 | * Signal synchronous inactive transactions unless this is a | ||
828 | * synchronous mount filesystem in which case we know that we're here | ||
829 | * because we've been called out of xfs_inactive which means that the | ||
830 | * last reference is gone and the unlink transaction has already hit | ||
831 | * the disk so async inactive transactions are safe. | ||
832 | */ | ||
833 | if (!(mp->m_flags & XFS_MOUNT_WSYNC)) { | ||
834 | if (dp->i_d.di_anextents > 0) | ||
835 | xfs_trans_set_sync(trans); | ||
836 | } | ||
837 | |||
838 | error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK, 0); | 826 | error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK, 0); |
839 | if (error) | 827 | if (error) |
840 | goto out; | 828 | goto out; |
@@ -973,7 +961,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
973 | * a new one. We need the inode to be in all transactions. | 961 | * a new one. We need the inode to be in all transactions. |
974 | */ | 962 | */ |
975 | if (committed) | 963 | if (committed) |
976 | xfs_trans_ijoin(args->trans, dp); | 964 | xfs_trans_ijoin(args->trans, dp, 0); |
977 | 965 | ||
978 | /* | 966 | /* |
979 | * Commit the current trans (including the inode) and start | 967 | * Commit the current trans (including the inode) and start |
@@ -1075,7 +1063,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
1075 | * in all transactions. | 1063 | * in all transactions. |
1076 | */ | 1064 | */ |
1077 | if (committed) | 1065 | if (committed) |
1078 | xfs_trans_ijoin(args->trans, dp); | 1066 | xfs_trans_ijoin(args->trans, dp, 0); |
1079 | } else | 1067 | } else |
1080 | xfs_da_buf_done(bp); | 1068 | xfs_da_buf_done(bp); |
1081 | 1069 | ||
@@ -1149,7 +1137,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) | |||
1149 | * a new one. We need the inode to be in all transactions. | 1137 | * a new one. We need the inode to be in all transactions. |
1150 | */ | 1138 | */ |
1151 | if (committed) | 1139 | if (committed) |
1152 | xfs_trans_ijoin(args->trans, dp); | 1140 | xfs_trans_ijoin(args->trans, dp, 0); |
1153 | } else | 1141 | } else |
1154 | xfs_da_buf_done(bp); | 1142 | xfs_da_buf_done(bp); |
1155 | return(0); | 1143 | return(0); |
@@ -1303,7 +1291,7 @@ restart: | |||
1303 | * in all transactions. | 1291 | * in all transactions. |
1304 | */ | 1292 | */ |
1305 | if (committed) | 1293 | if (committed) |
1306 | xfs_trans_ijoin(args->trans, dp); | 1294 | xfs_trans_ijoin(args->trans, dp, 0); |
1307 | 1295 | ||
1308 | /* | 1296 | /* |
1309 | * Commit the node conversion and start the next | 1297 | * Commit the node conversion and start the next |
@@ -1340,7 +1328,7 @@ restart: | |||
1340 | * a new one. We need the inode to be in all transactions. | 1328 | * a new one. We need the inode to be in all transactions. |
1341 | */ | 1329 | */ |
1342 | if (committed) | 1330 | if (committed) |
1343 | xfs_trans_ijoin(args->trans, dp); | 1331 | xfs_trans_ijoin(args->trans, dp, 0); |
1344 | } else { | 1332 | } else { |
1345 | /* | 1333 | /* |
1346 | * Addition succeeded, update Btree hashvals. | 1334 | * Addition succeeded, update Btree hashvals. |
@@ -1452,7 +1440,7 @@ restart: | |||
1452 | * in all transactions. | 1440 | * in all transactions. |
1453 | */ | 1441 | */ |
1454 | if (committed) | 1442 | if (committed) |
1455 | xfs_trans_ijoin(args->trans, dp); | 1443 | xfs_trans_ijoin(args->trans, dp, 0); |
1456 | } | 1444 | } |
1457 | 1445 | ||
1458 | /* | 1446 | /* |
@@ -1584,7 +1572,7 @@ xfs_attr_node_removename(xfs_da_args_t *args) | |||
1584 | * a new one. We need the inode to be in all transactions. | 1572 | * a new one. We need the inode to be in all transactions. |
1585 | */ | 1573 | */ |
1586 | if (committed) | 1574 | if (committed) |
1587 | xfs_trans_ijoin(args->trans, dp); | 1575 | xfs_trans_ijoin(args->trans, dp, 0); |
1588 | 1576 | ||
1589 | /* | 1577 | /* |
1590 | * Commit the Btree join operation and start a new trans. | 1578 | * Commit the Btree join operation and start a new trans. |
@@ -1635,7 +1623,7 @@ xfs_attr_node_removename(xfs_da_args_t *args) | |||
1635 | * in all transactions. | 1623 | * in all transactions. |
1636 | */ | 1624 | */ |
1637 | if (committed) | 1625 | if (committed) |
1638 | xfs_trans_ijoin(args->trans, dp); | 1626 | xfs_trans_ijoin(args->trans, dp, 0); |
1639 | } else | 1627 | } else |
1640 | xfs_da_brelse(args->trans, bp); | 1628 | xfs_da_brelse(args->trans, bp); |
1641 | } | 1629 | } |
@@ -1975,10 +1963,9 @@ xfs_attr_rmtval_get(xfs_da_args_t *args) | |||
1975 | lblkno = args->rmtblkno; | 1963 | lblkno = args->rmtblkno; |
1976 | while (valuelen > 0) { | 1964 | while (valuelen > 0) { |
1977 | nmap = ATTR_RMTVALUE_MAPSIZE; | 1965 | nmap = ATTR_RMTVALUE_MAPSIZE; |
1978 | error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno, | 1966 | error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno, |
1979 | args->rmtblkcnt, | 1967 | args->rmtblkcnt, map, &nmap, |
1980 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 1968 | XFS_BMAPI_ATTRFORK); |
1981 | NULL, 0, map, &nmap, NULL); | ||
1982 | if (error) | 1969 | if (error) |
1983 | return(error); | 1970 | return(error); |
1984 | ASSERT(nmap >= 1); | 1971 | ASSERT(nmap >= 1); |
@@ -2052,10 +2039,9 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) | |||
2052 | */ | 2039 | */ |
2053 | xfs_bmap_init(args->flist, args->firstblock); | 2040 | xfs_bmap_init(args->flist, args->firstblock); |
2054 | nmap = 1; | 2041 | nmap = 1; |
2055 | error = xfs_bmapi(args->trans, dp, (xfs_fileoff_t)lblkno, | 2042 | error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno, |
2056 | blkcnt, | 2043 | blkcnt, |
2057 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA | | 2044 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, |
2058 | XFS_BMAPI_WRITE, | ||
2059 | args->firstblock, args->total, &map, &nmap, | 2045 | args->firstblock, args->total, &map, &nmap, |
2060 | args->flist); | 2046 | args->flist); |
2061 | if (!error) { | 2047 | if (!error) { |
@@ -2074,7 +2060,7 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) | |||
2074 | * a new one. We need the inode to be in all transactions. | 2060 | * a new one. We need the inode to be in all transactions. |
2075 | */ | 2061 | */ |
2076 | if (committed) | 2062 | if (committed) |
2077 | xfs_trans_ijoin(args->trans, dp); | 2063 | xfs_trans_ijoin(args->trans, dp, 0); |
2078 | 2064 | ||
2079 | ASSERT(nmap == 1); | 2065 | ASSERT(nmap == 1); |
2080 | ASSERT((map.br_startblock != DELAYSTARTBLOCK) && | 2066 | ASSERT((map.br_startblock != DELAYSTARTBLOCK) && |
@@ -2104,14 +2090,11 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) | |||
2104 | */ | 2090 | */ |
2105 | xfs_bmap_init(args->flist, args->firstblock); | 2091 | xfs_bmap_init(args->flist, args->firstblock); |
2106 | nmap = 1; | 2092 | nmap = 1; |
2107 | error = xfs_bmapi(NULL, dp, (xfs_fileoff_t)lblkno, | 2093 | error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno, |
2108 | args->rmtblkcnt, | 2094 | args->rmtblkcnt, &map, &nmap, |
2109 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 2095 | XFS_BMAPI_ATTRFORK); |
2110 | args->firstblock, 0, &map, &nmap, | 2096 | if (error) |
2111 | NULL); | ||
2112 | if (error) { | ||
2113 | return(error); | 2097 | return(error); |
2114 | } | ||
2115 | ASSERT(nmap == 1); | 2098 | ASSERT(nmap == 1); |
2116 | ASSERT((map.br_startblock != DELAYSTARTBLOCK) && | 2099 | ASSERT((map.br_startblock != DELAYSTARTBLOCK) && |
2117 | (map.br_startblock != HOLESTARTBLOCK)); | 2100 | (map.br_startblock != HOLESTARTBLOCK)); |
@@ -2121,16 +2104,17 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) | |||
2121 | 2104 | ||
2122 | bp = xfs_buf_get(mp->m_ddev_targp, dblkno, blkcnt, | 2105 | bp = xfs_buf_get(mp->m_ddev_targp, dblkno, blkcnt, |
2123 | XBF_LOCK | XBF_DONT_BLOCK); | 2106 | XBF_LOCK | XBF_DONT_BLOCK); |
2124 | ASSERT(!xfs_buf_geterror(bp)); | 2107 | if (!bp) |
2125 | 2108 | return ENOMEM; | |
2126 | tmp = (valuelen < XFS_BUF_SIZE(bp)) ? valuelen : | 2109 | tmp = (valuelen < XFS_BUF_SIZE(bp)) ? valuelen : |
2127 | XFS_BUF_SIZE(bp); | 2110 | XFS_BUF_SIZE(bp); |
2128 | xfs_buf_iomove(bp, 0, tmp, src, XBRW_WRITE); | 2111 | xfs_buf_iomove(bp, 0, tmp, src, XBRW_WRITE); |
2129 | if (tmp < XFS_BUF_SIZE(bp)) | 2112 | if (tmp < XFS_BUF_SIZE(bp)) |
2130 | xfs_buf_zero(bp, tmp, XFS_BUF_SIZE(bp) - tmp); | 2113 | xfs_buf_zero(bp, tmp, XFS_BUF_SIZE(bp) - tmp); |
2131 | if ((error = xfs_bwrite(mp, bp))) {/* GROT: NOTE: synchronous write */ | 2114 | error = xfs_bwrite(bp); /* GROT: NOTE: synchronous write */ |
2132 | return (error); | 2115 | xfs_buf_relse(bp); |
2133 | } | 2116 | if (error) |
2117 | return error; | ||
2134 | src += tmp; | 2118 | src += tmp; |
2135 | valuelen -= tmp; | 2119 | valuelen -= tmp; |
2136 | 2120 | ||
@@ -2166,16 +2150,12 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args) | |||
2166 | /* | 2150 | /* |
2167 | * Try to remember where we decided to put the value. | 2151 | * Try to remember where we decided to put the value. |
2168 | */ | 2152 | */ |
2169 | xfs_bmap_init(args->flist, args->firstblock); | ||
2170 | nmap = 1; | 2153 | nmap = 1; |
2171 | error = xfs_bmapi(NULL, args->dp, (xfs_fileoff_t)lblkno, | 2154 | error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno, |
2172 | args->rmtblkcnt, | 2155 | args->rmtblkcnt, &map, &nmap, |
2173 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 2156 | XFS_BMAPI_ATTRFORK); |
2174 | args->firstblock, 0, &map, &nmap, | 2157 | if (error) |
2175 | args->flist); | ||
2176 | if (error) { | ||
2177 | return(error); | 2158 | return(error); |
2178 | } | ||
2179 | ASSERT(nmap == 1); | 2159 | ASSERT(nmap == 1); |
2180 | ASSERT((map.br_startblock != DELAYSTARTBLOCK) && | 2160 | ASSERT((map.br_startblock != DELAYSTARTBLOCK) && |
2181 | (map.br_startblock != HOLESTARTBLOCK)); | 2161 | (map.br_startblock != HOLESTARTBLOCK)); |
@@ -2188,8 +2168,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args) | |||
2188 | */ | 2168 | */ |
2189 | bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt, XBF_TRYLOCK); | 2169 | bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt, XBF_TRYLOCK); |
2190 | if (bp) { | 2170 | if (bp) { |
2191 | XFS_BUF_STALE(bp); | 2171 | xfs_buf_stale(bp); |
2192 | XFS_BUF_UNDELAYWRITE(bp); | ||
2193 | xfs_buf_relse(bp); | 2172 | xfs_buf_relse(bp); |
2194 | bp = NULL; | 2173 | bp = NULL; |
2195 | } | 2174 | } |
@@ -2227,7 +2206,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args) | |||
2227 | * a new one. We need the inode to be in all transactions. | 2206 | * a new one. We need the inode to be in all transactions. |
2228 | */ | 2207 | */ |
2229 | if (committed) | 2208 | if (committed) |
2230 | xfs_trans_ijoin(args->trans, args->dp); | 2209 | xfs_trans_ijoin(args->trans, args->dp, 0); |
2231 | 2210 | ||
2232 | /* | 2211 | /* |
2233 | * Close out trans and start the next one in the chain. | 2212 | * Close out trans and start the next one in the chain. |
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 8fad9602542b..d4906e7c9787 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c | |||
@@ -2926,9 +2926,8 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, | |||
2926 | * Try to remember where we decided to put the value. | 2926 | * Try to remember where we decided to put the value. |
2927 | */ | 2927 | */ |
2928 | nmap = 1; | 2928 | nmap = 1; |
2929 | error = xfs_bmapi(*trans, dp, (xfs_fileoff_t)tblkno, tblkcnt, | 2929 | error = xfs_bmapi_read(dp, (xfs_fileoff_t)tblkno, tblkcnt, |
2930 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 2930 | &map, &nmap, XFS_BMAPI_ATTRFORK); |
2931 | NULL, 0, &map, &nmap, NULL); | ||
2932 | if (error) { | 2931 | if (error) { |
2933 | return(error); | 2932 | return(error); |
2934 | } | 2933 | } |
@@ -2948,6 +2947,8 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, | |||
2948 | bp = xfs_trans_get_buf(*trans, | 2947 | bp = xfs_trans_get_buf(*trans, |
2949 | dp->i_mount->m_ddev_targp, | 2948 | dp->i_mount->m_ddev_targp, |
2950 | dblkno, dblkcnt, XBF_LOCK); | 2949 | dblkno, dblkcnt, XBF_LOCK); |
2950 | if (!bp) | ||
2951 | return ENOMEM; | ||
2951 | xfs_trans_binval(*trans, bp); | 2952 | xfs_trans_binval(*trans, bp); |
2952 | /* | 2953 | /* |
2953 | * Roll to next transaction. | 2954 | * Roll to next transaction. |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 452a291383ab..c68baeb0974a 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -50,17 +50,22 @@ | |||
50 | #include "xfs_trace.h" | 50 | #include "xfs_trace.h" |
51 | 51 | ||
52 | 52 | ||
53 | #ifdef DEBUG | ||
54 | STATIC void | ||
55 | xfs_bmap_check_leaf_extents(xfs_btree_cur_t *cur, xfs_inode_t *ip, int whichfork); | ||
56 | #endif | ||
57 | |||
58 | kmem_zone_t *xfs_bmap_free_item_zone; | 53 | kmem_zone_t *xfs_bmap_free_item_zone; |
59 | 54 | ||
60 | /* | 55 | /* |
61 | * Prototypes for internal bmap routines. | 56 | * Prototypes for internal bmap routines. |
62 | */ | 57 | */ |
63 | 58 | ||
59 | #ifdef DEBUG | ||
60 | STATIC void | ||
61 | xfs_bmap_check_leaf_extents( | ||
62 | struct xfs_btree_cur *cur, | ||
63 | struct xfs_inode *ip, | ||
64 | int whichfork); | ||
65 | #else | ||
66 | #define xfs_bmap_check_leaf_extents(cur, ip, whichfork) do { } while (0) | ||
67 | #endif | ||
68 | |||
64 | 69 | ||
65 | /* | 70 | /* |
66 | * Called from xfs_bmap_add_attrfork to handle extents format files. | 71 | * Called from xfs_bmap_add_attrfork to handle extents format files. |
@@ -85,58 +90,6 @@ xfs_bmap_add_attrfork_local( | |||
85 | int *flags); /* inode logging flags */ | 90 | int *flags); /* inode logging flags */ |
86 | 91 | ||
87 | /* | 92 | /* |
88 | * Called by xfs_bmap_add_extent to handle cases converting a delayed | ||
89 | * allocation to a real allocation. | ||
90 | */ | ||
91 | STATIC int /* error */ | ||
92 | xfs_bmap_add_extent_delay_real( | ||
93 | struct xfs_trans *tp, /* transaction pointer */ | ||
94 | xfs_inode_t *ip, /* incore inode pointer */ | ||
95 | xfs_extnum_t *idx, /* extent number to update/insert */ | ||
96 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ | ||
97 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | ||
98 | xfs_filblks_t *dnew, /* new delayed-alloc indirect blocks */ | ||
99 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | ||
100 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | ||
101 | int *logflagsp); /* inode logging flags */ | ||
102 | |||
103 | /* | ||
104 | * Called by xfs_bmap_add_extent to handle cases converting a hole | ||
105 | * to a delayed allocation. | ||
106 | */ | ||
107 | STATIC int /* error */ | ||
108 | xfs_bmap_add_extent_hole_delay( | ||
109 | xfs_inode_t *ip, /* incore inode pointer */ | ||
110 | xfs_extnum_t *idx, /* extent number to update/insert */ | ||
111 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | ||
112 | int *logflagsp); /* inode logging flags */ | ||
113 | |||
114 | /* | ||
115 | * Called by xfs_bmap_add_extent to handle cases converting a hole | ||
116 | * to a real allocation. | ||
117 | */ | ||
118 | STATIC int /* error */ | ||
119 | xfs_bmap_add_extent_hole_real( | ||
120 | xfs_inode_t *ip, /* incore inode pointer */ | ||
121 | xfs_extnum_t *idx, /* extent number to update/insert */ | ||
122 | xfs_btree_cur_t *cur, /* if null, not a btree */ | ||
123 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | ||
124 | int *logflagsp, /* inode logging flags */ | ||
125 | int whichfork); /* data or attr fork */ | ||
126 | |||
127 | /* | ||
128 | * Called by xfs_bmap_add_extent to handle cases converting an unwritten | ||
129 | * allocation to a real allocation or vice versa. | ||
130 | */ | ||
131 | STATIC int /* error */ | ||
132 | xfs_bmap_add_extent_unwritten_real( | ||
133 | xfs_inode_t *ip, /* incore inode pointer */ | ||
134 | xfs_extnum_t *idx, /* extent number to update/insert */ | ||
135 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ | ||
136 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | ||
137 | int *logflagsp); /* inode logging flags */ | ||
138 | |||
139 | /* | ||
140 | * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. | 93 | * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. |
141 | * It figures out where to ask the underlying allocator to put the new extent. | 94 | * It figures out where to ask the underlying allocator to put the new extent. |
142 | */ | 95 | */ |
@@ -215,19 +168,6 @@ xfs_bmap_search_extents( | |||
215 | xfs_bmbt_irec_t *prevp); /* out: previous extent entry found */ | 168 | xfs_bmbt_irec_t *prevp); /* out: previous extent entry found */ |
216 | 169 | ||
217 | /* | 170 | /* |
218 | * Check the last inode extent to determine whether this allocation will result | ||
219 | * in blocks being allocated at the end of the file. When we allocate new data | ||
220 | * blocks at the end of the file which do not start at the previous data block, | ||
221 | * we will try to align the new blocks at stripe unit boundaries. | ||
222 | */ | ||
223 | STATIC int /* error */ | ||
224 | xfs_bmap_isaeof( | ||
225 | xfs_inode_t *ip, /* incore inode pointer */ | ||
226 | xfs_fileoff_t off, /* file offset in fsblocks */ | ||
227 | int whichfork, /* data or attribute fork */ | ||
228 | char *aeof); /* return value */ | ||
229 | |||
230 | /* | ||
231 | * Compute the worst-case number of indirect blocks that will be used | 171 | * Compute the worst-case number of indirect blocks that will be used |
232 | * for ip's delayed extent of length "len". | 172 | * for ip's delayed extent of length "len". |
233 | */ | 173 | */ |
@@ -431,188 +371,13 @@ xfs_bmap_add_attrfork_local( | |||
431 | } | 371 | } |
432 | 372 | ||
433 | /* | 373 | /* |
434 | * Called by xfs_bmapi to update file extent records and the btree | 374 | * Convert a delayed allocation to a real allocation. |
435 | * after allocating space (or doing a delayed allocation). | ||
436 | */ | ||
437 | STATIC int /* error */ | ||
438 | xfs_bmap_add_extent( | ||
439 | struct xfs_trans *tp, /* transaction pointer */ | ||
440 | xfs_inode_t *ip, /* incore inode pointer */ | ||
441 | xfs_extnum_t *idx, /* extent number to update/insert */ | ||
442 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ | ||
443 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | ||
444 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | ||
445 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | ||
446 | int *logflagsp, /* inode logging flags */ | ||
447 | int whichfork) /* data or attr fork */ | ||
448 | { | ||
449 | xfs_btree_cur_t *cur; /* btree cursor or null */ | ||
450 | xfs_filblks_t da_new; /* new count del alloc blocks used */ | ||
451 | xfs_filblks_t da_old; /* old count del alloc blocks used */ | ||
452 | int error; /* error return value */ | ||
453 | xfs_ifork_t *ifp; /* inode fork ptr */ | ||
454 | int logflags; /* returned value */ | ||
455 | xfs_extnum_t nextents; /* number of extents in file now */ | ||
456 | |||
457 | XFS_STATS_INC(xs_add_exlist); | ||
458 | |||
459 | cur = *curp; | ||
460 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
461 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | ||
462 | da_old = da_new = 0; | ||
463 | error = 0; | ||
464 | |||
465 | ASSERT(*idx >= 0); | ||
466 | ASSERT(*idx <= nextents); | ||
467 | |||
468 | /* | ||
469 | * This is the first extent added to a new/empty file. | ||
470 | * Special case this one, so other routines get to assume there are | ||
471 | * already extents in the list. | ||
472 | */ | ||
473 | if (nextents == 0) { | ||
474 | xfs_iext_insert(ip, *idx, 1, new, | ||
475 | whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0); | ||
476 | |||
477 | ASSERT(cur == NULL); | ||
478 | |||
479 | if (!isnullstartblock(new->br_startblock)) { | ||
480 | XFS_IFORK_NEXT_SET(ip, whichfork, 1); | ||
481 | logflags = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); | ||
482 | } else | ||
483 | logflags = 0; | ||
484 | } | ||
485 | /* | ||
486 | * Any kind of new delayed allocation goes here. | ||
487 | */ | ||
488 | else if (isnullstartblock(new->br_startblock)) { | ||
489 | if (cur) | ||
490 | ASSERT((cur->bc_private.b.flags & | ||
491 | XFS_BTCUR_BPRV_WASDEL) == 0); | ||
492 | error = xfs_bmap_add_extent_hole_delay(ip, idx, new, | ||
493 | &logflags); | ||
494 | } | ||
495 | /* | ||
496 | * Real allocation off the end of the file. | ||
497 | */ | ||
498 | else if (*idx == nextents) { | ||
499 | if (cur) | ||
500 | ASSERT((cur->bc_private.b.flags & | ||
501 | XFS_BTCUR_BPRV_WASDEL) == 0); | ||
502 | error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new, | ||
503 | &logflags, whichfork); | ||
504 | } else { | ||
505 | xfs_bmbt_irec_t prev; /* old extent at offset idx */ | ||
506 | |||
507 | /* | ||
508 | * Get the record referred to by idx. | ||
509 | */ | ||
510 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx), &prev); | ||
511 | /* | ||
512 | * If it's a real allocation record, and the new allocation ends | ||
513 | * after the start of the referred to record, then we're filling | ||
514 | * in a delayed or unwritten allocation with a real one, or | ||
515 | * converting real back to unwritten. | ||
516 | */ | ||
517 | if (!isnullstartblock(new->br_startblock) && | ||
518 | new->br_startoff + new->br_blockcount > prev.br_startoff) { | ||
519 | if (prev.br_state != XFS_EXT_UNWRITTEN && | ||
520 | isnullstartblock(prev.br_startblock)) { | ||
521 | da_old = startblockval(prev.br_startblock); | ||
522 | if (cur) | ||
523 | ASSERT(cur->bc_private.b.flags & | ||
524 | XFS_BTCUR_BPRV_WASDEL); | ||
525 | error = xfs_bmap_add_extent_delay_real(tp, ip, | ||
526 | idx, &cur, new, &da_new, | ||
527 | first, flist, &logflags); | ||
528 | } else { | ||
529 | ASSERT(new->br_state == XFS_EXT_NORM || | ||
530 | new->br_state == XFS_EXT_UNWRITTEN); | ||
531 | |||
532 | error = xfs_bmap_add_extent_unwritten_real(ip, | ||
533 | idx, &cur, new, &logflags); | ||
534 | if (error) | ||
535 | goto done; | ||
536 | } | ||
537 | } | ||
538 | /* | ||
539 | * Otherwise we're filling in a hole with an allocation. | ||
540 | */ | ||
541 | else { | ||
542 | if (cur) | ||
543 | ASSERT((cur->bc_private.b.flags & | ||
544 | XFS_BTCUR_BPRV_WASDEL) == 0); | ||
545 | error = xfs_bmap_add_extent_hole_real(ip, idx, cur, | ||
546 | new, &logflags, whichfork); | ||
547 | } | ||
548 | } | ||
549 | |||
550 | if (error) | ||
551 | goto done; | ||
552 | ASSERT(*curp == cur || *curp == NULL); | ||
553 | |||
554 | /* | ||
555 | * Convert to a btree if necessary. | ||
556 | */ | ||
557 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS && | ||
558 | XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) { | ||
559 | int tmp_logflags; /* partial log flag return val */ | ||
560 | |||
561 | ASSERT(cur == NULL); | ||
562 | error = xfs_bmap_extents_to_btree(tp, ip, first, | ||
563 | flist, &cur, da_old > 0, &tmp_logflags, whichfork); | ||
564 | logflags |= tmp_logflags; | ||
565 | if (error) | ||
566 | goto done; | ||
567 | } | ||
568 | /* | ||
569 | * Adjust for changes in reserved delayed indirect blocks. | ||
570 | * Nothing to do for disk quotas here. | ||
571 | */ | ||
572 | if (da_old || da_new) { | ||
573 | xfs_filblks_t nblks; | ||
574 | |||
575 | nblks = da_new; | ||
576 | if (cur) | ||
577 | nblks += cur->bc_private.b.allocated; | ||
578 | ASSERT(nblks <= da_old); | ||
579 | if (nblks < da_old) | ||
580 | xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS, | ||
581 | (int64_t)(da_old - nblks), 0); | ||
582 | } | ||
583 | /* | ||
584 | * Clear out the allocated field, done with it now in any case. | ||
585 | */ | ||
586 | if (cur) { | ||
587 | cur->bc_private.b.allocated = 0; | ||
588 | *curp = cur; | ||
589 | } | ||
590 | done: | ||
591 | #ifdef DEBUG | ||
592 | if (!error) | ||
593 | xfs_bmap_check_leaf_extents(*curp, ip, whichfork); | ||
594 | #endif | ||
595 | *logflagsp = logflags; | ||
596 | return error; | ||
597 | } | ||
598 | |||
599 | /* | ||
600 | * Called by xfs_bmap_add_extent to handle cases converting a delayed | ||
601 | * allocation to a real allocation. | ||
602 | */ | 375 | */ |
603 | STATIC int /* error */ | 376 | STATIC int /* error */ |
604 | xfs_bmap_add_extent_delay_real( | 377 | xfs_bmap_add_extent_delay_real( |
605 | struct xfs_trans *tp, /* transaction pointer */ | 378 | struct xfs_bmalloca *bma) |
606 | xfs_inode_t *ip, /* incore inode pointer */ | ||
607 | xfs_extnum_t *idx, /* extent number to update/insert */ | ||
608 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ | ||
609 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | ||
610 | xfs_filblks_t *dnew, /* new delayed-alloc indirect blocks */ | ||
611 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | ||
612 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | ||
613 | int *logflagsp) /* inode logging flags */ | ||
614 | { | 379 | { |
615 | xfs_btree_cur_t *cur; /* btree cursor */ | 380 | struct xfs_bmbt_irec *new = &bma->got; |
616 | int diff; /* temp value */ | 381 | int diff; /* temp value */ |
617 | xfs_bmbt_rec_host_t *ep; /* extent entry for idx */ | 382 | xfs_bmbt_rec_host_t *ep; /* extent entry for idx */ |
618 | int error; /* error return value */ | 383 | int error; /* error return value */ |
@@ -623,10 +388,22 @@ xfs_bmap_add_extent_delay_real( | |||
623 | /* left is 0, right is 1, prev is 2 */ | 388 | /* left is 0, right is 1, prev is 2 */ |
624 | int rval=0; /* return value (logging flags) */ | 389 | int rval=0; /* return value (logging flags) */ |
625 | int state = 0;/* state bits, accessed thru macros */ | 390 | int state = 0;/* state bits, accessed thru macros */ |
626 | xfs_filblks_t temp=0; /* value for dnew calculations */ | 391 | xfs_filblks_t da_new; /* new count del alloc blocks used */ |
627 | xfs_filblks_t temp2=0;/* value for dnew calculations */ | 392 | xfs_filblks_t da_old; /* old count del alloc blocks used */ |
393 | xfs_filblks_t temp=0; /* value for da_new calculations */ | ||
394 | xfs_filblks_t temp2=0;/* value for da_new calculations */ | ||
628 | int tmp_rval; /* partial logging flags */ | 395 | int tmp_rval; /* partial logging flags */ |
629 | 396 | ||
397 | ifp = XFS_IFORK_PTR(bma->ip, XFS_DATA_FORK); | ||
398 | |||
399 | ASSERT(bma->idx >= 0); | ||
400 | ASSERT(bma->idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec)); | ||
401 | ASSERT(!isnullstartblock(new->br_startblock)); | ||
402 | ASSERT(!bma->cur || | ||
403 | (bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL)); | ||
404 | |||
405 | XFS_STATS_INC(xs_add_exlist); | ||
406 | |||
630 | #define LEFT r[0] | 407 | #define LEFT r[0] |
631 | #define RIGHT r[1] | 408 | #define RIGHT r[1] |
632 | #define PREV r[2] | 409 | #define PREV r[2] |
@@ -634,14 +411,15 @@ xfs_bmap_add_extent_delay_real( | |||
634 | /* | 411 | /* |
635 | * Set up a bunch of variables to make the tests simpler. | 412 | * Set up a bunch of variables to make the tests simpler. |
636 | */ | 413 | */ |
637 | cur = *curp; | 414 | ep = xfs_iext_get_ext(ifp, bma->idx); |
638 | ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); | ||
639 | ep = xfs_iext_get_ext(ifp, *idx); | ||
640 | xfs_bmbt_get_all(ep, &PREV); | 415 | xfs_bmbt_get_all(ep, &PREV); |
641 | new_endoff = new->br_startoff + new->br_blockcount; | 416 | new_endoff = new->br_startoff + new->br_blockcount; |
642 | ASSERT(PREV.br_startoff <= new->br_startoff); | 417 | ASSERT(PREV.br_startoff <= new->br_startoff); |
643 | ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff); | 418 | ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff); |
644 | 419 | ||
420 | da_old = startblockval(PREV.br_startblock); | ||
421 | da_new = 0; | ||
422 | |||
645 | /* | 423 | /* |
646 | * Set flags determining what part of the previous delayed allocation | 424 | * Set flags determining what part of the previous delayed allocation |
647 | * extent is being replaced by a real allocation. | 425 | * extent is being replaced by a real allocation. |
@@ -655,9 +433,9 @@ xfs_bmap_add_extent_delay_real( | |||
655 | * Check and set flags if this segment has a left neighbor. | 433 | * Check and set flags if this segment has a left neighbor. |
656 | * Don't set contiguous if the combined extent would be too large. | 434 | * Don't set contiguous if the combined extent would be too large. |
657 | */ | 435 | */ |
658 | if (*idx > 0) { | 436 | if (bma->idx > 0) { |
659 | state |= BMAP_LEFT_VALID; | 437 | state |= BMAP_LEFT_VALID; |
660 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx - 1), &LEFT); | 438 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1), &LEFT); |
661 | 439 | ||
662 | if (isnullstartblock(LEFT.br_startblock)) | 440 | if (isnullstartblock(LEFT.br_startblock)) |
663 | state |= BMAP_LEFT_DELAY; | 441 | state |= BMAP_LEFT_DELAY; |
@@ -675,9 +453,9 @@ xfs_bmap_add_extent_delay_real( | |||
675 | * Don't set contiguous if the combined extent would be too large. | 453 | * Don't set contiguous if the combined extent would be too large. |
676 | * Also check for all-three-contiguous being too large. | 454 | * Also check for all-three-contiguous being too large. |
677 | */ | 455 | */ |
678 | if (*idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1) { | 456 | if (bma->idx < bma->ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1) { |
679 | state |= BMAP_RIGHT_VALID; | 457 | state |= BMAP_RIGHT_VALID; |
680 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx + 1), &RIGHT); | 458 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx + 1), &RIGHT); |
681 | 459 | ||
682 | if (isnullstartblock(RIGHT.br_startblock)) | 460 | if (isnullstartblock(RIGHT.br_startblock)) |
683 | state |= BMAP_RIGHT_DELAY; | 461 | state |= BMAP_RIGHT_DELAY; |
@@ -708,38 +486,41 @@ xfs_bmap_add_extent_delay_real( | |||
708 | * Filling in all of a previously delayed allocation extent. | 486 | * Filling in all of a previously delayed allocation extent. |
709 | * The left and right neighbors are both contiguous with new. | 487 | * The left and right neighbors are both contiguous with new. |
710 | */ | 488 | */ |
711 | --*idx; | 489 | bma->idx--; |
712 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 490 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
713 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), | 491 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx), |
714 | LEFT.br_blockcount + PREV.br_blockcount + | 492 | LEFT.br_blockcount + PREV.br_blockcount + |
715 | RIGHT.br_blockcount); | 493 | RIGHT.br_blockcount); |
716 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 494 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
717 | 495 | ||
718 | xfs_iext_remove(ip, *idx + 1, 2, state); | 496 | xfs_iext_remove(bma->ip, bma->idx + 1, 2, state); |
719 | ip->i_d.di_nextents--; | 497 | bma->ip->i_d.di_nextents--; |
720 | if (cur == NULL) | 498 | if (bma->cur == NULL) |
721 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 499 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
722 | else { | 500 | else { |
723 | rval = XFS_ILOG_CORE; | 501 | rval = XFS_ILOG_CORE; |
724 | if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff, | 502 | error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff, |
725 | RIGHT.br_startblock, | 503 | RIGHT.br_startblock, |
726 | RIGHT.br_blockcount, &i))) | 504 | RIGHT.br_blockcount, &i); |
505 | if (error) | ||
727 | goto done; | 506 | goto done; |
728 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 507 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
729 | if ((error = xfs_btree_delete(cur, &i))) | 508 | error = xfs_btree_delete(bma->cur, &i); |
509 | if (error) | ||
730 | goto done; | 510 | goto done; |
731 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 511 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
732 | if ((error = xfs_btree_decrement(cur, 0, &i))) | 512 | error = xfs_btree_decrement(bma->cur, 0, &i); |
513 | if (error) | ||
733 | goto done; | 514 | goto done; |
734 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 515 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
735 | if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, | 516 | error = xfs_bmbt_update(bma->cur, LEFT.br_startoff, |
736 | LEFT.br_startblock, | 517 | LEFT.br_startblock, |
737 | LEFT.br_blockcount + | 518 | LEFT.br_blockcount + |
738 | PREV.br_blockcount + | 519 | PREV.br_blockcount + |
739 | RIGHT.br_blockcount, LEFT.br_state))) | 520 | RIGHT.br_blockcount, LEFT.br_state); |
521 | if (error) | ||
740 | goto done; | 522 | goto done; |
741 | } | 523 | } |
742 | *dnew = 0; | ||
743 | break; | 524 | break; |
744 | 525 | ||
745 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG: | 526 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG: |
@@ -747,30 +528,31 @@ xfs_bmap_add_extent_delay_real( | |||
747 | * Filling in all of a previously delayed allocation extent. | 528 | * Filling in all of a previously delayed allocation extent. |
748 | * The left neighbor is contiguous, the right is not. | 529 | * The left neighbor is contiguous, the right is not. |
749 | */ | 530 | */ |
750 | --*idx; | 531 | bma->idx--; |
751 | 532 | ||
752 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 533 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
753 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), | 534 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx), |
754 | LEFT.br_blockcount + PREV.br_blockcount); | 535 | LEFT.br_blockcount + PREV.br_blockcount); |
755 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 536 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
756 | 537 | ||
757 | xfs_iext_remove(ip, *idx + 1, 1, state); | 538 | xfs_iext_remove(bma->ip, bma->idx + 1, 1, state); |
758 | if (cur == NULL) | 539 | if (bma->cur == NULL) |
759 | rval = XFS_ILOG_DEXT; | 540 | rval = XFS_ILOG_DEXT; |
760 | else { | 541 | else { |
761 | rval = 0; | 542 | rval = 0; |
762 | if ((error = xfs_bmbt_lookup_eq(cur, LEFT.br_startoff, | 543 | error = xfs_bmbt_lookup_eq(bma->cur, LEFT.br_startoff, |
763 | LEFT.br_startblock, LEFT.br_blockcount, | 544 | LEFT.br_startblock, LEFT.br_blockcount, |
764 | &i))) | 545 | &i); |
546 | if (error) | ||
765 | goto done; | 547 | goto done; |
766 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 548 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
767 | if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, | 549 | error = xfs_bmbt_update(bma->cur, LEFT.br_startoff, |
768 | LEFT.br_startblock, | 550 | LEFT.br_startblock, |
769 | LEFT.br_blockcount + | 551 | LEFT.br_blockcount + |
770 | PREV.br_blockcount, LEFT.br_state))) | 552 | PREV.br_blockcount, LEFT.br_state); |
553 | if (error) | ||
771 | goto done; | 554 | goto done; |
772 | } | 555 | } |
773 | *dnew = 0; | ||
774 | break; | 556 | break; |
775 | 557 | ||
776 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: | 558 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: |
@@ -778,30 +560,30 @@ xfs_bmap_add_extent_delay_real( | |||
778 | * Filling in all of a previously delayed allocation extent. | 560 | * Filling in all of a previously delayed allocation extent. |
779 | * The right neighbor is contiguous, the left is not. | 561 | * The right neighbor is contiguous, the left is not. |
780 | */ | 562 | */ |
781 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 563 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
782 | xfs_bmbt_set_startblock(ep, new->br_startblock); | 564 | xfs_bmbt_set_startblock(ep, new->br_startblock); |
783 | xfs_bmbt_set_blockcount(ep, | 565 | xfs_bmbt_set_blockcount(ep, |
784 | PREV.br_blockcount + RIGHT.br_blockcount); | 566 | PREV.br_blockcount + RIGHT.br_blockcount); |
785 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 567 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
786 | 568 | ||
787 | xfs_iext_remove(ip, *idx + 1, 1, state); | 569 | xfs_iext_remove(bma->ip, bma->idx + 1, 1, state); |
788 | if (cur == NULL) | 570 | if (bma->cur == NULL) |
789 | rval = XFS_ILOG_DEXT; | 571 | rval = XFS_ILOG_DEXT; |
790 | else { | 572 | else { |
791 | rval = 0; | 573 | rval = 0; |
792 | if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff, | 574 | error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff, |
793 | RIGHT.br_startblock, | 575 | RIGHT.br_startblock, |
794 | RIGHT.br_blockcount, &i))) | 576 | RIGHT.br_blockcount, &i); |
577 | if (error) | ||
795 | goto done; | 578 | goto done; |
796 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 579 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
797 | if ((error = xfs_bmbt_update(cur, PREV.br_startoff, | 580 | error = xfs_bmbt_update(bma->cur, PREV.br_startoff, |
798 | new->br_startblock, | 581 | new->br_startblock, |
799 | PREV.br_blockcount + | 582 | PREV.br_blockcount + |
800 | RIGHT.br_blockcount, PREV.br_state))) | 583 | RIGHT.br_blockcount, PREV.br_state); |
584 | if (error) | ||
801 | goto done; | 585 | goto done; |
802 | } | 586 | } |
803 | |||
804 | *dnew = 0; | ||
805 | break; | 587 | break; |
806 | 588 | ||
807 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING: | 589 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING: |
@@ -810,27 +592,27 @@ xfs_bmap_add_extent_delay_real( | |||
810 | * Neither the left nor right neighbors are contiguous with | 592 | * Neither the left nor right neighbors are contiguous with |
811 | * the new one. | 593 | * the new one. |
812 | */ | 594 | */ |
813 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 595 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
814 | xfs_bmbt_set_startblock(ep, new->br_startblock); | 596 | xfs_bmbt_set_startblock(ep, new->br_startblock); |
815 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 597 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
816 | 598 | ||
817 | ip->i_d.di_nextents++; | 599 | bma->ip->i_d.di_nextents++; |
818 | if (cur == NULL) | 600 | if (bma->cur == NULL) |
819 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 601 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
820 | else { | 602 | else { |
821 | rval = XFS_ILOG_CORE; | 603 | rval = XFS_ILOG_CORE; |
822 | if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, | 604 | error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff, |
823 | new->br_startblock, new->br_blockcount, | 605 | new->br_startblock, new->br_blockcount, |
824 | &i))) | 606 | &i); |
607 | if (error) | ||
825 | goto done; | 608 | goto done; |
826 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); | 609 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
827 | cur->bc_rec.b.br_state = XFS_EXT_NORM; | 610 | bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; |
828 | if ((error = xfs_btree_insert(cur, &i))) | 611 | error = xfs_btree_insert(bma->cur, &i); |
612 | if (error) | ||
829 | goto done; | 613 | goto done; |
830 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 614 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
831 | } | 615 | } |
832 | |||
833 | *dnew = 0; | ||
834 | break; | 616 | break; |
835 | 617 | ||
836 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG: | 618 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG: |
@@ -838,39 +620,40 @@ xfs_bmap_add_extent_delay_real( | |||
838 | * Filling in the first part of a previous delayed allocation. | 620 | * Filling in the first part of a previous delayed allocation. |
839 | * The left neighbor is contiguous. | 621 | * The left neighbor is contiguous. |
840 | */ | 622 | */ |
841 | trace_xfs_bmap_pre_update(ip, *idx - 1, state, _THIS_IP_); | 623 | trace_xfs_bmap_pre_update(bma->ip, bma->idx - 1, state, _THIS_IP_); |
842 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx - 1), | 624 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx - 1), |
843 | LEFT.br_blockcount + new->br_blockcount); | 625 | LEFT.br_blockcount + new->br_blockcount); |
844 | xfs_bmbt_set_startoff(ep, | 626 | xfs_bmbt_set_startoff(ep, |
845 | PREV.br_startoff + new->br_blockcount); | 627 | PREV.br_startoff + new->br_blockcount); |
846 | trace_xfs_bmap_post_update(ip, *idx - 1, state, _THIS_IP_); | 628 | trace_xfs_bmap_post_update(bma->ip, bma->idx - 1, state, _THIS_IP_); |
847 | 629 | ||
848 | temp = PREV.br_blockcount - new->br_blockcount; | 630 | temp = PREV.br_blockcount - new->br_blockcount; |
849 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 631 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
850 | xfs_bmbt_set_blockcount(ep, temp); | 632 | xfs_bmbt_set_blockcount(ep, temp); |
851 | if (cur == NULL) | 633 | if (bma->cur == NULL) |
852 | rval = XFS_ILOG_DEXT; | 634 | rval = XFS_ILOG_DEXT; |
853 | else { | 635 | else { |
854 | rval = 0; | 636 | rval = 0; |
855 | if ((error = xfs_bmbt_lookup_eq(cur, LEFT.br_startoff, | 637 | error = xfs_bmbt_lookup_eq(bma->cur, LEFT.br_startoff, |
856 | LEFT.br_startblock, LEFT.br_blockcount, | 638 | LEFT.br_startblock, LEFT.br_blockcount, |
857 | &i))) | 639 | &i); |
640 | if (error) | ||
858 | goto done; | 641 | goto done; |
859 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 642 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
860 | if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, | 643 | error = xfs_bmbt_update(bma->cur, LEFT.br_startoff, |
861 | LEFT.br_startblock, | 644 | LEFT.br_startblock, |
862 | LEFT.br_blockcount + | 645 | LEFT.br_blockcount + |
863 | new->br_blockcount, | 646 | new->br_blockcount, |
864 | LEFT.br_state))) | 647 | LEFT.br_state); |
648 | if (error) | ||
865 | goto done; | 649 | goto done; |
866 | } | 650 | } |
867 | temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), | 651 | da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp), |
868 | startblockval(PREV.br_startblock)); | 652 | startblockval(PREV.br_startblock)); |
869 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); | 653 | xfs_bmbt_set_startblock(ep, nullstartblock(da_new)); |
870 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 654 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
871 | 655 | ||
872 | --*idx; | 656 | bma->idx--; |
873 | *dnew = temp; | ||
874 | break; | 657 | break; |
875 | 658 | ||
876 | case BMAP_LEFT_FILLING: | 659 | case BMAP_LEFT_FILLING: |
@@ -878,43 +661,43 @@ xfs_bmap_add_extent_delay_real( | |||
878 | * Filling in the first part of a previous delayed allocation. | 661 | * Filling in the first part of a previous delayed allocation. |
879 | * The left neighbor is not contiguous. | 662 | * The left neighbor is not contiguous. |
880 | */ | 663 | */ |
881 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 664 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
882 | xfs_bmbt_set_startoff(ep, new_endoff); | 665 | xfs_bmbt_set_startoff(ep, new_endoff); |
883 | temp = PREV.br_blockcount - new->br_blockcount; | 666 | temp = PREV.br_blockcount - new->br_blockcount; |
884 | xfs_bmbt_set_blockcount(ep, temp); | 667 | xfs_bmbt_set_blockcount(ep, temp); |
885 | xfs_iext_insert(ip, *idx, 1, new, state); | 668 | xfs_iext_insert(bma->ip, bma->idx, 1, new, state); |
886 | ip->i_d.di_nextents++; | 669 | bma->ip->i_d.di_nextents++; |
887 | if (cur == NULL) | 670 | if (bma->cur == NULL) |
888 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 671 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
889 | else { | 672 | else { |
890 | rval = XFS_ILOG_CORE; | 673 | rval = XFS_ILOG_CORE; |
891 | if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, | 674 | error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff, |
892 | new->br_startblock, new->br_blockcount, | 675 | new->br_startblock, new->br_blockcount, |
893 | &i))) | 676 | &i); |
677 | if (error) | ||
894 | goto done; | 678 | goto done; |
895 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); | 679 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
896 | cur->bc_rec.b.br_state = XFS_EXT_NORM; | 680 | bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; |
897 | if ((error = xfs_btree_insert(cur, &i))) | 681 | error = xfs_btree_insert(bma->cur, &i); |
682 | if (error) | ||
898 | goto done; | 683 | goto done; |
899 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 684 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
900 | } | 685 | } |
901 | if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && | 686 | if (bma->ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && |
902 | ip->i_d.di_nextents > ip->i_df.if_ext_max) { | 687 | bma->ip->i_d.di_nextents > bma->ip->i_df.if_ext_max) { |
903 | error = xfs_bmap_extents_to_btree(tp, ip, | 688 | error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, |
904 | first, flist, &cur, 1, &tmp_rval, | 689 | bma->firstblock, bma->flist, |
905 | XFS_DATA_FORK); | 690 | &bma->cur, 1, &tmp_rval, XFS_DATA_FORK); |
906 | rval |= tmp_rval; | 691 | rval |= tmp_rval; |
907 | if (error) | 692 | if (error) |
908 | goto done; | 693 | goto done; |
909 | } | 694 | } |
910 | temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), | 695 | da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp), |
911 | startblockval(PREV.br_startblock) - | 696 | startblockval(PREV.br_startblock) - |
912 | (cur ? cur->bc_private.b.allocated : 0)); | 697 | (bma->cur ? bma->cur->bc_private.b.allocated : 0)); |
913 | ep = xfs_iext_get_ext(ifp, *idx + 1); | 698 | ep = xfs_iext_get_ext(ifp, bma->idx + 1); |
914 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); | 699 | xfs_bmbt_set_startblock(ep, nullstartblock(da_new)); |
915 | trace_xfs_bmap_post_update(ip, *idx + 1, state, _THIS_IP_); | 700 | trace_xfs_bmap_post_update(bma->ip, bma->idx + 1, state, _THIS_IP_); |
916 | |||
917 | *dnew = temp; | ||
918 | break; | 701 | break; |
919 | 702 | ||
920 | case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: | 703 | case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: |
@@ -923,38 +706,39 @@ xfs_bmap_add_extent_delay_real( | |||
923 | * The right neighbor is contiguous with the new allocation. | 706 | * The right neighbor is contiguous with the new allocation. |
924 | */ | 707 | */ |
925 | temp = PREV.br_blockcount - new->br_blockcount; | 708 | temp = PREV.br_blockcount - new->br_blockcount; |
926 | trace_xfs_bmap_pre_update(ip, *idx + 1, state, _THIS_IP_); | 709 | trace_xfs_bmap_pre_update(bma->ip, bma->idx + 1, state, _THIS_IP_); |
927 | xfs_bmbt_set_blockcount(ep, temp); | 710 | xfs_bmbt_set_blockcount(ep, temp); |
928 | xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx + 1), | 711 | xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, bma->idx + 1), |
929 | new->br_startoff, new->br_startblock, | 712 | new->br_startoff, new->br_startblock, |
930 | new->br_blockcount + RIGHT.br_blockcount, | 713 | new->br_blockcount + RIGHT.br_blockcount, |
931 | RIGHT.br_state); | 714 | RIGHT.br_state); |
932 | trace_xfs_bmap_post_update(ip, *idx + 1, state, _THIS_IP_); | 715 | trace_xfs_bmap_post_update(bma->ip, bma->idx + 1, state, _THIS_IP_); |
933 | if (cur == NULL) | 716 | if (bma->cur == NULL) |
934 | rval = XFS_ILOG_DEXT; | 717 | rval = XFS_ILOG_DEXT; |
935 | else { | 718 | else { |
936 | rval = 0; | 719 | rval = 0; |
937 | if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff, | 720 | error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff, |
938 | RIGHT.br_startblock, | 721 | RIGHT.br_startblock, |
939 | RIGHT.br_blockcount, &i))) | 722 | RIGHT.br_blockcount, &i); |
723 | if (error) | ||
940 | goto done; | 724 | goto done; |
941 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 725 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
942 | if ((error = xfs_bmbt_update(cur, new->br_startoff, | 726 | error = xfs_bmbt_update(bma->cur, new->br_startoff, |
943 | new->br_startblock, | 727 | new->br_startblock, |
944 | new->br_blockcount + | 728 | new->br_blockcount + |
945 | RIGHT.br_blockcount, | 729 | RIGHT.br_blockcount, |
946 | RIGHT.br_state))) | 730 | RIGHT.br_state); |
731 | if (error) | ||
947 | goto done; | 732 | goto done; |
948 | } | 733 | } |
949 | 734 | ||
950 | temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), | 735 | da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp), |
951 | startblockval(PREV.br_startblock)); | 736 | startblockval(PREV.br_startblock)); |
952 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 737 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
953 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); | 738 | xfs_bmbt_set_startblock(ep, nullstartblock(da_new)); |
954 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 739 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
955 | 740 | ||
956 | ++*idx; | 741 | bma->idx++; |
957 | *dnew = temp; | ||
958 | break; | 742 | break; |
959 | 743 | ||
960 | case BMAP_RIGHT_FILLING: | 744 | case BMAP_RIGHT_FILLING: |
@@ -963,42 +747,43 @@ xfs_bmap_add_extent_delay_real( | |||
963 | * The right neighbor is not contiguous. | 747 | * The right neighbor is not contiguous. |
964 | */ | 748 | */ |
965 | temp = PREV.br_blockcount - new->br_blockcount; | 749 | temp = PREV.br_blockcount - new->br_blockcount; |
966 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 750 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
967 | xfs_bmbt_set_blockcount(ep, temp); | 751 | xfs_bmbt_set_blockcount(ep, temp); |
968 | xfs_iext_insert(ip, *idx + 1, 1, new, state); | 752 | xfs_iext_insert(bma->ip, bma->idx + 1, 1, new, state); |
969 | ip->i_d.di_nextents++; | 753 | bma->ip->i_d.di_nextents++; |
970 | if (cur == NULL) | 754 | if (bma->cur == NULL) |
971 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 755 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
972 | else { | 756 | else { |
973 | rval = XFS_ILOG_CORE; | 757 | rval = XFS_ILOG_CORE; |
974 | if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, | 758 | error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff, |
975 | new->br_startblock, new->br_blockcount, | 759 | new->br_startblock, new->br_blockcount, |
976 | &i))) | 760 | &i); |
761 | if (error) | ||
977 | goto done; | 762 | goto done; |
978 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); | 763 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
979 | cur->bc_rec.b.br_state = XFS_EXT_NORM; | 764 | bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; |
980 | if ((error = xfs_btree_insert(cur, &i))) | 765 | error = xfs_btree_insert(bma->cur, &i); |
766 | if (error) | ||
981 | goto done; | 767 | goto done; |
982 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 768 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
983 | } | 769 | } |
984 | if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && | 770 | if (bma->ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && |
985 | ip->i_d.di_nextents > ip->i_df.if_ext_max) { | 771 | bma->ip->i_d.di_nextents > bma->ip->i_df.if_ext_max) { |
986 | error = xfs_bmap_extents_to_btree(tp, ip, | 772 | error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, |
987 | first, flist, &cur, 1, &tmp_rval, | 773 | bma->firstblock, bma->flist, &bma->cur, 1, |
988 | XFS_DATA_FORK); | 774 | &tmp_rval, XFS_DATA_FORK); |
989 | rval |= tmp_rval; | 775 | rval |= tmp_rval; |
990 | if (error) | 776 | if (error) |
991 | goto done; | 777 | goto done; |
992 | } | 778 | } |
993 | temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), | 779 | da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp), |
994 | startblockval(PREV.br_startblock) - | 780 | startblockval(PREV.br_startblock) - |
995 | (cur ? cur->bc_private.b.allocated : 0)); | 781 | (bma->cur ? bma->cur->bc_private.b.allocated : 0)); |
996 | ep = xfs_iext_get_ext(ifp, *idx); | 782 | ep = xfs_iext_get_ext(ifp, bma->idx); |
997 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); | 783 | xfs_bmbt_set_startblock(ep, nullstartblock(da_new)); |
998 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 784 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
999 | 785 | ||
1000 | ++*idx; | 786 | bma->idx++; |
1001 | *dnew = temp; | ||
1002 | break; | 787 | break; |
1003 | 788 | ||
1004 | case 0: | 789 | case 0: |
@@ -1024,82 +809,65 @@ xfs_bmap_add_extent_delay_real( | |||
1024 | */ | 809 | */ |
1025 | temp = new->br_startoff - PREV.br_startoff; | 810 | temp = new->br_startoff - PREV.br_startoff; |
1026 | temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff; | 811 | temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff; |
1027 | trace_xfs_bmap_pre_update(ip, *idx, 0, _THIS_IP_); | 812 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, 0, _THIS_IP_); |
1028 | xfs_bmbt_set_blockcount(ep, temp); /* truncate PREV */ | 813 | xfs_bmbt_set_blockcount(ep, temp); /* truncate PREV */ |
1029 | LEFT = *new; | 814 | LEFT = *new; |
1030 | RIGHT.br_state = PREV.br_state; | 815 | RIGHT.br_state = PREV.br_state; |
1031 | RIGHT.br_startblock = nullstartblock( | 816 | RIGHT.br_startblock = nullstartblock( |
1032 | (int)xfs_bmap_worst_indlen(ip, temp2)); | 817 | (int)xfs_bmap_worst_indlen(bma->ip, temp2)); |
1033 | RIGHT.br_startoff = new_endoff; | 818 | RIGHT.br_startoff = new_endoff; |
1034 | RIGHT.br_blockcount = temp2; | 819 | RIGHT.br_blockcount = temp2; |
1035 | /* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */ | 820 | /* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */ |
1036 | xfs_iext_insert(ip, *idx + 1, 2, &LEFT, state); | 821 | xfs_iext_insert(bma->ip, bma->idx + 1, 2, &LEFT, state); |
1037 | ip->i_d.di_nextents++; | 822 | bma->ip->i_d.di_nextents++; |
1038 | if (cur == NULL) | 823 | if (bma->cur == NULL) |
1039 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 824 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
1040 | else { | 825 | else { |
1041 | rval = XFS_ILOG_CORE; | 826 | rval = XFS_ILOG_CORE; |
1042 | if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, | 827 | error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff, |
1043 | new->br_startblock, new->br_blockcount, | 828 | new->br_startblock, new->br_blockcount, |
1044 | &i))) | 829 | &i); |
830 | if (error) | ||
1045 | goto done; | 831 | goto done; |
1046 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); | 832 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
1047 | cur->bc_rec.b.br_state = XFS_EXT_NORM; | 833 | bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; |
1048 | if ((error = xfs_btree_insert(cur, &i))) | 834 | error = xfs_btree_insert(bma->cur, &i); |
835 | if (error) | ||
1049 | goto done; | 836 | goto done; |
1050 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 837 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1051 | } | 838 | } |
1052 | if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && | 839 | if (bma->ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && |
1053 | ip->i_d.di_nextents > ip->i_df.if_ext_max) { | 840 | bma->ip->i_d.di_nextents > bma->ip->i_df.if_ext_max) { |
1054 | error = xfs_bmap_extents_to_btree(tp, ip, | 841 | error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, |
1055 | first, flist, &cur, 1, &tmp_rval, | 842 | bma->firstblock, bma->flist, &bma->cur, |
1056 | XFS_DATA_FORK); | 843 | 1, &tmp_rval, XFS_DATA_FORK); |
1057 | rval |= tmp_rval; | 844 | rval |= tmp_rval; |
1058 | if (error) | 845 | if (error) |
1059 | goto done; | 846 | goto done; |
1060 | } | 847 | } |
1061 | temp = xfs_bmap_worst_indlen(ip, temp); | 848 | temp = xfs_bmap_worst_indlen(bma->ip, temp); |
1062 | temp2 = xfs_bmap_worst_indlen(ip, temp2); | 849 | temp2 = xfs_bmap_worst_indlen(bma->ip, temp2); |
1063 | diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) - | 850 | diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) - |
1064 | (cur ? cur->bc_private.b.allocated : 0)); | 851 | (bma->cur ? bma->cur->bc_private.b.allocated : 0)); |
1065 | if (diff > 0 && | 852 | if (diff > 0) { |
1066 | xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS, | 853 | error = xfs_icsb_modify_counters(bma->ip->i_mount, |
1067 | -((int64_t)diff), 0)) { | 854 | XFS_SBS_FDBLOCKS, |
1068 | /* | 855 | -((int64_t)diff), 0); |
1069 | * Ick gross gag me with a spoon. | 856 | ASSERT(!error); |
1070 | */ | 857 | if (error) |
1071 | ASSERT(0); /* want to see if this ever happens! */ | 858 | goto done; |
1072 | while (diff > 0) { | ||
1073 | if (temp) { | ||
1074 | temp--; | ||
1075 | diff--; | ||
1076 | if (!diff || | ||
1077 | !xfs_icsb_modify_counters(ip->i_mount, | ||
1078 | XFS_SBS_FDBLOCKS, | ||
1079 | -((int64_t)diff), 0)) | ||
1080 | break; | ||
1081 | } | ||
1082 | if (temp2) { | ||
1083 | temp2--; | ||
1084 | diff--; | ||
1085 | if (!diff || | ||
1086 | !xfs_icsb_modify_counters(ip->i_mount, | ||
1087 | XFS_SBS_FDBLOCKS, | ||
1088 | -((int64_t)diff), 0)) | ||
1089 | break; | ||
1090 | } | ||
1091 | } | ||
1092 | } | 859 | } |
1093 | ep = xfs_iext_get_ext(ifp, *idx); | 860 | |
861 | ep = xfs_iext_get_ext(ifp, bma->idx); | ||
1094 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); | 862 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); |
1095 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 863 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
1096 | trace_xfs_bmap_pre_update(ip, *idx + 2, state, _THIS_IP_); | 864 | trace_xfs_bmap_pre_update(bma->ip, bma->idx + 2, state, _THIS_IP_); |
1097 | xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx + 2), | 865 | xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, bma->idx + 2), |
1098 | nullstartblock((int)temp2)); | 866 | nullstartblock((int)temp2)); |
1099 | trace_xfs_bmap_post_update(ip, *idx + 2, state, _THIS_IP_); | 867 | trace_xfs_bmap_post_update(bma->ip, bma->idx + 2, state, _THIS_IP_); |
1100 | 868 | ||
1101 | ++*idx; | 869 | bma->idx++; |
1102 | *dnew = temp + temp2; | 870 | da_new = temp + temp2; |
1103 | break; | 871 | break; |
1104 | 872 | ||
1105 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: | 873 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: |
@@ -1114,9 +882,40 @@ xfs_bmap_add_extent_delay_real( | |||
1114 | */ | 882 | */ |
1115 | ASSERT(0); | 883 | ASSERT(0); |
1116 | } | 884 | } |
1117 | *curp = cur; | 885 | |
886 | /* convert to a btree if necessary */ | ||
887 | if (XFS_IFORK_FORMAT(bma->ip, XFS_DATA_FORK) == XFS_DINODE_FMT_EXTENTS && | ||
888 | XFS_IFORK_NEXTENTS(bma->ip, XFS_DATA_FORK) > ifp->if_ext_max) { | ||
889 | int tmp_logflags; /* partial log flag return val */ | ||
890 | |||
891 | ASSERT(bma->cur == NULL); | ||
892 | error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, | ||
893 | bma->firstblock, bma->flist, &bma->cur, | ||
894 | da_old > 0, &tmp_logflags, XFS_DATA_FORK); | ||
895 | bma->logflags |= tmp_logflags; | ||
896 | if (error) | ||
897 | goto done; | ||
898 | } | ||
899 | |||
900 | /* adjust for changes in reserved delayed indirect blocks */ | ||
901 | if (da_old || da_new) { | ||
902 | temp = da_new; | ||
903 | if (bma->cur) | ||
904 | temp += bma->cur->bc_private.b.allocated; | ||
905 | ASSERT(temp <= da_old); | ||
906 | if (temp < da_old) | ||
907 | xfs_icsb_modify_counters(bma->ip->i_mount, | ||
908 | XFS_SBS_FDBLOCKS, | ||
909 | (int64_t)(da_old - temp), 0); | ||
910 | } | ||
911 | |||
912 | /* clear out the allocated field, done with it now in any case. */ | ||
913 | if (bma->cur) | ||
914 | bma->cur->bc_private.b.allocated = 0; | ||
915 | |||
916 | xfs_bmap_check_leaf_extents(bma->cur, bma->ip, XFS_DATA_FORK); | ||
1118 | done: | 917 | done: |
1119 | *logflagsp = rval; | 918 | bma->logflags |= rval; |
1120 | return error; | 919 | return error; |
1121 | #undef LEFT | 920 | #undef LEFT |
1122 | #undef RIGHT | 921 | #undef RIGHT |
@@ -1124,15 +923,17 @@ done: | |||
1124 | } | 923 | } |
1125 | 924 | ||
1126 | /* | 925 | /* |
1127 | * Called by xfs_bmap_add_extent to handle cases converting an unwritten | 926 | * Convert an unwritten allocation to a real allocation or vice versa. |
1128 | * allocation to a real allocation or vice versa. | ||
1129 | */ | 927 | */ |
1130 | STATIC int /* error */ | 928 | STATIC int /* error */ |
1131 | xfs_bmap_add_extent_unwritten_real( | 929 | xfs_bmap_add_extent_unwritten_real( |
930 | struct xfs_trans *tp, | ||
1132 | xfs_inode_t *ip, /* incore inode pointer */ | 931 | xfs_inode_t *ip, /* incore inode pointer */ |
1133 | xfs_extnum_t *idx, /* extent number to update/insert */ | 932 | xfs_extnum_t *idx, /* extent number to update/insert */ |
1134 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ | 933 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ |
1135 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 934 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
935 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | ||
936 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | ||
1136 | int *logflagsp) /* inode logging flags */ | 937 | int *logflagsp) /* inode logging flags */ |
1137 | { | 938 | { |
1138 | xfs_btree_cur_t *cur; /* btree cursor */ | 939 | xfs_btree_cur_t *cur; /* btree cursor */ |
@@ -1148,15 +949,25 @@ xfs_bmap_add_extent_unwritten_real( | |||
1148 | int rval=0; /* return value (logging flags) */ | 949 | int rval=0; /* return value (logging flags) */ |
1149 | int state = 0;/* state bits, accessed thru macros */ | 950 | int state = 0;/* state bits, accessed thru macros */ |
1150 | 951 | ||
952 | *logflagsp = 0; | ||
953 | |||
954 | cur = *curp; | ||
955 | ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); | ||
956 | |||
957 | ASSERT(*idx >= 0); | ||
958 | ASSERT(*idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec)); | ||
959 | ASSERT(!isnullstartblock(new->br_startblock)); | ||
960 | |||
961 | XFS_STATS_INC(xs_add_exlist); | ||
962 | |||
1151 | #define LEFT r[0] | 963 | #define LEFT r[0] |
1152 | #define RIGHT r[1] | 964 | #define RIGHT r[1] |
1153 | #define PREV r[2] | 965 | #define PREV r[2] |
966 | |||
1154 | /* | 967 | /* |
1155 | * Set up a bunch of variables to make the tests simpler. | 968 | * Set up a bunch of variables to make the tests simpler. |
1156 | */ | 969 | */ |
1157 | error = 0; | 970 | error = 0; |
1158 | cur = *curp; | ||
1159 | ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); | ||
1160 | ep = xfs_iext_get_ext(ifp, *idx); | 971 | ep = xfs_iext_get_ext(ifp, *idx); |
1161 | xfs_bmbt_get_all(ep, &PREV); | 972 | xfs_bmbt_get_all(ep, &PREV); |
1162 | newext = new->br_state; | 973 | newext = new->br_state; |
@@ -1406,10 +1217,11 @@ xfs_bmap_add_extent_unwritten_real( | |||
1406 | goto done; | 1217 | goto done; |
1407 | if ((error = xfs_btree_decrement(cur, 0, &i))) | 1218 | if ((error = xfs_btree_decrement(cur, 0, &i))) |
1408 | goto done; | 1219 | goto done; |
1409 | if (xfs_bmbt_update(cur, LEFT.br_startoff, | 1220 | error = xfs_bmbt_update(cur, LEFT.br_startoff, |
1410 | LEFT.br_startblock, | 1221 | LEFT.br_startblock, |
1411 | LEFT.br_blockcount + new->br_blockcount, | 1222 | LEFT.br_blockcount + new->br_blockcount, |
1412 | LEFT.br_state)) | 1223 | LEFT.br_state); |
1224 | if (error) | ||
1413 | goto done; | 1225 | goto done; |
1414 | } | 1226 | } |
1415 | break; | 1227 | break; |
@@ -1607,9 +1419,29 @@ xfs_bmap_add_extent_unwritten_real( | |||
1607 | */ | 1419 | */ |
1608 | ASSERT(0); | 1420 | ASSERT(0); |
1609 | } | 1421 | } |
1610 | *curp = cur; | 1422 | |
1423 | /* convert to a btree if necessary */ | ||
1424 | if (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) == XFS_DINODE_FMT_EXTENTS && | ||
1425 | XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) > ifp->if_ext_max) { | ||
1426 | int tmp_logflags; /* partial log flag return val */ | ||
1427 | |||
1428 | ASSERT(cur == NULL); | ||
1429 | error = xfs_bmap_extents_to_btree(tp, ip, first, flist, &cur, | ||
1430 | 0, &tmp_logflags, XFS_DATA_FORK); | ||
1431 | *logflagsp |= tmp_logflags; | ||
1432 | if (error) | ||
1433 | goto done; | ||
1434 | } | ||
1435 | |||
1436 | /* clear out the allocated field, done with it now in any case. */ | ||
1437 | if (cur) { | ||
1438 | cur->bc_private.b.allocated = 0; | ||
1439 | *curp = cur; | ||
1440 | } | ||
1441 | |||
1442 | xfs_bmap_check_leaf_extents(*curp, ip, XFS_DATA_FORK); | ||
1611 | done: | 1443 | done: |
1612 | *logflagsp = rval; | 1444 | *logflagsp |= rval; |
1613 | return error; | 1445 | return error; |
1614 | #undef LEFT | 1446 | #undef LEFT |
1615 | #undef RIGHT | 1447 | #undef RIGHT |
@@ -1617,16 +1449,13 @@ done: | |||
1617 | } | 1449 | } |
1618 | 1450 | ||
1619 | /* | 1451 | /* |
1620 | * Called by xfs_bmap_add_extent to handle cases converting a hole | 1452 | * Convert a hole to a delayed allocation. |
1621 | * to a delayed allocation. | ||
1622 | */ | 1453 | */ |
1623 | /*ARGSUSED*/ | 1454 | STATIC void |
1624 | STATIC int /* error */ | ||
1625 | xfs_bmap_add_extent_hole_delay( | 1455 | xfs_bmap_add_extent_hole_delay( |
1626 | xfs_inode_t *ip, /* incore inode pointer */ | 1456 | xfs_inode_t *ip, /* incore inode pointer */ |
1627 | xfs_extnum_t *idx, /* extent number to update/insert */ | 1457 | xfs_extnum_t *idx, /* extent number to update/insert */ |
1628 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 1458 | xfs_bmbt_irec_t *new) /* new data to add to file extents */ |
1629 | int *logflagsp) /* inode logging flags */ | ||
1630 | { | 1459 | { |
1631 | xfs_ifork_t *ifp; /* inode fork pointer */ | 1460 | xfs_ifork_t *ifp; /* inode fork pointer */ |
1632 | xfs_bmbt_irec_t left; /* left neighbor extent entry */ | 1461 | xfs_bmbt_irec_t left; /* left neighbor extent entry */ |
@@ -1761,23 +1590,17 @@ xfs_bmap_add_extent_hole_delay( | |||
1761 | * Nothing to do for disk quota accounting here. | 1590 | * Nothing to do for disk quota accounting here. |
1762 | */ | 1591 | */ |
1763 | } | 1592 | } |
1764 | *logflagsp = 0; | ||
1765 | return 0; | ||
1766 | } | 1593 | } |
1767 | 1594 | ||
1768 | /* | 1595 | /* |
1769 | * Called by xfs_bmap_add_extent to handle cases converting a hole | 1596 | * Convert a hole to a real allocation. |
1770 | * to a real allocation. | ||
1771 | */ | 1597 | */ |
1772 | STATIC int /* error */ | 1598 | STATIC int /* error */ |
1773 | xfs_bmap_add_extent_hole_real( | 1599 | xfs_bmap_add_extent_hole_real( |
1774 | xfs_inode_t *ip, /* incore inode pointer */ | 1600 | struct xfs_bmalloca *bma, |
1775 | xfs_extnum_t *idx, /* extent number to update/insert */ | 1601 | int whichfork) |
1776 | xfs_btree_cur_t *cur, /* if null, not a btree */ | ||
1777 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | ||
1778 | int *logflagsp, /* inode logging flags */ | ||
1779 | int whichfork) /* data or attr fork */ | ||
1780 | { | 1602 | { |
1603 | struct xfs_bmbt_irec *new = &bma->got; | ||
1781 | int error; /* error return value */ | 1604 | int error; /* error return value */ |
1782 | int i; /* temp state */ | 1605 | int i; /* temp state */ |
1783 | xfs_ifork_t *ifp; /* inode fork pointer */ | 1606 | xfs_ifork_t *ifp; /* inode fork pointer */ |
@@ -1786,19 +1609,26 @@ xfs_bmap_add_extent_hole_real( | |||
1786 | int rval=0; /* return value (logging flags) */ | 1609 | int rval=0; /* return value (logging flags) */ |
1787 | int state; /* state bits, accessed thru macros */ | 1610 | int state; /* state bits, accessed thru macros */ |
1788 | 1611 | ||
1789 | ifp = XFS_IFORK_PTR(ip, whichfork); | 1612 | ifp = XFS_IFORK_PTR(bma->ip, whichfork); |
1790 | ASSERT(*idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)); | 1613 | |
1791 | state = 0; | 1614 | ASSERT(bma->idx >= 0); |
1615 | ASSERT(bma->idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec)); | ||
1616 | ASSERT(!isnullstartblock(new->br_startblock)); | ||
1617 | ASSERT(!bma->cur || | ||
1618 | !(bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL)); | ||
1619 | |||
1620 | XFS_STATS_INC(xs_add_exlist); | ||
1792 | 1621 | ||
1622 | state = 0; | ||
1793 | if (whichfork == XFS_ATTR_FORK) | 1623 | if (whichfork == XFS_ATTR_FORK) |
1794 | state |= BMAP_ATTRFORK; | 1624 | state |= BMAP_ATTRFORK; |
1795 | 1625 | ||
1796 | /* | 1626 | /* |
1797 | * Check and set flags if this segment has a left neighbor. | 1627 | * Check and set flags if this segment has a left neighbor. |
1798 | */ | 1628 | */ |
1799 | if (*idx > 0) { | 1629 | if (bma->idx > 0) { |
1800 | state |= BMAP_LEFT_VALID; | 1630 | state |= BMAP_LEFT_VALID; |
1801 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx - 1), &left); | 1631 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1), &left); |
1802 | if (isnullstartblock(left.br_startblock)) | 1632 | if (isnullstartblock(left.br_startblock)) |
1803 | state |= BMAP_LEFT_DELAY; | 1633 | state |= BMAP_LEFT_DELAY; |
1804 | } | 1634 | } |
@@ -1807,9 +1637,9 @@ xfs_bmap_add_extent_hole_real( | |||
1807 | * Check and set flags if this segment has a current value. | 1637 | * Check and set flags if this segment has a current value. |
1808 | * Not true if we're inserting into the "hole" at eof. | 1638 | * Not true if we're inserting into the "hole" at eof. |
1809 | */ | 1639 | */ |
1810 | if (*idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) { | 1640 | if (bma->idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) { |
1811 | state |= BMAP_RIGHT_VALID; | 1641 | state |= BMAP_RIGHT_VALID; |
1812 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx), &right); | 1642 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &right); |
1813 | if (isnullstartblock(right.br_startblock)) | 1643 | if (isnullstartblock(right.br_startblock)) |
1814 | state |= BMAP_RIGHT_DELAY; | 1644 | state |= BMAP_RIGHT_DELAY; |
1815 | } | 1645 | } |
@@ -1846,39 +1676,42 @@ xfs_bmap_add_extent_hole_real( | |||
1846 | * left and on the right. | 1676 | * left and on the right. |
1847 | * Merge all three into a single extent record. | 1677 | * Merge all three into a single extent record. |
1848 | */ | 1678 | */ |
1849 | --*idx; | 1679 | --bma->idx; |
1850 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 1680 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
1851 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), | 1681 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx), |
1852 | left.br_blockcount + new->br_blockcount + | 1682 | left.br_blockcount + new->br_blockcount + |
1853 | right.br_blockcount); | 1683 | right.br_blockcount); |
1854 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 1684 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
1855 | 1685 | ||
1856 | xfs_iext_remove(ip, *idx + 1, 1, state); | 1686 | xfs_iext_remove(bma->ip, bma->idx + 1, 1, state); |
1857 | 1687 | ||
1858 | XFS_IFORK_NEXT_SET(ip, whichfork, | 1688 | XFS_IFORK_NEXT_SET(bma->ip, whichfork, |
1859 | XFS_IFORK_NEXTENTS(ip, whichfork) - 1); | 1689 | XFS_IFORK_NEXTENTS(bma->ip, whichfork) - 1); |
1860 | if (cur == NULL) { | 1690 | if (bma->cur == NULL) { |
1861 | rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); | 1691 | rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); |
1862 | } else { | 1692 | } else { |
1863 | rval = XFS_ILOG_CORE; | 1693 | rval = XFS_ILOG_CORE; |
1864 | if ((error = xfs_bmbt_lookup_eq(cur, | 1694 | error = xfs_bmbt_lookup_eq(bma->cur, right.br_startoff, |
1865 | right.br_startoff, | 1695 | right.br_startblock, right.br_blockcount, |
1866 | right.br_startblock, | 1696 | &i); |
1867 | right.br_blockcount, &i))) | 1697 | if (error) |
1868 | goto done; | 1698 | goto done; |
1869 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1699 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1870 | if ((error = xfs_btree_delete(cur, &i))) | 1700 | error = xfs_btree_delete(bma->cur, &i); |
1701 | if (error) | ||
1871 | goto done; | 1702 | goto done; |
1872 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1703 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1873 | if ((error = xfs_btree_decrement(cur, 0, &i))) | 1704 | error = xfs_btree_decrement(bma->cur, 0, &i); |
1705 | if (error) | ||
1874 | goto done; | 1706 | goto done; |
1875 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1707 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1876 | if ((error = xfs_bmbt_update(cur, left.br_startoff, | 1708 | error = xfs_bmbt_update(bma->cur, left.br_startoff, |
1877 | left.br_startblock, | 1709 | left.br_startblock, |
1878 | left.br_blockcount + | 1710 | left.br_blockcount + |
1879 | new->br_blockcount + | 1711 | new->br_blockcount + |
1880 | right.br_blockcount, | 1712 | right.br_blockcount, |
1881 | left.br_state))) | 1713 | left.br_state); |
1714 | if (error) | ||
1882 | goto done; | 1715 | goto done; |
1883 | } | 1716 | } |
1884 | break; | 1717 | break; |
@@ -1889,27 +1722,28 @@ xfs_bmap_add_extent_hole_real( | |||
1889 | * on the left. | 1722 | * on the left. |
1890 | * Merge the new allocation with the left neighbor. | 1723 | * Merge the new allocation with the left neighbor. |
1891 | */ | 1724 | */ |
1892 | --*idx; | 1725 | --bma->idx; |
1893 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 1726 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
1894 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), | 1727 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx), |
1895 | left.br_blockcount + new->br_blockcount); | 1728 | left.br_blockcount + new->br_blockcount); |
1896 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 1729 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
1897 | 1730 | ||
1898 | if (cur == NULL) { | 1731 | if (bma->cur == NULL) { |
1899 | rval = xfs_ilog_fext(whichfork); | 1732 | rval = xfs_ilog_fext(whichfork); |
1900 | } else { | 1733 | } else { |
1901 | rval = 0; | 1734 | rval = 0; |
1902 | if ((error = xfs_bmbt_lookup_eq(cur, | 1735 | error = xfs_bmbt_lookup_eq(bma->cur, left.br_startoff, |
1903 | left.br_startoff, | 1736 | left.br_startblock, left.br_blockcount, |
1904 | left.br_startblock, | 1737 | &i); |
1905 | left.br_blockcount, &i))) | 1738 | if (error) |
1906 | goto done; | 1739 | goto done; |
1907 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1740 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1908 | if ((error = xfs_bmbt_update(cur, left.br_startoff, | 1741 | error = xfs_bmbt_update(bma->cur, left.br_startoff, |
1909 | left.br_startblock, | 1742 | left.br_startblock, |
1910 | left.br_blockcount + | 1743 | left.br_blockcount + |
1911 | new->br_blockcount, | 1744 | new->br_blockcount, |
1912 | left.br_state))) | 1745 | left.br_state); |
1746 | if (error) | ||
1913 | goto done; | 1747 | goto done; |
1914 | } | 1748 | } |
1915 | break; | 1749 | break; |
@@ -1920,28 +1754,30 @@ xfs_bmap_add_extent_hole_real( | |||
1920 | * on the right. | 1754 | * on the right. |
1921 | * Merge the new allocation with the right neighbor. | 1755 | * Merge the new allocation with the right neighbor. |
1922 | */ | 1756 | */ |
1923 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 1757 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
1924 | xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx), | 1758 | xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, bma->idx), |
1925 | new->br_startoff, new->br_startblock, | 1759 | new->br_startoff, new->br_startblock, |
1926 | new->br_blockcount + right.br_blockcount, | 1760 | new->br_blockcount + right.br_blockcount, |
1927 | right.br_state); | 1761 | right.br_state); |
1928 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 1762 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
1929 | 1763 | ||
1930 | if (cur == NULL) { | 1764 | if (bma->cur == NULL) { |
1931 | rval = xfs_ilog_fext(whichfork); | 1765 | rval = xfs_ilog_fext(whichfork); |
1932 | } else { | 1766 | } else { |
1933 | rval = 0; | 1767 | rval = 0; |
1934 | if ((error = xfs_bmbt_lookup_eq(cur, | 1768 | error = xfs_bmbt_lookup_eq(bma->cur, |
1935 | right.br_startoff, | 1769 | right.br_startoff, |
1936 | right.br_startblock, | 1770 | right.br_startblock, |
1937 | right.br_blockcount, &i))) | 1771 | right.br_blockcount, &i); |
1772 | if (error) | ||
1938 | goto done; | 1773 | goto done; |
1939 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1774 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1940 | if ((error = xfs_bmbt_update(cur, new->br_startoff, | 1775 | error = xfs_bmbt_update(bma->cur, new->br_startoff, |
1941 | new->br_startblock, | 1776 | new->br_startblock, |
1942 | new->br_blockcount + | 1777 | new->br_blockcount + |
1943 | right.br_blockcount, | 1778 | right.br_blockcount, |
1944 | right.br_state))) | 1779 | right.br_state); |
1780 | if (error) | ||
1945 | goto done; | 1781 | goto done; |
1946 | } | 1782 | } |
1947 | break; | 1783 | break; |
@@ -1952,28 +1788,50 @@ xfs_bmap_add_extent_hole_real( | |||
1952 | * real allocation. | 1788 | * real allocation. |
1953 | * Insert a new entry. | 1789 | * Insert a new entry. |
1954 | */ | 1790 | */ |
1955 | xfs_iext_insert(ip, *idx, 1, new, state); | 1791 | xfs_iext_insert(bma->ip, bma->idx, 1, new, state); |
1956 | XFS_IFORK_NEXT_SET(ip, whichfork, | 1792 | XFS_IFORK_NEXT_SET(bma->ip, whichfork, |
1957 | XFS_IFORK_NEXTENTS(ip, whichfork) + 1); | 1793 | XFS_IFORK_NEXTENTS(bma->ip, whichfork) + 1); |
1958 | if (cur == NULL) { | 1794 | if (bma->cur == NULL) { |
1959 | rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); | 1795 | rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); |
1960 | } else { | 1796 | } else { |
1961 | rval = XFS_ILOG_CORE; | 1797 | rval = XFS_ILOG_CORE; |
1962 | if ((error = xfs_bmbt_lookup_eq(cur, | 1798 | error = xfs_bmbt_lookup_eq(bma->cur, |
1963 | new->br_startoff, | 1799 | new->br_startoff, |
1964 | new->br_startblock, | 1800 | new->br_startblock, |
1965 | new->br_blockcount, &i))) | 1801 | new->br_blockcount, &i); |
1802 | if (error) | ||
1966 | goto done; | 1803 | goto done; |
1967 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); | 1804 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
1968 | cur->bc_rec.b.br_state = new->br_state; | 1805 | bma->cur->bc_rec.b.br_state = new->br_state; |
1969 | if ((error = xfs_btree_insert(cur, &i))) | 1806 | error = xfs_btree_insert(bma->cur, &i); |
1807 | if (error) | ||
1970 | goto done; | 1808 | goto done; |
1971 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1809 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1972 | } | 1810 | } |
1973 | break; | 1811 | break; |
1974 | } | 1812 | } |
1813 | |||
1814 | /* convert to a btree if necessary */ | ||
1815 | if (XFS_IFORK_FORMAT(bma->ip, whichfork) == XFS_DINODE_FMT_EXTENTS && | ||
1816 | XFS_IFORK_NEXTENTS(bma->ip, whichfork) > ifp->if_ext_max) { | ||
1817 | int tmp_logflags; /* partial log flag return val */ | ||
1818 | |||
1819 | ASSERT(bma->cur == NULL); | ||
1820 | error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, | ||
1821 | bma->firstblock, bma->flist, &bma->cur, | ||
1822 | 0, &tmp_logflags, whichfork); | ||
1823 | bma->logflags |= tmp_logflags; | ||
1824 | if (error) | ||
1825 | goto done; | ||
1826 | } | ||
1827 | |||
1828 | /* clear out the allocated field, done with it now in any case. */ | ||
1829 | if (bma->cur) | ||
1830 | bma->cur->bc_private.b.allocated = 0; | ||
1831 | |||
1832 | xfs_bmap_check_leaf_extents(bma->cur, bma->ip, whichfork); | ||
1975 | done: | 1833 | done: |
1976 | *logflagsp = rval; | 1834 | bma->logflags |= rval; |
1977 | return error; | 1835 | return error; |
1978 | } | 1836 | } |
1979 | 1837 | ||
@@ -2160,26 +2018,26 @@ xfs_bmap_adjacent( | |||
2160 | XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks) | 2018 | XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks) |
2161 | 2019 | ||
2162 | mp = ap->ip->i_mount; | 2020 | mp = ap->ip->i_mount; |
2163 | nullfb = ap->firstblock == NULLFSBLOCK; | 2021 | nullfb = *ap->firstblock == NULLFSBLOCK; |
2164 | rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata; | 2022 | rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata; |
2165 | fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); | 2023 | fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock); |
2166 | /* | 2024 | /* |
2167 | * If allocating at eof, and there's a previous real block, | 2025 | * If allocating at eof, and there's a previous real block, |
2168 | * try to use its last block as our starting point. | 2026 | * try to use its last block as our starting point. |
2169 | */ | 2027 | */ |
2170 | if (ap->eof && ap->prevp->br_startoff != NULLFILEOFF && | 2028 | if (ap->eof && ap->prev.br_startoff != NULLFILEOFF && |
2171 | !isnullstartblock(ap->prevp->br_startblock) && | 2029 | !isnullstartblock(ap->prev.br_startblock) && |
2172 | ISVALID(ap->prevp->br_startblock + ap->prevp->br_blockcount, | 2030 | ISVALID(ap->prev.br_startblock + ap->prev.br_blockcount, |
2173 | ap->prevp->br_startblock)) { | 2031 | ap->prev.br_startblock)) { |
2174 | ap->rval = ap->prevp->br_startblock + ap->prevp->br_blockcount; | 2032 | ap->blkno = ap->prev.br_startblock + ap->prev.br_blockcount; |
2175 | /* | 2033 | /* |
2176 | * Adjust for the gap between prevp and us. | 2034 | * Adjust for the gap between prevp and us. |
2177 | */ | 2035 | */ |
2178 | adjust = ap->off - | 2036 | adjust = ap->offset - |
2179 | (ap->prevp->br_startoff + ap->prevp->br_blockcount); | 2037 | (ap->prev.br_startoff + ap->prev.br_blockcount); |
2180 | if (adjust && | 2038 | if (adjust && |
2181 | ISVALID(ap->rval + adjust, ap->prevp->br_startblock)) | 2039 | ISVALID(ap->blkno + adjust, ap->prev.br_startblock)) |
2182 | ap->rval += adjust; | 2040 | ap->blkno += adjust; |
2183 | } | 2041 | } |
2184 | /* | 2042 | /* |
2185 | * If not at eof, then compare the two neighbor blocks. | 2043 | * If not at eof, then compare the two neighbor blocks. |
@@ -2196,17 +2054,17 @@ xfs_bmap_adjacent( | |||
2196 | * If there's a previous (left) block, select a requested | 2054 | * If there's a previous (left) block, select a requested |
2197 | * start block based on it. | 2055 | * start block based on it. |
2198 | */ | 2056 | */ |
2199 | if (ap->prevp->br_startoff != NULLFILEOFF && | 2057 | if (ap->prev.br_startoff != NULLFILEOFF && |
2200 | !isnullstartblock(ap->prevp->br_startblock) && | 2058 | !isnullstartblock(ap->prev.br_startblock) && |
2201 | (prevbno = ap->prevp->br_startblock + | 2059 | (prevbno = ap->prev.br_startblock + |
2202 | ap->prevp->br_blockcount) && | 2060 | ap->prev.br_blockcount) && |
2203 | ISVALID(prevbno, ap->prevp->br_startblock)) { | 2061 | ISVALID(prevbno, ap->prev.br_startblock)) { |
2204 | /* | 2062 | /* |
2205 | * Calculate gap to end of previous block. | 2063 | * Calculate gap to end of previous block. |
2206 | */ | 2064 | */ |
2207 | adjust = prevdiff = ap->off - | 2065 | adjust = prevdiff = ap->offset - |
2208 | (ap->prevp->br_startoff + | 2066 | (ap->prev.br_startoff + |
2209 | ap->prevp->br_blockcount); | 2067 | ap->prev.br_blockcount); |
2210 | /* | 2068 | /* |
2211 | * Figure the startblock based on the previous block's | 2069 | * Figure the startblock based on the previous block's |
2212 | * end and the gap size. | 2070 | * end and the gap size. |
@@ -2215,9 +2073,9 @@ xfs_bmap_adjacent( | |||
2215 | * allocating, or using it gives us an invalid block | 2073 | * allocating, or using it gives us an invalid block |
2216 | * number, then just use the end of the previous block. | 2074 | * number, then just use the end of the previous block. |
2217 | */ | 2075 | */ |
2218 | if (prevdiff <= XFS_ALLOC_GAP_UNITS * ap->alen && | 2076 | if (prevdiff <= XFS_ALLOC_GAP_UNITS * ap->length && |
2219 | ISVALID(prevbno + prevdiff, | 2077 | ISVALID(prevbno + prevdiff, |
2220 | ap->prevp->br_startblock)) | 2078 | ap->prev.br_startblock)) |
2221 | prevbno += adjust; | 2079 | prevbno += adjust; |
2222 | else | 2080 | else |
2223 | prevdiff += adjust; | 2081 | prevdiff += adjust; |
@@ -2238,16 +2096,16 @@ xfs_bmap_adjacent( | |||
2238 | * If there's a following (right) block, select a requested | 2096 | * If there's a following (right) block, select a requested |
2239 | * start block based on it. | 2097 | * start block based on it. |
2240 | */ | 2098 | */ |
2241 | if (!isnullstartblock(ap->gotp->br_startblock)) { | 2099 | if (!isnullstartblock(ap->got.br_startblock)) { |
2242 | /* | 2100 | /* |
2243 | * Calculate gap to start of next block. | 2101 | * Calculate gap to start of next block. |
2244 | */ | 2102 | */ |
2245 | adjust = gotdiff = ap->gotp->br_startoff - ap->off; | 2103 | adjust = gotdiff = ap->got.br_startoff - ap->offset; |
2246 | /* | 2104 | /* |
2247 | * Figure the startblock based on the next block's | 2105 | * Figure the startblock based on the next block's |
2248 | * start and the gap size. | 2106 | * start and the gap size. |
2249 | */ | 2107 | */ |
2250 | gotbno = ap->gotp->br_startblock; | 2108 | gotbno = ap->got.br_startblock; |
2251 | /* | 2109 | /* |
2252 | * Heuristic! | 2110 | * Heuristic! |
2253 | * If the gap is large relative to the piece we're | 2111 | * If the gap is large relative to the piece we're |
@@ -2255,12 +2113,12 @@ xfs_bmap_adjacent( | |||
2255 | * number, then just use the start of the next block | 2113 | * number, then just use the start of the next block |
2256 | * offset by our length. | 2114 | * offset by our length. |
2257 | */ | 2115 | */ |
2258 | if (gotdiff <= XFS_ALLOC_GAP_UNITS * ap->alen && | 2116 | if (gotdiff <= XFS_ALLOC_GAP_UNITS * ap->length && |
2259 | ISVALID(gotbno - gotdiff, gotbno)) | 2117 | ISVALID(gotbno - gotdiff, gotbno)) |
2260 | gotbno -= adjust; | 2118 | gotbno -= adjust; |
2261 | else if (ISVALID(gotbno - ap->alen, gotbno)) { | 2119 | else if (ISVALID(gotbno - ap->length, gotbno)) { |
2262 | gotbno -= ap->alen; | 2120 | gotbno -= ap->length; |
2263 | gotdiff += adjust - ap->alen; | 2121 | gotdiff += adjust - ap->length; |
2264 | } else | 2122 | } else |
2265 | gotdiff += adjust; | 2123 | gotdiff += adjust; |
2266 | /* | 2124 | /* |
@@ -2278,14 +2136,14 @@ xfs_bmap_adjacent( | |||
2278 | gotbno = NULLFSBLOCK; | 2136 | gotbno = NULLFSBLOCK; |
2279 | /* | 2137 | /* |
2280 | * If both valid, pick the better one, else the only good | 2138 | * If both valid, pick the better one, else the only good |
2281 | * one, else ap->rval is already set (to 0 or the inode block). | 2139 | * one, else ap->blkno is already set (to 0 or the inode block). |
2282 | */ | 2140 | */ |
2283 | if (prevbno != NULLFSBLOCK && gotbno != NULLFSBLOCK) | 2141 | if (prevbno != NULLFSBLOCK && gotbno != NULLFSBLOCK) |
2284 | ap->rval = prevdiff <= gotdiff ? prevbno : gotbno; | 2142 | ap->blkno = prevdiff <= gotdiff ? prevbno : gotbno; |
2285 | else if (prevbno != NULLFSBLOCK) | 2143 | else if (prevbno != NULLFSBLOCK) |
2286 | ap->rval = prevbno; | 2144 | ap->blkno = prevbno; |
2287 | else if (gotbno != NULLFSBLOCK) | 2145 | else if (gotbno != NULLFSBLOCK) |
2288 | ap->rval = gotbno; | 2146 | ap->blkno = gotbno; |
2289 | } | 2147 | } |
2290 | #undef ISVALID | 2148 | #undef ISVALID |
2291 | } | 2149 | } |
@@ -2305,24 +2163,24 @@ xfs_bmap_rtalloc( | |||
2305 | mp = ap->ip->i_mount; | 2163 | mp = ap->ip->i_mount; |
2306 | align = xfs_get_extsz_hint(ap->ip); | 2164 | align = xfs_get_extsz_hint(ap->ip); |
2307 | prod = align / mp->m_sb.sb_rextsize; | 2165 | prod = align / mp->m_sb.sb_rextsize; |
2308 | error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp, | 2166 | error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, |
2309 | align, 1, ap->eof, 0, | 2167 | align, 1, ap->eof, 0, |
2310 | ap->conv, &ap->off, &ap->alen); | 2168 | ap->conv, &ap->offset, &ap->length); |
2311 | if (error) | 2169 | if (error) |
2312 | return error; | 2170 | return error; |
2313 | ASSERT(ap->alen); | 2171 | ASSERT(ap->length); |
2314 | ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0); | 2172 | ASSERT(ap->length % mp->m_sb.sb_rextsize == 0); |
2315 | 2173 | ||
2316 | /* | 2174 | /* |
2317 | * If the offset & length are not perfectly aligned | 2175 | * If the offset & length are not perfectly aligned |
2318 | * then kill prod, it will just get us in trouble. | 2176 | * then kill prod, it will just get us in trouble. |
2319 | */ | 2177 | */ |
2320 | if (do_mod(ap->off, align) || ap->alen % align) | 2178 | if (do_mod(ap->offset, align) || ap->length % align) |
2321 | prod = 1; | 2179 | prod = 1; |
2322 | /* | 2180 | /* |
2323 | * Set ralen to be the actual requested length in rtextents. | 2181 | * Set ralen to be the actual requested length in rtextents. |
2324 | */ | 2182 | */ |
2325 | ralen = ap->alen / mp->m_sb.sb_rextsize; | 2183 | ralen = ap->length / mp->m_sb.sb_rextsize; |
2326 | /* | 2184 | /* |
2327 | * If the old value was close enough to MAXEXTLEN that | 2185 | * If the old value was close enough to MAXEXTLEN that |
2328 | * we rounded up to it, cut it back so it's valid again. | 2186 | * we rounded up to it, cut it back so it's valid again. |
@@ -2337,21 +2195,21 @@ xfs_bmap_rtalloc( | |||
2337 | * Lock out other modifications to the RT bitmap inode. | 2195 | * Lock out other modifications to the RT bitmap inode. |
2338 | */ | 2196 | */ |
2339 | xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); | 2197 | xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); |
2340 | xfs_trans_ijoin_ref(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL); | 2198 | xfs_trans_ijoin(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL); |
2341 | 2199 | ||
2342 | /* | 2200 | /* |
2343 | * If it's an allocation to an empty file at offset 0, | 2201 | * If it's an allocation to an empty file at offset 0, |
2344 | * pick an extent that will space things out in the rt area. | 2202 | * pick an extent that will space things out in the rt area. |
2345 | */ | 2203 | */ |
2346 | if (ap->eof && ap->off == 0) { | 2204 | if (ap->eof && ap->offset == 0) { |
2347 | xfs_rtblock_t uninitialized_var(rtx); /* realtime extent no */ | 2205 | xfs_rtblock_t uninitialized_var(rtx); /* realtime extent no */ |
2348 | 2206 | ||
2349 | error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx); | 2207 | error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx); |
2350 | if (error) | 2208 | if (error) |
2351 | return error; | 2209 | return error; |
2352 | ap->rval = rtx * mp->m_sb.sb_rextsize; | 2210 | ap->blkno = rtx * mp->m_sb.sb_rextsize; |
2353 | } else { | 2211 | } else { |
2354 | ap->rval = 0; | 2212 | ap->blkno = 0; |
2355 | } | 2213 | } |
2356 | 2214 | ||
2357 | xfs_bmap_adjacent(ap); | 2215 | xfs_bmap_adjacent(ap); |
@@ -2359,23 +2217,23 @@ xfs_bmap_rtalloc( | |||
2359 | /* | 2217 | /* |
2360 | * Realtime allocation, done through xfs_rtallocate_extent. | 2218 | * Realtime allocation, done through xfs_rtallocate_extent. |
2361 | */ | 2219 | */ |
2362 | atype = ap->rval == 0 ? XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO; | 2220 | atype = ap->blkno == 0 ? XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO; |
2363 | do_div(ap->rval, mp->m_sb.sb_rextsize); | 2221 | do_div(ap->blkno, mp->m_sb.sb_rextsize); |
2364 | rtb = ap->rval; | 2222 | rtb = ap->blkno; |
2365 | ap->alen = ralen; | 2223 | ap->length = ralen; |
2366 | if ((error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, ap->alen, | 2224 | if ((error = xfs_rtallocate_extent(ap->tp, ap->blkno, 1, ap->length, |
2367 | &ralen, atype, ap->wasdel, prod, &rtb))) | 2225 | &ralen, atype, ap->wasdel, prod, &rtb))) |
2368 | return error; | 2226 | return error; |
2369 | if (rtb == NULLFSBLOCK && prod > 1 && | 2227 | if (rtb == NULLFSBLOCK && prod > 1 && |
2370 | (error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, | 2228 | (error = xfs_rtallocate_extent(ap->tp, ap->blkno, 1, |
2371 | ap->alen, &ralen, atype, | 2229 | ap->length, &ralen, atype, |
2372 | ap->wasdel, 1, &rtb))) | 2230 | ap->wasdel, 1, &rtb))) |
2373 | return error; | 2231 | return error; |
2374 | ap->rval = rtb; | 2232 | ap->blkno = rtb; |
2375 | if (ap->rval != NULLFSBLOCK) { | 2233 | if (ap->blkno != NULLFSBLOCK) { |
2376 | ap->rval *= mp->m_sb.sb_rextsize; | 2234 | ap->blkno *= mp->m_sb.sb_rextsize; |
2377 | ralen *= mp->m_sb.sb_rextsize; | 2235 | ralen *= mp->m_sb.sb_rextsize; |
2378 | ap->alen = ralen; | 2236 | ap->length = ralen; |
2379 | ap->ip->i_d.di_nblocks += ralen; | 2237 | ap->ip->i_d.di_nblocks += ralen; |
2380 | xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); | 2238 | xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); |
2381 | if (ap->wasdel) | 2239 | if (ap->wasdel) |
@@ -2388,7 +2246,7 @@ xfs_bmap_rtalloc( | |||
2388 | ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT : | 2246 | ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT : |
2389 | XFS_TRANS_DQ_RTBCOUNT, (long) ralen); | 2247 | XFS_TRANS_DQ_RTBCOUNT, (long) ralen); |
2390 | } else { | 2248 | } else { |
2391 | ap->alen = 0; | 2249 | ap->length = 0; |
2392 | } | 2250 | } |
2393 | return 0; | 2251 | return 0; |
2394 | } | 2252 | } |
@@ -2503,7 +2361,7 @@ xfs_bmap_btalloc_nullfb( | |||
2503 | * AG as the stream may have moved. | 2361 | * AG as the stream may have moved. |
2504 | */ | 2362 | */ |
2505 | if (xfs_inode_is_filestream(ap->ip)) | 2363 | if (xfs_inode_is_filestream(ap->ip)) |
2506 | ap->rval = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0); | 2364 | ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0); |
2507 | 2365 | ||
2508 | return 0; | 2366 | return 0; |
2509 | } | 2367 | } |
@@ -2528,52 +2386,52 @@ xfs_bmap_btalloc( | |||
2528 | mp = ap->ip->i_mount; | 2386 | mp = ap->ip->i_mount; |
2529 | align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0; | 2387 | align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0; |
2530 | if (unlikely(align)) { | 2388 | if (unlikely(align)) { |
2531 | error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp, | 2389 | error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, |
2532 | align, 0, ap->eof, 0, ap->conv, | 2390 | align, 0, ap->eof, 0, ap->conv, |
2533 | &ap->off, &ap->alen); | 2391 | &ap->offset, &ap->length); |
2534 | ASSERT(!error); | 2392 | ASSERT(!error); |
2535 | ASSERT(ap->alen); | 2393 | ASSERT(ap->length); |
2536 | } | 2394 | } |
2537 | nullfb = ap->firstblock == NULLFSBLOCK; | 2395 | nullfb = *ap->firstblock == NULLFSBLOCK; |
2538 | fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); | 2396 | fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock); |
2539 | if (nullfb) { | 2397 | if (nullfb) { |
2540 | if (ap->userdata && xfs_inode_is_filestream(ap->ip)) { | 2398 | if (ap->userdata && xfs_inode_is_filestream(ap->ip)) { |
2541 | ag = xfs_filestream_lookup_ag(ap->ip); | 2399 | ag = xfs_filestream_lookup_ag(ap->ip); |
2542 | ag = (ag != NULLAGNUMBER) ? ag : 0; | 2400 | ag = (ag != NULLAGNUMBER) ? ag : 0; |
2543 | ap->rval = XFS_AGB_TO_FSB(mp, ag, 0); | 2401 | ap->blkno = XFS_AGB_TO_FSB(mp, ag, 0); |
2544 | } else { | 2402 | } else { |
2545 | ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino); | 2403 | ap->blkno = XFS_INO_TO_FSB(mp, ap->ip->i_ino); |
2546 | } | 2404 | } |
2547 | } else | 2405 | } else |
2548 | ap->rval = ap->firstblock; | 2406 | ap->blkno = *ap->firstblock; |
2549 | 2407 | ||
2550 | xfs_bmap_adjacent(ap); | 2408 | xfs_bmap_adjacent(ap); |
2551 | 2409 | ||
2552 | /* | 2410 | /* |
2553 | * If allowed, use ap->rval; otherwise must use firstblock since | 2411 | * If allowed, use ap->blkno; otherwise must use firstblock since |
2554 | * it's in the right allocation group. | 2412 | * it's in the right allocation group. |
2555 | */ | 2413 | */ |
2556 | if (nullfb || XFS_FSB_TO_AGNO(mp, ap->rval) == fb_agno) | 2414 | if (nullfb || XFS_FSB_TO_AGNO(mp, ap->blkno) == fb_agno) |
2557 | ; | 2415 | ; |
2558 | else | 2416 | else |
2559 | ap->rval = ap->firstblock; | 2417 | ap->blkno = *ap->firstblock; |
2560 | /* | 2418 | /* |
2561 | * Normal allocation, done through xfs_alloc_vextent. | 2419 | * Normal allocation, done through xfs_alloc_vextent. |
2562 | */ | 2420 | */ |
2563 | tryagain = isaligned = 0; | 2421 | tryagain = isaligned = 0; |
2564 | args.tp = ap->tp; | 2422 | args.tp = ap->tp; |
2565 | args.mp = mp; | 2423 | args.mp = mp; |
2566 | args.fsbno = ap->rval; | 2424 | args.fsbno = ap->blkno; |
2567 | 2425 | ||
2568 | /* Trim the allocation back to the maximum an AG can fit. */ | 2426 | /* Trim the allocation back to the maximum an AG can fit. */ |
2569 | args.maxlen = MIN(ap->alen, XFS_ALLOC_AG_MAX_USABLE(mp)); | 2427 | args.maxlen = MIN(ap->length, XFS_ALLOC_AG_MAX_USABLE(mp)); |
2570 | args.firstblock = ap->firstblock; | 2428 | args.firstblock = *ap->firstblock; |
2571 | blen = 0; | 2429 | blen = 0; |
2572 | if (nullfb) { | 2430 | if (nullfb) { |
2573 | error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); | 2431 | error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); |
2574 | if (error) | 2432 | if (error) |
2575 | return error; | 2433 | return error; |
2576 | } else if (ap->low) { | 2434 | } else if (ap->flist->xbf_low) { |
2577 | if (xfs_inode_is_filestream(ap->ip)) | 2435 | if (xfs_inode_is_filestream(ap->ip)) |
2578 | args.type = XFS_ALLOCTYPE_FIRST_AG; | 2436 | args.type = XFS_ALLOCTYPE_FIRST_AG; |
2579 | else | 2437 | else |
@@ -2587,14 +2445,14 @@ xfs_bmap_btalloc( | |||
2587 | /* apply extent size hints if obtained earlier */ | 2445 | /* apply extent size hints if obtained earlier */ |
2588 | if (unlikely(align)) { | 2446 | if (unlikely(align)) { |
2589 | args.prod = align; | 2447 | args.prod = align; |
2590 | if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod))) | 2448 | if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod))) |
2591 | args.mod = (xfs_extlen_t)(args.prod - args.mod); | 2449 | args.mod = (xfs_extlen_t)(args.prod - args.mod); |
2592 | } else if (mp->m_sb.sb_blocksize >= PAGE_CACHE_SIZE) { | 2450 | } else if (mp->m_sb.sb_blocksize >= PAGE_CACHE_SIZE) { |
2593 | args.prod = 1; | 2451 | args.prod = 1; |
2594 | args.mod = 0; | 2452 | args.mod = 0; |
2595 | } else { | 2453 | } else { |
2596 | args.prod = PAGE_CACHE_SIZE >> mp->m_sb.sb_blocklog; | 2454 | args.prod = PAGE_CACHE_SIZE >> mp->m_sb.sb_blocklog; |
2597 | if ((args.mod = (xfs_extlen_t)(do_mod(ap->off, args.prod)))) | 2455 | if ((args.mod = (xfs_extlen_t)(do_mod(ap->offset, args.prod)))) |
2598 | args.mod = (xfs_extlen_t)(args.prod - args.mod); | 2456 | args.mod = (xfs_extlen_t)(args.prod - args.mod); |
2599 | } | 2457 | } |
2600 | /* | 2458 | /* |
@@ -2606,8 +2464,8 @@ xfs_bmap_btalloc( | |||
2606 | * is >= the stripe unit and the allocation offset is | 2464 | * is >= the stripe unit and the allocation offset is |
2607 | * at the end of file. | 2465 | * at the end of file. |
2608 | */ | 2466 | */ |
2609 | if (!ap->low && ap->aeof) { | 2467 | if (!ap->flist->xbf_low && ap->aeof) { |
2610 | if (!ap->off) { | 2468 | if (!ap->offset) { |
2611 | args.alignment = mp->m_dalign; | 2469 | args.alignment = mp->m_dalign; |
2612 | atype = args.type; | 2470 | atype = args.type; |
2613 | isaligned = 1; | 2471 | isaligned = 1; |
@@ -2660,7 +2518,7 @@ xfs_bmap_btalloc( | |||
2660 | * turned on. | 2518 | * turned on. |
2661 | */ | 2519 | */ |
2662 | args.type = atype; | 2520 | args.type = atype; |
2663 | args.fsbno = ap->rval; | 2521 | args.fsbno = ap->blkno; |
2664 | args.alignment = mp->m_dalign; | 2522 | args.alignment = mp->m_dalign; |
2665 | args.minlen = nextminlen; | 2523 | args.minlen = nextminlen; |
2666 | args.minalignslop = 0; | 2524 | args.minalignslop = 0; |
@@ -2674,7 +2532,7 @@ xfs_bmap_btalloc( | |||
2674 | * try again. | 2532 | * try again. |
2675 | */ | 2533 | */ |
2676 | args.type = atype; | 2534 | args.type = atype; |
2677 | args.fsbno = ap->rval; | 2535 | args.fsbno = ap->blkno; |
2678 | args.alignment = 0; | 2536 | args.alignment = 0; |
2679 | if ((error = xfs_alloc_vextent(&args))) | 2537 | if ((error = xfs_alloc_vextent(&args))) |
2680 | return error; | 2538 | return error; |
@@ -2683,7 +2541,7 @@ xfs_bmap_btalloc( | |||
2683 | args.minlen > ap->minlen) { | 2541 | args.minlen > ap->minlen) { |
2684 | args.minlen = ap->minlen; | 2542 | args.minlen = ap->minlen; |
2685 | args.type = XFS_ALLOCTYPE_START_BNO; | 2543 | args.type = XFS_ALLOCTYPE_START_BNO; |
2686 | args.fsbno = ap->rval; | 2544 | args.fsbno = ap->blkno; |
2687 | if ((error = xfs_alloc_vextent(&args))) | 2545 | if ((error = xfs_alloc_vextent(&args))) |
2688 | return error; | 2546 | return error; |
2689 | } | 2547 | } |
@@ -2694,13 +2552,26 @@ xfs_bmap_btalloc( | |||
2694 | args.minleft = 0; | 2552 | args.minleft = 0; |
2695 | if ((error = xfs_alloc_vextent(&args))) | 2553 | if ((error = xfs_alloc_vextent(&args))) |
2696 | return error; | 2554 | return error; |
2697 | ap->low = 1; | 2555 | ap->flist->xbf_low = 1; |
2698 | } | 2556 | } |
2699 | if (args.fsbno != NULLFSBLOCK) { | 2557 | if (args.fsbno != NULLFSBLOCK) { |
2700 | ap->firstblock = ap->rval = args.fsbno; | 2558 | /* |
2559 | * check the allocation happened at the same or higher AG than | ||
2560 | * the first block that was allocated. | ||
2561 | */ | ||
2562 | ASSERT(*ap->firstblock == NULLFSBLOCK || | ||
2563 | XFS_FSB_TO_AGNO(mp, *ap->firstblock) == | ||
2564 | XFS_FSB_TO_AGNO(mp, args.fsbno) || | ||
2565 | (ap->flist->xbf_low && | ||
2566 | XFS_FSB_TO_AGNO(mp, *ap->firstblock) < | ||
2567 | XFS_FSB_TO_AGNO(mp, args.fsbno))); | ||
2568 | |||
2569 | ap->blkno = args.fsbno; | ||
2570 | if (*ap->firstblock == NULLFSBLOCK) | ||
2571 | *ap->firstblock = args.fsbno; | ||
2701 | ASSERT(nullfb || fb_agno == args.agno || | 2572 | ASSERT(nullfb || fb_agno == args.agno || |
2702 | (ap->low && fb_agno < args.agno)); | 2573 | (ap->flist->xbf_low && fb_agno < args.agno)); |
2703 | ap->alen = args.len; | 2574 | ap->length = args.len; |
2704 | ap->ip->i_d.di_nblocks += args.len; | 2575 | ap->ip->i_d.di_nblocks += args.len; |
2705 | xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); | 2576 | xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); |
2706 | if (ap->wasdel) | 2577 | if (ap->wasdel) |
@@ -2714,8 +2585,8 @@ xfs_bmap_btalloc( | |||
2714 | XFS_TRANS_DQ_BCOUNT, | 2585 | XFS_TRANS_DQ_BCOUNT, |
2715 | (long) args.len); | 2586 | (long) args.len); |
2716 | } else { | 2587 | } else { |
2717 | ap->rval = NULLFSBLOCK; | 2588 | ap->blkno = NULLFSBLOCK; |
2718 | ap->alen = 0; | 2589 | ap->length = 0; |
2719 | } | 2590 | } |
2720 | return 0; | 2591 | return 0; |
2721 | } | 2592 | } |
@@ -3589,7 +3460,7 @@ xfs_bmap_add_attrfork( | |||
3589 | } | 3460 | } |
3590 | ASSERT(ip->i_d.di_anextents == 0); | 3461 | ASSERT(ip->i_d.di_anextents == 0); |
3591 | 3462 | ||
3592 | xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); | 3463 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
3593 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 3464 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
3594 | 3465 | ||
3595 | switch (ip->i_d.di_format) { | 3466 | switch (ip->i_d.di_format) { |
@@ -3782,19 +3653,11 @@ xfs_bmap_compute_maxlevels( | |||
3782 | * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi | 3653 | * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi |
3783 | * caller. Frees all the extents that need freeing, which must be done | 3654 | * caller. Frees all the extents that need freeing, which must be done |
3784 | * last due to locking considerations. We never free any extents in | 3655 | * last due to locking considerations. We never free any extents in |
3785 | * the first transaction. This is to allow the caller to make the first | 3656 | * the first transaction. |
3786 | * transaction a synchronous one so that the pointers to the data being | ||
3787 | * broken in this transaction will be permanent before the data is actually | ||
3788 | * freed. This is necessary to prevent blocks from being reallocated | ||
3789 | * and written to before the free and reallocation are actually permanent. | ||
3790 | * We do not just make the first transaction synchronous here, because | ||
3791 | * there are more efficient ways to gain the same protection in some cases | ||
3792 | * (see the file truncation code). | ||
3793 | * | 3657 | * |
3794 | * Return 1 if the given transaction was committed and a new one | 3658 | * Return 1 if the given transaction was committed and a new one |
3795 | * started, and 0 otherwise in the committed parameter. | 3659 | * started, and 0 otherwise in the committed parameter. |
3796 | */ | 3660 | */ |
3797 | /*ARGSUSED*/ | ||
3798 | int /* error */ | 3661 | int /* error */ |
3799 | xfs_bmap_finish( | 3662 | xfs_bmap_finish( |
3800 | xfs_trans_t **tp, /* transaction pointer addr */ | 3663 | xfs_trans_t **tp, /* transaction pointer addr */ |
@@ -3994,42 +3857,122 @@ xfs_bmap_last_before( | |||
3994 | return 0; | 3857 | return 0; |
3995 | } | 3858 | } |
3996 | 3859 | ||
3860 | STATIC int | ||
3861 | xfs_bmap_last_extent( | ||
3862 | struct xfs_trans *tp, | ||
3863 | struct xfs_inode *ip, | ||
3864 | int whichfork, | ||
3865 | struct xfs_bmbt_irec *rec, | ||
3866 | int *is_empty) | ||
3867 | { | ||
3868 | struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); | ||
3869 | int error; | ||
3870 | int nextents; | ||
3871 | |||
3872 | if (!(ifp->if_flags & XFS_IFEXTENTS)) { | ||
3873 | error = xfs_iread_extents(tp, ip, whichfork); | ||
3874 | if (error) | ||
3875 | return error; | ||
3876 | } | ||
3877 | |||
3878 | nextents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); | ||
3879 | if (nextents == 0) { | ||
3880 | *is_empty = 1; | ||
3881 | return 0; | ||
3882 | } | ||
3883 | |||
3884 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, nextents - 1), rec); | ||
3885 | *is_empty = 0; | ||
3886 | return 0; | ||
3887 | } | ||
3888 | |||
3889 | /* | ||
3890 | * Check the last inode extent to determine whether this allocation will result | ||
3891 | * in blocks being allocated at the end of the file. When we allocate new data | ||
3892 | * blocks at the end of the file which do not start at the previous data block, | ||
3893 | * we will try to align the new blocks at stripe unit boundaries. | ||
3894 | * | ||
3895 | * Returns 0 in bma->aeof if the file (fork) is empty as any new write will be | ||
3896 | * at, or past the EOF. | ||
3897 | */ | ||
3898 | STATIC int | ||
3899 | xfs_bmap_isaeof( | ||
3900 | struct xfs_bmalloca *bma, | ||
3901 | int whichfork) | ||
3902 | { | ||
3903 | struct xfs_bmbt_irec rec; | ||
3904 | int is_empty; | ||
3905 | int error; | ||
3906 | |||
3907 | bma->aeof = 0; | ||
3908 | error = xfs_bmap_last_extent(NULL, bma->ip, whichfork, &rec, | ||
3909 | &is_empty); | ||
3910 | if (error || is_empty) | ||
3911 | return error; | ||
3912 | |||
3913 | /* | ||
3914 | * Check if we are allocation or past the last extent, or at least into | ||
3915 | * the last delayed allocated extent. | ||
3916 | */ | ||
3917 | bma->aeof = bma->offset >= rec.br_startoff + rec.br_blockcount || | ||
3918 | (bma->offset >= rec.br_startoff && | ||
3919 | isnullstartblock(rec.br_startblock)); | ||
3920 | return 0; | ||
3921 | } | ||
3922 | |||
3923 | /* | ||
3924 | * Check if the endoff is outside the last extent. If so the caller will grow | ||
3925 | * the allocation to a stripe unit boundary. All offsets are considered outside | ||
3926 | * the end of file for an empty fork, so 1 is returned in *eof in that case. | ||
3927 | */ | ||
3928 | int | ||
3929 | xfs_bmap_eof( | ||
3930 | struct xfs_inode *ip, | ||
3931 | xfs_fileoff_t endoff, | ||
3932 | int whichfork, | ||
3933 | int *eof) | ||
3934 | { | ||
3935 | struct xfs_bmbt_irec rec; | ||
3936 | int error; | ||
3937 | |||
3938 | error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, eof); | ||
3939 | if (error || *eof) | ||
3940 | return error; | ||
3941 | |||
3942 | *eof = endoff >= rec.br_startoff + rec.br_blockcount; | ||
3943 | return 0; | ||
3944 | } | ||
3945 | |||
3997 | /* | 3946 | /* |
3998 | * Returns the file-relative block number of the first block past eof in | 3947 | * Returns the file-relative block number of the first block past eof in |
3999 | * the file. This is not based on i_size, it is based on the extent records. | 3948 | * the file. This is not based on i_size, it is based on the extent records. |
4000 | * Returns 0 for local files, as they do not have extent records. | 3949 | * Returns 0 for local files, as they do not have extent records. |
4001 | */ | 3950 | */ |
4002 | int /* error */ | 3951 | int |
4003 | xfs_bmap_last_offset( | 3952 | xfs_bmap_last_offset( |
4004 | xfs_trans_t *tp, /* transaction pointer */ | 3953 | struct xfs_trans *tp, |
4005 | xfs_inode_t *ip, /* incore inode */ | 3954 | struct xfs_inode *ip, |
4006 | xfs_fileoff_t *last_block, /* last block */ | 3955 | xfs_fileoff_t *last_block, |
4007 | int whichfork) /* data or attr fork */ | 3956 | int whichfork) |
4008 | { | 3957 | { |
4009 | xfs_bmbt_rec_host_t *ep; /* pointer to last extent */ | 3958 | struct xfs_bmbt_irec rec; |
4010 | int error; /* error return value */ | 3959 | int is_empty; |
4011 | xfs_ifork_t *ifp; /* inode fork pointer */ | 3960 | int error; |
4012 | xfs_extnum_t nextents; /* number of extent entries */ | 3961 | |
3962 | *last_block = 0; | ||
3963 | |||
3964 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) | ||
3965 | return 0; | ||
4013 | 3966 | ||
4014 | if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && | 3967 | if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && |
4015 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && | 3968 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) |
4016 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL) | ||
4017 | return XFS_ERROR(EIO); | 3969 | return XFS_ERROR(EIO); |
4018 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { | 3970 | |
4019 | *last_block = 0; | 3971 | error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty); |
4020 | return 0; | 3972 | if (error || is_empty) |
4021 | } | ||
4022 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
4023 | if (!(ifp->if_flags & XFS_IFEXTENTS) && | ||
4024 | (error = xfs_iread_extents(tp, ip, whichfork))) | ||
4025 | return error; | 3973 | return error; |
4026 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | 3974 | |
4027 | if (!nextents) { | 3975 | *last_block = rec.br_startoff + rec.br_blockcount; |
4028 | *last_block = 0; | ||
4029 | return 0; | ||
4030 | } | ||
4031 | ep = xfs_iext_get_ext(ifp, nextents - 1); | ||
4032 | *last_block = xfs_bmbt_get_startoff(ep) + xfs_bmbt_get_blockcount(ep); | ||
4033 | return 0; | 3976 | return 0; |
4034 | } | 3977 | } |
4035 | 3978 | ||
@@ -4159,7 +4102,6 @@ xfs_bmap_read_extents( | |||
4159 | xfs_extnum_t num_recs; | 4102 | xfs_extnum_t num_recs; |
4160 | xfs_extnum_t start; | 4103 | xfs_extnum_t start; |
4161 | 4104 | ||
4162 | |||
4163 | num_recs = xfs_btree_get_numrecs(block); | 4105 | num_recs = xfs_btree_get_numrecs(block); |
4164 | if (unlikely(i + num_recs > room)) { | 4106 | if (unlikely(i + num_recs > room)) { |
4165 | ASSERT(i + num_recs <= room); | 4107 | ASSERT(i + num_recs <= room); |
@@ -4282,9 +4224,8 @@ xfs_bmap_validate_ret( | |||
4282 | ASSERT(i == 0 || | 4224 | ASSERT(i == 0 || |
4283 | mval[i - 1].br_startoff + mval[i - 1].br_blockcount == | 4225 | mval[i - 1].br_startoff + mval[i - 1].br_blockcount == |
4284 | mval[i].br_startoff); | 4226 | mval[i].br_startoff); |
4285 | if ((flags & XFS_BMAPI_WRITE) && !(flags & XFS_BMAPI_DELAY)) | 4227 | ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK && |
4286 | ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK && | 4228 | mval[i].br_startblock != HOLESTARTBLOCK); |
4287 | mval[i].br_startblock != HOLESTARTBLOCK); | ||
4288 | ASSERT(mval[i].br_state == XFS_EXT_NORM || | 4229 | ASSERT(mval[i].br_state == XFS_EXT_NORM || |
4289 | mval[i].br_state == XFS_EXT_UNWRITTEN); | 4230 | mval[i].br_state == XFS_EXT_UNWRITTEN); |
4290 | } | 4231 | } |
@@ -4293,66 +4234,609 @@ xfs_bmap_validate_ret( | |||
4293 | 4234 | ||
4294 | 4235 | ||
4295 | /* | 4236 | /* |
4296 | * Map file blocks to filesystem blocks. | 4237 | * Trim the returned map to the required bounds |
4297 | * File range is given by the bno/len pair. | 4238 | */ |
4298 | * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set) | 4239 | STATIC void |
4299 | * into a hole or past eof. | 4240 | xfs_bmapi_trim_map( |
4300 | * Only allocates blocks from a single allocation group, | 4241 | struct xfs_bmbt_irec *mval, |
4301 | * to avoid locking problems. | 4242 | struct xfs_bmbt_irec *got, |
4243 | xfs_fileoff_t *bno, | ||
4244 | xfs_filblks_t len, | ||
4245 | xfs_fileoff_t obno, | ||
4246 | xfs_fileoff_t end, | ||
4247 | int n, | ||
4248 | int flags) | ||
4249 | { | ||
4250 | if ((flags & XFS_BMAPI_ENTIRE) || | ||
4251 | got->br_startoff + got->br_blockcount <= obno) { | ||
4252 | *mval = *got; | ||
4253 | if (isnullstartblock(got->br_startblock)) | ||
4254 | mval->br_startblock = DELAYSTARTBLOCK; | ||
4255 | return; | ||
4256 | } | ||
4257 | |||
4258 | if (obno > *bno) | ||
4259 | *bno = obno; | ||
4260 | ASSERT((*bno >= obno) || (n == 0)); | ||
4261 | ASSERT(*bno < end); | ||
4262 | mval->br_startoff = *bno; | ||
4263 | if (isnullstartblock(got->br_startblock)) | ||
4264 | mval->br_startblock = DELAYSTARTBLOCK; | ||
4265 | else | ||
4266 | mval->br_startblock = got->br_startblock + | ||
4267 | (*bno - got->br_startoff); | ||
4268 | /* | ||
4269 | * Return the minimum of what we got and what we asked for for | ||
4270 | * the length. We can use the len variable here because it is | ||
4271 | * modified below and we could have been there before coming | ||
4272 | * here if the first part of the allocation didn't overlap what | ||
4273 | * was asked for. | ||
4274 | */ | ||
4275 | mval->br_blockcount = XFS_FILBLKS_MIN(end - *bno, | ||
4276 | got->br_blockcount - (*bno - got->br_startoff)); | ||
4277 | mval->br_state = got->br_state; | ||
4278 | ASSERT(mval->br_blockcount <= len); | ||
4279 | return; | ||
4280 | } | ||
4281 | |||
4282 | /* | ||
4283 | * Update and validate the extent map to return | ||
4284 | */ | ||
4285 | STATIC void | ||
4286 | xfs_bmapi_update_map( | ||
4287 | struct xfs_bmbt_irec **map, | ||
4288 | xfs_fileoff_t *bno, | ||
4289 | xfs_filblks_t *len, | ||
4290 | xfs_fileoff_t obno, | ||
4291 | xfs_fileoff_t end, | ||
4292 | int *n, | ||
4293 | int flags) | ||
4294 | { | ||
4295 | xfs_bmbt_irec_t *mval = *map; | ||
4296 | |||
4297 | ASSERT((flags & XFS_BMAPI_ENTIRE) || | ||
4298 | ((mval->br_startoff + mval->br_blockcount) <= end)); | ||
4299 | ASSERT((flags & XFS_BMAPI_ENTIRE) || (mval->br_blockcount <= *len) || | ||
4300 | (mval->br_startoff < obno)); | ||
4301 | |||
4302 | *bno = mval->br_startoff + mval->br_blockcount; | ||
4303 | *len = end - *bno; | ||
4304 | if (*n > 0 && mval->br_startoff == mval[-1].br_startoff) { | ||
4305 | /* update previous map with new information */ | ||
4306 | ASSERT(mval->br_startblock == mval[-1].br_startblock); | ||
4307 | ASSERT(mval->br_blockcount > mval[-1].br_blockcount); | ||
4308 | ASSERT(mval->br_state == mval[-1].br_state); | ||
4309 | mval[-1].br_blockcount = mval->br_blockcount; | ||
4310 | mval[-1].br_state = mval->br_state; | ||
4311 | } else if (*n > 0 && mval->br_startblock != DELAYSTARTBLOCK && | ||
4312 | mval[-1].br_startblock != DELAYSTARTBLOCK && | ||
4313 | mval[-1].br_startblock != HOLESTARTBLOCK && | ||
4314 | mval->br_startblock == mval[-1].br_startblock + | ||
4315 | mval[-1].br_blockcount && | ||
4316 | ((flags & XFS_BMAPI_IGSTATE) || | ||
4317 | mval[-1].br_state == mval->br_state)) { | ||
4318 | ASSERT(mval->br_startoff == | ||
4319 | mval[-1].br_startoff + mval[-1].br_blockcount); | ||
4320 | mval[-1].br_blockcount += mval->br_blockcount; | ||
4321 | } else if (*n > 0 && | ||
4322 | mval->br_startblock == DELAYSTARTBLOCK && | ||
4323 | mval[-1].br_startblock == DELAYSTARTBLOCK && | ||
4324 | mval->br_startoff == | ||
4325 | mval[-1].br_startoff + mval[-1].br_blockcount) { | ||
4326 | mval[-1].br_blockcount += mval->br_blockcount; | ||
4327 | mval[-1].br_state = mval->br_state; | ||
4328 | } else if (!((*n == 0) && | ||
4329 | ((mval->br_startoff + mval->br_blockcount) <= | ||
4330 | obno))) { | ||
4331 | mval++; | ||
4332 | (*n)++; | ||
4333 | } | ||
4334 | *map = mval; | ||
4335 | } | ||
4336 | |||
4337 | /* | ||
4338 | * Map file blocks to filesystem blocks without allocation. | ||
4339 | */ | ||
4340 | int | ||
4341 | xfs_bmapi_read( | ||
4342 | struct xfs_inode *ip, | ||
4343 | xfs_fileoff_t bno, | ||
4344 | xfs_filblks_t len, | ||
4345 | struct xfs_bmbt_irec *mval, | ||
4346 | int *nmap, | ||
4347 | int flags) | ||
4348 | { | ||
4349 | struct xfs_mount *mp = ip->i_mount; | ||
4350 | struct xfs_ifork *ifp; | ||
4351 | struct xfs_bmbt_irec got; | ||
4352 | struct xfs_bmbt_irec prev; | ||
4353 | xfs_fileoff_t obno; | ||
4354 | xfs_fileoff_t end; | ||
4355 | xfs_extnum_t lastx; | ||
4356 | int error; | ||
4357 | int eof; | ||
4358 | int n = 0; | ||
4359 | int whichfork = (flags & XFS_BMAPI_ATTRFORK) ? | ||
4360 | XFS_ATTR_FORK : XFS_DATA_FORK; | ||
4361 | |||
4362 | ASSERT(*nmap >= 1); | ||
4363 | ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK|XFS_BMAPI_ENTIRE| | ||
4364 | XFS_BMAPI_IGSTATE))); | ||
4365 | |||
4366 | if (unlikely(XFS_TEST_ERROR( | ||
4367 | (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && | ||
4368 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), | ||
4369 | mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { | ||
4370 | XFS_ERROR_REPORT("xfs_bmapi_read", XFS_ERRLEVEL_LOW, mp); | ||
4371 | return XFS_ERROR(EFSCORRUPTED); | ||
4372 | } | ||
4373 | |||
4374 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
4375 | return XFS_ERROR(EIO); | ||
4376 | |||
4377 | XFS_STATS_INC(xs_blk_mapr); | ||
4378 | |||
4379 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
4380 | ASSERT(ifp->if_ext_max == | ||
4381 | XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); | ||
4382 | |||
4383 | if (!(ifp->if_flags & XFS_IFEXTENTS)) { | ||
4384 | error = xfs_iread_extents(NULL, ip, whichfork); | ||
4385 | if (error) | ||
4386 | return error; | ||
4387 | } | ||
4388 | |||
4389 | xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev); | ||
4390 | end = bno + len; | ||
4391 | obno = bno; | ||
4392 | |||
4393 | while (bno < end && n < *nmap) { | ||
4394 | /* Reading past eof, act as though there's a hole up to end. */ | ||
4395 | if (eof) | ||
4396 | got.br_startoff = end; | ||
4397 | if (got.br_startoff > bno) { | ||
4398 | /* Reading in a hole. */ | ||
4399 | mval->br_startoff = bno; | ||
4400 | mval->br_startblock = HOLESTARTBLOCK; | ||
4401 | mval->br_blockcount = | ||
4402 | XFS_FILBLKS_MIN(len, got.br_startoff - bno); | ||
4403 | mval->br_state = XFS_EXT_NORM; | ||
4404 | bno += mval->br_blockcount; | ||
4405 | len -= mval->br_blockcount; | ||
4406 | mval++; | ||
4407 | n++; | ||
4408 | continue; | ||
4409 | } | ||
4410 | |||
4411 | /* set up the extent map to return. */ | ||
4412 | xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags); | ||
4413 | xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags); | ||
4414 | |||
4415 | /* If we're done, stop now. */ | ||
4416 | if (bno >= end || n >= *nmap) | ||
4417 | break; | ||
4418 | |||
4419 | /* Else go on to the next record. */ | ||
4420 | if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) | ||
4421 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx), &got); | ||
4422 | else | ||
4423 | eof = 1; | ||
4424 | } | ||
4425 | *nmap = n; | ||
4426 | return 0; | ||
4427 | } | ||
4428 | |||
4429 | STATIC int | ||
4430 | xfs_bmapi_reserve_delalloc( | ||
4431 | struct xfs_inode *ip, | ||
4432 | xfs_fileoff_t aoff, | ||
4433 | xfs_filblks_t len, | ||
4434 | struct xfs_bmbt_irec *got, | ||
4435 | struct xfs_bmbt_irec *prev, | ||
4436 | xfs_extnum_t *lastx, | ||
4437 | int eof) | ||
4438 | { | ||
4439 | struct xfs_mount *mp = ip->i_mount; | ||
4440 | struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); | ||
4441 | xfs_extlen_t alen; | ||
4442 | xfs_extlen_t indlen; | ||
4443 | char rt = XFS_IS_REALTIME_INODE(ip); | ||
4444 | xfs_extlen_t extsz; | ||
4445 | int error; | ||
4446 | |||
4447 | alen = XFS_FILBLKS_MIN(len, MAXEXTLEN); | ||
4448 | if (!eof) | ||
4449 | alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff); | ||
4450 | |||
4451 | /* Figure out the extent size, adjust alen */ | ||
4452 | extsz = xfs_get_extsz_hint(ip); | ||
4453 | if (extsz) { | ||
4454 | /* | ||
4455 | * Make sure we don't exceed a single extent length when we | ||
4456 | * align the extent by reducing length we are going to | ||
4457 | * allocate by the maximum amount extent size aligment may | ||
4458 | * require. | ||
4459 | */ | ||
4460 | alen = XFS_FILBLKS_MIN(len, MAXEXTLEN - (2 * extsz - 1)); | ||
4461 | error = xfs_bmap_extsize_align(mp, got, prev, extsz, rt, eof, | ||
4462 | 1, 0, &aoff, &alen); | ||
4463 | ASSERT(!error); | ||
4464 | } | ||
4465 | |||
4466 | if (rt) | ||
4467 | extsz = alen / mp->m_sb.sb_rextsize; | ||
4468 | |||
4469 | /* | ||
4470 | * Make a transaction-less quota reservation for delayed allocation | ||
4471 | * blocks. This number gets adjusted later. We return if we haven't | ||
4472 | * allocated blocks already inside this loop. | ||
4473 | */ | ||
4474 | error = xfs_trans_reserve_quota_nblks(NULL, ip, (long)alen, 0, | ||
4475 | rt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); | ||
4476 | if (error) | ||
4477 | return error; | ||
4478 | |||
4479 | /* | ||
4480 | * Split changing sb for alen and indlen since they could be coming | ||
4481 | * from different places. | ||
4482 | */ | ||
4483 | indlen = (xfs_extlen_t)xfs_bmap_worst_indlen(ip, alen); | ||
4484 | ASSERT(indlen > 0); | ||
4485 | |||
4486 | if (rt) { | ||
4487 | error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, | ||
4488 | -((int64_t)extsz), 0); | ||
4489 | } else { | ||
4490 | error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, | ||
4491 | -((int64_t)alen), 0); | ||
4492 | } | ||
4493 | |||
4494 | if (error) | ||
4495 | goto out_unreserve_quota; | ||
4496 | |||
4497 | error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, | ||
4498 | -((int64_t)indlen), 0); | ||
4499 | if (error) | ||
4500 | goto out_unreserve_blocks; | ||
4501 | |||
4502 | |||
4503 | ip->i_delayed_blks += alen; | ||
4504 | |||
4505 | got->br_startoff = aoff; | ||
4506 | got->br_startblock = nullstartblock(indlen); | ||
4507 | got->br_blockcount = alen; | ||
4508 | got->br_state = XFS_EXT_NORM; | ||
4509 | xfs_bmap_add_extent_hole_delay(ip, lastx, got); | ||
4510 | |||
4511 | /* | ||
4512 | * Update our extent pointer, given that xfs_bmap_add_extent_hole_delay | ||
4513 | * might have merged it into one of the neighbouring ones. | ||
4514 | */ | ||
4515 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got); | ||
4516 | |||
4517 | ASSERT(got->br_startoff <= aoff); | ||
4518 | ASSERT(got->br_startoff + got->br_blockcount >= aoff + alen); | ||
4519 | ASSERT(isnullstartblock(got->br_startblock)); | ||
4520 | ASSERT(got->br_state == XFS_EXT_NORM); | ||
4521 | return 0; | ||
4522 | |||
4523 | out_unreserve_blocks: | ||
4524 | if (rt) | ||
4525 | xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, 0); | ||
4526 | else | ||
4527 | xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, alen, 0); | ||
4528 | out_unreserve_quota: | ||
4529 | if (XFS_IS_QUOTA_ON(mp)) | ||
4530 | xfs_trans_unreserve_quota_nblks(NULL, ip, alen, 0, rt ? | ||
4531 | XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); | ||
4532 | return error; | ||
4533 | } | ||
4534 | |||
4535 | /* | ||
4536 | * Map file blocks to filesystem blocks, adding delayed allocations as needed. | ||
4537 | */ | ||
4538 | int | ||
4539 | xfs_bmapi_delay( | ||
4540 | struct xfs_inode *ip, /* incore inode */ | ||
4541 | xfs_fileoff_t bno, /* starting file offs. mapped */ | ||
4542 | xfs_filblks_t len, /* length to map in file */ | ||
4543 | struct xfs_bmbt_irec *mval, /* output: map values */ | ||
4544 | int *nmap, /* i/o: mval size/count */ | ||
4545 | int flags) /* XFS_BMAPI_... */ | ||
4546 | { | ||
4547 | struct xfs_mount *mp = ip->i_mount; | ||
4548 | struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); | ||
4549 | struct xfs_bmbt_irec got; /* current file extent record */ | ||
4550 | struct xfs_bmbt_irec prev; /* previous file extent record */ | ||
4551 | xfs_fileoff_t obno; /* old block number (offset) */ | ||
4552 | xfs_fileoff_t end; /* end of mapped file region */ | ||
4553 | xfs_extnum_t lastx; /* last useful extent number */ | ||
4554 | int eof; /* we've hit the end of extents */ | ||
4555 | int n = 0; /* current extent index */ | ||
4556 | int error = 0; | ||
4557 | |||
4558 | ASSERT(*nmap >= 1); | ||
4559 | ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); | ||
4560 | ASSERT(!(flags & ~XFS_BMAPI_ENTIRE)); | ||
4561 | |||
4562 | if (unlikely(XFS_TEST_ERROR( | ||
4563 | (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_EXTENTS && | ||
4564 | XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_BTREE), | ||
4565 | mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { | ||
4566 | XFS_ERROR_REPORT("xfs_bmapi_delay", XFS_ERRLEVEL_LOW, mp); | ||
4567 | return XFS_ERROR(EFSCORRUPTED); | ||
4568 | } | ||
4569 | |||
4570 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
4571 | return XFS_ERROR(EIO); | ||
4572 | |||
4573 | XFS_STATS_INC(xs_blk_mapw); | ||
4574 | |||
4575 | if (!(ifp->if_flags & XFS_IFEXTENTS)) { | ||
4576 | error = xfs_iread_extents(NULL, ip, XFS_DATA_FORK); | ||
4577 | if (error) | ||
4578 | return error; | ||
4579 | } | ||
4580 | |||
4581 | xfs_bmap_search_extents(ip, bno, XFS_DATA_FORK, &eof, &lastx, &got, &prev); | ||
4582 | end = bno + len; | ||
4583 | obno = bno; | ||
4584 | |||
4585 | while (bno < end && n < *nmap) { | ||
4586 | if (eof || got.br_startoff > bno) { | ||
4587 | error = xfs_bmapi_reserve_delalloc(ip, bno, len, &got, | ||
4588 | &prev, &lastx, eof); | ||
4589 | if (error) { | ||
4590 | if (n == 0) { | ||
4591 | *nmap = 0; | ||
4592 | return error; | ||
4593 | } | ||
4594 | break; | ||
4595 | } | ||
4596 | } | ||
4597 | |||
4598 | /* set up the extent map to return. */ | ||
4599 | xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags); | ||
4600 | xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags); | ||
4601 | |||
4602 | /* If we're done, stop now. */ | ||
4603 | if (bno >= end || n >= *nmap) | ||
4604 | break; | ||
4605 | |||
4606 | /* Else go on to the next record. */ | ||
4607 | prev = got; | ||
4608 | if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) | ||
4609 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx), &got); | ||
4610 | else | ||
4611 | eof = 1; | ||
4612 | } | ||
4613 | |||
4614 | *nmap = n; | ||
4615 | return 0; | ||
4616 | } | ||
4617 | |||
4618 | |||
4619 | STATIC int | ||
4620 | xfs_bmapi_allocate( | ||
4621 | struct xfs_bmalloca *bma, | ||
4622 | int flags) | ||
4623 | { | ||
4624 | struct xfs_mount *mp = bma->ip->i_mount; | ||
4625 | int whichfork = (flags & XFS_BMAPI_ATTRFORK) ? | ||
4626 | XFS_ATTR_FORK : XFS_DATA_FORK; | ||
4627 | struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork); | ||
4628 | int tmp_logflags = 0; | ||
4629 | int error; | ||
4630 | int rt; | ||
4631 | |||
4632 | rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(bma->ip); | ||
4633 | |||
4634 | /* | ||
4635 | * For the wasdelay case, we could also just allocate the stuff asked | ||
4636 | * for in this bmap call but that wouldn't be as good. | ||
4637 | */ | ||
4638 | if (bma->wasdel) { | ||
4639 | bma->length = (xfs_extlen_t)bma->got.br_blockcount; | ||
4640 | bma->offset = bma->got.br_startoff; | ||
4641 | if (bma->idx != NULLEXTNUM && bma->idx) { | ||
4642 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1), | ||
4643 | &bma->prev); | ||
4644 | } | ||
4645 | } else { | ||
4646 | bma->length = XFS_FILBLKS_MIN(bma->length, MAXEXTLEN); | ||
4647 | if (!bma->eof) | ||
4648 | bma->length = XFS_FILBLKS_MIN(bma->length, | ||
4649 | bma->got.br_startoff - bma->offset); | ||
4650 | } | ||
4651 | |||
4652 | /* | ||
4653 | * Indicate if this is the first user data in the file, or just any | ||
4654 | * user data. | ||
4655 | */ | ||
4656 | if (!(flags & XFS_BMAPI_METADATA)) { | ||
4657 | bma->userdata = (bma->offset == 0) ? | ||
4658 | XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA; | ||
4659 | } | ||
4660 | |||
4661 | bma->minlen = (flags & XFS_BMAPI_CONTIG) ? bma->length : 1; | ||
4662 | |||
4663 | /* | ||
4664 | * Only want to do the alignment at the eof if it is userdata and | ||
4665 | * allocation length is larger than a stripe unit. | ||
4666 | */ | ||
4667 | if (mp->m_dalign && bma->length >= mp->m_dalign && | ||
4668 | !(flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) { | ||
4669 | error = xfs_bmap_isaeof(bma, whichfork); | ||
4670 | if (error) | ||
4671 | return error; | ||
4672 | } | ||
4673 | |||
4674 | error = xfs_bmap_alloc(bma); | ||
4675 | if (error) | ||
4676 | return error; | ||
4677 | |||
4678 | if (bma->flist->xbf_low) | ||
4679 | bma->minleft = 0; | ||
4680 | if (bma->cur) | ||
4681 | bma->cur->bc_private.b.firstblock = *bma->firstblock; | ||
4682 | if (bma->blkno == NULLFSBLOCK) | ||
4683 | return 0; | ||
4684 | if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) { | ||
4685 | bma->cur = xfs_bmbt_init_cursor(mp, bma->tp, bma->ip, whichfork); | ||
4686 | bma->cur->bc_private.b.firstblock = *bma->firstblock; | ||
4687 | bma->cur->bc_private.b.flist = bma->flist; | ||
4688 | } | ||
4689 | /* | ||
4690 | * Bump the number of extents we've allocated | ||
4691 | * in this call. | ||
4692 | */ | ||
4693 | bma->nallocs++; | ||
4694 | |||
4695 | if (bma->cur) | ||
4696 | bma->cur->bc_private.b.flags = | ||
4697 | bma->wasdel ? XFS_BTCUR_BPRV_WASDEL : 0; | ||
4698 | |||
4699 | bma->got.br_startoff = bma->offset; | ||
4700 | bma->got.br_startblock = bma->blkno; | ||
4701 | bma->got.br_blockcount = bma->length; | ||
4702 | bma->got.br_state = XFS_EXT_NORM; | ||
4703 | |||
4704 | /* | ||
4705 | * A wasdelay extent has been initialized, so shouldn't be flagged | ||
4706 | * as unwritten. | ||
4707 | */ | ||
4708 | if (!bma->wasdel && (flags & XFS_BMAPI_PREALLOC) && | ||
4709 | xfs_sb_version_hasextflgbit(&mp->m_sb)) | ||
4710 | bma->got.br_state = XFS_EXT_UNWRITTEN; | ||
4711 | |||
4712 | if (bma->wasdel) | ||
4713 | error = xfs_bmap_add_extent_delay_real(bma); | ||
4714 | else | ||
4715 | error = xfs_bmap_add_extent_hole_real(bma, whichfork); | ||
4716 | |||
4717 | bma->logflags |= tmp_logflags; | ||
4718 | if (error) | ||
4719 | return error; | ||
4720 | |||
4721 | /* | ||
4722 | * Update our extent pointer, given that xfs_bmap_add_extent_delay_real | ||
4723 | * or xfs_bmap_add_extent_hole_real might have merged it into one of | ||
4724 | * the neighbouring ones. | ||
4725 | */ | ||
4726 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &bma->got); | ||
4727 | |||
4728 | ASSERT(bma->got.br_startoff <= bma->offset); | ||
4729 | ASSERT(bma->got.br_startoff + bma->got.br_blockcount >= | ||
4730 | bma->offset + bma->length); | ||
4731 | ASSERT(bma->got.br_state == XFS_EXT_NORM || | ||
4732 | bma->got.br_state == XFS_EXT_UNWRITTEN); | ||
4733 | return 0; | ||
4734 | } | ||
4735 | |||
4736 | STATIC int | ||
4737 | xfs_bmapi_convert_unwritten( | ||
4738 | struct xfs_bmalloca *bma, | ||
4739 | struct xfs_bmbt_irec *mval, | ||
4740 | xfs_filblks_t len, | ||
4741 | int flags) | ||
4742 | { | ||
4743 | int whichfork = (flags & XFS_BMAPI_ATTRFORK) ? | ||
4744 | XFS_ATTR_FORK : XFS_DATA_FORK; | ||
4745 | struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork); | ||
4746 | int tmp_logflags = 0; | ||
4747 | int error; | ||
4748 | |||
4749 | /* check if we need to do unwritten->real conversion */ | ||
4750 | if (mval->br_state == XFS_EXT_UNWRITTEN && | ||
4751 | (flags & XFS_BMAPI_PREALLOC)) | ||
4752 | return 0; | ||
4753 | |||
4754 | /* check if we need to do real->unwritten conversion */ | ||
4755 | if (mval->br_state == XFS_EXT_NORM && | ||
4756 | (flags & (XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT)) != | ||
4757 | (XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT)) | ||
4758 | return 0; | ||
4759 | |||
4760 | /* | ||
4761 | * Modify (by adding) the state flag, if writing. | ||
4762 | */ | ||
4763 | ASSERT(mval->br_blockcount <= len); | ||
4764 | if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) { | ||
4765 | bma->cur = xfs_bmbt_init_cursor(bma->ip->i_mount, bma->tp, | ||
4766 | bma->ip, whichfork); | ||
4767 | bma->cur->bc_private.b.firstblock = *bma->firstblock; | ||
4768 | bma->cur->bc_private.b.flist = bma->flist; | ||
4769 | } | ||
4770 | mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN) | ||
4771 | ? XFS_EXT_NORM : XFS_EXT_UNWRITTEN; | ||
4772 | |||
4773 | error = xfs_bmap_add_extent_unwritten_real(bma->tp, bma->ip, &bma->idx, | ||
4774 | &bma->cur, mval, bma->firstblock, bma->flist, | ||
4775 | &tmp_logflags); | ||
4776 | bma->logflags |= tmp_logflags; | ||
4777 | if (error) | ||
4778 | return error; | ||
4779 | |||
4780 | /* | ||
4781 | * Update our extent pointer, given that | ||
4782 | * xfs_bmap_add_extent_unwritten_real might have merged it into one | ||
4783 | * of the neighbouring ones. | ||
4784 | */ | ||
4785 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &bma->got); | ||
4786 | |||
4787 | /* | ||
4788 | * We may have combined previously unwritten space with written space, | ||
4789 | * so generate another request. | ||
4790 | */ | ||
4791 | if (mval->br_blockcount < len) | ||
4792 | return EAGAIN; | ||
4793 | return 0; | ||
4794 | } | ||
4795 | |||
4796 | /* | ||
4797 | * Map file blocks to filesystem blocks, and allocate blocks or convert the | ||
4798 | * extent state if necessary. Details behaviour is controlled by the flags | ||
4799 | * parameter. Only allocates blocks from a single allocation group, to avoid | ||
4800 | * locking problems. | ||
4801 | * | ||
4302 | * The returned value in "firstblock" from the first call in a transaction | 4802 | * The returned value in "firstblock" from the first call in a transaction |
4303 | * must be remembered and presented to subsequent calls in "firstblock". | 4803 | * must be remembered and presented to subsequent calls in "firstblock". |
4304 | * An upper bound for the number of blocks to be allocated is supplied to | 4804 | * An upper bound for the number of blocks to be allocated is supplied to |
4305 | * the first call in "total"; if no allocation group has that many free | 4805 | * the first call in "total"; if no allocation group has that many free |
4306 | * blocks then the call will fail (return NULLFSBLOCK in "firstblock"). | 4806 | * blocks then the call will fail (return NULLFSBLOCK in "firstblock"). |
4307 | */ | 4807 | */ |
4308 | int /* error */ | 4808 | int |
4309 | xfs_bmapi( | 4809 | xfs_bmapi_write( |
4310 | xfs_trans_t *tp, /* transaction pointer */ | 4810 | struct xfs_trans *tp, /* transaction pointer */ |
4311 | xfs_inode_t *ip, /* incore inode */ | 4811 | struct xfs_inode *ip, /* incore inode */ |
4312 | xfs_fileoff_t bno, /* starting file offs. mapped */ | 4812 | xfs_fileoff_t bno, /* starting file offs. mapped */ |
4313 | xfs_filblks_t len, /* length to map in file */ | 4813 | xfs_filblks_t len, /* length to map in file */ |
4314 | int flags, /* XFS_BMAPI_... */ | 4814 | int flags, /* XFS_BMAPI_... */ |
4315 | xfs_fsblock_t *firstblock, /* first allocated block | 4815 | xfs_fsblock_t *firstblock, /* first allocated block |
4316 | controls a.g. for allocs */ | 4816 | controls a.g. for allocs */ |
4317 | xfs_extlen_t total, /* total blocks needed */ | 4817 | xfs_extlen_t total, /* total blocks needed */ |
4318 | xfs_bmbt_irec_t *mval, /* output: map values */ | 4818 | struct xfs_bmbt_irec *mval, /* output: map values */ |
4319 | int *nmap, /* i/o: mval size/count */ | 4819 | int *nmap, /* i/o: mval size/count */ |
4320 | xfs_bmap_free_t *flist) /* i/o: list extents to free */ | 4820 | struct xfs_bmap_free *flist) /* i/o: list extents to free */ |
4321 | { | 4821 | { |
4322 | xfs_fsblock_t abno; /* allocated block number */ | 4822 | struct xfs_mount *mp = ip->i_mount; |
4323 | xfs_extlen_t alen; /* allocated extent length */ | 4823 | struct xfs_ifork *ifp; |
4324 | xfs_fileoff_t aoff; /* allocated file offset */ | 4824 | struct xfs_bmalloca bma = { 0 }; /* args for xfs_bmap_alloc */ |
4325 | xfs_bmalloca_t bma = { 0 }; /* args for xfs_bmap_alloc */ | 4825 | xfs_fileoff_t end; /* end of mapped file region */ |
4326 | xfs_btree_cur_t *cur; /* bmap btree cursor */ | 4826 | int eof; /* after the end of extents */ |
4327 | xfs_fileoff_t end; /* end of mapped file region */ | 4827 | int error; /* error return */ |
4328 | int eof; /* we've hit the end of extents */ | 4828 | int n; /* current extent index */ |
4329 | xfs_bmbt_rec_host_t *ep; /* extent record pointer */ | 4829 | xfs_fileoff_t obno; /* old block number (offset) */ |
4330 | int error; /* error return */ | 4830 | int whichfork; /* data or attr fork */ |
4331 | xfs_bmbt_irec_t got; /* current file extent record */ | 4831 | char inhole; /* current location is hole in file */ |
4332 | xfs_ifork_t *ifp; /* inode fork pointer */ | 4832 | char wasdelay; /* old extent was delayed */ |
4333 | xfs_extlen_t indlen; /* indirect blocks length */ | 4833 | |
4334 | xfs_extnum_t lastx; /* last useful extent number */ | ||
4335 | int logflags; /* flags for transaction logging */ | ||
4336 | xfs_extlen_t minleft; /* min blocks left after allocation */ | ||
4337 | xfs_extlen_t minlen; /* min allocation size */ | ||
4338 | xfs_mount_t *mp; /* xfs mount structure */ | ||
4339 | int n; /* current extent index */ | ||
4340 | int nallocs; /* number of extents alloc'd */ | ||
4341 | xfs_extnum_t nextents; /* number of extents in file */ | ||
4342 | xfs_fileoff_t obno; /* old block number (offset) */ | ||
4343 | xfs_bmbt_irec_t prev; /* previous file extent record */ | ||
4344 | int tmp_logflags; /* temp flags holder */ | ||
4345 | int whichfork; /* data or attr fork */ | ||
4346 | char inhole; /* current location is hole in file */ | ||
4347 | char wasdelay; /* old extent was delayed */ | ||
4348 | char wr; /* this is a write request */ | ||
4349 | char rt; /* this is a realtime file */ | ||
4350 | #ifdef DEBUG | 4834 | #ifdef DEBUG |
4351 | xfs_fileoff_t orig_bno; /* original block number value */ | 4835 | xfs_fileoff_t orig_bno; /* original block number value */ |
4352 | int orig_flags; /* original flags arg value */ | 4836 | int orig_flags; /* original flags arg value */ |
4353 | xfs_filblks_t orig_len; /* original value of len arg */ | 4837 | xfs_filblks_t orig_len; /* original value of len arg */ |
4354 | xfs_bmbt_irec_t *orig_mval; /* original value of mval */ | 4838 | struct xfs_bmbt_irec *orig_mval; /* original value of mval */ |
4355 | int orig_nmap; /* original value of *nmap */ | 4839 | int orig_nmap; /* original value of *nmap */ |
4356 | 4840 | ||
4357 | orig_bno = bno; | 4841 | orig_bno = bno; |
4358 | orig_len = len; | 4842 | orig_len = len; |
@@ -4360,488 +4844,133 @@ xfs_bmapi( | |||
4360 | orig_mval = mval; | 4844 | orig_mval = mval; |
4361 | orig_nmap = *nmap; | 4845 | orig_nmap = *nmap; |
4362 | #endif | 4846 | #endif |
4847 | |||
4363 | ASSERT(*nmap >= 1); | 4848 | ASSERT(*nmap >= 1); |
4364 | ASSERT(*nmap <= XFS_BMAP_MAX_NMAP || !(flags & XFS_BMAPI_WRITE)); | 4849 | ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); |
4850 | ASSERT(!(flags & XFS_BMAPI_IGSTATE)); | ||
4851 | ASSERT(tp != NULL); | ||
4852 | |||
4365 | whichfork = (flags & XFS_BMAPI_ATTRFORK) ? | 4853 | whichfork = (flags & XFS_BMAPI_ATTRFORK) ? |
4366 | XFS_ATTR_FORK : XFS_DATA_FORK; | 4854 | XFS_ATTR_FORK : XFS_DATA_FORK; |
4367 | mp = ip->i_mount; | 4855 | |
4368 | if (unlikely(XFS_TEST_ERROR( | 4856 | if (unlikely(XFS_TEST_ERROR( |
4369 | (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && | 4857 | (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && |
4370 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && | 4858 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && |
4371 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL), | 4859 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL), |
4372 | mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { | 4860 | mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { |
4373 | XFS_ERROR_REPORT("xfs_bmapi", XFS_ERRLEVEL_LOW, mp); | 4861 | XFS_ERROR_REPORT("xfs_bmapi_write", XFS_ERRLEVEL_LOW, mp); |
4374 | return XFS_ERROR(EFSCORRUPTED); | 4862 | return XFS_ERROR(EFSCORRUPTED); |
4375 | } | 4863 | } |
4864 | |||
4376 | if (XFS_FORCED_SHUTDOWN(mp)) | 4865 | if (XFS_FORCED_SHUTDOWN(mp)) |
4377 | return XFS_ERROR(EIO); | 4866 | return XFS_ERROR(EIO); |
4378 | rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip); | 4867 | |
4379 | ifp = XFS_IFORK_PTR(ip, whichfork); | 4868 | ifp = XFS_IFORK_PTR(ip, whichfork); |
4380 | ASSERT(ifp->if_ext_max == | 4869 | ASSERT(ifp->if_ext_max == |
4381 | XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); | 4870 | XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); |
4382 | if ((wr = (flags & XFS_BMAPI_WRITE)) != 0) | 4871 | |
4383 | XFS_STATS_INC(xs_blk_mapw); | 4872 | XFS_STATS_INC(xs_blk_mapw); |
4384 | else | 4873 | |
4385 | XFS_STATS_INC(xs_blk_mapr); | ||
4386 | /* | ||
4387 | * IGSTATE flag is used to combine extents which | ||
4388 | * differ only due to the state of the extents. | ||
4389 | * This technique is used from xfs_getbmap() | ||
4390 | * when the caller does not wish to see the | ||
4391 | * separation (which is the default). | ||
4392 | * | ||
4393 | * This technique is also used when writing a | ||
4394 | * buffer which has been partially written, | ||
4395 | * (usually by being flushed during a chunkread), | ||
4396 | * to ensure one write takes place. This also | ||
4397 | * prevents a change in the xfs inode extents at | ||
4398 | * this time, intentionally. This change occurs | ||
4399 | * on completion of the write operation, in | ||
4400 | * xfs_strat_comp(), where the xfs_bmapi() call | ||
4401 | * is transactioned, and the extents combined. | ||
4402 | */ | ||
4403 | if ((flags & XFS_BMAPI_IGSTATE) && wr) /* if writing unwritten space */ | ||
4404 | wr = 0; /* no allocations are allowed */ | ||
4405 | ASSERT(wr || !(flags & XFS_BMAPI_DELAY)); | ||
4406 | logflags = 0; | ||
4407 | nallocs = 0; | ||
4408 | cur = NULL; | ||
4409 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { | 4874 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { |
4410 | ASSERT(wr && tp); | 4875 | error = xfs_bmap_local_to_extents(tp, ip, firstblock, total, |
4411 | if ((error = xfs_bmap_local_to_extents(tp, ip, | 4876 | &bma.logflags, whichfork); |
4412 | firstblock, total, &logflags, whichfork))) | 4877 | if (error) |
4413 | goto error0; | 4878 | goto error0; |
4414 | } | 4879 | } |
4415 | if (wr && *firstblock == NULLFSBLOCK) { | 4880 | |
4881 | if (*firstblock == NULLFSBLOCK) { | ||
4416 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE) | 4882 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE) |
4417 | minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1; | 4883 | bma.minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1; |
4418 | else | 4884 | else |
4419 | minleft = 1; | 4885 | bma.minleft = 1; |
4420 | } else | 4886 | } else { |
4421 | minleft = 0; | 4887 | bma.minleft = 0; |
4422 | if (!(ifp->if_flags & XFS_IFEXTENTS) && | 4888 | } |
4423 | (error = xfs_iread_extents(tp, ip, whichfork))) | 4889 | |
4424 | goto error0; | 4890 | if (!(ifp->if_flags & XFS_IFEXTENTS)) { |
4425 | ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, | 4891 | error = xfs_iread_extents(tp, ip, whichfork); |
4426 | &prev); | 4892 | if (error) |
4427 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | 4893 | goto error0; |
4894 | } | ||
4895 | |||
4896 | xfs_bmap_search_extents(ip, bno, whichfork, &eof, &bma.idx, &bma.got, | ||
4897 | &bma.prev); | ||
4428 | n = 0; | 4898 | n = 0; |
4429 | end = bno + len; | 4899 | end = bno + len; |
4430 | obno = bno; | 4900 | obno = bno; |
4431 | bma.ip = NULL; | 4901 | |
4902 | bma.tp = tp; | ||
4903 | bma.ip = ip; | ||
4904 | bma.total = total; | ||
4905 | bma.userdata = 0; | ||
4906 | bma.flist = flist; | ||
4907 | bma.firstblock = firstblock; | ||
4432 | 4908 | ||
4433 | while (bno < end && n < *nmap) { | 4909 | while (bno < end && n < *nmap) { |
4434 | /* | 4910 | inhole = eof || bma.got.br_startoff > bno; |
4435 | * Reading past eof, act as though there's a hole | 4911 | wasdelay = !inhole && isnullstartblock(bma.got.br_startblock); |
4436 | * up to end. | 4912 | |
4437 | */ | ||
4438 | if (eof && !wr) | ||
4439 | got.br_startoff = end; | ||
4440 | inhole = eof || got.br_startoff > bno; | ||
4441 | wasdelay = wr && !inhole && !(flags & XFS_BMAPI_DELAY) && | ||
4442 | isnullstartblock(got.br_startblock); | ||
4443 | /* | 4913 | /* |
4444 | * First, deal with the hole before the allocated space | 4914 | * First, deal with the hole before the allocated space |
4445 | * that we found, if any. | 4915 | * that we found, if any. |
4446 | */ | 4916 | */ |
4447 | if (wr && (inhole || wasdelay)) { | 4917 | if (inhole || wasdelay) { |
4448 | /* | 4918 | bma.eof = eof; |
4449 | * For the wasdelay case, we could also just | 4919 | bma.conv = !!(flags & XFS_BMAPI_CONVERT); |
4450 | * allocate the stuff asked for in this bmap call | 4920 | bma.wasdel = wasdelay; |
4451 | * but that wouldn't be as good. | 4921 | bma.length = len; |
4452 | */ | 4922 | bma.offset = bno; |
4453 | if (wasdelay) { | 4923 | |
4454 | alen = (xfs_extlen_t)got.br_blockcount; | 4924 | error = xfs_bmapi_allocate(&bma, flags); |
4455 | aoff = got.br_startoff; | ||
4456 | if (lastx != NULLEXTNUM && lastx) { | ||
4457 | ep = xfs_iext_get_ext(ifp, lastx - 1); | ||
4458 | xfs_bmbt_get_all(ep, &prev); | ||
4459 | } | ||
4460 | } else { | ||
4461 | alen = (xfs_extlen_t) | ||
4462 | XFS_FILBLKS_MIN(len, MAXEXTLEN); | ||
4463 | if (!eof) | ||
4464 | alen = (xfs_extlen_t) | ||
4465 | XFS_FILBLKS_MIN(alen, | ||
4466 | got.br_startoff - bno); | ||
4467 | aoff = bno; | ||
4468 | } | ||
4469 | minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1; | ||
4470 | if (flags & XFS_BMAPI_DELAY) { | ||
4471 | xfs_extlen_t extsz; | ||
4472 | |||
4473 | /* Figure out the extent size, adjust alen */ | ||
4474 | extsz = xfs_get_extsz_hint(ip); | ||
4475 | if (extsz) { | ||
4476 | /* | ||
4477 | * make sure we don't exceed a single | ||
4478 | * extent length when we align the | ||
4479 | * extent by reducing length we are | ||
4480 | * going to allocate by the maximum | ||
4481 | * amount extent size aligment may | ||
4482 | * require. | ||
4483 | */ | ||
4484 | alen = XFS_FILBLKS_MIN(len, | ||
4485 | MAXEXTLEN - (2 * extsz - 1)); | ||
4486 | error = xfs_bmap_extsize_align(mp, | ||
4487 | &got, &prev, extsz, | ||
4488 | rt, eof, | ||
4489 | flags&XFS_BMAPI_DELAY, | ||
4490 | flags&XFS_BMAPI_CONVERT, | ||
4491 | &aoff, &alen); | ||
4492 | ASSERT(!error); | ||
4493 | } | ||
4494 | |||
4495 | if (rt) | ||
4496 | extsz = alen / mp->m_sb.sb_rextsize; | ||
4497 | |||
4498 | /* | ||
4499 | * Make a transaction-less quota reservation for | ||
4500 | * delayed allocation blocks. This number gets | ||
4501 | * adjusted later. We return if we haven't | ||
4502 | * allocated blocks already inside this loop. | ||
4503 | */ | ||
4504 | error = xfs_trans_reserve_quota_nblks( | ||
4505 | NULL, ip, (long)alen, 0, | ||
4506 | rt ? XFS_QMOPT_RES_RTBLKS : | ||
4507 | XFS_QMOPT_RES_REGBLKS); | ||
4508 | if (error) { | ||
4509 | if (n == 0) { | ||
4510 | *nmap = 0; | ||
4511 | ASSERT(cur == NULL); | ||
4512 | return error; | ||
4513 | } | ||
4514 | break; | ||
4515 | } | ||
4516 | |||
4517 | /* | ||
4518 | * Split changing sb for alen and indlen since | ||
4519 | * they could be coming from different places. | ||
4520 | */ | ||
4521 | indlen = (xfs_extlen_t) | ||
4522 | xfs_bmap_worst_indlen(ip, alen); | ||
4523 | ASSERT(indlen > 0); | ||
4524 | |||
4525 | if (rt) { | ||
4526 | error = xfs_mod_incore_sb(mp, | ||
4527 | XFS_SBS_FREXTENTS, | ||
4528 | -((int64_t)extsz), 0); | ||
4529 | } else { | ||
4530 | error = xfs_icsb_modify_counters(mp, | ||
4531 | XFS_SBS_FDBLOCKS, | ||
4532 | -((int64_t)alen), 0); | ||
4533 | } | ||
4534 | if (!error) { | ||
4535 | error = xfs_icsb_modify_counters(mp, | ||
4536 | XFS_SBS_FDBLOCKS, | ||
4537 | -((int64_t)indlen), 0); | ||
4538 | if (error && rt) | ||
4539 | xfs_mod_incore_sb(mp, | ||
4540 | XFS_SBS_FREXTENTS, | ||
4541 | (int64_t)extsz, 0); | ||
4542 | else if (error) | ||
4543 | xfs_icsb_modify_counters(mp, | ||
4544 | XFS_SBS_FDBLOCKS, | ||
4545 | (int64_t)alen, 0); | ||
4546 | } | ||
4547 | |||
4548 | if (error) { | ||
4549 | if (XFS_IS_QUOTA_ON(mp)) | ||
4550 | /* unreserve the blocks now */ | ||
4551 | (void) | ||
4552 | xfs_trans_unreserve_quota_nblks( | ||
4553 | NULL, ip, | ||
4554 | (long)alen, 0, rt ? | ||
4555 | XFS_QMOPT_RES_RTBLKS : | ||
4556 | XFS_QMOPT_RES_REGBLKS); | ||
4557 | break; | ||
4558 | } | ||
4559 | |||
4560 | ip->i_delayed_blks += alen; | ||
4561 | abno = nullstartblock(indlen); | ||
4562 | } else { | ||
4563 | /* | ||
4564 | * If first time, allocate and fill in | ||
4565 | * once-only bma fields. | ||
4566 | */ | ||
4567 | if (bma.ip == NULL) { | ||
4568 | bma.tp = tp; | ||
4569 | bma.ip = ip; | ||
4570 | bma.prevp = &prev; | ||
4571 | bma.gotp = &got; | ||
4572 | bma.total = total; | ||
4573 | bma.userdata = 0; | ||
4574 | } | ||
4575 | /* Indicate if this is the first user data | ||
4576 | * in the file, or just any user data. | ||
4577 | */ | ||
4578 | if (!(flags & XFS_BMAPI_METADATA)) { | ||
4579 | bma.userdata = (aoff == 0) ? | ||
4580 | XFS_ALLOC_INITIAL_USER_DATA : | ||
4581 | XFS_ALLOC_USERDATA; | ||
4582 | } | ||
4583 | /* | ||
4584 | * Fill in changeable bma fields. | ||
4585 | */ | ||
4586 | bma.eof = eof; | ||
4587 | bma.firstblock = *firstblock; | ||
4588 | bma.alen = alen; | ||
4589 | bma.off = aoff; | ||
4590 | bma.conv = !!(flags & XFS_BMAPI_CONVERT); | ||
4591 | bma.wasdel = wasdelay; | ||
4592 | bma.minlen = minlen; | ||
4593 | bma.low = flist->xbf_low; | ||
4594 | bma.minleft = minleft; | ||
4595 | /* | ||
4596 | * Only want to do the alignment at the | ||
4597 | * eof if it is userdata and allocation length | ||
4598 | * is larger than a stripe unit. | ||
4599 | */ | ||
4600 | if (mp->m_dalign && alen >= mp->m_dalign && | ||
4601 | (!(flags & XFS_BMAPI_METADATA)) && | ||
4602 | (whichfork == XFS_DATA_FORK)) { | ||
4603 | if ((error = xfs_bmap_isaeof(ip, aoff, | ||
4604 | whichfork, &bma.aeof))) | ||
4605 | goto error0; | ||
4606 | } else | ||
4607 | bma.aeof = 0; | ||
4608 | /* | ||
4609 | * Call allocator. | ||
4610 | */ | ||
4611 | if ((error = xfs_bmap_alloc(&bma))) | ||
4612 | goto error0; | ||
4613 | /* | ||
4614 | * Copy out result fields. | ||
4615 | */ | ||
4616 | abno = bma.rval; | ||
4617 | if ((flist->xbf_low = bma.low)) | ||
4618 | minleft = 0; | ||
4619 | alen = bma.alen; | ||
4620 | aoff = bma.off; | ||
4621 | ASSERT(*firstblock == NULLFSBLOCK || | ||
4622 | XFS_FSB_TO_AGNO(mp, *firstblock) == | ||
4623 | XFS_FSB_TO_AGNO(mp, bma.firstblock) || | ||
4624 | (flist->xbf_low && | ||
4625 | XFS_FSB_TO_AGNO(mp, *firstblock) < | ||
4626 | XFS_FSB_TO_AGNO(mp, bma.firstblock))); | ||
4627 | *firstblock = bma.firstblock; | ||
4628 | if (cur) | ||
4629 | cur->bc_private.b.firstblock = | ||
4630 | *firstblock; | ||
4631 | if (abno == NULLFSBLOCK) | ||
4632 | break; | ||
4633 | if ((ifp->if_flags & XFS_IFBROOT) && !cur) { | ||
4634 | cur = xfs_bmbt_init_cursor(mp, tp, | ||
4635 | ip, whichfork); | ||
4636 | cur->bc_private.b.firstblock = | ||
4637 | *firstblock; | ||
4638 | cur->bc_private.b.flist = flist; | ||
4639 | } | ||
4640 | /* | ||
4641 | * Bump the number of extents we've allocated | ||
4642 | * in this call. | ||
4643 | */ | ||
4644 | nallocs++; | ||
4645 | } | ||
4646 | if (cur) | ||
4647 | cur->bc_private.b.flags = | ||
4648 | wasdelay ? XFS_BTCUR_BPRV_WASDEL : 0; | ||
4649 | got.br_startoff = aoff; | ||
4650 | got.br_startblock = abno; | ||
4651 | got.br_blockcount = alen; | ||
4652 | got.br_state = XFS_EXT_NORM; /* assume normal */ | ||
4653 | /* | ||
4654 | * Determine state of extent, and the filesystem. | ||
4655 | * A wasdelay extent has been initialized, so | ||
4656 | * shouldn't be flagged as unwritten. | ||
4657 | */ | ||
4658 | if (wr && xfs_sb_version_hasextflgbit(&mp->m_sb)) { | ||
4659 | if (!wasdelay && (flags & XFS_BMAPI_PREALLOC)) | ||
4660 | got.br_state = XFS_EXT_UNWRITTEN; | ||
4661 | } | ||
4662 | error = xfs_bmap_add_extent(tp, ip, &lastx, &cur, &got, | ||
4663 | firstblock, flist, &tmp_logflags, | ||
4664 | whichfork); | ||
4665 | logflags |= tmp_logflags; | ||
4666 | if (error) | 4925 | if (error) |
4667 | goto error0; | 4926 | goto error0; |
4668 | ep = xfs_iext_get_ext(ifp, lastx); | 4927 | if (bma.blkno == NULLFSBLOCK) |
4669 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | 4928 | break; |
4670 | xfs_bmbt_get_all(ep, &got); | ||
4671 | ASSERT(got.br_startoff <= aoff); | ||
4672 | ASSERT(got.br_startoff + got.br_blockcount >= | ||
4673 | aoff + alen); | ||
4674 | #ifdef DEBUG | ||
4675 | if (flags & XFS_BMAPI_DELAY) { | ||
4676 | ASSERT(isnullstartblock(got.br_startblock)); | ||
4677 | ASSERT(startblockval(got.br_startblock) > 0); | ||
4678 | } | ||
4679 | ASSERT(got.br_state == XFS_EXT_NORM || | ||
4680 | got.br_state == XFS_EXT_UNWRITTEN); | ||
4681 | #endif | ||
4682 | /* | ||
4683 | * Fall down into the found allocated space case. | ||
4684 | */ | ||
4685 | } else if (inhole) { | ||
4686 | /* | ||
4687 | * Reading in a hole. | ||
4688 | */ | ||
4689 | mval->br_startoff = bno; | ||
4690 | mval->br_startblock = HOLESTARTBLOCK; | ||
4691 | mval->br_blockcount = | ||
4692 | XFS_FILBLKS_MIN(len, got.br_startoff - bno); | ||
4693 | mval->br_state = XFS_EXT_NORM; | ||
4694 | bno += mval->br_blockcount; | ||
4695 | len -= mval->br_blockcount; | ||
4696 | mval++; | ||
4697 | n++; | ||
4698 | continue; | ||
4699 | } | ||
4700 | /* | ||
4701 | * Then deal with the allocated space we found. | ||
4702 | */ | ||
4703 | ASSERT(ep != NULL); | ||
4704 | if (!(flags & XFS_BMAPI_ENTIRE) && | ||
4705 | (got.br_startoff + got.br_blockcount > obno)) { | ||
4706 | if (obno > bno) | ||
4707 | bno = obno; | ||
4708 | ASSERT((bno >= obno) || (n == 0)); | ||
4709 | ASSERT(bno < end); | ||
4710 | mval->br_startoff = bno; | ||
4711 | if (isnullstartblock(got.br_startblock)) { | ||
4712 | ASSERT(!wr || (flags & XFS_BMAPI_DELAY)); | ||
4713 | mval->br_startblock = DELAYSTARTBLOCK; | ||
4714 | } else | ||
4715 | mval->br_startblock = | ||
4716 | got.br_startblock + | ||
4717 | (bno - got.br_startoff); | ||
4718 | /* | ||
4719 | * Return the minimum of what we got and what we | ||
4720 | * asked for for the length. We can use the len | ||
4721 | * variable here because it is modified below | ||
4722 | * and we could have been there before coming | ||
4723 | * here if the first part of the allocation | ||
4724 | * didn't overlap what was asked for. | ||
4725 | */ | ||
4726 | mval->br_blockcount = | ||
4727 | XFS_FILBLKS_MIN(end - bno, got.br_blockcount - | ||
4728 | (bno - got.br_startoff)); | ||
4729 | mval->br_state = got.br_state; | ||
4730 | ASSERT(mval->br_blockcount <= len); | ||
4731 | } else { | ||
4732 | *mval = got; | ||
4733 | if (isnullstartblock(mval->br_startblock)) { | ||
4734 | ASSERT(!wr || (flags & XFS_BMAPI_DELAY)); | ||
4735 | mval->br_startblock = DELAYSTARTBLOCK; | ||
4736 | } | ||
4737 | } | 4929 | } |
4738 | 4930 | ||
4739 | /* | 4931 | /* Deal with the allocated space we found. */ |
4740 | * Check if writing previously allocated but | 4932 | xfs_bmapi_trim_map(mval, &bma.got, &bno, len, obno, |
4741 | * unwritten extents. | 4933 | end, n, flags); |
4742 | */ | 4934 | |
4743 | if (wr && | 4935 | /* Execute unwritten extent conversion if necessary */ |
4744 | ((mval->br_state == XFS_EXT_UNWRITTEN && | 4936 | error = xfs_bmapi_convert_unwritten(&bma, mval, len, flags); |
4745 | ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) || | 4937 | if (error == EAGAIN) |
4746 | (mval->br_state == XFS_EXT_NORM && | 4938 | continue; |
4747 | ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_CONVERT)) == | 4939 | if (error) |
4748 | (XFS_BMAPI_PREALLOC|XFS_BMAPI_CONVERT))))) { | 4940 | goto error0; |
4749 | /* | 4941 | |
4750 | * Modify (by adding) the state flag, if writing. | 4942 | /* update the extent map to return */ |
4751 | */ | 4943 | xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags); |
4752 | ASSERT(mval->br_blockcount <= len); | ||
4753 | if ((ifp->if_flags & XFS_IFBROOT) && !cur) { | ||
4754 | cur = xfs_bmbt_init_cursor(mp, | ||
4755 | tp, ip, whichfork); | ||
4756 | cur->bc_private.b.firstblock = | ||
4757 | *firstblock; | ||
4758 | cur->bc_private.b.flist = flist; | ||
4759 | } | ||
4760 | mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN) | ||
4761 | ? XFS_EXT_NORM | ||
4762 | : XFS_EXT_UNWRITTEN; | ||
4763 | error = xfs_bmap_add_extent(tp, ip, &lastx, &cur, mval, | ||
4764 | firstblock, flist, &tmp_logflags, | ||
4765 | whichfork); | ||
4766 | logflags |= tmp_logflags; | ||
4767 | if (error) | ||
4768 | goto error0; | ||
4769 | ep = xfs_iext_get_ext(ifp, lastx); | ||
4770 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | ||
4771 | xfs_bmbt_get_all(ep, &got); | ||
4772 | /* | ||
4773 | * We may have combined previously unwritten | ||
4774 | * space with written space, so generate | ||
4775 | * another request. | ||
4776 | */ | ||
4777 | if (mval->br_blockcount < len) | ||
4778 | continue; | ||
4779 | } | ||
4780 | 4944 | ||
4781 | ASSERT((flags & XFS_BMAPI_ENTIRE) || | ||
4782 | ((mval->br_startoff + mval->br_blockcount) <= end)); | ||
4783 | ASSERT((flags & XFS_BMAPI_ENTIRE) || | ||
4784 | (mval->br_blockcount <= len) || | ||
4785 | (mval->br_startoff < obno)); | ||
4786 | bno = mval->br_startoff + mval->br_blockcount; | ||
4787 | len = end - bno; | ||
4788 | if (n > 0 && mval->br_startoff == mval[-1].br_startoff) { | ||
4789 | ASSERT(mval->br_startblock == mval[-1].br_startblock); | ||
4790 | ASSERT(mval->br_blockcount > mval[-1].br_blockcount); | ||
4791 | ASSERT(mval->br_state == mval[-1].br_state); | ||
4792 | mval[-1].br_blockcount = mval->br_blockcount; | ||
4793 | mval[-1].br_state = mval->br_state; | ||
4794 | } else if (n > 0 && mval->br_startblock != DELAYSTARTBLOCK && | ||
4795 | mval[-1].br_startblock != DELAYSTARTBLOCK && | ||
4796 | mval[-1].br_startblock != HOLESTARTBLOCK && | ||
4797 | mval->br_startblock == | ||
4798 | mval[-1].br_startblock + mval[-1].br_blockcount && | ||
4799 | ((flags & XFS_BMAPI_IGSTATE) || | ||
4800 | mval[-1].br_state == mval->br_state)) { | ||
4801 | ASSERT(mval->br_startoff == | ||
4802 | mval[-1].br_startoff + mval[-1].br_blockcount); | ||
4803 | mval[-1].br_blockcount += mval->br_blockcount; | ||
4804 | } else if (n > 0 && | ||
4805 | mval->br_startblock == DELAYSTARTBLOCK && | ||
4806 | mval[-1].br_startblock == DELAYSTARTBLOCK && | ||
4807 | mval->br_startoff == | ||
4808 | mval[-1].br_startoff + mval[-1].br_blockcount) { | ||
4809 | mval[-1].br_blockcount += mval->br_blockcount; | ||
4810 | mval[-1].br_state = mval->br_state; | ||
4811 | } else if (!((n == 0) && | ||
4812 | ((mval->br_startoff + mval->br_blockcount) <= | ||
4813 | obno))) { | ||
4814 | mval++; | ||
4815 | n++; | ||
4816 | } | ||
4817 | /* | 4945 | /* |
4818 | * If we're done, stop now. Stop when we've allocated | 4946 | * If we're done, stop now. Stop when we've allocated |
4819 | * XFS_BMAP_MAX_NMAP extents no matter what. Otherwise | 4947 | * XFS_BMAP_MAX_NMAP extents no matter what. Otherwise |
4820 | * the transaction may get too big. | 4948 | * the transaction may get too big. |
4821 | */ | 4949 | */ |
4822 | if (bno >= end || n >= *nmap || nallocs >= *nmap) | 4950 | if (bno >= end || n >= *nmap || bma.nallocs >= *nmap) |
4823 | break; | 4951 | break; |
4824 | /* | 4952 | |
4825 | * Else go on to the next record. | 4953 | /* Else go on to the next record. */ |
4826 | */ | 4954 | bma.prev = bma.got; |
4827 | prev = got; | 4955 | if (++bma.idx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) { |
4828 | if (++lastx < nextents) { | 4956 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma.idx), |
4829 | ep = xfs_iext_get_ext(ifp, lastx); | 4957 | &bma.got); |
4830 | xfs_bmbt_get_all(ep, &got); | 4958 | } else |
4831 | } else { | ||
4832 | eof = 1; | 4959 | eof = 1; |
4833 | } | ||
4834 | } | 4960 | } |
4835 | *nmap = n; | 4961 | *nmap = n; |
4962 | |||
4836 | /* | 4963 | /* |
4837 | * Transform from btree to extents, give it cur. | 4964 | * Transform from btree to extents, give it cur. |
4838 | */ | 4965 | */ |
4839 | if (tp && XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE && | 4966 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE && |
4840 | XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) { | 4967 | XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) { |
4841 | ASSERT(wr && cur); | 4968 | int tmp_logflags = 0; |
4842 | error = xfs_bmap_btree_to_extents(tp, ip, cur, | 4969 | |
4970 | ASSERT(bma.cur); | ||
4971 | error = xfs_bmap_btree_to_extents(tp, ip, bma.cur, | ||
4843 | &tmp_logflags, whichfork); | 4972 | &tmp_logflags, whichfork); |
4844 | logflags |= tmp_logflags; | 4973 | bma.logflags |= tmp_logflags; |
4845 | if (error) | 4974 | if (error) |
4846 | goto error0; | 4975 | goto error0; |
4847 | } | 4976 | } |
@@ -4855,34 +4984,33 @@ error0: | |||
4855 | * Log everything. Do this after conversion, there's no point in | 4984 | * Log everything. Do this after conversion, there's no point in |
4856 | * logging the extent records if we've converted to btree format. | 4985 | * logging the extent records if we've converted to btree format. |
4857 | */ | 4986 | */ |
4858 | if ((logflags & xfs_ilog_fext(whichfork)) && | 4987 | if ((bma.logflags & xfs_ilog_fext(whichfork)) && |
4859 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) | 4988 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) |
4860 | logflags &= ~xfs_ilog_fext(whichfork); | 4989 | bma.logflags &= ~xfs_ilog_fext(whichfork); |
4861 | else if ((logflags & xfs_ilog_fbroot(whichfork)) && | 4990 | else if ((bma.logflags & xfs_ilog_fbroot(whichfork)) && |
4862 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) | 4991 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) |
4863 | logflags &= ~xfs_ilog_fbroot(whichfork); | 4992 | bma.logflags &= ~xfs_ilog_fbroot(whichfork); |
4864 | /* | 4993 | /* |
4865 | * Log whatever the flags say, even if error. Otherwise we might miss | 4994 | * Log whatever the flags say, even if error. Otherwise we might miss |
4866 | * detecting a case where the data is changed, there's an error, | 4995 | * detecting a case where the data is changed, there's an error, |
4867 | * and it's not logged so we don't shutdown when we should. | 4996 | * and it's not logged so we don't shutdown when we should. |
4868 | */ | 4997 | */ |
4869 | if (logflags) { | 4998 | if (bma.logflags) |
4870 | ASSERT(tp && wr); | 4999 | xfs_trans_log_inode(tp, ip, bma.logflags); |
4871 | xfs_trans_log_inode(tp, ip, logflags); | 5000 | |
4872 | } | 5001 | if (bma.cur) { |
4873 | if (cur) { | ||
4874 | if (!error) { | 5002 | if (!error) { |
4875 | ASSERT(*firstblock == NULLFSBLOCK || | 5003 | ASSERT(*firstblock == NULLFSBLOCK || |
4876 | XFS_FSB_TO_AGNO(mp, *firstblock) == | 5004 | XFS_FSB_TO_AGNO(mp, *firstblock) == |
4877 | XFS_FSB_TO_AGNO(mp, | 5005 | XFS_FSB_TO_AGNO(mp, |
4878 | cur->bc_private.b.firstblock) || | 5006 | bma.cur->bc_private.b.firstblock) || |
4879 | (flist->xbf_low && | 5007 | (flist->xbf_low && |
4880 | XFS_FSB_TO_AGNO(mp, *firstblock) < | 5008 | XFS_FSB_TO_AGNO(mp, *firstblock) < |
4881 | XFS_FSB_TO_AGNO(mp, | 5009 | XFS_FSB_TO_AGNO(mp, |
4882 | cur->bc_private.b.firstblock))); | 5010 | bma.cur->bc_private.b.firstblock))); |
4883 | *firstblock = cur->bc_private.b.firstblock; | 5011 | *firstblock = bma.cur->bc_private.b.firstblock; |
4884 | } | 5012 | } |
4885 | xfs_btree_del_cursor(cur, | 5013 | xfs_btree_del_cursor(bma.cur, |
4886 | error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); | 5014 | error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); |
4887 | } | 5015 | } |
4888 | if (!error) | 5016 | if (!error) |
@@ -4892,58 +5020,6 @@ error0: | |||
4892 | } | 5020 | } |
4893 | 5021 | ||
4894 | /* | 5022 | /* |
4895 | * Map file blocks to filesystem blocks, simple version. | ||
4896 | * One block (extent) only, read-only. | ||
4897 | * For flags, only the XFS_BMAPI_ATTRFORK flag is examined. | ||
4898 | * For the other flag values, the effect is as if XFS_BMAPI_METADATA | ||
4899 | * was set and all the others were clear. | ||
4900 | */ | ||
4901 | int /* error */ | ||
4902 | xfs_bmapi_single( | ||
4903 | xfs_trans_t *tp, /* transaction pointer */ | ||
4904 | xfs_inode_t *ip, /* incore inode */ | ||
4905 | int whichfork, /* data or attr fork */ | ||
4906 | xfs_fsblock_t *fsb, /* output: mapped block */ | ||
4907 | xfs_fileoff_t bno) /* starting file offs. mapped */ | ||
4908 | { | ||
4909 | int eof; /* we've hit the end of extents */ | ||
4910 | int error; /* error return */ | ||
4911 | xfs_bmbt_irec_t got; /* current file extent record */ | ||
4912 | xfs_ifork_t *ifp; /* inode fork pointer */ | ||
4913 | xfs_extnum_t lastx; /* last useful extent number */ | ||
4914 | xfs_bmbt_irec_t prev; /* previous file extent record */ | ||
4915 | |||
4916 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
4917 | if (unlikely( | ||
4918 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && | ||
4919 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)) { | ||
4920 | XFS_ERROR_REPORT("xfs_bmapi_single", XFS_ERRLEVEL_LOW, | ||
4921 | ip->i_mount); | ||
4922 | return XFS_ERROR(EFSCORRUPTED); | ||
4923 | } | ||
4924 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
4925 | return XFS_ERROR(EIO); | ||
4926 | XFS_STATS_INC(xs_blk_mapr); | ||
4927 | if (!(ifp->if_flags & XFS_IFEXTENTS) && | ||
4928 | (error = xfs_iread_extents(tp, ip, whichfork))) | ||
4929 | return error; | ||
4930 | (void)xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, | ||
4931 | &prev); | ||
4932 | /* | ||
4933 | * Reading past eof, act as though there's a hole | ||
4934 | * up to end. | ||
4935 | */ | ||
4936 | if (eof || got.br_startoff > bno) { | ||
4937 | *fsb = NULLFSBLOCK; | ||
4938 | return 0; | ||
4939 | } | ||
4940 | ASSERT(!isnullstartblock(got.br_startblock)); | ||
4941 | ASSERT(bno < got.br_startoff + got.br_blockcount); | ||
4942 | *fsb = got.br_startblock + (bno - got.br_startoff); | ||
4943 | return 0; | ||
4944 | } | ||
4945 | |||
4946 | /* | ||
4947 | * Unmap (remove) blocks from a file. | 5023 | * Unmap (remove) blocks from a file. |
4948 | * If nexts is nonzero then the number of extents to remove is limited to | 5024 | * If nexts is nonzero then the number of extents to remove is limited to |
4949 | * that value. If not all extents in the block range can be removed then | 5025 | * that value. If not all extents in the block range can be removed then |
@@ -5114,9 +5190,9 @@ xfs_bunmapi( | |||
5114 | del.br_blockcount = mod; | 5190 | del.br_blockcount = mod; |
5115 | } | 5191 | } |
5116 | del.br_state = XFS_EXT_UNWRITTEN; | 5192 | del.br_state = XFS_EXT_UNWRITTEN; |
5117 | error = xfs_bmap_add_extent(tp, ip, &lastx, &cur, &del, | 5193 | error = xfs_bmap_add_extent_unwritten_real(tp, ip, |
5118 | firstblock, flist, &logflags, | 5194 | &lastx, &cur, &del, firstblock, flist, |
5119 | XFS_DATA_FORK); | 5195 | &logflags); |
5120 | if (error) | 5196 | if (error) |
5121 | goto error0; | 5197 | goto error0; |
5122 | goto nodelete; | 5198 | goto nodelete; |
@@ -5172,18 +5248,18 @@ xfs_bunmapi( | |||
5172 | } | 5248 | } |
5173 | prev.br_state = XFS_EXT_UNWRITTEN; | 5249 | prev.br_state = XFS_EXT_UNWRITTEN; |
5174 | lastx--; | 5250 | lastx--; |
5175 | error = xfs_bmap_add_extent(tp, ip, &lastx, | 5251 | error = xfs_bmap_add_extent_unwritten_real(tp, |
5176 | &cur, &prev, firstblock, flist, | 5252 | ip, &lastx, &cur, &prev, |
5177 | &logflags, XFS_DATA_FORK); | 5253 | firstblock, flist, &logflags); |
5178 | if (error) | 5254 | if (error) |
5179 | goto error0; | 5255 | goto error0; |
5180 | goto nodelete; | 5256 | goto nodelete; |
5181 | } else { | 5257 | } else { |
5182 | ASSERT(del.br_state == XFS_EXT_NORM); | 5258 | ASSERT(del.br_state == XFS_EXT_NORM); |
5183 | del.br_state = XFS_EXT_UNWRITTEN; | 5259 | del.br_state = XFS_EXT_UNWRITTEN; |
5184 | error = xfs_bmap_add_extent(tp, ip, &lastx, | 5260 | error = xfs_bmap_add_extent_unwritten_real(tp, |
5185 | &cur, &del, firstblock, flist, | 5261 | ip, &lastx, &cur, &del, |
5186 | &logflags, XFS_DATA_FORK); | 5262 | firstblock, flist, &logflags); |
5187 | if (error) | 5263 | if (error) |
5188 | goto error0; | 5264 | goto error0; |
5189 | goto nodelete; | 5265 | goto nodelete; |
@@ -5505,10 +5581,9 @@ xfs_getbmap( | |||
5505 | 5581 | ||
5506 | do { | 5582 | do { |
5507 | nmap = (nexleft > subnex) ? subnex : nexleft; | 5583 | nmap = (nexleft > subnex) ? subnex : nexleft; |
5508 | error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), | 5584 | error = xfs_bmapi_read(ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), |
5509 | XFS_BB_TO_FSB(mp, bmv->bmv_length), | 5585 | XFS_BB_TO_FSB(mp, bmv->bmv_length), |
5510 | bmapi_flags, NULL, 0, map, &nmap, | 5586 | map, &nmap, bmapi_flags); |
5511 | NULL); | ||
5512 | if (error) | 5587 | if (error) |
5513 | goto out_free_map; | 5588 | goto out_free_map; |
5514 | ASSERT(nmap <= subnex); | 5589 | ASSERT(nmap <= subnex); |
@@ -5582,89 +5657,6 @@ xfs_getbmap( | |||
5582 | return error; | 5657 | return error; |
5583 | } | 5658 | } |
5584 | 5659 | ||
5585 | /* | ||
5586 | * Check the last inode extent to determine whether this allocation will result | ||
5587 | * in blocks being allocated at the end of the file. When we allocate new data | ||
5588 | * blocks at the end of the file which do not start at the previous data block, | ||
5589 | * we will try to align the new blocks at stripe unit boundaries. | ||
5590 | */ | ||
5591 | STATIC int /* error */ | ||
5592 | xfs_bmap_isaeof( | ||
5593 | xfs_inode_t *ip, /* incore inode pointer */ | ||
5594 | xfs_fileoff_t off, /* file offset in fsblocks */ | ||
5595 | int whichfork, /* data or attribute fork */ | ||
5596 | char *aeof) /* return value */ | ||
5597 | { | ||
5598 | int error; /* error return value */ | ||
5599 | xfs_ifork_t *ifp; /* inode fork pointer */ | ||
5600 | xfs_bmbt_rec_host_t *lastrec; /* extent record pointer */ | ||
5601 | xfs_extnum_t nextents; /* number of file extents */ | ||
5602 | xfs_bmbt_irec_t s; /* expanded extent record */ | ||
5603 | |||
5604 | ASSERT(whichfork == XFS_DATA_FORK); | ||
5605 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
5606 | if (!(ifp->if_flags & XFS_IFEXTENTS) && | ||
5607 | (error = xfs_iread_extents(NULL, ip, whichfork))) | ||
5608 | return error; | ||
5609 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | ||
5610 | if (nextents == 0) { | ||
5611 | *aeof = 1; | ||
5612 | return 0; | ||
5613 | } | ||
5614 | /* | ||
5615 | * Go to the last extent | ||
5616 | */ | ||
5617 | lastrec = xfs_iext_get_ext(ifp, nextents - 1); | ||
5618 | xfs_bmbt_get_all(lastrec, &s); | ||
5619 | /* | ||
5620 | * Check we are allocating in the last extent (for delayed allocations) | ||
5621 | * or past the last extent for non-delayed allocations. | ||
5622 | */ | ||
5623 | *aeof = (off >= s.br_startoff && | ||
5624 | off < s.br_startoff + s.br_blockcount && | ||
5625 | isnullstartblock(s.br_startblock)) || | ||
5626 | off >= s.br_startoff + s.br_blockcount; | ||
5627 | return 0; | ||
5628 | } | ||
5629 | |||
5630 | /* | ||
5631 | * Check if the endoff is outside the last extent. If so the caller will grow | ||
5632 | * the allocation to a stripe unit boundary. | ||
5633 | */ | ||
5634 | int /* error */ | ||
5635 | xfs_bmap_eof( | ||
5636 | xfs_inode_t *ip, /* incore inode pointer */ | ||
5637 | xfs_fileoff_t endoff, /* file offset in fsblocks */ | ||
5638 | int whichfork, /* data or attribute fork */ | ||
5639 | int *eof) /* result value */ | ||
5640 | { | ||
5641 | xfs_fsblock_t blockcount; /* extent block count */ | ||
5642 | int error; /* error return value */ | ||
5643 | xfs_ifork_t *ifp; /* inode fork pointer */ | ||
5644 | xfs_bmbt_rec_host_t *lastrec; /* extent record pointer */ | ||
5645 | xfs_extnum_t nextents; /* number of file extents */ | ||
5646 | xfs_fileoff_t startoff; /* extent starting file offset */ | ||
5647 | |||
5648 | ASSERT(whichfork == XFS_DATA_FORK); | ||
5649 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
5650 | if (!(ifp->if_flags & XFS_IFEXTENTS) && | ||
5651 | (error = xfs_iread_extents(NULL, ip, whichfork))) | ||
5652 | return error; | ||
5653 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | ||
5654 | if (nextents == 0) { | ||
5655 | *eof = 1; | ||
5656 | return 0; | ||
5657 | } | ||
5658 | /* | ||
5659 | * Go to the last extent | ||
5660 | */ | ||
5661 | lastrec = xfs_iext_get_ext(ifp, nextents - 1); | ||
5662 | startoff = xfs_bmbt_get_startoff(lastrec); | ||
5663 | blockcount = xfs_bmbt_get_blockcount(lastrec); | ||
5664 | *eof = endoff >= startoff + blockcount; | ||
5665 | return 0; | ||
5666 | } | ||
5667 | |||
5668 | #ifdef DEBUG | 5660 | #ifdef DEBUG |
5669 | STATIC struct xfs_buf * | 5661 | STATIC struct xfs_buf * |
5670 | xfs_bmap_get_bp( | 5662 | xfs_bmap_get_bp( |
@@ -6099,9 +6091,8 @@ xfs_bmap_punch_delalloc_range( | |||
6099 | * trying to remove a real extent (which requires a | 6091 | * trying to remove a real extent (which requires a |
6100 | * transaction) or a hole, which is probably a bad idea... | 6092 | * transaction) or a hole, which is probably a bad idea... |
6101 | */ | 6093 | */ |
6102 | error = xfs_bmapi(NULL, ip, start_fsb, 1, | 6094 | error = xfs_bmapi_read(ip, start_fsb, 1, &imap, &nimaps, |
6103 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, | 6095 | XFS_BMAPI_ENTIRE); |
6104 | &nimaps, NULL); | ||
6105 | 6096 | ||
6106 | if (error) { | 6097 | if (error) { |
6107 | /* something screwed, just bail */ | 6098 | /* something screwed, just bail */ |
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index c62234bde053..89ee672d378a 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
@@ -62,27 +62,23 @@ typedef struct xfs_bmap_free | |||
62 | #define XFS_BMAP_MAX_NMAP 4 | 62 | #define XFS_BMAP_MAX_NMAP 4 |
63 | 63 | ||
64 | /* | 64 | /* |
65 | * Flags for xfs_bmapi | 65 | * Flags for xfs_bmapi_* |
66 | */ | 66 | */ |
67 | #define XFS_BMAPI_WRITE 0x001 /* write operation: allocate space */ | 67 | #define XFS_BMAPI_ENTIRE 0x001 /* return entire extent, not trimmed */ |
68 | #define XFS_BMAPI_DELAY 0x002 /* delayed write operation */ | 68 | #define XFS_BMAPI_METADATA 0x002 /* mapping metadata not user data */ |
69 | #define XFS_BMAPI_ENTIRE 0x004 /* return entire extent, not trimmed */ | 69 | #define XFS_BMAPI_ATTRFORK 0x004 /* use attribute fork not data */ |
70 | #define XFS_BMAPI_METADATA 0x008 /* mapping metadata not user data */ | 70 | #define XFS_BMAPI_PREALLOC 0x008 /* preallocation op: unwritten space */ |
71 | #define XFS_BMAPI_ATTRFORK 0x010 /* use attribute fork not data */ | 71 | #define XFS_BMAPI_IGSTATE 0x010 /* Ignore state - */ |
72 | #define XFS_BMAPI_PREALLOC 0x040 /* preallocation op: unwritten space */ | ||
73 | #define XFS_BMAPI_IGSTATE 0x080 /* Ignore state - */ | ||
74 | /* combine contig. space */ | 72 | /* combine contig. space */ |
75 | #define XFS_BMAPI_CONTIG 0x100 /* must allocate only one extent */ | 73 | #define XFS_BMAPI_CONTIG 0x020 /* must allocate only one extent */ |
76 | /* | 74 | /* |
77 | * unwritten extent conversion - this needs write cache flushing and no additional | 75 | * unwritten extent conversion - this needs write cache flushing and no additional |
78 | * allocation alignments. When specified with XFS_BMAPI_PREALLOC it converts | 76 | * allocation alignments. When specified with XFS_BMAPI_PREALLOC it converts |
79 | * from written to unwritten, otherwise convert from unwritten to written. | 77 | * from written to unwritten, otherwise convert from unwritten to written. |
80 | */ | 78 | */ |
81 | #define XFS_BMAPI_CONVERT 0x200 | 79 | #define XFS_BMAPI_CONVERT 0x040 |
82 | 80 | ||
83 | #define XFS_BMAPI_FLAGS \ | 81 | #define XFS_BMAPI_FLAGS \ |
84 | { XFS_BMAPI_WRITE, "WRITE" }, \ | ||
85 | { XFS_BMAPI_DELAY, "DELAY" }, \ | ||
86 | { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ | 82 | { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ |
87 | { XFS_BMAPI_METADATA, "METADATA" }, \ | 83 | { XFS_BMAPI_METADATA, "METADATA" }, \ |
88 | { XFS_BMAPI_ATTRFORK, "ATTRFORK" }, \ | 84 | { XFS_BMAPI_ATTRFORK, "ATTRFORK" }, \ |
@@ -113,21 +109,28 @@ static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp) | |||
113 | * Argument structure for xfs_bmap_alloc. | 109 | * Argument structure for xfs_bmap_alloc. |
114 | */ | 110 | */ |
115 | typedef struct xfs_bmalloca { | 111 | typedef struct xfs_bmalloca { |
116 | xfs_fsblock_t firstblock; /* i/o first block allocated */ | 112 | xfs_fsblock_t *firstblock; /* i/o first block allocated */ |
117 | xfs_fsblock_t rval; /* starting block of new extent */ | 113 | struct xfs_bmap_free *flist; /* bmap freelist */ |
118 | xfs_fileoff_t off; /* offset in file filling in */ | ||
119 | struct xfs_trans *tp; /* transaction pointer */ | 114 | struct xfs_trans *tp; /* transaction pointer */ |
120 | struct xfs_inode *ip; /* incore inode pointer */ | 115 | struct xfs_inode *ip; /* incore inode pointer */ |
121 | struct xfs_bmbt_irec *prevp; /* extent before the new one */ | 116 | struct xfs_bmbt_irec prev; /* extent before the new one */ |
122 | struct xfs_bmbt_irec *gotp; /* extent after, or delayed */ | 117 | struct xfs_bmbt_irec got; /* extent after, or delayed */ |
123 | xfs_extlen_t alen; /* i/o length asked/allocated */ | 118 | |
119 | xfs_fileoff_t offset; /* offset in file filling in */ | ||
120 | xfs_extlen_t length; /* i/o length asked/allocated */ | ||
121 | xfs_fsblock_t blkno; /* starting block of new extent */ | ||
122 | |||
123 | struct xfs_btree_cur *cur; /* btree cursor */ | ||
124 | xfs_extnum_t idx; /* current extent index */ | ||
125 | int nallocs;/* number of extents alloc'd */ | ||
126 | int logflags;/* flags for transaction logging */ | ||
127 | |||
124 | xfs_extlen_t total; /* total blocks needed for xaction */ | 128 | xfs_extlen_t total; /* total blocks needed for xaction */ |
125 | xfs_extlen_t minlen; /* minimum allocation size (blocks) */ | 129 | xfs_extlen_t minlen; /* minimum allocation size (blocks) */ |
126 | xfs_extlen_t minleft; /* amount must be left after alloc */ | 130 | xfs_extlen_t minleft; /* amount must be left after alloc */ |
127 | char eof; /* set if allocating past last extent */ | 131 | char eof; /* set if allocating past last extent */ |
128 | char wasdel; /* replacing a delayed allocation */ | 132 | char wasdel; /* replacing a delayed allocation */ |
129 | char userdata;/* set if is user data */ | 133 | char userdata;/* set if is user data */ |
130 | char low; /* low on space, using seq'l ags */ | ||
131 | char aeof; /* allocated space at eof */ | 134 | char aeof; /* allocated space at eof */ |
132 | char conv; /* overwriting unwritten extents */ | 135 | char conv; /* overwriting unwritten extents */ |
133 | } xfs_bmalloca_t; | 136 | } xfs_bmalloca_t; |
@@ -152,251 +155,62 @@ typedef struct xfs_bmalloca { | |||
152 | { BMAP_RIGHT_FILLING, "RF" }, \ | 155 | { BMAP_RIGHT_FILLING, "RF" }, \ |
153 | { BMAP_ATTRFORK, "ATTR" } | 156 | { BMAP_ATTRFORK, "ATTR" } |
154 | 157 | ||
155 | /* | ||
156 | * Add bmap trace insert entries for all the contents of the extent list. | ||
157 | * | ||
158 | * Quite excessive tracing. Only do this for debug builds. | ||
159 | */ | ||
160 | #if defined(__KERNEL) && defined(DEBUG) | 158 | #if defined(__KERNEL) && defined(DEBUG) |
161 | void | 159 | void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, |
162 | xfs_bmap_trace_exlist( | 160 | int whichfork, unsigned long caller_ip); |
163 | struct xfs_inode *ip, /* incore inode pointer */ | ||
164 | xfs_extnum_t cnt, /* count of entries in list */ | ||
165 | int whichfork, | ||
166 | unsigned long caller_ip); /* data or attr fork */ | ||
167 | #define XFS_BMAP_TRACE_EXLIST(ip,c,w) \ | 161 | #define XFS_BMAP_TRACE_EXLIST(ip,c,w) \ |
168 | xfs_bmap_trace_exlist(ip,c,w, _THIS_IP_) | 162 | xfs_bmap_trace_exlist(ip,c,w, _THIS_IP_) |
169 | #else | 163 | #else |
170 | #define XFS_BMAP_TRACE_EXLIST(ip,c,w) | 164 | #define XFS_BMAP_TRACE_EXLIST(ip,c,w) |
171 | #endif | 165 | #endif |
172 | 166 | ||
173 | /* | 167 | int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); |
174 | * Convert inode from non-attributed to attributed. | 168 | void xfs_bmap_add_free(xfs_fsblock_t bno, xfs_filblks_t len, |
175 | * Must not be in a transaction, ip must not be locked. | 169 | struct xfs_bmap_free *flist, struct xfs_mount *mp); |
176 | */ | 170 | void xfs_bmap_cancel(struct xfs_bmap_free *flist); |
177 | int /* error code */ | 171 | void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); |
178 | xfs_bmap_add_attrfork( | 172 | int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, |
179 | struct xfs_inode *ip, /* incore inode pointer */ | 173 | xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork); |
180 | int size, /* space needed for new attribute */ | 174 | int xfs_bmap_last_before(struct xfs_trans *tp, struct xfs_inode *ip, |
181 | int rsvd); /* flag for reserved block allocation */ | 175 | xfs_fileoff_t *last_block, int whichfork); |
182 | 176 | int xfs_bmap_last_offset(struct xfs_trans *tp, struct xfs_inode *ip, | |
183 | /* | 177 | xfs_fileoff_t *unused, int whichfork); |
184 | * Add the extent to the list of extents to be free at transaction end. | 178 | int xfs_bmap_one_block(struct xfs_inode *ip, int whichfork); |
185 | * The list is maintained sorted (by block number). | 179 | int xfs_bmap_read_extents(struct xfs_trans *tp, struct xfs_inode *ip, |
186 | */ | 180 | int whichfork); |
187 | void | 181 | int xfs_bmapi_read(struct xfs_inode *ip, xfs_fileoff_t bno, |
188 | xfs_bmap_add_free( | 182 | xfs_filblks_t len, struct xfs_bmbt_irec *mval, |
189 | xfs_fsblock_t bno, /* fs block number of extent */ | 183 | int *nmap, int flags); |
190 | xfs_filblks_t len, /* length of extent */ | 184 | int xfs_bmapi_delay(struct xfs_inode *ip, xfs_fileoff_t bno, |
191 | xfs_bmap_free_t *flist, /* list of extents */ | 185 | xfs_filblks_t len, struct xfs_bmbt_irec *mval, |
192 | struct xfs_mount *mp); /* mount point structure */ | 186 | int *nmap, int flags); |
193 | 187 | int xfs_bmapi_write(struct xfs_trans *tp, struct xfs_inode *ip, | |
194 | /* | 188 | xfs_fileoff_t bno, xfs_filblks_t len, int flags, |
195 | * Routine to clean up the free list data structure when | 189 | xfs_fsblock_t *firstblock, xfs_extlen_t total, |
196 | * an error occurs during a transaction. | 190 | struct xfs_bmbt_irec *mval, int *nmap, |
197 | */ | 191 | struct xfs_bmap_free *flist); |
198 | void | 192 | int xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, |
199 | xfs_bmap_cancel( | 193 | xfs_fileoff_t bno, xfs_filblks_t len, int flags, |
200 | xfs_bmap_free_t *flist); /* free list to clean up */ | 194 | xfs_extnum_t nexts, xfs_fsblock_t *firstblock, |
201 | 195 | struct xfs_bmap_free *flist, int *done); | |
202 | /* | 196 | int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx, |
203 | * Compute and fill in the value of the maximum depth of a bmap btree | 197 | xfs_extnum_t num); |
204 | * in this filesystem. Done once, during mount. | 198 | uint xfs_default_attroffset(struct xfs_inode *ip); |
205 | */ | ||
206 | void | ||
207 | xfs_bmap_compute_maxlevels( | ||
208 | struct xfs_mount *mp, /* file system mount structure */ | ||
209 | int whichfork); /* data or attr fork */ | ||
210 | |||
211 | /* | ||
212 | * Returns the file-relative block number of the first unused block in the file. | ||
213 | * This is the lowest-address hole if the file has holes, else the first block | ||
214 | * past the end of file. | ||
215 | */ | ||
216 | int /* error */ | ||
217 | xfs_bmap_first_unused( | ||
218 | struct xfs_trans *tp, /* transaction pointer */ | ||
219 | struct xfs_inode *ip, /* incore inode */ | ||
220 | xfs_extlen_t len, /* size of hole to find */ | ||
221 | xfs_fileoff_t *unused, /* unused block num */ | ||
222 | int whichfork); /* data or attr fork */ | ||
223 | |||
224 | /* | ||
225 | * Returns the file-relative block number of the last block + 1 before | ||
226 | * last_block (input value) in the file. | ||
227 | * This is not based on i_size, it is based on the extent list. | ||
228 | * Returns 0 for local files, as they do not have an extent list. | ||
229 | */ | ||
230 | int /* error */ | ||
231 | xfs_bmap_last_before( | ||
232 | struct xfs_trans *tp, /* transaction pointer */ | ||
233 | struct xfs_inode *ip, /* incore inode */ | ||
234 | xfs_fileoff_t *last_block, /* last block */ | ||
235 | int whichfork); /* data or attr fork */ | ||
236 | |||
237 | /* | ||
238 | * Returns the file-relative block number of the first block past eof in | ||
239 | * the file. This is not based on i_size, it is based on the extent list. | ||
240 | * Returns 0 for local files, as they do not have an extent list. | ||
241 | */ | ||
242 | int /* error */ | ||
243 | xfs_bmap_last_offset( | ||
244 | struct xfs_trans *tp, /* transaction pointer */ | ||
245 | struct xfs_inode *ip, /* incore inode */ | ||
246 | xfs_fileoff_t *unused, /* last block num */ | ||
247 | int whichfork); /* data or attr fork */ | ||
248 | |||
249 | /* | ||
250 | * Returns whether the selected fork of the inode has exactly one | ||
251 | * block or not. For the data fork we check this matches di_size, | ||
252 | * implying the file's range is 0..bsize-1. | ||
253 | */ | ||
254 | int | ||
255 | xfs_bmap_one_block( | ||
256 | struct xfs_inode *ip, /* incore inode */ | ||
257 | int whichfork); /* data or attr fork */ | ||
258 | |||
259 | /* | ||
260 | * Read in the extents to iu_extents. | ||
261 | * All inode fields are set up by caller, we just traverse the btree | ||
262 | * and copy the records in. | ||
263 | */ | ||
264 | int /* error */ | ||
265 | xfs_bmap_read_extents( | ||
266 | struct xfs_trans *tp, /* transaction pointer */ | ||
267 | struct xfs_inode *ip, /* incore inode */ | ||
268 | int whichfork); /* data or attr fork */ | ||
269 | |||
270 | /* | ||
271 | * Map file blocks to filesystem blocks. | ||
272 | * File range is given by the bno/len pair. | ||
273 | * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set) | ||
274 | * into a hole or past eof. | ||
275 | * Only allocates blocks from a single allocation group, | ||
276 | * to avoid locking problems. | ||
277 | * The returned value in "firstblock" from the first call in a transaction | ||
278 | * must be remembered and presented to subsequent calls in "firstblock". | ||
279 | * An upper bound for the number of blocks to be allocated is supplied to | ||
280 | * the first call in "total"; if no allocation group has that many free | ||
281 | * blocks then the call will fail (return NULLFSBLOCK in "firstblock"). | ||
282 | */ | ||
283 | int /* error */ | ||
284 | xfs_bmapi( | ||
285 | struct xfs_trans *tp, /* transaction pointer */ | ||
286 | struct xfs_inode *ip, /* incore inode */ | ||
287 | xfs_fileoff_t bno, /* starting file offs. mapped */ | ||
288 | xfs_filblks_t len, /* length to map in file */ | ||
289 | int flags, /* XFS_BMAPI_... */ | ||
290 | xfs_fsblock_t *firstblock, /* first allocated block | ||
291 | controls a.g. for allocs */ | ||
292 | xfs_extlen_t total, /* total blocks needed */ | ||
293 | struct xfs_bmbt_irec *mval, /* output: map values */ | ||
294 | int *nmap, /* i/o: mval size/count */ | ||
295 | xfs_bmap_free_t *flist); /* i/o: list extents to free */ | ||
296 | |||
297 | /* | ||
298 | * Map file blocks to filesystem blocks, simple version. | ||
299 | * One block only, read-only. | ||
300 | * For flags, only the XFS_BMAPI_ATTRFORK flag is examined. | ||
301 | * For the other flag values, the effect is as if XFS_BMAPI_METADATA | ||
302 | * was set and all the others were clear. | ||
303 | */ | ||
304 | int /* error */ | ||
305 | xfs_bmapi_single( | ||
306 | struct xfs_trans *tp, /* transaction pointer */ | ||
307 | struct xfs_inode *ip, /* incore inode */ | ||
308 | int whichfork, /* data or attr fork */ | ||
309 | xfs_fsblock_t *fsb, /* output: mapped block */ | ||
310 | xfs_fileoff_t bno); /* starting file offs. mapped */ | ||
311 | |||
312 | /* | ||
313 | * Unmap (remove) blocks from a file. | ||
314 | * If nexts is nonzero then the number of extents to remove is limited to | ||
315 | * that value. If not all extents in the block range can be removed then | ||
316 | * *done is set. | ||
317 | */ | ||
318 | int /* error */ | ||
319 | xfs_bunmapi( | ||
320 | struct xfs_trans *tp, /* transaction pointer */ | ||
321 | struct xfs_inode *ip, /* incore inode */ | ||
322 | xfs_fileoff_t bno, /* starting offset to unmap */ | ||
323 | xfs_filblks_t len, /* length to unmap in file */ | ||
324 | int flags, /* XFS_BMAPI_... */ | ||
325 | xfs_extnum_t nexts, /* number of extents max */ | ||
326 | xfs_fsblock_t *firstblock, /* first allocated block | ||
327 | controls a.g. for allocs */ | ||
328 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ | ||
329 | int *done); /* set if not done yet */ | ||
330 | |||
331 | /* | ||
332 | * Check an extent list, which has just been read, for | ||
333 | * any bit in the extent flag field. | ||
334 | */ | ||
335 | int | ||
336 | xfs_check_nostate_extents( | ||
337 | struct xfs_ifork *ifp, | ||
338 | xfs_extnum_t idx, | ||
339 | xfs_extnum_t num); | ||
340 | |||
341 | uint | ||
342 | xfs_default_attroffset( | ||
343 | struct xfs_inode *ip); | ||
344 | 199 | ||
345 | #ifdef __KERNEL__ | 200 | #ifdef __KERNEL__ |
346 | |||
347 | /* | ||
348 | * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi | ||
349 | * caller. Frees all the extents that need freeing, which must be done | ||
350 | * last due to locking considerations. | ||
351 | * | ||
352 | * Return 1 if the given transaction was committed and a new one allocated, | ||
353 | * and 0 otherwise. | ||
354 | */ | ||
355 | int /* error */ | ||
356 | xfs_bmap_finish( | ||
357 | struct xfs_trans **tp, /* transaction pointer addr */ | ||
358 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ | ||
359 | int *committed); /* xact committed or not */ | ||
360 | |||
361 | /* bmap to userspace formatter - copy to user & advance pointer */ | 201 | /* bmap to userspace formatter - copy to user & advance pointer */ |
362 | typedef int (*xfs_bmap_format_t)(void **, struct getbmapx *, int *); | 202 | typedef int (*xfs_bmap_format_t)(void **, struct getbmapx *, int *); |
363 | 203 | ||
364 | /* | 204 | int xfs_bmap_finish(struct xfs_trans **tp, struct xfs_bmap_free *flist, |
365 | * Get inode's extents as described in bmv, and format for output. | 205 | int *committed); |
366 | */ | 206 | int xfs_getbmap(struct xfs_inode *ip, struct getbmapx *bmv, |
367 | int /* error code */ | 207 | xfs_bmap_format_t formatter, void *arg); |
368 | xfs_getbmap( | 208 | int xfs_bmap_eof(struct xfs_inode *ip, xfs_fileoff_t endoff, |
369 | xfs_inode_t *ip, | 209 | int whichfork, int *eof); |
370 | struct getbmapx *bmv, /* user bmap structure */ | 210 | int xfs_bmap_count_blocks(struct xfs_trans *tp, struct xfs_inode *ip, |
371 | xfs_bmap_format_t formatter, /* format to user */ | 211 | int whichfork, int *count); |
372 | void *arg); /* formatter arg */ | 212 | int xfs_bmap_punch_delalloc_range(struct xfs_inode *ip, |
373 | 213 | xfs_fileoff_t start_fsb, xfs_fileoff_t length); | |
374 | /* | ||
375 | * Check if the endoff is outside the last extent. If so the caller will grow | ||
376 | * the allocation to a stripe unit boundary | ||
377 | */ | ||
378 | int | ||
379 | xfs_bmap_eof( | ||
380 | struct xfs_inode *ip, | ||
381 | xfs_fileoff_t endoff, | ||
382 | int whichfork, | ||
383 | int *eof); | ||
384 | |||
385 | /* | ||
386 | * Count fsblocks of the given fork. | ||
387 | */ | ||
388 | int | ||
389 | xfs_bmap_count_blocks( | ||
390 | xfs_trans_t *tp, | ||
391 | struct xfs_inode *ip, | ||
392 | int whichfork, | ||
393 | int *count); | ||
394 | |||
395 | int | ||
396 | xfs_bmap_punch_delalloc_range( | ||
397 | struct xfs_inode *ip, | ||
398 | xfs_fileoff_t start_fsb, | ||
399 | xfs_fileoff_t length); | ||
400 | #endif /* __KERNEL__ */ | 214 | #endif /* __KERNEL__ */ |
401 | 215 | ||
402 | #endif /* __XFS_BMAP_H__ */ | 216 | #endif /* __XFS_BMAP_H__ */ |
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index 2b9fd385e27d..1f19f03af9d3 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c | |||
@@ -631,7 +631,7 @@ xfs_btree_read_bufl( | |||
631 | } | 631 | } |
632 | ASSERT(!xfs_buf_geterror(bp)); | 632 | ASSERT(!xfs_buf_geterror(bp)); |
633 | if (bp) | 633 | if (bp) |
634 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval); | 634 | xfs_buf_set_ref(bp, refval); |
635 | *bpp = bp; | 635 | *bpp = bp; |
636 | return 0; | 636 | return 0; |
637 | } | 637 | } |
@@ -939,13 +939,13 @@ xfs_btree_set_refs( | |||
939 | switch (cur->bc_btnum) { | 939 | switch (cur->bc_btnum) { |
940 | case XFS_BTNUM_BNO: | 940 | case XFS_BTNUM_BNO: |
941 | case XFS_BTNUM_CNT: | 941 | case XFS_BTNUM_CNT: |
942 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, XFS_ALLOC_BTREE_REF); | 942 | xfs_buf_set_ref(bp, XFS_ALLOC_BTREE_REF); |
943 | break; | 943 | break; |
944 | case XFS_BTNUM_INO: | 944 | case XFS_BTNUM_INO: |
945 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_INOMAP, XFS_INO_BTREE_REF); | 945 | xfs_buf_set_ref(bp, XFS_INO_BTREE_REF); |
946 | break; | 946 | break; |
947 | case XFS_BTNUM_BMAP: | 947 | case XFS_BTNUM_BMAP: |
948 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, XFS_BMAP_BTREE_REF); | 948 | xfs_buf_set_ref(bp, XFS_BMAP_BTREE_REF); |
949 | break; | 949 | break; |
950 | default: | 950 | default: |
951 | ASSERT(0); | 951 | ASSERT(0); |
@@ -970,7 +970,8 @@ xfs_btree_get_buf_block( | |||
970 | *bpp = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d, | 970 | *bpp = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d, |
971 | mp->m_bsize, flags); | 971 | mp->m_bsize, flags); |
972 | 972 | ||
973 | ASSERT(!xfs_buf_geterror(*bpp)); | 973 | if (!*bpp) |
974 | return ENOMEM; | ||
974 | 975 | ||
975 | *block = XFS_BUF_TO_BLOCK(*bpp); | 976 | *block = XFS_BUF_TO_BLOCK(*bpp); |
976 | return 0; | 977 | return 0; |
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index c57836dc778f..cf0ac056815f 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c | |||
@@ -43,7 +43,6 @@ | |||
43 | 43 | ||
44 | static kmem_zone_t *xfs_buf_zone; | 44 | static kmem_zone_t *xfs_buf_zone; |
45 | STATIC int xfsbufd(void *); | 45 | STATIC int xfsbufd(void *); |
46 | STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int); | ||
47 | 46 | ||
48 | static struct workqueue_struct *xfslogd_workqueue; | 47 | static struct workqueue_struct *xfslogd_workqueue; |
49 | struct workqueue_struct *xfsdatad_workqueue; | 48 | struct workqueue_struct *xfsdatad_workqueue; |
@@ -66,10 +65,6 @@ struct workqueue_struct *xfsconvertd_workqueue; | |||
66 | #define xb_to_km(flags) \ | 65 | #define xb_to_km(flags) \ |
67 | (((flags) & XBF_DONT_BLOCK) ? KM_NOFS : KM_SLEEP) | 66 | (((flags) & XBF_DONT_BLOCK) ? KM_NOFS : KM_SLEEP) |
68 | 67 | ||
69 | #define xfs_buf_allocate(flags) \ | ||
70 | kmem_zone_alloc(xfs_buf_zone, xb_to_km(flags)) | ||
71 | #define xfs_buf_deallocate(bp) \ | ||
72 | kmem_zone_free(xfs_buf_zone, (bp)); | ||
73 | 68 | ||
74 | static inline int | 69 | static inline int |
75 | xfs_buf_is_vmapped( | 70 | xfs_buf_is_vmapped( |
@@ -152,6 +147,7 @@ xfs_buf_stale( | |||
152 | struct xfs_buf *bp) | 147 | struct xfs_buf *bp) |
153 | { | 148 | { |
154 | bp->b_flags |= XBF_STALE; | 149 | bp->b_flags |= XBF_STALE; |
150 | xfs_buf_delwri_dequeue(bp); | ||
155 | atomic_set(&(bp)->b_lru_ref, 0); | 151 | atomic_set(&(bp)->b_lru_ref, 0); |
156 | if (!list_empty(&bp->b_lru)) { | 152 | if (!list_empty(&bp->b_lru)) { |
157 | struct xfs_buftarg *btp = bp->b_target; | 153 | struct xfs_buftarg *btp = bp->b_target; |
@@ -167,14 +163,19 @@ xfs_buf_stale( | |||
167 | ASSERT(atomic_read(&bp->b_hold) >= 1); | 163 | ASSERT(atomic_read(&bp->b_hold) >= 1); |
168 | } | 164 | } |
169 | 165 | ||
170 | STATIC void | 166 | struct xfs_buf * |
171 | _xfs_buf_initialize( | 167 | xfs_buf_alloc( |
172 | xfs_buf_t *bp, | 168 | struct xfs_buftarg *target, |
173 | xfs_buftarg_t *target, | ||
174 | xfs_off_t range_base, | 169 | xfs_off_t range_base, |
175 | size_t range_length, | 170 | size_t range_length, |
176 | xfs_buf_flags_t flags) | 171 | xfs_buf_flags_t flags) |
177 | { | 172 | { |
173 | struct xfs_buf *bp; | ||
174 | |||
175 | bp = kmem_zone_alloc(xfs_buf_zone, xb_to_km(flags)); | ||
176 | if (unlikely(!bp)) | ||
177 | return NULL; | ||
178 | |||
178 | /* | 179 | /* |
179 | * We don't want certain flags to appear in b_flags. | 180 | * We don't want certain flags to appear in b_flags. |
180 | */ | 181 | */ |
@@ -203,8 +204,9 @@ _xfs_buf_initialize( | |||
203 | init_waitqueue_head(&bp->b_waiters); | 204 | init_waitqueue_head(&bp->b_waiters); |
204 | 205 | ||
205 | XFS_STATS_INC(xb_create); | 206 | XFS_STATS_INC(xb_create); |
206 | |||
207 | trace_xfs_buf_init(bp, _RET_IP_); | 207 | trace_xfs_buf_init(bp, _RET_IP_); |
208 | |||
209 | return bp; | ||
208 | } | 210 | } |
209 | 211 | ||
210 | /* | 212 | /* |
@@ -277,7 +279,7 @@ xfs_buf_free( | |||
277 | } else if (bp->b_flags & _XBF_KMEM) | 279 | } else if (bp->b_flags & _XBF_KMEM) |
278 | kmem_free(bp->b_addr); | 280 | kmem_free(bp->b_addr); |
279 | _xfs_buf_free_pages(bp); | 281 | _xfs_buf_free_pages(bp); |
280 | xfs_buf_deallocate(bp); | 282 | kmem_zone_free(xfs_buf_zone, bp); |
281 | } | 283 | } |
282 | 284 | ||
283 | /* | 285 | /* |
@@ -416,10 +418,7 @@ _xfs_buf_map_pages( | |||
416 | /* | 418 | /* |
417 | * Look up, and creates if absent, a lockable buffer for | 419 | * Look up, and creates if absent, a lockable buffer for |
418 | * a given range of an inode. The buffer is returned | 420 | * a given range of an inode. The buffer is returned |
419 | * locked. If other overlapping buffers exist, they are | 421 | * locked. No I/O is implied by this call. |
420 | * released before the new buffer is created and locked, | ||
421 | * which may imply that this call will block until those buffers | ||
422 | * are unlocked. No I/O is implied by this call. | ||
423 | */ | 422 | */ |
424 | xfs_buf_t * | 423 | xfs_buf_t * |
425 | _xfs_buf_find( | 424 | _xfs_buf_find( |
@@ -481,8 +480,6 @@ _xfs_buf_find( | |||
481 | 480 | ||
482 | /* No match found */ | 481 | /* No match found */ |
483 | if (new_bp) { | 482 | if (new_bp) { |
484 | _xfs_buf_initialize(new_bp, btp, range_base, | ||
485 | range_length, flags); | ||
486 | rb_link_node(&new_bp->b_rbnode, parent, rbp); | 483 | rb_link_node(&new_bp->b_rbnode, parent, rbp); |
487 | rb_insert_color(&new_bp->b_rbnode, &pag->pag_buf_tree); | 484 | rb_insert_color(&new_bp->b_rbnode, &pag->pag_buf_tree); |
488 | /* the buffer keeps the perag reference until it is freed */ | 485 | /* the buffer keeps the perag reference until it is freed */ |
@@ -525,35 +522,51 @@ found: | |||
525 | } | 522 | } |
526 | 523 | ||
527 | /* | 524 | /* |
528 | * Assembles a buffer covering the specified range. | 525 | * Assembles a buffer covering the specified range. The code is optimised for |
529 | * Storage in memory for all portions of the buffer will be allocated, | 526 | * cache hits, as metadata intensive workloads will see 3 orders of magnitude |
530 | * although backing storage may not be. | 527 | * more hits than misses. |
531 | */ | 528 | */ |
532 | xfs_buf_t * | 529 | struct xfs_buf * |
533 | xfs_buf_get( | 530 | xfs_buf_get( |
534 | xfs_buftarg_t *target,/* target for buffer */ | 531 | xfs_buftarg_t *target,/* target for buffer */ |
535 | xfs_off_t ioff, /* starting offset of range */ | 532 | xfs_off_t ioff, /* starting offset of range */ |
536 | size_t isize, /* length of range */ | 533 | size_t isize, /* length of range */ |
537 | xfs_buf_flags_t flags) | 534 | xfs_buf_flags_t flags) |
538 | { | 535 | { |
539 | xfs_buf_t *bp, *new_bp; | 536 | struct xfs_buf *bp; |
537 | struct xfs_buf *new_bp; | ||
540 | int error = 0; | 538 | int error = 0; |
541 | 539 | ||
542 | new_bp = xfs_buf_allocate(flags); | 540 | bp = _xfs_buf_find(target, ioff, isize, flags, NULL); |
541 | if (likely(bp)) | ||
542 | goto found; | ||
543 | |||
544 | new_bp = xfs_buf_alloc(target, ioff << BBSHIFT, isize << BBSHIFT, | ||
545 | flags); | ||
543 | if (unlikely(!new_bp)) | 546 | if (unlikely(!new_bp)) |
544 | return NULL; | 547 | return NULL; |
545 | 548 | ||
546 | bp = _xfs_buf_find(target, ioff, isize, flags, new_bp); | 549 | bp = _xfs_buf_find(target, ioff, isize, flags, new_bp); |
550 | if (!bp) { | ||
551 | kmem_zone_free(xfs_buf_zone, new_bp); | ||
552 | return NULL; | ||
553 | } | ||
554 | |||
547 | if (bp == new_bp) { | 555 | if (bp == new_bp) { |
548 | error = xfs_buf_allocate_memory(bp, flags); | 556 | error = xfs_buf_allocate_memory(bp, flags); |
549 | if (error) | 557 | if (error) |
550 | goto no_buffer; | 558 | goto no_buffer; |
551 | } else { | 559 | } else |
552 | xfs_buf_deallocate(new_bp); | 560 | kmem_zone_free(xfs_buf_zone, new_bp); |
553 | if (unlikely(bp == NULL)) | ||
554 | return NULL; | ||
555 | } | ||
556 | 561 | ||
562 | /* | ||
563 | * Now we have a workable buffer, fill in the block number so | ||
564 | * that we can do IO on it. | ||
565 | */ | ||
566 | bp->b_bn = ioff; | ||
567 | bp->b_count_desired = bp->b_buffer_length; | ||
568 | |||
569 | found: | ||
557 | if (!(bp->b_flags & XBF_MAPPED)) { | 570 | if (!(bp->b_flags & XBF_MAPPED)) { |
558 | error = _xfs_buf_map_pages(bp, flags); | 571 | error = _xfs_buf_map_pages(bp, flags); |
559 | if (unlikely(error)) { | 572 | if (unlikely(error)) { |
@@ -564,18 +577,10 @@ xfs_buf_get( | |||
564 | } | 577 | } |
565 | 578 | ||
566 | XFS_STATS_INC(xb_get); | 579 | XFS_STATS_INC(xb_get); |
567 | |||
568 | /* | ||
569 | * Always fill in the block number now, the mapped cases can do | ||
570 | * their own overlay of this later. | ||
571 | */ | ||
572 | bp->b_bn = ioff; | ||
573 | bp->b_count_desired = bp->b_buffer_length; | ||
574 | |||
575 | trace_xfs_buf_get(bp, flags, _RET_IP_); | 580 | trace_xfs_buf_get(bp, flags, _RET_IP_); |
576 | return bp; | 581 | return bp; |
577 | 582 | ||
578 | no_buffer: | 583 | no_buffer: |
579 | if (flags & (XBF_LOCK | XBF_TRYLOCK)) | 584 | if (flags & (XBF_LOCK | XBF_TRYLOCK)) |
580 | xfs_buf_unlock(bp); | 585 | xfs_buf_unlock(bp); |
581 | xfs_buf_rele(bp); | 586 | xfs_buf_rele(bp); |
@@ -689,19 +694,6 @@ xfs_buf_read_uncached( | |||
689 | return bp; | 694 | return bp; |
690 | } | 695 | } |
691 | 696 | ||
692 | xfs_buf_t * | ||
693 | xfs_buf_get_empty( | ||
694 | size_t len, | ||
695 | xfs_buftarg_t *target) | ||
696 | { | ||
697 | xfs_buf_t *bp; | ||
698 | |||
699 | bp = xfs_buf_allocate(0); | ||
700 | if (bp) | ||
701 | _xfs_buf_initialize(bp, target, 0, len, 0); | ||
702 | return bp; | ||
703 | } | ||
704 | |||
705 | /* | 697 | /* |
706 | * Return a buffer allocated as an empty buffer and associated to external | 698 | * Return a buffer allocated as an empty buffer and associated to external |
707 | * memory via xfs_buf_associate_memory() back to it's empty state. | 699 | * memory via xfs_buf_associate_memory() back to it's empty state. |
@@ -787,10 +779,9 @@ xfs_buf_get_uncached( | |||
787 | int error, i; | 779 | int error, i; |
788 | xfs_buf_t *bp; | 780 | xfs_buf_t *bp; |
789 | 781 | ||
790 | bp = xfs_buf_allocate(0); | 782 | bp = xfs_buf_alloc(target, 0, len, 0); |
791 | if (unlikely(bp == NULL)) | 783 | if (unlikely(bp == NULL)) |
792 | goto fail; | 784 | goto fail; |
793 | _xfs_buf_initialize(bp, target, 0, len, 0); | ||
794 | 785 | ||
795 | error = _xfs_buf_get_pages(bp, page_count, 0); | 786 | error = _xfs_buf_get_pages(bp, page_count, 0); |
796 | if (error) | 787 | if (error) |
@@ -818,7 +809,7 @@ xfs_buf_get_uncached( | |||
818 | __free_page(bp->b_pages[i]); | 809 | __free_page(bp->b_pages[i]); |
819 | _xfs_buf_free_pages(bp); | 810 | _xfs_buf_free_pages(bp); |
820 | fail_free_buf: | 811 | fail_free_buf: |
821 | xfs_buf_deallocate(bp); | 812 | kmem_zone_free(xfs_buf_zone, bp); |
822 | fail: | 813 | fail: |
823 | return NULL; | 814 | return NULL; |
824 | } | 815 | } |
@@ -937,12 +928,6 @@ void | |||
937 | xfs_buf_unlock( | 928 | xfs_buf_unlock( |
938 | struct xfs_buf *bp) | 929 | struct xfs_buf *bp) |
939 | { | 930 | { |
940 | if ((bp->b_flags & (XBF_DELWRI|_XBF_DELWRI_Q)) == XBF_DELWRI) { | ||
941 | atomic_inc(&bp->b_hold); | ||
942 | bp->b_flags |= XBF_ASYNC; | ||
943 | xfs_buf_delwri_queue(bp, 0); | ||
944 | } | ||
945 | |||
946 | XB_CLEAR_OWNER(bp); | 931 | XB_CLEAR_OWNER(bp); |
947 | up(&bp->b_sema); | 932 | up(&bp->b_sema); |
948 | 933 | ||
@@ -1019,9 +1004,19 @@ xfs_buf_ioerror( | |||
1019 | trace_xfs_buf_ioerror(bp, error, _RET_IP_); | 1004 | trace_xfs_buf_ioerror(bp, error, _RET_IP_); |
1020 | } | 1005 | } |
1021 | 1006 | ||
1007 | void | ||
1008 | xfs_buf_ioerror_alert( | ||
1009 | struct xfs_buf *bp, | ||
1010 | const char *func) | ||
1011 | { | ||
1012 | xfs_alert(bp->b_target->bt_mount, | ||
1013 | "metadata I/O error: block 0x%llx (\"%s\") error %d buf count %zd", | ||
1014 | (__uint64_t)XFS_BUF_ADDR(bp), func, | ||
1015 | bp->b_error, XFS_BUF_COUNT(bp)); | ||
1016 | } | ||
1017 | |||
1022 | int | 1018 | int |
1023 | xfs_bwrite( | 1019 | xfs_bwrite( |
1024 | struct xfs_mount *mp, | ||
1025 | struct xfs_buf *bp) | 1020 | struct xfs_buf *bp) |
1026 | { | 1021 | { |
1027 | int error; | 1022 | int error; |
@@ -1033,25 +1028,13 @@ xfs_bwrite( | |||
1033 | xfs_bdstrat_cb(bp); | 1028 | xfs_bdstrat_cb(bp); |
1034 | 1029 | ||
1035 | error = xfs_buf_iowait(bp); | 1030 | error = xfs_buf_iowait(bp); |
1036 | if (error) | 1031 | if (error) { |
1037 | xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); | 1032 | xfs_force_shutdown(bp->b_target->bt_mount, |
1038 | xfs_buf_relse(bp); | 1033 | SHUTDOWN_META_IO_ERROR); |
1034 | } | ||
1039 | return error; | 1035 | return error; |
1040 | } | 1036 | } |
1041 | 1037 | ||
1042 | void | ||
1043 | xfs_bdwrite( | ||
1044 | void *mp, | ||
1045 | struct xfs_buf *bp) | ||
1046 | { | ||
1047 | trace_xfs_buf_bdwrite(bp, _RET_IP_); | ||
1048 | |||
1049 | bp->b_flags &= ~XBF_READ; | ||
1050 | bp->b_flags |= (XBF_DELWRI | XBF_ASYNC); | ||
1051 | |||
1052 | xfs_buf_delwri_queue(bp, 1); | ||
1053 | } | ||
1054 | |||
1055 | /* | 1038 | /* |
1056 | * Called when we want to stop a buffer from getting written or read. | 1039 | * Called when we want to stop a buffer from getting written or read. |
1057 | * We attach the EIO error, muck with its flags, and call xfs_buf_ioend | 1040 | * We attach the EIO error, muck with its flags, and call xfs_buf_ioend |
@@ -1074,9 +1057,8 @@ xfs_bioerror( | |||
1074 | * We're calling xfs_buf_ioend, so delete XBF_DONE flag. | 1057 | * We're calling xfs_buf_ioend, so delete XBF_DONE flag. |
1075 | */ | 1058 | */ |
1076 | XFS_BUF_UNREAD(bp); | 1059 | XFS_BUF_UNREAD(bp); |
1077 | XFS_BUF_UNDELAYWRITE(bp); | ||
1078 | XFS_BUF_UNDONE(bp); | 1060 | XFS_BUF_UNDONE(bp); |
1079 | XFS_BUF_STALE(bp); | 1061 | xfs_buf_stale(bp); |
1080 | 1062 | ||
1081 | xfs_buf_ioend(bp, 0); | 1063 | xfs_buf_ioend(bp, 0); |
1082 | 1064 | ||
@@ -1103,9 +1085,8 @@ xfs_bioerror_relse( | |||
1103 | * change that interface. | 1085 | * change that interface. |
1104 | */ | 1086 | */ |
1105 | XFS_BUF_UNREAD(bp); | 1087 | XFS_BUF_UNREAD(bp); |
1106 | XFS_BUF_UNDELAYWRITE(bp); | ||
1107 | XFS_BUF_DONE(bp); | 1088 | XFS_BUF_DONE(bp); |
1108 | XFS_BUF_STALE(bp); | 1089 | xfs_buf_stale(bp); |
1109 | bp->b_iodone = NULL; | 1090 | bp->b_iodone = NULL; |
1110 | if (!(fl & XBF_ASYNC)) { | 1091 | if (!(fl & XBF_ASYNC)) { |
1111 | /* | 1092 | /* |
@@ -1115,7 +1096,7 @@ xfs_bioerror_relse( | |||
1115 | * ASYNC buffers. | 1096 | * ASYNC buffers. |
1116 | */ | 1097 | */ |
1117 | xfs_buf_ioerror(bp, EIO); | 1098 | xfs_buf_ioerror(bp, EIO); |
1118 | XFS_BUF_FINISH_IOWAIT(bp); | 1099 | complete(&bp->b_iowait); |
1119 | } else { | 1100 | } else { |
1120 | xfs_buf_relse(bp); | 1101 | xfs_buf_relse(bp); |
1121 | } | 1102 | } |
@@ -1275,15 +1256,10 @@ xfs_buf_iorequest( | |||
1275 | { | 1256 | { |
1276 | trace_xfs_buf_iorequest(bp, _RET_IP_); | 1257 | trace_xfs_buf_iorequest(bp, _RET_IP_); |
1277 | 1258 | ||
1278 | if (bp->b_flags & XBF_DELWRI) { | 1259 | ASSERT(!(bp->b_flags & XBF_DELWRI)); |
1279 | xfs_buf_delwri_queue(bp, 1); | ||
1280 | return 0; | ||
1281 | } | ||
1282 | 1260 | ||
1283 | if (bp->b_flags & XBF_WRITE) { | 1261 | if (bp->b_flags & XBF_WRITE) |
1284 | xfs_buf_wait_unpin(bp); | 1262 | xfs_buf_wait_unpin(bp); |
1285 | } | ||
1286 | |||
1287 | xfs_buf_hold(bp); | 1263 | xfs_buf_hold(bp); |
1288 | 1264 | ||
1289 | /* Set the count to 1 initially, this will stop an I/O | 1265 | /* Set the count to 1 initially, this will stop an I/O |
@@ -1481,9 +1457,13 @@ xfs_setsize_buftarg_flags( | |||
1481 | btp->bt_smask = sectorsize - 1; | 1457 | btp->bt_smask = sectorsize - 1; |
1482 | 1458 | ||
1483 | if (set_blocksize(btp->bt_bdev, sectorsize)) { | 1459 | if (set_blocksize(btp->bt_bdev, sectorsize)) { |
1460 | char name[BDEVNAME_SIZE]; | ||
1461 | |||
1462 | bdevname(btp->bt_bdev, name); | ||
1463 | |||
1484 | xfs_warn(btp->bt_mount, | 1464 | xfs_warn(btp->bt_mount, |
1485 | "Cannot set_blocksize to %u on device %s\n", | 1465 | "Cannot set_blocksize to %u on device %s\n", |
1486 | sectorsize, xfs_buf_target_name(btp)); | 1466 | sectorsize, name); |
1487 | return EINVAL; | 1467 | return EINVAL; |
1488 | } | 1468 | } |
1489 | 1469 | ||
@@ -1514,12 +1494,12 @@ xfs_setsize_buftarg( | |||
1514 | } | 1494 | } |
1515 | 1495 | ||
1516 | STATIC int | 1496 | STATIC int |
1517 | xfs_alloc_delwrite_queue( | 1497 | xfs_alloc_delwri_queue( |
1518 | xfs_buftarg_t *btp, | 1498 | xfs_buftarg_t *btp, |
1519 | const char *fsname) | 1499 | const char *fsname) |
1520 | { | 1500 | { |
1521 | INIT_LIST_HEAD(&btp->bt_delwrite_queue); | 1501 | INIT_LIST_HEAD(&btp->bt_delwri_queue); |
1522 | spin_lock_init(&btp->bt_delwrite_lock); | 1502 | spin_lock_init(&btp->bt_delwri_lock); |
1523 | btp->bt_flags = 0; | 1503 | btp->bt_flags = 0; |
1524 | btp->bt_task = kthread_run(xfsbufd, btp, "xfsbufd/%s", fsname); | 1504 | btp->bt_task = kthread_run(xfsbufd, btp, "xfsbufd/%s", fsname); |
1525 | if (IS_ERR(btp->bt_task)) | 1505 | if (IS_ERR(btp->bt_task)) |
@@ -1549,7 +1529,7 @@ xfs_alloc_buftarg( | |||
1549 | spin_lock_init(&btp->bt_lru_lock); | 1529 | spin_lock_init(&btp->bt_lru_lock); |
1550 | if (xfs_setsize_buftarg_early(btp, bdev)) | 1530 | if (xfs_setsize_buftarg_early(btp, bdev)) |
1551 | goto error; | 1531 | goto error; |
1552 | if (xfs_alloc_delwrite_queue(btp, fsname)) | 1532 | if (xfs_alloc_delwri_queue(btp, fsname)) |
1553 | goto error; | 1533 | goto error; |
1554 | btp->bt_shrinker.shrink = xfs_buftarg_shrink; | 1534 | btp->bt_shrinker.shrink = xfs_buftarg_shrink; |
1555 | btp->bt_shrinker.seeks = DEFAULT_SEEKS; | 1535 | btp->bt_shrinker.seeks = DEFAULT_SEEKS; |
@@ -1565,56 +1545,48 @@ error: | |||
1565 | /* | 1545 | /* |
1566 | * Delayed write buffer handling | 1546 | * Delayed write buffer handling |
1567 | */ | 1547 | */ |
1568 | STATIC void | 1548 | void |
1569 | xfs_buf_delwri_queue( | 1549 | xfs_buf_delwri_queue( |
1570 | xfs_buf_t *bp, | 1550 | xfs_buf_t *bp) |
1571 | int unlock) | ||
1572 | { | 1551 | { |
1573 | struct list_head *dwq = &bp->b_target->bt_delwrite_queue; | 1552 | struct xfs_buftarg *btp = bp->b_target; |
1574 | spinlock_t *dwlk = &bp->b_target->bt_delwrite_lock; | ||
1575 | 1553 | ||
1576 | trace_xfs_buf_delwri_queue(bp, _RET_IP_); | 1554 | trace_xfs_buf_delwri_queue(bp, _RET_IP_); |
1577 | 1555 | ||
1578 | ASSERT((bp->b_flags&(XBF_DELWRI|XBF_ASYNC)) == (XBF_DELWRI|XBF_ASYNC)); | 1556 | ASSERT(!(bp->b_flags & XBF_READ)); |
1579 | 1557 | ||
1580 | spin_lock(dwlk); | 1558 | spin_lock(&btp->bt_delwri_lock); |
1581 | /* If already in the queue, dequeue and place at tail */ | ||
1582 | if (!list_empty(&bp->b_list)) { | 1559 | if (!list_empty(&bp->b_list)) { |
1560 | /* if already in the queue, move it to the tail */ | ||
1583 | ASSERT(bp->b_flags & _XBF_DELWRI_Q); | 1561 | ASSERT(bp->b_flags & _XBF_DELWRI_Q); |
1584 | if (unlock) | 1562 | list_move_tail(&bp->b_list, &btp->bt_delwri_queue); |
1585 | atomic_dec(&bp->b_hold); | 1563 | } else { |
1586 | list_del(&bp->b_list); | ||
1587 | } | ||
1588 | |||
1589 | if (list_empty(dwq)) { | ||
1590 | /* start xfsbufd as it is about to have something to do */ | 1564 | /* start xfsbufd as it is about to have something to do */ |
1591 | wake_up_process(bp->b_target->bt_task); | 1565 | if (list_empty(&btp->bt_delwri_queue)) |
1592 | } | 1566 | wake_up_process(bp->b_target->bt_task); |
1593 | 1567 | ||
1594 | bp->b_flags |= _XBF_DELWRI_Q; | 1568 | atomic_inc(&bp->b_hold); |
1595 | list_add_tail(&bp->b_list, dwq); | 1569 | bp->b_flags |= XBF_DELWRI | _XBF_DELWRI_Q | XBF_ASYNC; |
1570 | list_add_tail(&bp->b_list, &btp->bt_delwri_queue); | ||
1571 | } | ||
1596 | bp->b_queuetime = jiffies; | 1572 | bp->b_queuetime = jiffies; |
1597 | spin_unlock(dwlk); | 1573 | spin_unlock(&btp->bt_delwri_lock); |
1598 | |||
1599 | if (unlock) | ||
1600 | xfs_buf_unlock(bp); | ||
1601 | } | 1574 | } |
1602 | 1575 | ||
1603 | void | 1576 | void |
1604 | xfs_buf_delwri_dequeue( | 1577 | xfs_buf_delwri_dequeue( |
1605 | xfs_buf_t *bp) | 1578 | xfs_buf_t *bp) |
1606 | { | 1579 | { |
1607 | spinlock_t *dwlk = &bp->b_target->bt_delwrite_lock; | ||
1608 | int dequeued = 0; | 1580 | int dequeued = 0; |
1609 | 1581 | ||
1610 | spin_lock(dwlk); | 1582 | spin_lock(&bp->b_target->bt_delwri_lock); |
1611 | if ((bp->b_flags & XBF_DELWRI) && !list_empty(&bp->b_list)) { | 1583 | if ((bp->b_flags & XBF_DELWRI) && !list_empty(&bp->b_list)) { |
1612 | ASSERT(bp->b_flags & _XBF_DELWRI_Q); | 1584 | ASSERT(bp->b_flags & _XBF_DELWRI_Q); |
1613 | list_del_init(&bp->b_list); | 1585 | list_del_init(&bp->b_list); |
1614 | dequeued = 1; | 1586 | dequeued = 1; |
1615 | } | 1587 | } |
1616 | bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q); | 1588 | bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q); |
1617 | spin_unlock(dwlk); | 1589 | spin_unlock(&bp->b_target->bt_delwri_lock); |
1618 | 1590 | ||
1619 | if (dequeued) | 1591 | if (dequeued) |
1620 | xfs_buf_rele(bp); | 1592 | xfs_buf_rele(bp); |
@@ -1646,16 +1618,9 @@ xfs_buf_delwri_promote( | |||
1646 | if (bp->b_queuetime < jiffies - age) | 1618 | if (bp->b_queuetime < jiffies - age) |
1647 | return; | 1619 | return; |
1648 | bp->b_queuetime = jiffies - age; | 1620 | bp->b_queuetime = jiffies - age; |
1649 | spin_lock(&btp->bt_delwrite_lock); | 1621 | spin_lock(&btp->bt_delwri_lock); |
1650 | list_move(&bp->b_list, &btp->bt_delwrite_queue); | 1622 | list_move(&bp->b_list, &btp->bt_delwri_queue); |
1651 | spin_unlock(&btp->bt_delwrite_lock); | 1623 | spin_unlock(&btp->bt_delwri_lock); |
1652 | } | ||
1653 | |||
1654 | STATIC void | ||
1655 | xfs_buf_runall_queues( | ||
1656 | struct workqueue_struct *queue) | ||
1657 | { | ||
1658 | flush_workqueue(queue); | ||
1659 | } | 1624 | } |
1660 | 1625 | ||
1661 | /* | 1626 | /* |
@@ -1669,15 +1634,13 @@ xfs_buf_delwri_split( | |||
1669 | unsigned long age) | 1634 | unsigned long age) |
1670 | { | 1635 | { |
1671 | xfs_buf_t *bp, *n; | 1636 | xfs_buf_t *bp, *n; |
1672 | struct list_head *dwq = &target->bt_delwrite_queue; | ||
1673 | spinlock_t *dwlk = &target->bt_delwrite_lock; | ||
1674 | int skipped = 0; | 1637 | int skipped = 0; |
1675 | int force; | 1638 | int force; |
1676 | 1639 | ||
1677 | force = test_and_clear_bit(XBT_FORCE_FLUSH, &target->bt_flags); | 1640 | force = test_and_clear_bit(XBT_FORCE_FLUSH, &target->bt_flags); |
1678 | INIT_LIST_HEAD(list); | 1641 | INIT_LIST_HEAD(list); |
1679 | spin_lock(dwlk); | 1642 | spin_lock(&target->bt_delwri_lock); |
1680 | list_for_each_entry_safe(bp, n, dwq, b_list) { | 1643 | list_for_each_entry_safe(bp, n, &target->bt_delwri_queue, b_list) { |
1681 | ASSERT(bp->b_flags & XBF_DELWRI); | 1644 | ASSERT(bp->b_flags & XBF_DELWRI); |
1682 | 1645 | ||
1683 | if (!xfs_buf_ispinned(bp) && xfs_buf_trylock(bp)) { | 1646 | if (!xfs_buf_ispinned(bp) && xfs_buf_trylock(bp)) { |
@@ -1694,10 +1657,9 @@ xfs_buf_delwri_split( | |||
1694 | } else | 1657 | } else |
1695 | skipped++; | 1658 | skipped++; |
1696 | } | 1659 | } |
1697 | spin_unlock(dwlk); | ||
1698 | 1660 | ||
1661 | spin_unlock(&target->bt_delwri_lock); | ||
1699 | return skipped; | 1662 | return skipped; |
1700 | |||
1701 | } | 1663 | } |
1702 | 1664 | ||
1703 | /* | 1665 | /* |
@@ -1747,7 +1709,7 @@ xfsbufd( | |||
1747 | } | 1709 | } |
1748 | 1710 | ||
1749 | /* sleep for a long time if there is nothing to do. */ | 1711 | /* sleep for a long time if there is nothing to do. */ |
1750 | if (list_empty(&target->bt_delwrite_queue)) | 1712 | if (list_empty(&target->bt_delwri_queue)) |
1751 | tout = MAX_SCHEDULE_TIMEOUT; | 1713 | tout = MAX_SCHEDULE_TIMEOUT; |
1752 | schedule_timeout_interruptible(tout); | 1714 | schedule_timeout_interruptible(tout); |
1753 | 1715 | ||
@@ -1783,9 +1745,7 @@ xfs_flush_buftarg( | |||
1783 | LIST_HEAD(wait_list); | 1745 | LIST_HEAD(wait_list); |
1784 | struct blk_plug plug; | 1746 | struct blk_plug plug; |
1785 | 1747 | ||
1786 | xfs_buf_runall_queues(xfsconvertd_workqueue); | 1748 | flush_workqueue(xfslogd_workqueue); |
1787 | xfs_buf_runall_queues(xfsdatad_workqueue); | ||
1788 | xfs_buf_runall_queues(xfslogd_workqueue); | ||
1789 | 1749 | ||
1790 | set_bit(XBT_FORCE_FLUSH, &target->bt_flags); | 1750 | set_bit(XBT_FORCE_FLUSH, &target->bt_flags); |
1791 | pincount = xfs_buf_delwri_split(target, &tmp_list, 0); | 1751 | pincount = xfs_buf_delwri_split(target, &tmp_list, 0); |
@@ -1866,11 +1826,3 @@ xfs_buf_terminate(void) | |||
1866 | destroy_workqueue(xfslogd_workqueue); | 1826 | destroy_workqueue(xfslogd_workqueue); |
1867 | kmem_zone_destroy(xfs_buf_zone); | 1827 | kmem_zone_destroy(xfs_buf_zone); |
1868 | } | 1828 | } |
1869 | |||
1870 | #ifdef CONFIG_KDB_MODULES | ||
1871 | struct list_head * | ||
1872 | xfs_get_buftarg_list(void) | ||
1873 | { | ||
1874 | return &xfs_buftarg_list; | ||
1875 | } | ||
1876 | #endif | ||
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index 620972b8094d..5bab046e859f 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h | |||
@@ -105,8 +105,8 @@ typedef struct xfs_buftarg { | |||
105 | 105 | ||
106 | /* per device delwri queue */ | 106 | /* per device delwri queue */ |
107 | struct task_struct *bt_task; | 107 | struct task_struct *bt_task; |
108 | struct list_head bt_delwrite_queue; | 108 | struct list_head bt_delwri_queue; |
109 | spinlock_t bt_delwrite_lock; | 109 | spinlock_t bt_delwri_lock; |
110 | unsigned long bt_flags; | 110 | unsigned long bt_flags; |
111 | 111 | ||
112 | /* LRU control structures */ | 112 | /* LRU control structures */ |
@@ -175,7 +175,8 @@ extern xfs_buf_t *xfs_buf_get(xfs_buftarg_t *, xfs_off_t, size_t, | |||
175 | extern xfs_buf_t *xfs_buf_read(xfs_buftarg_t *, xfs_off_t, size_t, | 175 | extern xfs_buf_t *xfs_buf_read(xfs_buftarg_t *, xfs_off_t, size_t, |
176 | xfs_buf_flags_t); | 176 | xfs_buf_flags_t); |
177 | 177 | ||
178 | extern xfs_buf_t *xfs_buf_get_empty(size_t, xfs_buftarg_t *); | 178 | struct xfs_buf *xfs_buf_alloc(struct xfs_buftarg *, xfs_off_t, size_t, |
179 | xfs_buf_flags_t); | ||
179 | extern void xfs_buf_set_empty(struct xfs_buf *bp, size_t len); | 180 | extern void xfs_buf_set_empty(struct xfs_buf *bp, size_t len); |
180 | extern xfs_buf_t *xfs_buf_get_uncached(struct xfs_buftarg *, size_t, int); | 181 | extern xfs_buf_t *xfs_buf_get_uncached(struct xfs_buftarg *, size_t, int); |
181 | extern int xfs_buf_associate_memory(xfs_buf_t *, void *, size_t); | 182 | extern int xfs_buf_associate_memory(xfs_buf_t *, void *, size_t); |
@@ -197,14 +198,14 @@ extern void xfs_buf_unlock(xfs_buf_t *); | |||
197 | ((bp)->b_sema.count <= 0) | 198 | ((bp)->b_sema.count <= 0) |
198 | 199 | ||
199 | /* Buffer Read and Write Routines */ | 200 | /* Buffer Read and Write Routines */ |
200 | extern int xfs_bwrite(struct xfs_mount *mp, struct xfs_buf *bp); | 201 | extern int xfs_bwrite(struct xfs_buf *bp); |
201 | extern void xfs_bdwrite(void *mp, xfs_buf_t *bp); | ||
202 | 202 | ||
203 | extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *); | 203 | extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *); |
204 | extern int xfs_bdstrat_cb(struct xfs_buf *); | 204 | extern int xfs_bdstrat_cb(struct xfs_buf *); |
205 | 205 | ||
206 | extern void xfs_buf_ioend(xfs_buf_t *, int); | 206 | extern void xfs_buf_ioend(xfs_buf_t *, int); |
207 | extern void xfs_buf_ioerror(xfs_buf_t *, int); | 207 | extern void xfs_buf_ioerror(xfs_buf_t *, int); |
208 | extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func); | ||
208 | extern int xfs_buf_iorequest(xfs_buf_t *); | 209 | extern int xfs_buf_iorequest(xfs_buf_t *); |
209 | extern int xfs_buf_iowait(xfs_buf_t *); | 210 | extern int xfs_buf_iowait(xfs_buf_t *); |
210 | extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *, | 211 | extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *, |
@@ -221,38 +222,22 @@ static inline int xfs_buf_geterror(xfs_buf_t *bp) | |||
221 | extern xfs_caddr_t xfs_buf_offset(xfs_buf_t *, size_t); | 222 | extern xfs_caddr_t xfs_buf_offset(xfs_buf_t *, size_t); |
222 | 223 | ||
223 | /* Delayed Write Buffer Routines */ | 224 | /* Delayed Write Buffer Routines */ |
224 | extern void xfs_buf_delwri_dequeue(xfs_buf_t *); | 225 | extern void xfs_buf_delwri_queue(struct xfs_buf *); |
225 | extern void xfs_buf_delwri_promote(xfs_buf_t *); | 226 | extern void xfs_buf_delwri_dequeue(struct xfs_buf *); |
227 | extern void xfs_buf_delwri_promote(struct xfs_buf *); | ||
226 | 228 | ||
227 | /* Buffer Daemon Setup Routines */ | 229 | /* Buffer Daemon Setup Routines */ |
228 | extern int xfs_buf_init(void); | 230 | extern int xfs_buf_init(void); |
229 | extern void xfs_buf_terminate(void); | 231 | extern void xfs_buf_terminate(void); |
230 | 232 | ||
231 | static inline const char * | ||
232 | xfs_buf_target_name(struct xfs_buftarg *target) | ||
233 | { | ||
234 | static char __b[BDEVNAME_SIZE]; | ||
235 | |||
236 | return bdevname(target->bt_bdev, __b); | ||
237 | } | ||
238 | |||
239 | |||
240 | #define XFS_BUF_ZEROFLAGS(bp) \ | 233 | #define XFS_BUF_ZEROFLAGS(bp) \ |
241 | ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI| \ | 234 | ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI| \ |
242 | XBF_SYNCIO|XBF_FUA|XBF_FLUSH)) | 235 | XBF_SYNCIO|XBF_FUA|XBF_FLUSH)) |
243 | 236 | ||
244 | void xfs_buf_stale(struct xfs_buf *bp); | 237 | void xfs_buf_stale(struct xfs_buf *bp); |
245 | #define XFS_BUF_STALE(bp) xfs_buf_stale(bp); | ||
246 | #define XFS_BUF_UNSTALE(bp) ((bp)->b_flags &= ~XBF_STALE) | 238 | #define XFS_BUF_UNSTALE(bp) ((bp)->b_flags &= ~XBF_STALE) |
247 | #define XFS_BUF_ISSTALE(bp) ((bp)->b_flags & XBF_STALE) | 239 | #define XFS_BUF_ISSTALE(bp) ((bp)->b_flags & XBF_STALE) |
248 | #define XFS_BUF_SUPER_STALE(bp) do { \ | 240 | |
249 | XFS_BUF_STALE(bp); \ | ||
250 | xfs_buf_delwri_dequeue(bp); \ | ||
251 | XFS_BUF_DONE(bp); \ | ||
252 | } while (0) | ||
253 | |||
254 | #define XFS_BUF_DELAYWRITE(bp) ((bp)->b_flags |= XBF_DELWRI) | ||
255 | #define XFS_BUF_UNDELAYWRITE(bp) xfs_buf_delwri_dequeue(bp) | ||
256 | #define XFS_BUF_ISDELAYWRITE(bp) ((bp)->b_flags & XBF_DELWRI) | 241 | #define XFS_BUF_ISDELAYWRITE(bp) ((bp)->b_flags & XBF_DELWRI) |
257 | 242 | ||
258 | #define XFS_BUF_DONE(bp) ((bp)->b_flags |= XBF_DONE) | 243 | #define XFS_BUF_DONE(bp) ((bp)->b_flags |= XBF_DONE) |
@@ -280,23 +265,16 @@ void xfs_buf_stale(struct xfs_buf *bp); | |||
280 | #define XFS_BUF_SIZE(bp) ((bp)->b_buffer_length) | 265 | #define XFS_BUF_SIZE(bp) ((bp)->b_buffer_length) |
281 | #define XFS_BUF_SET_SIZE(bp, cnt) ((bp)->b_buffer_length = (cnt)) | 266 | #define XFS_BUF_SET_SIZE(bp, cnt) ((bp)->b_buffer_length = (cnt)) |
282 | 267 | ||
283 | static inline void | 268 | static inline void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref) |
284 | xfs_buf_set_ref( | ||
285 | struct xfs_buf *bp, | ||
286 | int lru_ref) | ||
287 | { | 269 | { |
288 | atomic_set(&bp->b_lru_ref, lru_ref); | 270 | atomic_set(&bp->b_lru_ref, lru_ref); |
289 | } | 271 | } |
290 | #define XFS_BUF_SET_VTYPE_REF(bp, type, ref) xfs_buf_set_ref(bp, ref) | ||
291 | #define XFS_BUF_SET_VTYPE(bp, type) do { } while (0) | ||
292 | 272 | ||
293 | static inline int xfs_buf_ispinned(struct xfs_buf *bp) | 273 | static inline int xfs_buf_ispinned(struct xfs_buf *bp) |
294 | { | 274 | { |
295 | return atomic_read(&bp->b_pin_count); | 275 | return atomic_read(&bp->b_pin_count); |
296 | } | 276 | } |
297 | 277 | ||
298 | #define XFS_BUF_FINISH_IOWAIT(bp) complete(&bp->b_iowait); | ||
299 | |||
300 | static inline void xfs_buf_relse(xfs_buf_t *bp) | 278 | static inline void xfs_buf_relse(xfs_buf_t *bp) |
301 | { | 279 | { |
302 | xfs_buf_unlock(bp); | 280 | xfs_buf_unlock(bp); |
@@ -313,14 +291,7 @@ extern void xfs_wait_buftarg(xfs_buftarg_t *); | |||
313 | extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int); | 291 | extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int); |
314 | extern int xfs_flush_buftarg(xfs_buftarg_t *, int); | 292 | extern int xfs_flush_buftarg(xfs_buftarg_t *, int); |
315 | 293 | ||
316 | #ifdef CONFIG_KDB_MODULES | ||
317 | extern struct list_head *xfs_get_buftarg_list(void); | ||
318 | #endif | ||
319 | |||
320 | #define xfs_getsize_buftarg(buftarg) block_size((buftarg)->bt_bdev) | 294 | #define xfs_getsize_buftarg(buftarg) block_size((buftarg)->bt_bdev) |
321 | #define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev) | 295 | #define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev) |
322 | 296 | ||
323 | #define xfs_binval(buftarg) xfs_flush_buftarg(buftarg, 1) | ||
324 | #define XFS_bflush(buftarg) xfs_flush_buftarg(buftarg, 1) | ||
325 | |||
326 | #endif /* __XFS_BUF_H__ */ | 297 | #endif /* __XFS_BUF_H__ */ |
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index ef43fce519a1..1a3513881bce 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -967,7 +967,8 @@ xfs_buf_iodone_callbacks( | |||
967 | * I/O errors, there's no point in giving this a retry. | 967 | * I/O errors, there's no point in giving this a retry. |
968 | */ | 968 | */ |
969 | if (XFS_FORCED_SHUTDOWN(mp)) { | 969 | if (XFS_FORCED_SHUTDOWN(mp)) { |
970 | XFS_BUF_SUPER_STALE(bp); | 970 | xfs_buf_stale(bp); |
971 | XFS_BUF_DONE(bp); | ||
971 | trace_xfs_buf_item_iodone(bp, _RET_IP_); | 972 | trace_xfs_buf_item_iodone(bp, _RET_IP_); |
972 | goto do_callbacks; | 973 | goto do_callbacks; |
973 | } | 974 | } |
@@ -975,9 +976,7 @@ xfs_buf_iodone_callbacks( | |||
975 | if (bp->b_target != lasttarg || | 976 | if (bp->b_target != lasttarg || |
976 | time_after(jiffies, (lasttime + 5*HZ))) { | 977 | time_after(jiffies, (lasttime + 5*HZ))) { |
977 | lasttime = jiffies; | 978 | lasttime = jiffies; |
978 | xfs_alert(mp, "Device %s: metadata write error block 0x%llx", | 979 | xfs_buf_ioerror_alert(bp, __func__); |
979 | xfs_buf_target_name(bp->b_target), | ||
980 | (__uint64_t)XFS_BUF_ADDR(bp)); | ||
981 | } | 980 | } |
982 | lasttarg = bp->b_target; | 981 | lasttarg = bp->b_target; |
983 | 982 | ||
@@ -993,7 +992,7 @@ xfs_buf_iodone_callbacks( | |||
993 | xfs_buf_ioerror(bp, 0); /* errno of 0 unsets the flag */ | 992 | xfs_buf_ioerror(bp, 0); /* errno of 0 unsets the flag */ |
994 | 993 | ||
995 | if (!XFS_BUF_ISSTALE(bp)) { | 994 | if (!XFS_BUF_ISSTALE(bp)) { |
996 | XFS_BUF_DELAYWRITE(bp); | 995 | xfs_buf_delwri_queue(bp); |
997 | XFS_BUF_DONE(bp); | 996 | XFS_BUF_DONE(bp); |
998 | } | 997 | } |
999 | ASSERT(bp->b_iodone != NULL); | 998 | ASSERT(bp->b_iodone != NULL); |
@@ -1006,9 +1005,8 @@ xfs_buf_iodone_callbacks( | |||
1006 | * If the write of the buffer was synchronous, we want to make | 1005 | * If the write of the buffer was synchronous, we want to make |
1007 | * sure to return the error to the caller of xfs_bwrite(). | 1006 | * sure to return the error to the caller of xfs_bwrite(). |
1008 | */ | 1007 | */ |
1009 | XFS_BUF_STALE(bp); | 1008 | xfs_buf_stale(bp); |
1010 | XFS_BUF_DONE(bp); | 1009 | XFS_BUF_DONE(bp); |
1011 | XFS_BUF_UNDELAYWRITE(bp); | ||
1012 | 1010 | ||
1013 | trace_xfs_buf_error_relse(bp, _RET_IP_); | 1011 | trace_xfs_buf_error_relse(bp, _RET_IP_); |
1014 | 1012 | ||
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index ee9d5427fcd4..77c74257c2a3 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c | |||
@@ -1578,9 +1578,8 @@ xfs_da_grow_inode_int( | |||
1578 | */ | 1578 | */ |
1579 | nmap = 1; | 1579 | nmap = 1; |
1580 | ASSERT(args->firstblock != NULL); | 1580 | ASSERT(args->firstblock != NULL); |
1581 | error = xfs_bmapi(tp, dp, *bno, count, | 1581 | error = xfs_bmapi_write(tp, dp, *bno, count, |
1582 | xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA| | 1582 | xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, |
1583 | XFS_BMAPI_CONTIG, | ||
1584 | args->firstblock, args->total, &map, &nmap, | 1583 | args->firstblock, args->total, &map, &nmap, |
1585 | args->flist); | 1584 | args->flist); |
1586 | if (error) | 1585 | if (error) |
@@ -1602,9 +1601,8 @@ xfs_da_grow_inode_int( | |||
1602 | for (b = *bno, mapi = 0; b < *bno + count; ) { | 1601 | for (b = *bno, mapi = 0; b < *bno + count; ) { |
1603 | nmap = MIN(XFS_BMAP_MAX_NMAP, count); | 1602 | nmap = MIN(XFS_BMAP_MAX_NMAP, count); |
1604 | c = (int)(*bno + count - b); | 1603 | c = (int)(*bno + count - b); |
1605 | error = xfs_bmapi(tp, dp, b, c, | 1604 | error = xfs_bmapi_write(tp, dp, b, c, |
1606 | xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE| | 1605 | xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA, |
1607 | XFS_BMAPI_METADATA, | ||
1608 | args->firstblock, args->total, | 1606 | args->firstblock, args->total, |
1609 | &mapp[mapi], &nmap, args->flist); | 1607 | &mapp[mapi], &nmap, args->flist); |
1610 | if (error) | 1608 | if (error) |
@@ -1975,33 +1973,16 @@ xfs_da_do_buf( | |||
1975 | /* | 1973 | /* |
1976 | * Optimize the one-block case. | 1974 | * Optimize the one-block case. |
1977 | */ | 1975 | */ |
1978 | if (nfsb == 1) { | 1976 | if (nfsb == 1) |
1979 | xfs_fsblock_t fsb; | ||
1980 | |||
1981 | if ((error = | ||
1982 | xfs_bmapi_single(trans, dp, whichfork, &fsb, | ||
1983 | (xfs_fileoff_t)bno))) { | ||
1984 | return error; | ||
1985 | } | ||
1986 | mapp = ↦ | 1977 | mapp = ↦ |
1987 | if (fsb == NULLFSBLOCK) { | 1978 | else |
1988 | nmap = 0; | ||
1989 | } else { | ||
1990 | map.br_startblock = fsb; | ||
1991 | map.br_startoff = (xfs_fileoff_t)bno; | ||
1992 | map.br_blockcount = 1; | ||
1993 | nmap = 1; | ||
1994 | } | ||
1995 | } else { | ||
1996 | mapp = kmem_alloc(sizeof(*mapp) * nfsb, KM_SLEEP); | 1979 | mapp = kmem_alloc(sizeof(*mapp) * nfsb, KM_SLEEP); |
1997 | nmap = nfsb; | 1980 | |
1998 | if ((error = xfs_bmapi(trans, dp, (xfs_fileoff_t)bno, | 1981 | nmap = nfsb; |
1999 | nfsb, | 1982 | error = xfs_bmapi_read(dp, (xfs_fileoff_t)bno, nfsb, mapp, |
2000 | XFS_BMAPI_METADATA | | 1983 | &nmap, xfs_bmapi_aflag(whichfork)); |
2001 | xfs_bmapi_aflag(whichfork), | 1984 | if (error) |
2002 | NULL, 0, mapp, &nmap, NULL))) | 1985 | goto exit0; |
2003 | goto exit0; | ||
2004 | } | ||
2005 | } else { | 1986 | } else { |
2006 | map.br_startblock = XFS_DADDR_TO_FSB(mp, mappedbno); | 1987 | map.br_startblock = XFS_DADDR_TO_FSB(mp, mappedbno); |
2007 | map.br_startoff = (xfs_fileoff_t)bno; | 1988 | map.br_startoff = (xfs_fileoff_t)bno; |
@@ -2072,13 +2053,10 @@ xfs_da_do_buf( | |||
2072 | if (!bp) | 2053 | if (!bp) |
2073 | continue; | 2054 | continue; |
2074 | if (caller == 1) { | 2055 | if (caller == 1) { |
2075 | if (whichfork == XFS_ATTR_FORK) { | 2056 | if (whichfork == XFS_ATTR_FORK) |
2076 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_ATTR_BTREE, | 2057 | xfs_buf_set_ref(bp, XFS_ATTR_BTREE_REF); |
2077 | XFS_ATTR_BTREE_REF); | 2058 | else |
2078 | } else { | 2059 | xfs_buf_set_ref(bp, XFS_DIR_BTREE_REF); |
2079 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_DIR_BTREE, | ||
2080 | XFS_DIR_BTREE_REF); | ||
2081 | } | ||
2082 | } | 2060 | } |
2083 | if (bplist) { | 2061 | if (bplist) { |
2084 | bplist[nbplist++] = bp; | 2062 | bplist[nbplist++] = bp; |
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 9a84a85c03b1..654dc6f05bac 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c | |||
@@ -425,8 +425,8 @@ xfs_swap_extents( | |||
425 | } | 425 | } |
426 | 426 | ||
427 | 427 | ||
428 | xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | 428 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
429 | xfs_trans_ijoin_ref(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | 429 | xfs_trans_ijoin(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
430 | 430 | ||
431 | xfs_trans_log_inode(tp, ip, ilf_fields); | 431 | xfs_trans_log_inode(tp, ip, ilf_fields); |
432 | xfs_trans_log_inode(tp, tip, tilf_fields); | 432 | xfs_trans_log_inode(tp, tip, tilf_fields); |
@@ -438,7 +438,7 @@ xfs_swap_extents( | |||
438 | if (mp->m_flags & XFS_MOUNT_WSYNC) | 438 | if (mp->m_flags & XFS_MOUNT_WSYNC) |
439 | xfs_trans_set_sync(tp); | 439 | xfs_trans_set_sync(tp); |
440 | 440 | ||
441 | error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT); | 441 | error = xfs_trans_commit(tp, 0); |
442 | 442 | ||
443 | trace_xfs_swap_extent_after(ip, 0); | 443 | trace_xfs_swap_extent_after(ip, 0); |
444 | trace_xfs_swap_extent_after(tip, 1); | 444 | trace_xfs_swap_extent_after(tip, 1); |
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index ca2386d82cdf..66e108f561a3 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c | |||
@@ -888,12 +888,10 @@ xfs_dir2_leaf_getdents( | |||
888 | * we already have in the table. | 888 | * we already have in the table. |
889 | */ | 889 | */ |
890 | nmap = map_size - map_valid; | 890 | nmap = map_size - map_valid; |
891 | error = xfs_bmapi(NULL, dp, | 891 | error = xfs_bmapi_read(dp, map_off, |
892 | map_off, | ||
893 | xfs_dir2_byte_to_da(mp, | 892 | xfs_dir2_byte_to_da(mp, |
894 | XFS_DIR2_LEAF_OFFSET) - map_off, | 893 | XFS_DIR2_LEAF_OFFSET) - map_off, |
895 | XFS_BMAPI_METADATA, NULL, 0, | 894 | &map[map_valid], &nmap, 0); |
896 | &map[map_valid], &nmap, NULL); | ||
897 | /* | 895 | /* |
898 | * Don't know if we should ignore this or | 896 | * Don't know if we should ignore this or |
899 | * try to return an error. | 897 | * try to return an error. |
diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c index 244e797dae32..8a24f0c6c860 100644 --- a/fs/xfs/xfs_discard.c +++ b/fs/xfs/xfs_discard.c | |||
@@ -38,7 +38,7 @@ xfs_trim_extents( | |||
38 | struct xfs_mount *mp, | 38 | struct xfs_mount *mp, |
39 | xfs_agnumber_t agno, | 39 | xfs_agnumber_t agno, |
40 | xfs_fsblock_t start, | 40 | xfs_fsblock_t start, |
41 | xfs_fsblock_t len, | 41 | xfs_fsblock_t end, |
42 | xfs_fsblock_t minlen, | 42 | xfs_fsblock_t minlen, |
43 | __uint64_t *blocks_trimmed) | 43 | __uint64_t *blocks_trimmed) |
44 | { | 44 | { |
@@ -100,7 +100,7 @@ xfs_trim_extents( | |||
100 | * down partially overlapping ranges for now. | 100 | * down partially overlapping ranges for now. |
101 | */ | 101 | */ |
102 | if (XFS_AGB_TO_FSB(mp, agno, fbno) + flen < start || | 102 | if (XFS_AGB_TO_FSB(mp, agno, fbno) + flen < start || |
103 | XFS_AGB_TO_FSB(mp, agno, fbno) >= start + len) { | 103 | XFS_AGB_TO_FSB(mp, agno, fbno) > end) { |
104 | trace_xfs_discard_exclude(mp, agno, fbno, flen); | 104 | trace_xfs_discard_exclude(mp, agno, fbno, flen); |
105 | goto next_extent; | 105 | goto next_extent; |
106 | } | 106 | } |
@@ -145,7 +145,7 @@ xfs_ioc_trim( | |||
145 | struct request_queue *q = mp->m_ddev_targp->bt_bdev->bd_disk->queue; | 145 | struct request_queue *q = mp->m_ddev_targp->bt_bdev->bd_disk->queue; |
146 | unsigned int granularity = q->limits.discard_granularity; | 146 | unsigned int granularity = q->limits.discard_granularity; |
147 | struct fstrim_range range; | 147 | struct fstrim_range range; |
148 | xfs_fsblock_t start, len, minlen; | 148 | xfs_fsblock_t start, end, minlen; |
149 | xfs_agnumber_t start_agno, end_agno, agno; | 149 | xfs_agnumber_t start_agno, end_agno, agno; |
150 | __uint64_t blocks_trimmed = 0; | 150 | __uint64_t blocks_trimmed = 0; |
151 | int error, last_error = 0; | 151 | int error, last_error = 0; |
@@ -165,19 +165,19 @@ xfs_ioc_trim( | |||
165 | * matter as trimming blocks is an advisory interface. | 165 | * matter as trimming blocks is an advisory interface. |
166 | */ | 166 | */ |
167 | start = XFS_B_TO_FSBT(mp, range.start); | 167 | start = XFS_B_TO_FSBT(mp, range.start); |
168 | len = XFS_B_TO_FSBT(mp, range.len); | 168 | end = start + XFS_B_TO_FSBT(mp, range.len) - 1; |
169 | minlen = XFS_B_TO_FSB(mp, max_t(u64, granularity, range.minlen)); | 169 | minlen = XFS_B_TO_FSB(mp, max_t(u64, granularity, range.minlen)); |
170 | 170 | ||
171 | start_agno = XFS_FSB_TO_AGNO(mp, start); | 171 | if (start >= mp->m_sb.sb_dblocks) |
172 | if (start_agno >= mp->m_sb.sb_agcount) | ||
173 | return -XFS_ERROR(EINVAL); | 172 | return -XFS_ERROR(EINVAL); |
173 | if (end > mp->m_sb.sb_dblocks - 1) | ||
174 | end = mp->m_sb.sb_dblocks - 1; | ||
174 | 175 | ||
175 | end_agno = XFS_FSB_TO_AGNO(mp, start + len); | 176 | start_agno = XFS_FSB_TO_AGNO(mp, start); |
176 | if (end_agno >= mp->m_sb.sb_agcount) | 177 | end_agno = XFS_FSB_TO_AGNO(mp, end); |
177 | end_agno = mp->m_sb.sb_agcount - 1; | ||
178 | 178 | ||
179 | for (agno = start_agno; agno <= end_agno; agno++) { | 179 | for (agno = start_agno; agno <= end_agno; agno++) { |
180 | error = -xfs_trim_extents(mp, agno, start, len, minlen, | 180 | error = -xfs_trim_extents(mp, agno, start, end, minlen, |
181 | &blocks_trimmed); | 181 | &blocks_trimmed); |
182 | if (error) | 182 | if (error) |
183 | last_error = error; | 183 | last_error = error; |
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index db62959bed13..25d7280e9f6b 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c | |||
@@ -377,16 +377,14 @@ xfs_qm_dqalloc( | |||
377 | return (ESRCH); | 377 | return (ESRCH); |
378 | } | 378 | } |
379 | 379 | ||
380 | xfs_trans_ijoin_ref(tp, quotip, XFS_ILOCK_EXCL); | 380 | xfs_trans_ijoin(tp, quotip, XFS_ILOCK_EXCL); |
381 | nmaps = 1; | 381 | nmaps = 1; |
382 | if ((error = xfs_bmapi(tp, quotip, | 382 | error = xfs_bmapi_write(tp, quotip, offset_fsb, |
383 | offset_fsb, XFS_DQUOT_CLUSTER_SIZE_FSB, | 383 | XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA, |
384 | XFS_BMAPI_METADATA | XFS_BMAPI_WRITE, | 384 | &firstblock, XFS_QM_DQALLOC_SPACE_RES(mp), |
385 | &firstblock, | 385 | &map, &nmaps, &flist); |
386 | XFS_QM_DQALLOC_SPACE_RES(mp), | 386 | if (error) |
387 | &map, &nmaps, &flist))) { | ||
388 | goto error0; | 387 | goto error0; |
389 | } | ||
390 | ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB); | 388 | ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB); |
391 | ASSERT(nmaps == 1); | 389 | ASSERT(nmaps == 1); |
392 | ASSERT((map.br_startblock != DELAYSTARTBLOCK) && | 390 | ASSERT((map.br_startblock != DELAYSTARTBLOCK) && |
@@ -402,8 +400,11 @@ xfs_qm_dqalloc( | |||
402 | dqp->q_blkno, | 400 | dqp->q_blkno, |
403 | mp->m_quotainfo->qi_dqchunklen, | 401 | mp->m_quotainfo->qi_dqchunklen, |
404 | 0); | 402 | 0); |
405 | if (!bp || (error = xfs_buf_geterror(bp))) | 403 | |
404 | error = xfs_buf_geterror(bp); | ||
405 | if (error) | ||
406 | goto error1; | 406 | goto error1; |
407 | |||
407 | /* | 408 | /* |
408 | * Make a chunk of dquots out of this buffer and log | 409 | * Make a chunk of dquots out of this buffer and log |
409 | * the entire thing. | 410 | * the entire thing. |
@@ -485,9 +486,8 @@ xfs_qm_dqtobp( | |||
485 | /* | 486 | /* |
486 | * Find the block map; no allocations yet | 487 | * Find the block map; no allocations yet |
487 | */ | 488 | */ |
488 | error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset, | 489 | error = xfs_bmapi_read(quotip, dqp->q_fileoffset, |
489 | XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA, | 490 | XFS_DQUOT_CLUSTER_SIZE_FSB, &map, &nmaps, 0); |
490 | NULL, 0, &map, &nmaps, NULL); | ||
491 | 491 | ||
492 | xfs_iunlock(quotip, XFS_ILOCK_SHARED); | 492 | xfs_iunlock(quotip, XFS_ILOCK_SHARED); |
493 | if (error) | 493 | if (error) |
@@ -605,7 +605,7 @@ xfs_qm_dqread( | |||
605 | dqp->q_res_rtbcount = be64_to_cpu(ddqp->d_rtbcount); | 605 | dqp->q_res_rtbcount = be64_to_cpu(ddqp->d_rtbcount); |
606 | 606 | ||
607 | /* Mark the buf so that this will stay incore a little longer */ | 607 | /* Mark the buf so that this will stay incore a little longer */ |
608 | XFS_BUF_SET_VTYPE_REF(bp, B_FS_DQUOT, XFS_DQUOT_REF); | 608 | xfs_buf_set_ref(bp, XFS_DQUOT_REF); |
609 | 609 | ||
610 | /* | 610 | /* |
611 | * We got the buffer with a xfs_trans_read_buf() (in dqtobp()) | 611 | * We got the buffer with a xfs_trans_read_buf() (in dqtobp()) |
@@ -1242,9 +1242,11 @@ xfs_qm_dqflush( | |||
1242 | } | 1242 | } |
1243 | 1243 | ||
1244 | if (flags & SYNC_WAIT) | 1244 | if (flags & SYNC_WAIT) |
1245 | error = xfs_bwrite(mp, bp); | 1245 | error = xfs_bwrite(bp); |
1246 | else | 1246 | else |
1247 | xfs_bdwrite(mp, bp); | 1247 | xfs_buf_delwri_queue(bp); |
1248 | |||
1249 | xfs_buf_relse(bp); | ||
1248 | 1250 | ||
1249 | trace_xfs_dqflush_done(dqp); | 1251 | trace_xfs_dqflush_done(dqp); |
1250 | 1252 | ||
diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c index 75e5d322e48f..da108977b21f 100644 --- a/fs/xfs/xfs_export.c +++ b/fs/xfs/xfs_export.c | |||
@@ -229,16 +229,16 @@ xfs_fs_nfs_commit_metadata( | |||
229 | { | 229 | { |
230 | struct xfs_inode *ip = XFS_I(inode); | 230 | struct xfs_inode *ip = XFS_I(inode); |
231 | struct xfs_mount *mp = ip->i_mount; | 231 | struct xfs_mount *mp = ip->i_mount; |
232 | int error = 0; | 232 | xfs_lsn_t lsn = 0; |
233 | 233 | ||
234 | xfs_ilock(ip, XFS_ILOCK_SHARED); | 234 | xfs_ilock(ip, XFS_ILOCK_SHARED); |
235 | if (xfs_ipincount(ip)) { | 235 | if (xfs_ipincount(ip)) |
236 | error = _xfs_log_force_lsn(mp, ip->i_itemp->ili_last_lsn, | 236 | lsn = ip->i_itemp->ili_last_lsn; |
237 | XFS_LOG_SYNC, NULL); | ||
238 | } | ||
239 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 237 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
240 | 238 | ||
241 | return error; | 239 | if (!lsn) |
240 | return 0; | ||
241 | return _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL); | ||
242 | } | 242 | } |
243 | 243 | ||
244 | const struct export_operations xfs_export_operations = { | 244 | const struct export_operations xfs_export_operations = { |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 7f7b42469ea7..753ed9b5c70b 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -124,6 +124,35 @@ xfs_iozero( | |||
124 | return (-status); | 124 | return (-status); |
125 | } | 125 | } |
126 | 126 | ||
127 | /* | ||
128 | * Fsync operations on directories are much simpler than on regular files, | ||
129 | * as there is no file data to flush, and thus also no need for explicit | ||
130 | * cache flush operations, and there are no non-transaction metadata updates | ||
131 | * on directories either. | ||
132 | */ | ||
133 | STATIC int | ||
134 | xfs_dir_fsync( | ||
135 | struct file *file, | ||
136 | loff_t start, | ||
137 | loff_t end, | ||
138 | int datasync) | ||
139 | { | ||
140 | struct xfs_inode *ip = XFS_I(file->f_mapping->host); | ||
141 | struct xfs_mount *mp = ip->i_mount; | ||
142 | xfs_lsn_t lsn = 0; | ||
143 | |||
144 | trace_xfs_dir_fsync(ip); | ||
145 | |||
146 | xfs_ilock(ip, XFS_ILOCK_SHARED); | ||
147 | if (xfs_ipincount(ip)) | ||
148 | lsn = ip->i_itemp->ili_last_lsn; | ||
149 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
150 | |||
151 | if (!lsn) | ||
152 | return 0; | ||
153 | return _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL); | ||
154 | } | ||
155 | |||
127 | STATIC int | 156 | STATIC int |
128 | xfs_file_fsync( | 157 | xfs_file_fsync( |
129 | struct file *file, | 158 | struct file *file, |
@@ -137,6 +166,7 @@ xfs_file_fsync( | |||
137 | struct xfs_trans *tp; | 166 | struct xfs_trans *tp; |
138 | int error = 0; | 167 | int error = 0; |
139 | int log_flushed = 0; | 168 | int log_flushed = 0; |
169 | xfs_lsn_t lsn = 0; | ||
140 | 170 | ||
141 | trace_xfs_file_fsync(ip); | 171 | trace_xfs_file_fsync(ip); |
142 | 172 | ||
@@ -149,10 +179,6 @@ xfs_file_fsync( | |||
149 | 179 | ||
150 | xfs_iflags_clear(ip, XFS_ITRUNCATED); | 180 | xfs_iflags_clear(ip, XFS_ITRUNCATED); |
151 | 181 | ||
152 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | ||
153 | xfs_ioend_wait(ip); | ||
154 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | ||
155 | |||
156 | if (mp->m_flags & XFS_MOUNT_BARRIER) { | 182 | if (mp->m_flags & XFS_MOUNT_BARRIER) { |
157 | /* | 183 | /* |
158 | * If we have an RT and/or log subvolume we need to make sure | 184 | * If we have an RT and/or log subvolume we need to make sure |
@@ -216,11 +242,11 @@ xfs_file_fsync( | |||
216 | * transaction. So we play it safe and fire off the | 242 | * transaction. So we play it safe and fire off the |
217 | * transaction anyway. | 243 | * transaction anyway. |
218 | */ | 244 | */ |
219 | xfs_trans_ijoin(tp, ip); | 245 | xfs_trans_ijoin(tp, ip, 0); |
220 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 246 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
221 | xfs_trans_set_sync(tp); | 247 | error = xfs_trans_commit(tp, 0); |
222 | error = _xfs_trans_commit(tp, 0, &log_flushed); | ||
223 | 248 | ||
249 | lsn = ip->i_itemp->ili_last_lsn; | ||
224 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 250 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
225 | } else { | 251 | } else { |
226 | /* | 252 | /* |
@@ -231,14 +257,14 @@ xfs_file_fsync( | |||
231 | * disk yet, the inode will be still be pinned. If it is, | 257 | * disk yet, the inode will be still be pinned. If it is, |
232 | * force the log. | 258 | * force the log. |
233 | */ | 259 | */ |
234 | if (xfs_ipincount(ip)) { | 260 | if (xfs_ipincount(ip)) |
235 | error = _xfs_log_force_lsn(mp, | 261 | lsn = ip->i_itemp->ili_last_lsn; |
236 | ip->i_itemp->ili_last_lsn, | ||
237 | XFS_LOG_SYNC, &log_flushed); | ||
238 | } | ||
239 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 262 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
240 | } | 263 | } |
241 | 264 | ||
265 | if (!error && lsn) | ||
266 | error = _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, &log_flushed); | ||
267 | |||
242 | /* | 268 | /* |
243 | * If we only have a single device, and the log force about was | 269 | * If we only have a single device, and the log force about was |
244 | * a no-op we might have to flush the data device cache here. | 270 | * a no-op we might have to flush the data device cache here. |
@@ -317,7 +343,19 @@ xfs_file_aio_read( | |||
317 | if (XFS_FORCED_SHUTDOWN(mp)) | 343 | if (XFS_FORCED_SHUTDOWN(mp)) |
318 | return -EIO; | 344 | return -EIO; |
319 | 345 | ||
320 | if (unlikely(ioflags & IO_ISDIRECT)) { | 346 | /* |
347 | * Locking is a bit tricky here. If we take an exclusive lock | ||
348 | * for direct IO, we effectively serialise all new concurrent | ||
349 | * read IO to this file and block it behind IO that is currently in | ||
350 | * progress because IO in progress holds the IO lock shared. We only | ||
351 | * need to hold the lock exclusive to blow away the page cache, so | ||
352 | * only take lock exclusively if the page cache needs invalidation. | ||
353 | * This allows the normal direct IO case of no page cache pages to | ||
354 | * proceeed concurrently without serialisation. | ||
355 | */ | ||
356 | xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); | ||
357 | if ((ioflags & IO_ISDIRECT) && inode->i_mapping->nrpages) { | ||
358 | xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); | ||
321 | xfs_rw_ilock(ip, XFS_IOLOCK_EXCL); | 359 | xfs_rw_ilock(ip, XFS_IOLOCK_EXCL); |
322 | 360 | ||
323 | if (inode->i_mapping->nrpages) { | 361 | if (inode->i_mapping->nrpages) { |
@@ -330,8 +368,7 @@ xfs_file_aio_read( | |||
330 | } | 368 | } |
331 | } | 369 | } |
332 | xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); | 370 | xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); |
333 | } else | 371 | } |
334 | xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); | ||
335 | 372 | ||
336 | trace_xfs_file_read(ip, size, iocb->ki_pos, ioflags); | 373 | trace_xfs_file_read(ip, size, iocb->ki_pos, ioflags); |
337 | 374 | ||
@@ -407,11 +444,13 @@ xfs_aio_write_isize_update( | |||
407 | */ | 444 | */ |
408 | STATIC void | 445 | STATIC void |
409 | xfs_aio_write_newsize_update( | 446 | xfs_aio_write_newsize_update( |
410 | struct xfs_inode *ip) | 447 | struct xfs_inode *ip, |
448 | xfs_fsize_t new_size) | ||
411 | { | 449 | { |
412 | if (ip->i_new_size) { | 450 | if (new_size == ip->i_new_size) { |
413 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL); | 451 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL); |
414 | ip->i_new_size = 0; | 452 | if (new_size == ip->i_new_size) |
453 | ip->i_new_size = 0; | ||
415 | if (ip->i_d.di_size > ip->i_size) | 454 | if (ip->i_d.di_size > ip->i_size) |
416 | ip->i_d.di_size = ip->i_size; | 455 | ip->i_d.di_size = ip->i_size; |
417 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); | 456 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); |
@@ -462,7 +501,7 @@ xfs_file_splice_write( | |||
462 | ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags); | 501 | ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags); |
463 | 502 | ||
464 | xfs_aio_write_isize_update(inode, ppos, ret); | 503 | xfs_aio_write_isize_update(inode, ppos, ret); |
465 | xfs_aio_write_newsize_update(ip); | 504 | xfs_aio_write_newsize_update(ip, new_size); |
466 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | 505 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); |
467 | return ret; | 506 | return ret; |
468 | } | 507 | } |
@@ -500,11 +539,9 @@ xfs_zero_last_block( | |||
500 | 539 | ||
501 | last_fsb = XFS_B_TO_FSBT(mp, isize); | 540 | last_fsb = XFS_B_TO_FSBT(mp, isize); |
502 | nimaps = 1; | 541 | nimaps = 1; |
503 | error = xfs_bmapi(NULL, ip, last_fsb, 1, 0, NULL, 0, &imap, | 542 | error = xfs_bmapi_read(ip, last_fsb, 1, &imap, &nimaps, 0); |
504 | &nimaps, NULL); | 543 | if (error) |
505 | if (error) { | ||
506 | return error; | 544 | return error; |
507 | } | ||
508 | ASSERT(nimaps > 0); | 545 | ASSERT(nimaps > 0); |
509 | /* | 546 | /* |
510 | * If the block underlying isize is just a hole, then there | 547 | * If the block underlying isize is just a hole, then there |
@@ -595,8 +632,8 @@ xfs_zero_eof( | |||
595 | while (start_zero_fsb <= end_zero_fsb) { | 632 | while (start_zero_fsb <= end_zero_fsb) { |
596 | nimaps = 1; | 633 | nimaps = 1; |
597 | zero_count_fsb = end_zero_fsb - start_zero_fsb + 1; | 634 | zero_count_fsb = end_zero_fsb - start_zero_fsb + 1; |
598 | error = xfs_bmapi(NULL, ip, start_zero_fsb, zero_count_fsb, | 635 | error = xfs_bmapi_read(ip, start_zero_fsb, zero_count_fsb, |
599 | 0, NULL, 0, &imap, &nimaps, NULL); | 636 | &imap, &nimaps, 0); |
600 | if (error) { | 637 | if (error) { |
601 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL)); | 638 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL)); |
602 | return error; | 639 | return error; |
@@ -659,6 +696,7 @@ xfs_file_aio_write_checks( | |||
659 | struct file *file, | 696 | struct file *file, |
660 | loff_t *pos, | 697 | loff_t *pos, |
661 | size_t *count, | 698 | size_t *count, |
699 | xfs_fsize_t *new_sizep, | ||
662 | int *iolock) | 700 | int *iolock) |
663 | { | 701 | { |
664 | struct inode *inode = file->f_mapping->host; | 702 | struct inode *inode = file->f_mapping->host; |
@@ -666,6 +704,9 @@ xfs_file_aio_write_checks( | |||
666 | xfs_fsize_t new_size; | 704 | xfs_fsize_t new_size; |
667 | int error = 0; | 705 | int error = 0; |
668 | 706 | ||
707 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL); | ||
708 | *new_sizep = 0; | ||
709 | restart: | ||
669 | error = generic_write_checks(file, pos, count, S_ISBLK(inode->i_mode)); | 710 | error = generic_write_checks(file, pos, count, S_ISBLK(inode->i_mode)); |
670 | if (error) { | 711 | if (error) { |
671 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock); | 712 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock); |
@@ -673,20 +714,41 @@ xfs_file_aio_write_checks( | |||
673 | return error; | 714 | return error; |
674 | } | 715 | } |
675 | 716 | ||
676 | new_size = *pos + *count; | ||
677 | if (new_size > ip->i_size) | ||
678 | ip->i_new_size = new_size; | ||
679 | |||
680 | if (likely(!(file->f_mode & FMODE_NOCMTIME))) | 717 | if (likely(!(file->f_mode & FMODE_NOCMTIME))) |
681 | file_update_time(file); | 718 | file_update_time(file); |
682 | 719 | ||
683 | /* | 720 | /* |
684 | * If the offset is beyond the size of the file, we need to zero any | 721 | * If the offset is beyond the size of the file, we need to zero any |
685 | * blocks that fall between the existing EOF and the start of this | 722 | * blocks that fall between the existing EOF and the start of this |
686 | * write. | 723 | * write. There is no need to issue zeroing if another in-flght IO ends |
724 | * at or before this one If zeronig is needed and we are currently | ||
725 | * holding the iolock shared, we need to update it to exclusive which | ||
726 | * involves dropping all locks and relocking to maintain correct locking | ||
727 | * order. If we do this, restart the function to ensure all checks and | ||
728 | * values are still valid. | ||
687 | */ | 729 | */ |
688 | if (*pos > ip->i_size) | 730 | if ((ip->i_new_size && *pos > ip->i_new_size) || |
731 | (!ip->i_new_size && *pos > ip->i_size)) { | ||
732 | if (*iolock == XFS_IOLOCK_SHARED) { | ||
733 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock); | ||
734 | *iolock = XFS_IOLOCK_EXCL; | ||
735 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock); | ||
736 | goto restart; | ||
737 | } | ||
689 | error = -xfs_zero_eof(ip, *pos, ip->i_size); | 738 | error = -xfs_zero_eof(ip, *pos, ip->i_size); |
739 | } | ||
740 | |||
741 | /* | ||
742 | * If this IO extends beyond EOF, we may need to update ip->i_new_size. | ||
743 | * We have already zeroed space beyond EOF (if necessary). Only update | ||
744 | * ip->i_new_size if this IO ends beyond any other in-flight writes. | ||
745 | */ | ||
746 | new_size = *pos + *count; | ||
747 | if (new_size > ip->i_size) { | ||
748 | if (new_size > ip->i_new_size) | ||
749 | ip->i_new_size = new_size; | ||
750 | *new_sizep = new_size; | ||
751 | } | ||
690 | 752 | ||
691 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); | 753 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); |
692 | if (error) | 754 | if (error) |
@@ -721,7 +783,7 @@ xfs_file_aio_write_checks( | |||
721 | * the dio layer. To avoid the problem with aio, we also need to wait for | 783 | * the dio layer. To avoid the problem with aio, we also need to wait for |
722 | * outstanding IOs to complete so that unwritten extent conversion is completed | 784 | * outstanding IOs to complete so that unwritten extent conversion is completed |
723 | * before we try to map the overlapping block. This is currently implemented by | 785 | * before we try to map the overlapping block. This is currently implemented by |
724 | * hitting it with a big hammer (i.e. xfs_ioend_wait()). | 786 | * hitting it with a big hammer (i.e. inode_dio_wait()). |
725 | * | 787 | * |
726 | * Returns with locks held indicated by @iolock and errors indicated by | 788 | * Returns with locks held indicated by @iolock and errors indicated by |
727 | * negative return values. | 789 | * negative return values. |
@@ -733,6 +795,7 @@ xfs_file_dio_aio_write( | |||
733 | unsigned long nr_segs, | 795 | unsigned long nr_segs, |
734 | loff_t pos, | 796 | loff_t pos, |
735 | size_t ocount, | 797 | size_t ocount, |
798 | xfs_fsize_t *new_size, | ||
736 | int *iolock) | 799 | int *iolock) |
737 | { | 800 | { |
738 | struct file *file = iocb->ki_filp; | 801 | struct file *file = iocb->ki_filp; |
@@ -753,18 +816,35 @@ xfs_file_dio_aio_write( | |||
753 | if ((pos & mp->m_blockmask) || ((pos + count) & mp->m_blockmask)) | 816 | if ((pos & mp->m_blockmask) || ((pos + count) & mp->m_blockmask)) |
754 | unaligned_io = 1; | 817 | unaligned_io = 1; |
755 | 818 | ||
756 | if (unaligned_io || mapping->nrpages || pos > ip->i_size) | 819 | /* |
820 | * We don't need to take an exclusive lock unless there page cache needs | ||
821 | * to be invalidated or unaligned IO is being executed. We don't need to | ||
822 | * consider the EOF extension case here because | ||
823 | * xfs_file_aio_write_checks() will relock the inode as necessary for | ||
824 | * EOF zeroing cases and fill out the new inode size as appropriate. | ||
825 | */ | ||
826 | if (unaligned_io || mapping->nrpages) | ||
757 | *iolock = XFS_IOLOCK_EXCL; | 827 | *iolock = XFS_IOLOCK_EXCL; |
758 | else | 828 | else |
759 | *iolock = XFS_IOLOCK_SHARED; | 829 | *iolock = XFS_IOLOCK_SHARED; |
760 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock); | 830 | xfs_rw_ilock(ip, *iolock); |
761 | 831 | ||
762 | ret = xfs_file_aio_write_checks(file, &pos, &count, iolock); | 832 | /* |
833 | * Recheck if there are cached pages that need invalidate after we got | ||
834 | * the iolock to protect against other threads adding new pages while | ||
835 | * we were waiting for the iolock. | ||
836 | */ | ||
837 | if (mapping->nrpages && *iolock == XFS_IOLOCK_SHARED) { | ||
838 | xfs_rw_iunlock(ip, *iolock); | ||
839 | *iolock = XFS_IOLOCK_EXCL; | ||
840 | xfs_rw_ilock(ip, *iolock); | ||
841 | } | ||
842 | |||
843 | ret = xfs_file_aio_write_checks(file, &pos, &count, new_size, iolock); | ||
763 | if (ret) | 844 | if (ret) |
764 | return ret; | 845 | return ret; |
765 | 846 | ||
766 | if (mapping->nrpages) { | 847 | if (mapping->nrpages) { |
767 | WARN_ON(*iolock != XFS_IOLOCK_EXCL); | ||
768 | ret = -xfs_flushinval_pages(ip, (pos & PAGE_CACHE_MASK), -1, | 848 | ret = -xfs_flushinval_pages(ip, (pos & PAGE_CACHE_MASK), -1, |
769 | FI_REMAPF_LOCKED); | 849 | FI_REMAPF_LOCKED); |
770 | if (ret) | 850 | if (ret) |
@@ -776,7 +856,7 @@ xfs_file_dio_aio_write( | |||
776 | * otherwise demote the lock if we had to flush cached pages | 856 | * otherwise demote the lock if we had to flush cached pages |
777 | */ | 857 | */ |
778 | if (unaligned_io) | 858 | if (unaligned_io) |
779 | xfs_ioend_wait(ip); | 859 | inode_dio_wait(inode); |
780 | else if (*iolock == XFS_IOLOCK_EXCL) { | 860 | else if (*iolock == XFS_IOLOCK_EXCL) { |
781 | xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); | 861 | xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); |
782 | *iolock = XFS_IOLOCK_SHARED; | 862 | *iolock = XFS_IOLOCK_SHARED; |
@@ -798,6 +878,7 @@ xfs_file_buffered_aio_write( | |||
798 | unsigned long nr_segs, | 878 | unsigned long nr_segs, |
799 | loff_t pos, | 879 | loff_t pos, |
800 | size_t ocount, | 880 | size_t ocount, |
881 | xfs_fsize_t *new_size, | ||
801 | int *iolock) | 882 | int *iolock) |
802 | { | 883 | { |
803 | struct file *file = iocb->ki_filp; | 884 | struct file *file = iocb->ki_filp; |
@@ -809,9 +890,9 @@ xfs_file_buffered_aio_write( | |||
809 | size_t count = ocount; | 890 | size_t count = ocount; |
810 | 891 | ||
811 | *iolock = XFS_IOLOCK_EXCL; | 892 | *iolock = XFS_IOLOCK_EXCL; |
812 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock); | 893 | xfs_rw_ilock(ip, *iolock); |
813 | 894 | ||
814 | ret = xfs_file_aio_write_checks(file, &pos, &count, iolock); | 895 | ret = xfs_file_aio_write_checks(file, &pos, &count, new_size, iolock); |
815 | if (ret) | 896 | if (ret) |
816 | return ret; | 897 | return ret; |
817 | 898 | ||
@@ -851,6 +932,7 @@ xfs_file_aio_write( | |||
851 | ssize_t ret; | 932 | ssize_t ret; |
852 | int iolock; | 933 | int iolock; |
853 | size_t ocount = 0; | 934 | size_t ocount = 0; |
935 | xfs_fsize_t new_size = 0; | ||
854 | 936 | ||
855 | XFS_STATS_INC(xs_write_calls); | 937 | XFS_STATS_INC(xs_write_calls); |
856 | 938 | ||
@@ -870,10 +952,10 @@ xfs_file_aio_write( | |||
870 | 952 | ||
871 | if (unlikely(file->f_flags & O_DIRECT)) | 953 | if (unlikely(file->f_flags & O_DIRECT)) |
872 | ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, | 954 | ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, |
873 | ocount, &iolock); | 955 | ocount, &new_size, &iolock); |
874 | else | 956 | else |
875 | ret = xfs_file_buffered_aio_write(iocb, iovp, nr_segs, pos, | 957 | ret = xfs_file_buffered_aio_write(iocb, iovp, nr_segs, pos, |
876 | ocount, &iolock); | 958 | ocount, &new_size, &iolock); |
877 | 959 | ||
878 | xfs_aio_write_isize_update(inode, &iocb->ki_pos, ret); | 960 | xfs_aio_write_isize_update(inode, &iocb->ki_pos, ret); |
879 | 961 | ||
@@ -894,7 +976,7 @@ xfs_file_aio_write( | |||
894 | } | 976 | } |
895 | 977 | ||
896 | out_unlock: | 978 | out_unlock: |
897 | xfs_aio_write_newsize_update(ip); | 979 | xfs_aio_write_newsize_update(ip, new_size); |
898 | xfs_rw_iunlock(ip, iolock); | 980 | xfs_rw_iunlock(ip, iolock); |
899 | return ret; | 981 | return ret; |
900 | } | 982 | } |
@@ -1087,7 +1169,7 @@ const struct file_operations xfs_dir_file_operations = { | |||
1087 | #ifdef CONFIG_COMPAT | 1169 | #ifdef CONFIG_COMPAT |
1088 | .compat_ioctl = xfs_file_compat_ioctl, | 1170 | .compat_ioctl = xfs_file_compat_ioctl, |
1089 | #endif | 1171 | #endif |
1090 | .fsync = xfs_file_fsync, | 1172 | .fsync = xfs_dir_fsync, |
1091 | }; | 1173 | }; |
1092 | 1174 | ||
1093 | static const struct vm_operations_struct xfs_file_vm_ops = { | 1175 | static const struct vm_operations_struct xfs_file_vm_ops = { |
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index 3ff3d9e23ded..5170306a1009 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c | |||
@@ -682,7 +682,7 @@ xfs_filestream_new_ag( | |||
682 | ip = ap->ip; | 682 | ip = ap->ip; |
683 | mp = ip->i_mount; | 683 | mp = ip->i_mount; |
684 | cache = mp->m_filestream; | 684 | cache = mp->m_filestream; |
685 | minlen = ap->alen; | 685 | minlen = ap->length; |
686 | *agp = NULLAGNUMBER; | 686 | *agp = NULLAGNUMBER; |
687 | 687 | ||
688 | /* | 688 | /* |
@@ -761,7 +761,7 @@ xfs_filestream_new_ag( | |||
761 | */ | 761 | */ |
762 | ag = (ag == NULLAGNUMBER) ? 0 : (ag + 1) % mp->m_sb.sb_agcount; | 762 | ag = (ag == NULLAGNUMBER) ? 0 : (ag + 1) % mp->m_sb.sb_agcount; |
763 | flags = (ap->userdata ? XFS_PICK_USERDATA : 0) | | 763 | flags = (ap->userdata ? XFS_PICK_USERDATA : 0) | |
764 | (ap->low ? XFS_PICK_LOWSPACE : 0); | 764 | (ap->flist->xbf_low ? XFS_PICK_LOWSPACE : 0); |
765 | 765 | ||
766 | err = _xfs_filestream_pick_ag(mp, ag, agp, flags, minlen); | 766 | err = _xfs_filestream_pick_ag(mp, ag, agp, flags, minlen); |
767 | if (err || *agp == NULLAGNUMBER) | 767 | if (err || *agp == NULLAGNUMBER) |
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 9153d2c77caf..1c6fdeb702ff 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -194,6 +194,10 @@ xfs_growfs_data_private( | |||
194 | bp = xfs_buf_get(mp->m_ddev_targp, | 194 | bp = xfs_buf_get(mp->m_ddev_targp, |
195 | XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), | 195 | XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), |
196 | XFS_FSS_TO_BB(mp, 1), XBF_LOCK | XBF_MAPPED); | 196 | XFS_FSS_TO_BB(mp, 1), XBF_LOCK | XBF_MAPPED); |
197 | if (!bp) { | ||
198 | error = ENOMEM; | ||
199 | goto error0; | ||
200 | } | ||
197 | agf = XFS_BUF_TO_AGF(bp); | 201 | agf = XFS_BUF_TO_AGF(bp); |
198 | memset(agf, 0, mp->m_sb.sb_sectsize); | 202 | memset(agf, 0, mp->m_sb.sb_sectsize); |
199 | agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC); | 203 | agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC); |
@@ -216,16 +220,21 @@ xfs_growfs_data_private( | |||
216 | tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp); | 220 | tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp); |
217 | agf->agf_freeblks = cpu_to_be32(tmpsize); | 221 | agf->agf_freeblks = cpu_to_be32(tmpsize); |
218 | agf->agf_longest = cpu_to_be32(tmpsize); | 222 | agf->agf_longest = cpu_to_be32(tmpsize); |
219 | error = xfs_bwrite(mp, bp); | 223 | error = xfs_bwrite(bp); |
220 | if (error) { | 224 | xfs_buf_relse(bp); |
225 | if (error) | ||
221 | goto error0; | 226 | goto error0; |
222 | } | 227 | |
223 | /* | 228 | /* |
224 | * AG inode header block | 229 | * AG inode header block |
225 | */ | 230 | */ |
226 | bp = xfs_buf_get(mp->m_ddev_targp, | 231 | bp = xfs_buf_get(mp->m_ddev_targp, |
227 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), | 232 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), |
228 | XFS_FSS_TO_BB(mp, 1), XBF_LOCK | XBF_MAPPED); | 233 | XFS_FSS_TO_BB(mp, 1), XBF_LOCK | XBF_MAPPED); |
234 | if (!bp) { | ||
235 | error = ENOMEM; | ||
236 | goto error0; | ||
237 | } | ||
229 | agi = XFS_BUF_TO_AGI(bp); | 238 | agi = XFS_BUF_TO_AGI(bp); |
230 | memset(agi, 0, mp->m_sb.sb_sectsize); | 239 | memset(agi, 0, mp->m_sb.sb_sectsize); |
231 | agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC); | 240 | agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC); |
@@ -240,10 +249,11 @@ xfs_growfs_data_private( | |||
240 | agi->agi_dirino = cpu_to_be32(NULLAGINO); | 249 | agi->agi_dirino = cpu_to_be32(NULLAGINO); |
241 | for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) | 250 | for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) |
242 | agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO); | 251 | agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO); |
243 | error = xfs_bwrite(mp, bp); | 252 | error = xfs_bwrite(bp); |
244 | if (error) { | 253 | xfs_buf_relse(bp); |
254 | if (error) | ||
245 | goto error0; | 255 | goto error0; |
246 | } | 256 | |
247 | /* | 257 | /* |
248 | * BNO btree root block | 258 | * BNO btree root block |
249 | */ | 259 | */ |
@@ -251,6 +261,10 @@ xfs_growfs_data_private( | |||
251 | XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)), | 261 | XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)), |
252 | BTOBB(mp->m_sb.sb_blocksize), | 262 | BTOBB(mp->m_sb.sb_blocksize), |
253 | XBF_LOCK | XBF_MAPPED); | 263 | XBF_LOCK | XBF_MAPPED); |
264 | if (!bp) { | ||
265 | error = ENOMEM; | ||
266 | goto error0; | ||
267 | } | ||
254 | block = XFS_BUF_TO_BLOCK(bp); | 268 | block = XFS_BUF_TO_BLOCK(bp); |
255 | memset(block, 0, mp->m_sb.sb_blocksize); | 269 | memset(block, 0, mp->m_sb.sb_blocksize); |
256 | block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC); | 270 | block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC); |
@@ -262,10 +276,11 @@ xfs_growfs_data_private( | |||
262 | arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); | 276 | arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); |
263 | arec->ar_blockcount = cpu_to_be32( | 277 | arec->ar_blockcount = cpu_to_be32( |
264 | agsize - be32_to_cpu(arec->ar_startblock)); | 278 | agsize - be32_to_cpu(arec->ar_startblock)); |
265 | error = xfs_bwrite(mp, bp); | 279 | error = xfs_bwrite(bp); |
266 | if (error) { | 280 | xfs_buf_relse(bp); |
281 | if (error) | ||
267 | goto error0; | 282 | goto error0; |
268 | } | 283 | |
269 | /* | 284 | /* |
270 | * CNT btree root block | 285 | * CNT btree root block |
271 | */ | 286 | */ |
@@ -273,6 +288,10 @@ xfs_growfs_data_private( | |||
273 | XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)), | 288 | XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)), |
274 | BTOBB(mp->m_sb.sb_blocksize), | 289 | BTOBB(mp->m_sb.sb_blocksize), |
275 | XBF_LOCK | XBF_MAPPED); | 290 | XBF_LOCK | XBF_MAPPED); |
291 | if (!bp) { | ||
292 | error = ENOMEM; | ||
293 | goto error0; | ||
294 | } | ||
276 | block = XFS_BUF_TO_BLOCK(bp); | 295 | block = XFS_BUF_TO_BLOCK(bp); |
277 | memset(block, 0, mp->m_sb.sb_blocksize); | 296 | memset(block, 0, mp->m_sb.sb_blocksize); |
278 | block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC); | 297 | block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC); |
@@ -285,10 +304,11 @@ xfs_growfs_data_private( | |||
285 | arec->ar_blockcount = cpu_to_be32( | 304 | arec->ar_blockcount = cpu_to_be32( |
286 | agsize - be32_to_cpu(arec->ar_startblock)); | 305 | agsize - be32_to_cpu(arec->ar_startblock)); |
287 | nfree += be32_to_cpu(arec->ar_blockcount); | 306 | nfree += be32_to_cpu(arec->ar_blockcount); |
288 | error = xfs_bwrite(mp, bp); | 307 | error = xfs_bwrite(bp); |
289 | if (error) { | 308 | xfs_buf_relse(bp); |
309 | if (error) | ||
290 | goto error0; | 310 | goto error0; |
291 | } | 311 | |
292 | /* | 312 | /* |
293 | * INO btree root block | 313 | * INO btree root block |
294 | */ | 314 | */ |
@@ -296,6 +316,10 @@ xfs_growfs_data_private( | |||
296 | XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)), | 316 | XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)), |
297 | BTOBB(mp->m_sb.sb_blocksize), | 317 | BTOBB(mp->m_sb.sb_blocksize), |
298 | XBF_LOCK | XBF_MAPPED); | 318 | XBF_LOCK | XBF_MAPPED); |
319 | if (!bp) { | ||
320 | error = ENOMEM; | ||
321 | goto error0; | ||
322 | } | ||
299 | block = XFS_BUF_TO_BLOCK(bp); | 323 | block = XFS_BUF_TO_BLOCK(bp); |
300 | memset(block, 0, mp->m_sb.sb_blocksize); | 324 | memset(block, 0, mp->m_sb.sb_blocksize); |
301 | block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC); | 325 | block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC); |
@@ -303,10 +327,10 @@ xfs_growfs_data_private( | |||
303 | block->bb_numrecs = 0; | 327 | block->bb_numrecs = 0; |
304 | block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK); | 328 | block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK); |
305 | block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK); | 329 | block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK); |
306 | error = xfs_bwrite(mp, bp); | 330 | error = xfs_bwrite(bp); |
307 | if (error) { | 331 | xfs_buf_relse(bp); |
332 | if (error) | ||
308 | goto error0; | 333 | goto error0; |
309 | } | ||
310 | } | 334 | } |
311 | xfs_trans_agblocks_delta(tp, nfree); | 335 | xfs_trans_agblocks_delta(tp, nfree); |
312 | /* | 336 | /* |
@@ -396,9 +420,9 @@ xfs_growfs_data_private( | |||
396 | * just issue a warning and continue. The real work is | 420 | * just issue a warning and continue. The real work is |
397 | * already done and committed. | 421 | * already done and committed. |
398 | */ | 422 | */ |
399 | if (!(error = xfs_bwrite(mp, bp))) { | 423 | error = xfs_bwrite(bp); |
400 | continue; | 424 | xfs_buf_relse(bp); |
401 | } else { | 425 | if (error) { |
402 | xfs_warn(mp, | 426 | xfs_warn(mp, |
403 | "write error %d updating secondary superblock for ag %d", | 427 | "write error %d updating secondary superblock for ag %d", |
404 | error, agno); | 428 | error, agno); |
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 9f24ec28283b..169380e66057 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c | |||
@@ -150,7 +150,7 @@ xfs_check_agi_freecount( | |||
150 | /* | 150 | /* |
151 | * Initialise a new set of inodes. | 151 | * Initialise a new set of inodes. |
152 | */ | 152 | */ |
153 | STATIC void | 153 | STATIC int |
154 | xfs_ialloc_inode_init( | 154 | xfs_ialloc_inode_init( |
155 | struct xfs_mount *mp, | 155 | struct xfs_mount *mp, |
156 | struct xfs_trans *tp, | 156 | struct xfs_trans *tp, |
@@ -202,8 +202,8 @@ xfs_ialloc_inode_init( | |||
202 | fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, | 202 | fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, |
203 | mp->m_bsize * blks_per_cluster, | 203 | mp->m_bsize * blks_per_cluster, |
204 | XBF_LOCK); | 204 | XBF_LOCK); |
205 | ASSERT(!xfs_buf_geterror(fbuf)); | 205 | if (!fbuf) |
206 | 206 | return ENOMEM; | |
207 | /* | 207 | /* |
208 | * Initialize all inodes in this buffer and then log them. | 208 | * Initialize all inodes in this buffer and then log them. |
209 | * | 209 | * |
@@ -225,6 +225,7 @@ xfs_ialloc_inode_init( | |||
225 | } | 225 | } |
226 | xfs_trans_inode_alloc_buf(tp, fbuf); | 226 | xfs_trans_inode_alloc_buf(tp, fbuf); |
227 | } | 227 | } |
228 | return 0; | ||
228 | } | 229 | } |
229 | 230 | ||
230 | /* | 231 | /* |
@@ -369,9 +370,11 @@ xfs_ialloc_ag_alloc( | |||
369 | * rather than a linear progression to prevent the next generation | 370 | * rather than a linear progression to prevent the next generation |
370 | * number from being easily guessable. | 371 | * number from being easily guessable. |
371 | */ | 372 | */ |
372 | xfs_ialloc_inode_init(args.mp, tp, agno, args.agbno, args.len, | 373 | error = xfs_ialloc_inode_init(args.mp, tp, agno, args.agbno, |
373 | random32()); | 374 | args.len, random32()); |
374 | 375 | ||
376 | if (error) | ||
377 | return error; | ||
375 | /* | 378 | /* |
376 | * Convert the results. | 379 | * Convert the results. |
377 | */ | 380 | */ |
@@ -1502,7 +1505,7 @@ xfs_read_agi( | |||
1502 | return XFS_ERROR(EFSCORRUPTED); | 1505 | return XFS_ERROR(EFSCORRUPTED); |
1503 | } | 1506 | } |
1504 | 1507 | ||
1505 | XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_AGI, XFS_AGI_REF); | 1508 | xfs_buf_set_ref(*bpp, XFS_AGI_REF); |
1506 | 1509 | ||
1507 | xfs_check_agi_unlinked(agi); | 1510 | xfs_check_agi_unlinked(agi); |
1508 | return 0; | 1511 | return 0; |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 7759812c1bbe..0fa98b1c70ea 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -75,7 +75,6 @@ xfs_inode_alloc( | |||
75 | return NULL; | 75 | return NULL; |
76 | } | 76 | } |
77 | 77 | ||
78 | ASSERT(atomic_read(&ip->i_iocount) == 0); | ||
79 | ASSERT(atomic_read(&ip->i_pincount) == 0); | 78 | ASSERT(atomic_read(&ip->i_pincount) == 0); |
80 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); | 79 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); |
81 | ASSERT(completion_done(&ip->i_flush)); | 80 | ASSERT(completion_done(&ip->i_flush)); |
@@ -150,7 +149,6 @@ xfs_inode_free( | |||
150 | } | 149 | } |
151 | 150 | ||
152 | /* asserts to verify all state is correct here */ | 151 | /* asserts to verify all state is correct here */ |
153 | ASSERT(atomic_read(&ip->i_iocount) == 0); | ||
154 | ASSERT(atomic_read(&ip->i_pincount) == 0); | 152 | ASSERT(atomic_read(&ip->i_pincount) == 0); |
155 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); | 153 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); |
156 | ASSERT(completion_done(&ip->i_flush)); | 154 | ASSERT(completion_done(&ip->i_flush)); |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 0239a7c7c886..c0237c602f11 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -190,12 +190,6 @@ xfs_imap_to_bp( | |||
190 | } | 190 | } |
191 | 191 | ||
192 | xfs_inobp_check(mp, bp); | 192 | xfs_inobp_check(mp, bp); |
193 | |||
194 | /* | ||
195 | * Mark the buffer as an inode buffer now that it looks good | ||
196 | */ | ||
197 | XFS_BUF_SET_VTYPE(bp, B_FS_INO); | ||
198 | |||
199 | *bpp = bp; | 193 | *bpp = bp; |
200 | return 0; | 194 | return 0; |
201 | } | 195 | } |
@@ -1152,7 +1146,7 @@ xfs_ialloc( | |||
1152 | /* | 1146 | /* |
1153 | * Log the new values stuffed into the inode. | 1147 | * Log the new values stuffed into the inode. |
1154 | */ | 1148 | */ |
1155 | xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); | 1149 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
1156 | xfs_trans_log_inode(tp, ip, flags); | 1150 | xfs_trans_log_inode(tp, ip, flags); |
1157 | 1151 | ||
1158 | /* now that we have an i_mode we can setup inode ops and unlock */ | 1152 | /* now that we have an i_mode we can setup inode ops and unlock */ |
@@ -1187,6 +1181,7 @@ xfs_isize_check( | |||
1187 | xfs_fileoff_t map_first; | 1181 | xfs_fileoff_t map_first; |
1188 | int nimaps; | 1182 | int nimaps; |
1189 | xfs_bmbt_irec_t imaps[2]; | 1183 | xfs_bmbt_irec_t imaps[2]; |
1184 | int error; | ||
1190 | 1185 | ||
1191 | if (!S_ISREG(ip->i_d.di_mode)) | 1186 | if (!S_ISREG(ip->i_d.di_mode)) |
1192 | return; | 1187 | return; |
@@ -1203,13 +1198,12 @@ xfs_isize_check( | |||
1203 | * The filesystem could be shutting down, so bmapi may return | 1198 | * The filesystem could be shutting down, so bmapi may return |
1204 | * an error. | 1199 | * an error. |
1205 | */ | 1200 | */ |
1206 | if (xfs_bmapi(NULL, ip, map_first, | 1201 | error = xfs_bmapi_read(ip, map_first, |
1207 | (XFS_B_TO_FSB(mp, | 1202 | (XFS_B_TO_FSB(mp, |
1208 | (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) - | 1203 | (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) - map_first), |
1209 | map_first), | 1204 | imaps, &nimaps, XFS_BMAPI_ENTIRE); |
1210 | XFS_BMAPI_ENTIRE, NULL, 0, imaps, &nimaps, | 1205 | if (error) |
1211 | NULL)) | 1206 | return; |
1212 | return; | ||
1213 | ASSERT(nimaps == 1); | 1207 | ASSERT(nimaps == 1); |
1214 | ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK); | 1208 | ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK); |
1215 | } | 1209 | } |
@@ -1297,7 +1291,7 @@ xfs_itruncate_extents( | |||
1297 | */ | 1291 | */ |
1298 | error = xfs_bmap_finish(&tp, &free_list, &committed); | 1292 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
1299 | if (committed) | 1293 | if (committed) |
1300 | xfs_trans_ijoin(tp, ip); | 1294 | xfs_trans_ijoin(tp, ip, 0); |
1301 | if (error) | 1295 | if (error) |
1302 | goto out_bmap_cancel; | 1296 | goto out_bmap_cancel; |
1303 | 1297 | ||
@@ -1313,7 +1307,7 @@ xfs_itruncate_extents( | |||
1313 | error = xfs_trans_commit(tp, 0); | 1307 | error = xfs_trans_commit(tp, 0); |
1314 | tp = ntp; | 1308 | tp = ntp; |
1315 | 1309 | ||
1316 | xfs_trans_ijoin(tp, ip); | 1310 | xfs_trans_ijoin(tp, ip, 0); |
1317 | 1311 | ||
1318 | if (error) | 1312 | if (error) |
1319 | goto out; | 1313 | goto out; |
@@ -1644,7 +1638,7 @@ xfs_iunlink_remove( | |||
1644 | * inodes that are in memory - they all must be marked stale and attached to | 1638 | * inodes that are in memory - they all must be marked stale and attached to |
1645 | * the cluster buffer. | 1639 | * the cluster buffer. |
1646 | */ | 1640 | */ |
1647 | STATIC void | 1641 | STATIC int |
1648 | xfs_ifree_cluster( | 1642 | xfs_ifree_cluster( |
1649 | xfs_inode_t *free_ip, | 1643 | xfs_inode_t *free_ip, |
1650 | xfs_trans_t *tp, | 1644 | xfs_trans_t *tp, |
@@ -1690,6 +1684,8 @@ xfs_ifree_cluster( | |||
1690 | mp->m_bsize * blks_per_cluster, | 1684 | mp->m_bsize * blks_per_cluster, |
1691 | XBF_LOCK); | 1685 | XBF_LOCK); |
1692 | 1686 | ||
1687 | if (!bp) | ||
1688 | return ENOMEM; | ||
1693 | /* | 1689 | /* |
1694 | * Walk the inodes already attached to the buffer and mark them | 1690 | * Walk the inodes already attached to the buffer and mark them |
1695 | * stale. These will all have the flush locks held, so an | 1691 | * stale. These will all have the flush locks held, so an |
@@ -1799,6 +1795,7 @@ retry: | |||
1799 | } | 1795 | } |
1800 | 1796 | ||
1801 | xfs_perag_put(pag); | 1797 | xfs_perag_put(pag); |
1798 | return 0; | ||
1802 | } | 1799 | } |
1803 | 1800 | ||
1804 | /* | 1801 | /* |
@@ -1878,10 +1875,10 @@ xfs_ifree( | |||
1878 | dip->di_mode = 0; | 1875 | dip->di_mode = 0; |
1879 | 1876 | ||
1880 | if (delete) { | 1877 | if (delete) { |
1881 | xfs_ifree_cluster(ip, tp, first_ino); | 1878 | error = xfs_ifree_cluster(ip, tp, first_ino); |
1882 | } | 1879 | } |
1883 | 1880 | ||
1884 | return 0; | 1881 | return error; |
1885 | } | 1882 | } |
1886 | 1883 | ||
1887 | /* | 1884 | /* |
@@ -2472,11 +2469,11 @@ cluster_corrupt_out: | |||
2472 | */ | 2469 | */ |
2473 | if (bp->b_iodone) { | 2470 | if (bp->b_iodone) { |
2474 | XFS_BUF_UNDONE(bp); | 2471 | XFS_BUF_UNDONE(bp); |
2475 | XFS_BUF_STALE(bp); | 2472 | xfs_buf_stale(bp); |
2476 | xfs_buf_ioerror(bp, EIO); | 2473 | xfs_buf_ioerror(bp, EIO); |
2477 | xfs_buf_ioend(bp, 0); | 2474 | xfs_buf_ioend(bp, 0); |
2478 | } else { | 2475 | } else { |
2479 | XFS_BUF_STALE(bp); | 2476 | xfs_buf_stale(bp); |
2480 | xfs_buf_relse(bp); | 2477 | xfs_buf_relse(bp); |
2481 | } | 2478 | } |
2482 | } | 2479 | } |
@@ -2597,9 +2594,11 @@ xfs_iflush( | |||
2597 | goto cluster_corrupt_out; | 2594 | goto cluster_corrupt_out; |
2598 | 2595 | ||
2599 | if (flags & SYNC_WAIT) | 2596 | if (flags & SYNC_WAIT) |
2600 | error = xfs_bwrite(mp, bp); | 2597 | error = xfs_bwrite(bp); |
2601 | else | 2598 | else |
2602 | xfs_bdwrite(mp, bp); | 2599 | xfs_buf_delwri_queue(bp); |
2600 | |||
2601 | xfs_buf_relse(bp); | ||
2603 | return error; | 2602 | return error; |
2604 | 2603 | ||
2605 | corrupt_out: | 2604 | corrupt_out: |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 2380a4bcbece..760140d1dd66 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -257,7 +257,6 @@ typedef struct xfs_inode { | |||
257 | 257 | ||
258 | xfs_fsize_t i_size; /* in-memory size */ | 258 | xfs_fsize_t i_size; /* in-memory size */ |
259 | xfs_fsize_t i_new_size; /* size when write completes */ | 259 | xfs_fsize_t i_new_size; /* size when write completes */ |
260 | atomic_t i_iocount; /* outstanding I/O count */ | ||
261 | 260 | ||
262 | /* VFS inode */ | 261 | /* VFS inode */ |
263 | struct inode i_vnode; /* embedded VFS inode */ | 262 | struct inode i_vnode; /* embedded VFS inode */ |
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 836ad80d4f2b..b7cf21ba240f 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -658,10 +658,8 @@ xfs_inode_item_unlock( | |||
658 | 658 | ||
659 | lock_flags = iip->ili_lock_flags; | 659 | lock_flags = iip->ili_lock_flags; |
660 | iip->ili_lock_flags = 0; | 660 | iip->ili_lock_flags = 0; |
661 | if (lock_flags) { | 661 | if (lock_flags) |
662 | xfs_iunlock(ip, lock_flags); | 662 | xfs_iunlock(ip, lock_flags); |
663 | IRELE(ip); | ||
664 | } | ||
665 | } | 663 | } |
666 | 664 | ||
667 | /* | 665 | /* |
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index f7ce7debe14c..d99a90518909 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
@@ -1069,7 +1069,7 @@ xfs_ioctl_setattr( | |||
1069 | } | 1069 | } |
1070 | } | 1070 | } |
1071 | 1071 | ||
1072 | xfs_trans_ijoin(tp, ip); | 1072 | xfs_trans_ijoin(tp, ip, 0); |
1073 | 1073 | ||
1074 | /* | 1074 | /* |
1075 | * Change file ownership. Must be the owner or privileged. | 1075 | * Change file ownership. Must be the owner or privileged. |
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 091d82b94c4d..9afa282aa937 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -208,22 +208,20 @@ xfs_iomap_write_direct( | |||
208 | if (error) | 208 | if (error) |
209 | goto error1; | 209 | goto error1; |
210 | 210 | ||
211 | xfs_trans_ijoin(tp, ip); | 211 | xfs_trans_ijoin(tp, ip, 0); |
212 | 212 | ||
213 | bmapi_flag = XFS_BMAPI_WRITE; | 213 | bmapi_flag = 0; |
214 | if (offset < ip->i_size || extsz) | 214 | if (offset < ip->i_size || extsz) |
215 | bmapi_flag |= XFS_BMAPI_PREALLOC; | 215 | bmapi_flag |= XFS_BMAPI_PREALLOC; |
216 | 216 | ||
217 | /* | 217 | /* |
218 | * Issue the xfs_bmapi() call to allocate the blocks. | ||
219 | * | ||
220 | * From this point onwards we overwrite the imap pointer that the | 218 | * From this point onwards we overwrite the imap pointer that the |
221 | * caller gave to us. | 219 | * caller gave to us. |
222 | */ | 220 | */ |
223 | xfs_bmap_init(&free_list, &firstfsb); | 221 | xfs_bmap_init(&free_list, &firstfsb); |
224 | nimaps = 1; | 222 | nimaps = 1; |
225 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, bmapi_flag, | 223 | error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, bmapi_flag, |
226 | &firstfsb, 0, imap, &nimaps, &free_list); | 224 | &firstfsb, 0, imap, &nimaps, &free_list); |
227 | if (error) | 225 | if (error) |
228 | goto error0; | 226 | goto error0; |
229 | 227 | ||
@@ -300,8 +298,8 @@ xfs_iomap_eof_want_preallocate( | |||
300 | while (count_fsb > 0) { | 298 | while (count_fsb > 0) { |
301 | imaps = nimaps; | 299 | imaps = nimaps; |
302 | firstblock = NULLFSBLOCK; | 300 | firstblock = NULLFSBLOCK; |
303 | error = xfs_bmapi(NULL, ip, start_fsb, count_fsb, 0, | 301 | error = xfs_bmapi_read(ip, start_fsb, count_fsb, imap, &imaps, |
304 | &firstblock, 0, imap, &imaps, NULL); | 302 | 0); |
305 | if (error) | 303 | if (error) |
306 | return error; | 304 | return error; |
307 | for (n = 0; n < imaps; n++) { | 305 | for (n = 0; n < imaps; n++) { |
@@ -381,7 +379,6 @@ xfs_iomap_write_delay( | |||
381 | xfs_fileoff_t last_fsb; | 379 | xfs_fileoff_t last_fsb; |
382 | xfs_off_t aligned_offset; | 380 | xfs_off_t aligned_offset; |
383 | xfs_fileoff_t ioalign; | 381 | xfs_fileoff_t ioalign; |
384 | xfs_fsblock_t firstblock; | ||
385 | xfs_extlen_t extsz; | 382 | xfs_extlen_t extsz; |
386 | int nimaps; | 383 | int nimaps; |
387 | xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; | 384 | xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; |
@@ -425,12 +422,8 @@ retry: | |||
425 | } | 422 | } |
426 | 423 | ||
427 | nimaps = XFS_WRITE_IMAPS; | 424 | nimaps = XFS_WRITE_IMAPS; |
428 | firstblock = NULLFSBLOCK; | 425 | error = xfs_bmapi_delay(ip, offset_fsb, last_fsb - offset_fsb, |
429 | error = xfs_bmapi(NULL, ip, offset_fsb, | 426 | imap, &nimaps, XFS_BMAPI_ENTIRE); |
430 | (xfs_filblks_t)(last_fsb - offset_fsb), | ||
431 | XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | | ||
432 | XFS_BMAPI_ENTIRE, &firstblock, 1, imap, | ||
433 | &nimaps, NULL); | ||
434 | switch (error) { | 427 | switch (error) { |
435 | case 0: | 428 | case 0: |
436 | case ENOSPC: | 429 | case ENOSPC: |
@@ -535,7 +528,7 @@ xfs_iomap_write_allocate( | |||
535 | return XFS_ERROR(error); | 528 | return XFS_ERROR(error); |
536 | } | 529 | } |
537 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 530 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
538 | xfs_trans_ijoin(tp, ip); | 531 | xfs_trans_ijoin(tp, ip, 0); |
539 | 532 | ||
540 | xfs_bmap_init(&free_list, &first_block); | 533 | xfs_bmap_init(&free_list, &first_block); |
541 | 534 | ||
@@ -587,14 +580,12 @@ xfs_iomap_write_allocate( | |||
587 | } | 580 | } |
588 | 581 | ||
589 | /* | 582 | /* |
590 | * Go get the actual blocks. | ||
591 | * | ||
592 | * From this point onwards we overwrite the imap | 583 | * From this point onwards we overwrite the imap |
593 | * pointer that the caller gave to us. | 584 | * pointer that the caller gave to us. |
594 | */ | 585 | */ |
595 | error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb, | 586 | error = xfs_bmapi_write(tp, ip, map_start_fsb, |
596 | XFS_BMAPI_WRITE, &first_block, 1, | 587 | count_fsb, 0, &first_block, 1, |
597 | imap, &nimaps, &free_list); | 588 | imap, &nimaps, &free_list); |
598 | if (error) | 589 | if (error) |
599 | goto trans_cancel; | 590 | goto trans_cancel; |
600 | 591 | ||
@@ -701,15 +692,15 @@ xfs_iomap_write_unwritten( | |||
701 | } | 692 | } |
702 | 693 | ||
703 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 694 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
704 | xfs_trans_ijoin(tp, ip); | 695 | xfs_trans_ijoin(tp, ip, 0); |
705 | 696 | ||
706 | /* | 697 | /* |
707 | * Modify the unwritten extent state of the buffer. | 698 | * Modify the unwritten extent state of the buffer. |
708 | */ | 699 | */ |
709 | xfs_bmap_init(&free_list, &firstfsb); | 700 | xfs_bmap_init(&free_list, &firstfsb); |
710 | nimaps = 1; | 701 | nimaps = 1; |
711 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, | 702 | error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, |
712 | XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb, | 703 | XFS_BMAPI_CONVERT, &firstfsb, |
713 | 1, &imap, &nimaps, &free_list); | 704 | 1, &imap, &nimaps, &free_list); |
714 | if (error) | 705 | if (error) |
715 | goto error_on_bmapi_transaction; | 706 | goto error_on_bmapi_transaction; |
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 28856accb4fa..9ba2a07b7343 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
@@ -466,7 +466,7 @@ xfs_vn_getattr( | |||
466 | trace_xfs_getattr(ip); | 466 | trace_xfs_getattr(ip); |
467 | 467 | ||
468 | if (XFS_FORCED_SHUTDOWN(mp)) | 468 | if (XFS_FORCED_SHUTDOWN(mp)) |
469 | return XFS_ERROR(EIO); | 469 | return -XFS_ERROR(EIO); |
470 | 470 | ||
471 | stat->size = XFS_ISIZE(ip); | 471 | stat->size = XFS_ISIZE(ip); |
472 | stat->dev = inode->i_sb->s_dev; | 472 | stat->dev = inode->i_sb->s_dev; |
@@ -612,7 +612,7 @@ xfs_setattr_nonsize( | |||
612 | } | 612 | } |
613 | } | 613 | } |
614 | 614 | ||
615 | xfs_trans_ijoin(tp, ip); | 615 | xfs_trans_ijoin(tp, ip, 0); |
616 | 616 | ||
617 | /* | 617 | /* |
618 | * Change file ownership. Must be the owner or privileged. | 618 | * Change file ownership. Must be the owner or privileged. |
@@ -834,16 +834,16 @@ xfs_setattr_size( | |||
834 | * care about here. | 834 | * care about here. |
835 | */ | 835 | */ |
836 | if (ip->i_size != ip->i_d.di_size && iattr->ia_size > ip->i_d.di_size) { | 836 | if (ip->i_size != ip->i_d.di_size && iattr->ia_size > ip->i_d.di_size) { |
837 | error = xfs_flush_pages(ip, ip->i_d.di_size, iattr->ia_size, | 837 | error = xfs_flush_pages(ip, ip->i_d.di_size, iattr->ia_size, 0, |
838 | XBF_ASYNC, FI_NONE); | 838 | FI_NONE); |
839 | if (error) | 839 | if (error) |
840 | goto out_unlock; | 840 | goto out_unlock; |
841 | } | 841 | } |
842 | 842 | ||
843 | /* | 843 | /* |
844 | * Wait for all I/O to complete. | 844 | * Wait for all direct I/O to complete. |
845 | */ | 845 | */ |
846 | xfs_ioend_wait(ip); | 846 | inode_dio_wait(inode); |
847 | 847 | ||
848 | error = -block_truncate_page(inode->i_mapping, iattr->ia_size, | 848 | error = -block_truncate_page(inode->i_mapping, iattr->ia_size, |
849 | xfs_get_blocks); | 849 | xfs_get_blocks); |
@@ -864,7 +864,7 @@ xfs_setattr_size( | |||
864 | 864 | ||
865 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 865 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
866 | 866 | ||
867 | xfs_trans_ijoin(tp, ip); | 867 | xfs_trans_ijoin(tp, ip, 0); |
868 | 868 | ||
869 | /* | 869 | /* |
870 | * Only change the c/mtime if we are changing the size or we are | 870 | * Only change the c/mtime if we are changing the size or we are |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 3a8d4f66d702..2758a6277c52 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -880,8 +880,8 @@ xlog_iodone(xfs_buf_t *bp) | |||
880 | */ | 880 | */ |
881 | if (XFS_TEST_ERROR((xfs_buf_geterror(bp)), l->l_mp, | 881 | if (XFS_TEST_ERROR((xfs_buf_geterror(bp)), l->l_mp, |
882 | XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) { | 882 | XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) { |
883 | xfs_ioerror_alert("xlog_iodone", l->l_mp, bp, XFS_BUF_ADDR(bp)); | 883 | xfs_buf_ioerror_alert(bp, __func__); |
884 | XFS_BUF_STALE(bp); | 884 | xfs_buf_stale(bp); |
885 | xfs_force_shutdown(l->l_mp, SHUTDOWN_LOG_IO_ERROR); | 885 | xfs_force_shutdown(l->l_mp, SHUTDOWN_LOG_IO_ERROR); |
886 | /* | 886 | /* |
887 | * This flag will be propagated to the trans-committed | 887 | * This flag will be propagated to the trans-committed |
@@ -1047,7 +1047,7 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1047 | xlog_get_iclog_buffer_size(mp, log); | 1047 | xlog_get_iclog_buffer_size(mp, log); |
1048 | 1048 | ||
1049 | error = ENOMEM; | 1049 | error = ENOMEM; |
1050 | bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp); | 1050 | bp = xfs_buf_alloc(mp->m_logdev_targp, 0, log->l_iclog_size, 0); |
1051 | if (!bp) | 1051 | if (!bp) |
1052 | goto out_free_log; | 1052 | goto out_free_log; |
1053 | bp->b_iodone = xlog_iodone; | 1053 | bp->b_iodone = xlog_iodone; |
@@ -1247,7 +1247,7 @@ xlog_bdstrat( | |||
1247 | 1247 | ||
1248 | if (iclog->ic_state & XLOG_STATE_IOERROR) { | 1248 | if (iclog->ic_state & XLOG_STATE_IOERROR) { |
1249 | xfs_buf_ioerror(bp, EIO); | 1249 | xfs_buf_ioerror(bp, EIO); |
1250 | XFS_BUF_STALE(bp); | 1250 | xfs_buf_stale(bp); |
1251 | xfs_buf_ioend(bp, 0); | 1251 | xfs_buf_ioend(bp, 0); |
1252 | /* | 1252 | /* |
1253 | * It would seem logical to return EIO here, but we rely on | 1253 | * It would seem logical to return EIO here, but we rely on |
@@ -1387,9 +1387,9 @@ xlog_sync(xlog_t *log, | |||
1387 | */ | 1387 | */ |
1388 | XFS_BUF_WRITE(bp); | 1388 | XFS_BUF_WRITE(bp); |
1389 | 1389 | ||
1390 | if ((error = xlog_bdstrat(bp))) { | 1390 | error = xlog_bdstrat(bp); |
1391 | xfs_ioerror_alert("xlog_sync", log->l_mp, bp, | 1391 | if (error) { |
1392 | XFS_BUF_ADDR(bp)); | 1392 | xfs_buf_ioerror_alert(bp, "xlog_sync"); |
1393 | return error; | 1393 | return error; |
1394 | } | 1394 | } |
1395 | if (split) { | 1395 | if (split) { |
@@ -1423,9 +1423,9 @@ xlog_sync(xlog_t *log, | |||
1423 | /* account for internal log which doesn't start at block #0 */ | 1423 | /* account for internal log which doesn't start at block #0 */ |
1424 | XFS_BUF_SET_ADDR(bp, XFS_BUF_ADDR(bp) + log->l_logBBstart); | 1424 | XFS_BUF_SET_ADDR(bp, XFS_BUF_ADDR(bp) + log->l_logBBstart); |
1425 | XFS_BUF_WRITE(bp); | 1425 | XFS_BUF_WRITE(bp); |
1426 | if ((error = xlog_bdstrat(bp))) { | 1426 | error = xlog_bdstrat(bp); |
1427 | xfs_ioerror_alert("xlog_sync (split)", log->l_mp, | 1427 | if (error) { |
1428 | bp, XFS_BUF_ADDR(bp)); | 1428 | xfs_buf_ioerror_alert(bp, "xlog_sync (split)"); |
1429 | return error; | 1429 | return error; |
1430 | } | 1430 | } |
1431 | } | 1431 | } |
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index a199dbcee7d8..541a508adea1 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -183,8 +183,7 @@ xlog_bread_noalign( | |||
183 | xfsbdstrat(log->l_mp, bp); | 183 | xfsbdstrat(log->l_mp, bp); |
184 | error = xfs_buf_iowait(bp); | 184 | error = xfs_buf_iowait(bp); |
185 | if (error) | 185 | if (error) |
186 | xfs_ioerror_alert("xlog_bread", log->l_mp, | 186 | xfs_buf_ioerror_alert(bp, __func__); |
187 | bp, XFS_BUF_ADDR(bp)); | ||
188 | return error; | 187 | return error; |
189 | } | 188 | } |
190 | 189 | ||
@@ -268,9 +267,10 @@ xlog_bwrite( | |||
268 | xfs_buf_lock(bp); | 267 | xfs_buf_lock(bp); |
269 | XFS_BUF_SET_COUNT(bp, BBTOB(nbblks)); | 268 | XFS_BUF_SET_COUNT(bp, BBTOB(nbblks)); |
270 | 269 | ||
271 | if ((error = xfs_bwrite(log->l_mp, bp))) | 270 | error = xfs_bwrite(bp); |
272 | xfs_ioerror_alert("xlog_bwrite", log->l_mp, | 271 | if (error) |
273 | bp, XFS_BUF_ADDR(bp)); | 272 | xfs_buf_ioerror_alert(bp, __func__); |
273 | xfs_buf_relse(bp); | ||
274 | return error; | 274 | return error; |
275 | } | 275 | } |
276 | 276 | ||
@@ -361,9 +361,7 @@ xlog_recover_iodone( | |||
361 | * We're not going to bother about retrying | 361 | * We're not going to bother about retrying |
362 | * this during recovery. One strike! | 362 | * this during recovery. One strike! |
363 | */ | 363 | */ |
364 | xfs_ioerror_alert("xlog_recover_iodone", | 364 | xfs_buf_ioerror_alert(bp, __func__); |
365 | bp->b_target->bt_mount, bp, | ||
366 | XFS_BUF_ADDR(bp)); | ||
367 | xfs_force_shutdown(bp->b_target->bt_mount, | 365 | xfs_force_shutdown(bp->b_target->bt_mount, |
368 | SHUTDOWN_META_IO_ERROR); | 366 | SHUTDOWN_META_IO_ERROR); |
369 | } | 367 | } |
@@ -2135,8 +2133,7 @@ xlog_recover_buffer_pass2( | |||
2135 | return XFS_ERROR(ENOMEM); | 2133 | return XFS_ERROR(ENOMEM); |
2136 | error = bp->b_error; | 2134 | error = bp->b_error; |
2137 | if (error) { | 2135 | if (error) { |
2138 | xfs_ioerror_alert("xlog_recover_do..(read#1)", mp, | 2136 | xfs_buf_ioerror_alert(bp, "xlog_recover_do..(read#1)"); |
2139 | bp, buf_f->blf_blkno); | ||
2140 | xfs_buf_relse(bp); | 2137 | xfs_buf_relse(bp); |
2141 | return error; | 2138 | return error; |
2142 | } | 2139 | } |
@@ -2171,15 +2168,16 @@ xlog_recover_buffer_pass2( | |||
2171 | be16_to_cpu(*((__be16 *)xfs_buf_offset(bp, 0))) && | 2168 | be16_to_cpu(*((__be16 *)xfs_buf_offset(bp, 0))) && |
2172 | (XFS_BUF_COUNT(bp) != MAX(log->l_mp->m_sb.sb_blocksize, | 2169 | (XFS_BUF_COUNT(bp) != MAX(log->l_mp->m_sb.sb_blocksize, |
2173 | (__uint32_t)XFS_INODE_CLUSTER_SIZE(log->l_mp)))) { | 2170 | (__uint32_t)XFS_INODE_CLUSTER_SIZE(log->l_mp)))) { |
2174 | XFS_BUF_STALE(bp); | 2171 | xfs_buf_stale(bp); |
2175 | error = xfs_bwrite(mp, bp); | 2172 | error = xfs_bwrite(bp); |
2176 | } else { | 2173 | } else { |
2177 | ASSERT(bp->b_target->bt_mount == mp); | 2174 | ASSERT(bp->b_target->bt_mount == mp); |
2178 | bp->b_iodone = xlog_recover_iodone; | 2175 | bp->b_iodone = xlog_recover_iodone; |
2179 | xfs_bdwrite(mp, bp); | 2176 | xfs_buf_delwri_queue(bp); |
2180 | } | 2177 | } |
2181 | 2178 | ||
2182 | return (error); | 2179 | xfs_buf_relse(bp); |
2180 | return error; | ||
2183 | } | 2181 | } |
2184 | 2182 | ||
2185 | STATIC int | 2183 | STATIC int |
@@ -2230,8 +2228,7 @@ xlog_recover_inode_pass2( | |||
2230 | } | 2228 | } |
2231 | error = bp->b_error; | 2229 | error = bp->b_error; |
2232 | if (error) { | 2230 | if (error) { |
2233 | xfs_ioerror_alert("xlog_recover_do..(read#2)", mp, | 2231 | xfs_buf_ioerror_alert(bp, "xlog_recover_do..(read#2)"); |
2234 | bp, in_f->ilf_blkno); | ||
2235 | xfs_buf_relse(bp); | 2232 | xfs_buf_relse(bp); |
2236 | goto error; | 2233 | goto error; |
2237 | } | 2234 | } |
@@ -2439,7 +2436,8 @@ xlog_recover_inode_pass2( | |||
2439 | write_inode_buffer: | 2436 | write_inode_buffer: |
2440 | ASSERT(bp->b_target->bt_mount == mp); | 2437 | ASSERT(bp->b_target->bt_mount == mp); |
2441 | bp->b_iodone = xlog_recover_iodone; | 2438 | bp->b_iodone = xlog_recover_iodone; |
2442 | xfs_bdwrite(mp, bp); | 2439 | xfs_buf_delwri_queue(bp); |
2440 | xfs_buf_relse(bp); | ||
2443 | error: | 2441 | error: |
2444 | if (need_free) | 2442 | if (need_free) |
2445 | kmem_free(in_f); | 2443 | kmem_free(in_f); |
@@ -2537,8 +2535,7 @@ xlog_recover_dquot_pass2( | |||
2537 | XFS_FSB_TO_BB(mp, dq_f->qlf_len), | 2535 | XFS_FSB_TO_BB(mp, dq_f->qlf_len), |
2538 | 0, &bp); | 2536 | 0, &bp); |
2539 | if (error) { | 2537 | if (error) { |
2540 | xfs_ioerror_alert("xlog_recover_do..(read#3)", mp, | 2538 | xfs_buf_ioerror_alert(bp, "xlog_recover_do..(read#3)"); |
2541 | bp, dq_f->qlf_blkno); | ||
2542 | return error; | 2539 | return error; |
2543 | } | 2540 | } |
2544 | ASSERT(bp); | 2541 | ASSERT(bp); |
@@ -2561,7 +2558,8 @@ xlog_recover_dquot_pass2( | |||
2561 | ASSERT(dq_f->qlf_size == 2); | 2558 | ASSERT(dq_f->qlf_size == 2); |
2562 | ASSERT(bp->b_target->bt_mount == mp); | 2559 | ASSERT(bp->b_target->bt_mount == mp); |
2563 | bp->b_iodone = xlog_recover_iodone; | 2560 | bp->b_iodone = xlog_recover_iodone; |
2564 | xfs_bdwrite(mp, bp); | 2561 | xfs_buf_delwri_queue(bp); |
2562 | xfs_buf_relse(bp); | ||
2565 | 2563 | ||
2566 | return (0); | 2564 | return (0); |
2567 | } | 2565 | } |
@@ -3656,7 +3654,7 @@ xlog_do_recover( | |||
3656 | return error; | 3654 | return error; |
3657 | } | 3655 | } |
3658 | 3656 | ||
3659 | XFS_bflush(log->l_mp->m_ddev_targp); | 3657 | xfs_flush_buftarg(log->l_mp->m_ddev_targp, 1); |
3660 | 3658 | ||
3661 | /* | 3659 | /* |
3662 | * If IO errors happened during recovery, bail out. | 3660 | * If IO errors happened during recovery, bail out. |
@@ -3689,8 +3687,7 @@ xlog_do_recover( | |||
3689 | xfsbdstrat(log->l_mp, bp); | 3687 | xfsbdstrat(log->l_mp, bp); |
3690 | error = xfs_buf_iowait(bp); | 3688 | error = xfs_buf_iowait(bp); |
3691 | if (error) { | 3689 | if (error) { |
3692 | xfs_ioerror_alert("xlog_do_recover", | 3690 | xfs_buf_ioerror_alert(bp, __func__); |
3693 | log->l_mp, bp, XFS_BUF_ADDR(bp)); | ||
3694 | ASSERT(0); | 3691 | ASSERT(0); |
3695 | xfs_buf_relse(bp); | 3692 | xfs_buf_relse(bp); |
3696 | return error; | 3693 | return error; |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 0081657ad985..d06afbc3540d 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -44,9 +44,6 @@ | |||
44 | #include "xfs_trace.h" | 44 | #include "xfs_trace.h" |
45 | 45 | ||
46 | 46 | ||
47 | STATIC void xfs_unmountfs_wait(xfs_mount_t *); | ||
48 | |||
49 | |||
50 | #ifdef HAVE_PERCPU_SB | 47 | #ifdef HAVE_PERCPU_SB |
51 | STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t, | 48 | STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t, |
52 | int); | 49 | int); |
@@ -1484,7 +1481,7 @@ xfs_unmountfs( | |||
1484 | * state as much as possible. | 1481 | * state as much as possible. |
1485 | */ | 1482 | */ |
1486 | xfs_reclaim_inodes(mp, 0); | 1483 | xfs_reclaim_inodes(mp, 0); |
1487 | XFS_bflush(mp->m_ddev_targp); | 1484 | xfs_flush_buftarg(mp->m_ddev_targp, 1); |
1488 | xfs_reclaim_inodes(mp, SYNC_WAIT); | 1485 | xfs_reclaim_inodes(mp, SYNC_WAIT); |
1489 | 1486 | ||
1490 | xfs_qm_unmount(mp); | 1487 | xfs_qm_unmount(mp); |
@@ -1496,11 +1493,6 @@ xfs_unmountfs( | |||
1496 | */ | 1493 | */ |
1497 | xfs_log_force(mp, XFS_LOG_SYNC); | 1494 | xfs_log_force(mp, XFS_LOG_SYNC); |
1498 | 1495 | ||
1499 | xfs_binval(mp->m_ddev_targp); | ||
1500 | if (mp->m_rtdev_targp) { | ||
1501 | xfs_binval(mp->m_rtdev_targp); | ||
1502 | } | ||
1503 | |||
1504 | /* | 1496 | /* |
1505 | * Unreserve any blocks we have so that when we unmount we don't account | 1497 | * Unreserve any blocks we have so that when we unmount we don't account |
1506 | * the reserved free space as used. This is really only necessary for | 1498 | * the reserved free space as used. This is really only necessary for |
@@ -1526,7 +1518,16 @@ xfs_unmountfs( | |||
1526 | xfs_warn(mp, "Unable to update superblock counters. " | 1518 | xfs_warn(mp, "Unable to update superblock counters. " |
1527 | "Freespace may not be correct on next mount."); | 1519 | "Freespace may not be correct on next mount."); |
1528 | xfs_unmountfs_writesb(mp); | 1520 | xfs_unmountfs_writesb(mp); |
1529 | xfs_unmountfs_wait(mp); /* wait for async bufs */ | 1521 | |
1522 | /* | ||
1523 | * Make sure all buffers have been flushed and completed before | ||
1524 | * unmounting the log. | ||
1525 | */ | ||
1526 | error = xfs_flush_buftarg(mp->m_ddev_targp, 1); | ||
1527 | if (error) | ||
1528 | xfs_warn(mp, "%d busy buffers during unmount.", error); | ||
1529 | xfs_wait_buftarg(mp->m_ddev_targp); | ||
1530 | |||
1530 | xfs_log_unmount_write(mp); | 1531 | xfs_log_unmount_write(mp); |
1531 | xfs_log_unmount(mp); | 1532 | xfs_log_unmount(mp); |
1532 | xfs_uuid_unmount(mp); | 1533 | xfs_uuid_unmount(mp); |
@@ -1537,16 +1538,6 @@ xfs_unmountfs( | |||
1537 | xfs_free_perag(mp); | 1538 | xfs_free_perag(mp); |
1538 | } | 1539 | } |
1539 | 1540 | ||
1540 | STATIC void | ||
1541 | xfs_unmountfs_wait(xfs_mount_t *mp) | ||
1542 | { | ||
1543 | if (mp->m_logdev_targp != mp->m_ddev_targp) | ||
1544 | xfs_wait_buftarg(mp->m_logdev_targp); | ||
1545 | if (mp->m_rtdev_targp) | ||
1546 | xfs_wait_buftarg(mp->m_rtdev_targp); | ||
1547 | xfs_wait_buftarg(mp->m_ddev_targp); | ||
1548 | } | ||
1549 | |||
1550 | int | 1541 | int |
1551 | xfs_fs_writable(xfs_mount_t *mp) | 1542 | xfs_fs_writable(xfs_mount_t *mp) |
1552 | { | 1543 | { |
@@ -1612,15 +1603,14 @@ xfs_unmountfs_writesb(xfs_mount_t *mp) | |||
1612 | 1603 | ||
1613 | XFS_BUF_UNDONE(sbp); | 1604 | XFS_BUF_UNDONE(sbp); |
1614 | XFS_BUF_UNREAD(sbp); | 1605 | XFS_BUF_UNREAD(sbp); |
1615 | XFS_BUF_UNDELAYWRITE(sbp); | 1606 | xfs_buf_delwri_dequeue(sbp); |
1616 | XFS_BUF_WRITE(sbp); | 1607 | XFS_BUF_WRITE(sbp); |
1617 | XFS_BUF_UNASYNC(sbp); | 1608 | XFS_BUF_UNASYNC(sbp); |
1618 | ASSERT(sbp->b_target == mp->m_ddev_targp); | 1609 | ASSERT(sbp->b_target == mp->m_ddev_targp); |
1619 | xfsbdstrat(mp, sbp); | 1610 | xfsbdstrat(mp, sbp); |
1620 | error = xfs_buf_iowait(sbp); | 1611 | error = xfs_buf_iowait(sbp); |
1621 | if (error) | 1612 | if (error) |
1622 | xfs_ioerror_alert("xfs_unmountfs_writesb", | 1613 | xfs_buf_ioerror_alert(sbp, __func__); |
1623 | mp, sbp, XFS_BUF_ADDR(sbp)); | ||
1624 | xfs_buf_relse(sbp); | 1614 | xfs_buf_relse(sbp); |
1625 | } | 1615 | } |
1626 | return error; | 1616 | return error; |
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 9a0aa76facdf..5cff443f6cdb 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c | |||
@@ -1296,7 +1296,8 @@ xfs_qm_dqiter_bufs( | |||
1296 | break; | 1296 | break; |
1297 | 1297 | ||
1298 | xfs_qm_reset_dqcounts(mp, bp, firstid, type); | 1298 | xfs_qm_reset_dqcounts(mp, bp, firstid, type); |
1299 | xfs_bdwrite(mp, bp); | 1299 | xfs_buf_delwri_queue(bp); |
1300 | xfs_buf_relse(bp); | ||
1300 | /* | 1301 | /* |
1301 | * goto the next block. | 1302 | * goto the next block. |
1302 | */ | 1303 | */ |
@@ -1346,11 +1347,8 @@ xfs_qm_dqiterate( | |||
1346 | * the inode is never added to the transaction. | 1347 | * the inode is never added to the transaction. |
1347 | */ | 1348 | */ |
1348 | xfs_ilock(qip, XFS_ILOCK_SHARED); | 1349 | xfs_ilock(qip, XFS_ILOCK_SHARED); |
1349 | error = xfs_bmapi(NULL, qip, lblkno, | 1350 | error = xfs_bmapi_read(qip, lblkno, maxlblkcnt - lblkno, |
1350 | maxlblkcnt - lblkno, | 1351 | map, &nmaps, 0); |
1351 | XFS_BMAPI_METADATA, | ||
1352 | NULL, | ||
1353 | 0, map, &nmaps, NULL); | ||
1354 | xfs_iunlock(qip, XFS_ILOCK_SHARED); | 1352 | xfs_iunlock(qip, XFS_ILOCK_SHARED); |
1355 | if (error) | 1353 | if (error) |
1356 | break; | 1354 | break; |
@@ -1683,7 +1681,7 @@ xfs_qm_quotacheck( | |||
1683 | * quotacheck'd stamp on the superblock. So, here we do a synchronous | 1681 | * quotacheck'd stamp on the superblock. So, here we do a synchronous |
1684 | * flush. | 1682 | * flush. |
1685 | */ | 1683 | */ |
1686 | XFS_bflush(mp->m_ddev_targp); | 1684 | xfs_flush_buftarg(mp->m_ddev_targp, 1); |
1687 | 1685 | ||
1688 | /* | 1686 | /* |
1689 | * If one type of quotas is off, then it will lose its | 1687 | * If one type of quotas is off, then it will lose its |
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index 609246f42e6c..5cc3dde1bc90 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c | |||
@@ -261,7 +261,7 @@ xfs_qm_scall_trunc_qfile( | |||
261 | } | 261 | } |
262 | 262 | ||
263 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 263 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
264 | xfs_trans_ijoin(tp, ip); | 264 | xfs_trans_ijoin(tp, ip, 0); |
265 | 265 | ||
266 | error = xfs_itruncate_data(&tp, ip, 0); | 266 | error = xfs_itruncate_data(&tp, ip, 0); |
267 | if (error) { | 267 | if (error) { |
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c index df78c297d1a1..866de277079a 100644 --- a/fs/xfs/xfs_rename.c +++ b/fs/xfs/xfs_rename.c | |||
@@ -170,12 +170,12 @@ xfs_rename( | |||
170 | * we can rely on either trans_commit or trans_cancel to unlock | 170 | * we can rely on either trans_commit or trans_cancel to unlock |
171 | * them. | 171 | * them. |
172 | */ | 172 | */ |
173 | xfs_trans_ijoin_ref(tp, src_dp, XFS_ILOCK_EXCL); | 173 | xfs_trans_ijoin(tp, src_dp, XFS_ILOCK_EXCL); |
174 | if (new_parent) | 174 | if (new_parent) |
175 | xfs_trans_ijoin_ref(tp, target_dp, XFS_ILOCK_EXCL); | 175 | xfs_trans_ijoin(tp, target_dp, XFS_ILOCK_EXCL); |
176 | xfs_trans_ijoin_ref(tp, src_ip, XFS_ILOCK_EXCL); | 176 | xfs_trans_ijoin(tp, src_ip, XFS_ILOCK_EXCL); |
177 | if (target_ip) | 177 | if (target_ip) |
178 | xfs_trans_ijoin_ref(tp, target_ip, XFS_ILOCK_EXCL); | 178 | xfs_trans_ijoin(tp, target_ip, XFS_ILOCK_EXCL); |
179 | 179 | ||
180 | /* | 180 | /* |
181 | * If we are using project inheritance, we only allow renames | 181 | * If we are using project inheritance, we only allow renames |
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 35561a511b57..87323f1ded64 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c | |||
@@ -112,7 +112,7 @@ xfs_growfs_rt_alloc( | |||
112 | * Lock the inode. | 112 | * Lock the inode. |
113 | */ | 113 | */ |
114 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 114 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
115 | xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); | 115 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
116 | 116 | ||
117 | xfs_bmap_init(&flist, &firstblock); | 117 | xfs_bmap_init(&flist, &firstblock); |
118 | /* | 118 | /* |
@@ -120,9 +120,9 @@ xfs_growfs_rt_alloc( | |||
120 | */ | 120 | */ |
121 | nmap = 1; | 121 | nmap = 1; |
122 | cancelflags |= XFS_TRANS_ABORT; | 122 | cancelflags |= XFS_TRANS_ABORT; |
123 | error = xfs_bmapi(tp, ip, oblocks, nblocks - oblocks, | 123 | error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks, |
124 | XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &firstblock, | 124 | XFS_BMAPI_METADATA, &firstblock, |
125 | resblks, &map, &nmap, &flist); | 125 | resblks, &map, &nmap, &flist); |
126 | if (!error && nmap < 1) | 126 | if (!error && nmap < 1) |
127 | error = XFS_ERROR(ENOSPC); | 127 | error = XFS_ERROR(ENOSPC); |
128 | if (error) | 128 | if (error) |
@@ -155,7 +155,7 @@ xfs_growfs_rt_alloc( | |||
155 | * Lock the bitmap inode. | 155 | * Lock the bitmap inode. |
156 | */ | 156 | */ |
157 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 157 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
158 | xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); | 158 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
159 | /* | 159 | /* |
160 | * Get a buffer for the block. | 160 | * Get a buffer for the block. |
161 | */ | 161 | */ |
@@ -856,33 +856,23 @@ xfs_rtbuf_get( | |||
856 | xfs_buf_t **bpp) /* output: buffer for the block */ | 856 | xfs_buf_t **bpp) /* output: buffer for the block */ |
857 | { | 857 | { |
858 | xfs_buf_t *bp; /* block buffer, result */ | 858 | xfs_buf_t *bp; /* block buffer, result */ |
859 | xfs_daddr_t d; /* disk addr of block */ | ||
860 | int error; /* error value */ | ||
861 | xfs_fsblock_t fsb; /* fs block number for block */ | ||
862 | xfs_inode_t *ip; /* bitmap or summary inode */ | 859 | xfs_inode_t *ip; /* bitmap or summary inode */ |
860 | xfs_bmbt_irec_t map; | ||
861 | int nmap; | ||
862 | int error; /* error value */ | ||
863 | 863 | ||
864 | ip = issum ? mp->m_rsumip : mp->m_rbmip; | 864 | ip = issum ? mp->m_rsumip : mp->m_rbmip; |
865 | /* | 865 | |
866 | * Map from the file offset (block) and inode number to the | 866 | error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK); |
867 | * file system block. | 867 | if (error) |
868 | */ | ||
869 | error = xfs_bmapi_single(tp, ip, XFS_DATA_FORK, &fsb, block); | ||
870 | if (error) { | ||
871 | return error; | 868 | return error; |
872 | } | 869 | |
873 | ASSERT(fsb != NULLFSBLOCK); | 870 | ASSERT(map.br_startblock != NULLFSBLOCK); |
874 | /* | 871 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, |
875 | * Convert to disk address for buffer cache. | 872 | XFS_FSB_TO_DADDR(mp, map.br_startblock), |
876 | */ | ||
877 | d = XFS_FSB_TO_DADDR(mp, fsb); | ||
878 | /* | ||
879 | * Read the buffer. | ||
880 | */ | ||
881 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d, | ||
882 | mp->m_bsize, 0, &bp); | 873 | mp->m_bsize, 0, &bp); |
883 | if (error) { | 874 | if (error) |
884 | return error; | 875 | return error; |
885 | } | ||
886 | ASSERT(!xfs_buf_geterror(bp)); | 876 | ASSERT(!xfs_buf_geterror(bp)); |
887 | *bpp = bp; | 877 | *bpp = bp; |
888 | return 0; | 878 | return 0; |
@@ -1970,7 +1960,7 @@ xfs_growfs_rt( | |||
1970 | * Lock out other callers by grabbing the bitmap inode lock. | 1960 | * Lock out other callers by grabbing the bitmap inode lock. |
1971 | */ | 1961 | */ |
1972 | xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); | 1962 | xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); |
1973 | xfs_trans_ijoin_ref(tp, mp->m_rbmip, XFS_ILOCK_EXCL); | 1963 | xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL); |
1974 | /* | 1964 | /* |
1975 | * Update the bitmap inode's size. | 1965 | * Update the bitmap inode's size. |
1976 | */ | 1966 | */ |
@@ -1982,7 +1972,7 @@ xfs_growfs_rt( | |||
1982 | * Get the summary inode into the transaction. | 1972 | * Get the summary inode into the transaction. |
1983 | */ | 1973 | */ |
1984 | xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL); | 1974 | xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL); |
1985 | xfs_trans_ijoin_ref(tp, mp->m_rsumip, XFS_ILOCK_EXCL); | 1975 | xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL); |
1986 | /* | 1976 | /* |
1987 | * Update the summary inode's size. | 1977 | * Update the summary inode's size. |
1988 | */ | 1978 | */ |
@@ -2153,7 +2143,7 @@ xfs_rtfree_extent( | |||
2153 | * Synchronize by locking the bitmap inode. | 2143 | * Synchronize by locking the bitmap inode. |
2154 | */ | 2144 | */ |
2155 | xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); | 2145 | xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); |
2156 | xfs_trans_ijoin_ref(tp, mp->m_rbmip, XFS_ILOCK_EXCL); | 2146 | xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL); |
2157 | 2147 | ||
2158 | #if defined(__KERNEL__) && defined(DEBUG) | 2148 | #if defined(__KERNEL__) && defined(DEBUG) |
2159 | /* | 2149 | /* |
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index c96a8a05ac03..597d044a09a1 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c | |||
@@ -92,24 +92,6 @@ xfs_do_force_shutdown( | |||
92 | } | 92 | } |
93 | 93 | ||
94 | /* | 94 | /* |
95 | * Prints out an ALERT message about I/O error. | ||
96 | */ | ||
97 | void | ||
98 | xfs_ioerror_alert( | ||
99 | char *func, | ||
100 | struct xfs_mount *mp, | ||
101 | xfs_buf_t *bp, | ||
102 | xfs_daddr_t blkno) | ||
103 | { | ||
104 | xfs_alert(mp, | ||
105 | "I/O error occurred: meta-data dev %s block 0x%llx" | ||
106 | " (\"%s\") error %d buf count %zd", | ||
107 | xfs_buf_target_name(bp->b_target), | ||
108 | (__uint64_t)blkno, func, | ||
109 | bp->b_error, XFS_BUF_COUNT(bp)); | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * This isn't an absolute requirement, but it is | 95 | * This isn't an absolute requirement, but it is |
114 | * just a good idea to call xfs_read_buf instead of | 96 | * just a good idea to call xfs_read_buf instead of |
115 | * directly doing a read_buf call. For one, we shouldn't | 97 | * directly doing a read_buf call. For one, we shouldn't |
@@ -143,14 +125,13 @@ xfs_read_buf( | |||
143 | } else { | 125 | } else { |
144 | *bpp = NULL; | 126 | *bpp = NULL; |
145 | if (error) { | 127 | if (error) { |
146 | xfs_ioerror_alert("xfs_read_buf", mp, bp, XFS_BUF_ADDR(bp)); | 128 | xfs_buf_ioerror_alert(bp, __func__); |
147 | } else { | 129 | } else { |
148 | error = XFS_ERROR(EIO); | 130 | error = XFS_ERROR(EIO); |
149 | } | 131 | } |
150 | if (bp) { | 132 | if (bp) { |
151 | XFS_BUF_UNDONE(bp); | 133 | XFS_BUF_UNDONE(bp); |
152 | XFS_BUF_UNDELAYWRITE(bp); | 134 | xfs_buf_stale(bp); |
153 | XFS_BUF_STALE(bp); | ||
154 | /* | 135 | /* |
155 | * brelse clears B_ERROR and b_error | 136 | * brelse clears B_ERROR and b_error |
156 | */ | 137 | */ |
diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h index 11c41ec6ed75..bbdb9ad6a4ba 100644 --- a/fs/xfs/xfs_rw.h +++ b/fs/xfs/xfs_rw.h | |||
@@ -42,8 +42,6 @@ xfs_fsb_to_db(struct xfs_inode *ip, xfs_fsblock_t fsb) | |||
42 | extern int xfs_read_buf(struct xfs_mount *mp, xfs_buftarg_t *btp, | 42 | extern int xfs_read_buf(struct xfs_mount *mp, xfs_buftarg_t *btp, |
43 | xfs_daddr_t blkno, int len, uint flags, | 43 | xfs_daddr_t blkno, int len, uint flags, |
44 | struct xfs_buf **bpp); | 44 | struct xfs_buf **bpp); |
45 | extern void xfs_ioerror_alert(char *func, struct xfs_mount *mp, | ||
46 | xfs_buf_t *bp, xfs_daddr_t blkno); | ||
47 | extern xfs_extlen_t xfs_get_extsz_hint(struct xfs_inode *ip); | 45 | extern xfs_extlen_t xfs_get_extsz_hint(struct xfs_inode *ip); |
48 | 46 | ||
49 | #endif /* __XFS_RW_H__ */ | 47 | #endif /* __XFS_RW_H__ */ |
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 5cf06b85fd9d..3eca58f51ae9 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c | |||
@@ -796,8 +796,6 @@ xfs_fs_destroy_inode( | |||
796 | if (is_bad_inode(inode)) | 796 | if (is_bad_inode(inode)) |
797 | goto out_reclaim; | 797 | goto out_reclaim; |
798 | 798 | ||
799 | xfs_ioend_wait(ip); | ||
800 | |||
801 | ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); | 799 | ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); |
802 | 800 | ||
803 | /* | 801 | /* |
@@ -837,7 +835,6 @@ xfs_fs_inode_init_once( | |||
837 | inode_init_once(VFS_I(ip)); | 835 | inode_init_once(VFS_I(ip)); |
838 | 836 | ||
839 | /* xfs inode */ | 837 | /* xfs inode */ |
840 | atomic_set(&ip->i_iocount, 0); | ||
841 | atomic_set(&ip->i_pincount, 0); | 838 | atomic_set(&ip->i_pincount, 0); |
842 | spin_lock_init(&ip->i_flags_lock); | 839 | spin_lock_init(&ip->i_flags_lock); |
843 | init_waitqueue_head(&ip->i_ipin_wait); | 840 | init_waitqueue_head(&ip->i_ipin_wait); |
@@ -887,7 +884,7 @@ xfs_log_inode( | |||
887 | } | 884 | } |
888 | 885 | ||
889 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 886 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
890 | xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); | 887 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
891 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 888 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
892 | return xfs_trans_commit(tp, 0); | 889 | return xfs_trans_commit(tp, 0); |
893 | } | 890 | } |
@@ -914,9 +911,8 @@ xfs_fs_write_inode( | |||
914 | * of forcing it all the way to stable storage using a | 911 | * of forcing it all the way to stable storage using a |
915 | * synchronous transaction we let the log force inside the | 912 | * synchronous transaction we let the log force inside the |
916 | * ->sync_fs call do that for thus, which reduces the number | 913 | * ->sync_fs call do that for thus, which reduces the number |
917 | * of synchronous log foces dramatically. | 914 | * of synchronous log forces dramatically. |
918 | */ | 915 | */ |
919 | xfs_ioend_wait(ip); | ||
920 | error = xfs_log_inode(ip); | 916 | error = xfs_log_inode(ip); |
921 | if (error) | 917 | if (error) |
922 | goto out; | 918 | goto out; |
@@ -1019,7 +1015,7 @@ xfs_fs_put_super( | |||
1019 | */ | 1015 | */ |
1020 | xfs_filestream_unmount(mp); | 1016 | xfs_filestream_unmount(mp); |
1021 | 1017 | ||
1022 | XFS_bflush(mp->m_ddev_targp); | 1018 | xfs_flush_buftarg(mp->m_ddev_targp, 1); |
1023 | 1019 | ||
1024 | xfs_unmountfs(mp); | 1020 | xfs_unmountfs(mp); |
1025 | xfs_freesb(mp); | 1021 | xfs_freesb(mp); |
@@ -1443,7 +1439,7 @@ xfs_fs_fill_super( | |||
1443 | */ | 1439 | */ |
1444 | xfs_filestream_unmount(mp); | 1440 | xfs_filestream_unmount(mp); |
1445 | 1441 | ||
1446 | XFS_bflush(mp->m_ddev_targp); | 1442 | xfs_flush_buftarg(mp->m_ddev_targp, 1); |
1447 | 1443 | ||
1448 | xfs_unmountfs(mp); | 1444 | xfs_unmountfs(mp); |
1449 | goto out_free_sb; | 1445 | goto out_free_sb; |
@@ -1670,7 +1666,6 @@ init_xfs_fs(void) | |||
1670 | printk(KERN_INFO XFS_VERSION_STRING " with " | 1666 | printk(KERN_INFO XFS_VERSION_STRING " with " |
1671 | XFS_BUILD_OPTIONS " enabled\n"); | 1667 | XFS_BUILD_OPTIONS " enabled\n"); |
1672 | 1668 | ||
1673 | xfs_ioend_init(); | ||
1674 | xfs_dir_startup(); | 1669 | xfs_dir_startup(); |
1675 | 1670 | ||
1676 | error = xfs_init_zones(); | 1671 | error = xfs_init_zones(); |
diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c index 4604f90f86a3..aa3dc1a4d53d 100644 --- a/fs/xfs/xfs_sync.c +++ b/fs/xfs/xfs_sync.c | |||
@@ -227,21 +227,17 @@ xfs_sync_inode_data( | |||
227 | int error = 0; | 227 | int error = 0; |
228 | 228 | ||
229 | if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) | 229 | if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) |
230 | goto out_wait; | 230 | return 0; |
231 | 231 | ||
232 | if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) { | 232 | if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) { |
233 | if (flags & SYNC_TRYLOCK) | 233 | if (flags & SYNC_TRYLOCK) |
234 | goto out_wait; | 234 | return 0; |
235 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | 235 | xfs_ilock(ip, XFS_IOLOCK_SHARED); |
236 | } | 236 | } |
237 | 237 | ||
238 | error = xfs_flush_pages(ip, 0, -1, (flags & SYNC_WAIT) ? | 238 | error = xfs_flush_pages(ip, 0, -1, (flags & SYNC_WAIT) ? |
239 | 0 : XBF_ASYNC, FI_NONE); | 239 | 0 : XBF_ASYNC, FI_NONE); |
240 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | 240 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
241 | |||
242 | out_wait: | ||
243 | if (flags & SYNC_WAIT) | ||
244 | xfs_ioend_wait(ip); | ||
245 | return error; | 241 | return error; |
246 | } | 242 | } |
247 | 243 | ||
@@ -322,6 +318,7 @@ xfs_sync_fsdata( | |||
322 | struct xfs_mount *mp) | 318 | struct xfs_mount *mp) |
323 | { | 319 | { |
324 | struct xfs_buf *bp; | 320 | struct xfs_buf *bp; |
321 | int error; | ||
325 | 322 | ||
326 | /* | 323 | /* |
327 | * If the buffer is pinned then push on the log so we won't get stuck | 324 | * If the buffer is pinned then push on the log so we won't get stuck |
@@ -334,8 +331,9 @@ xfs_sync_fsdata( | |||
334 | bp = xfs_getsb(mp, 0); | 331 | bp = xfs_getsb(mp, 0); |
335 | if (xfs_buf_ispinned(bp)) | 332 | if (xfs_buf_ispinned(bp)) |
336 | xfs_log_force(mp, 0); | 333 | xfs_log_force(mp, 0); |
337 | 334 | error = xfs_bwrite(bp); | |
338 | return xfs_bwrite(mp, bp); | 335 | xfs_buf_relse(bp); |
336 | return error; | ||
339 | } | 337 | } |
340 | 338 | ||
341 | /* | 339 | /* |
@@ -379,7 +377,7 @@ xfs_quiesce_data( | |||
379 | 377 | ||
380 | /* flush data-only devices */ | 378 | /* flush data-only devices */ |
381 | if (mp->m_rtdev_targp) | 379 | if (mp->m_rtdev_targp) |
382 | XFS_bflush(mp->m_rtdev_targp); | 380 | xfs_flush_buftarg(mp->m_rtdev_targp, 1); |
383 | 381 | ||
384 | return error ? error : error2; | 382 | return error ? error : error2; |
385 | } | 383 | } |
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 690fc7a7bd72..f1d2802b2f07 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h | |||
@@ -30,6 +30,7 @@ struct xfs_buf_log_item; | |||
30 | struct xfs_da_args; | 30 | struct xfs_da_args; |
31 | struct xfs_da_node_entry; | 31 | struct xfs_da_node_entry; |
32 | struct xfs_dquot; | 32 | struct xfs_dquot; |
33 | struct xfs_log_item; | ||
33 | struct xlog_ticket; | 34 | struct xlog_ticket; |
34 | struct log; | 35 | struct log; |
35 | struct xlog_recover; | 36 | struct xlog_recover; |
@@ -320,7 +321,6 @@ DEFINE_BUF_EVENT(xfs_buf_rele); | |||
320 | DEFINE_BUF_EVENT(xfs_buf_iodone); | 321 | DEFINE_BUF_EVENT(xfs_buf_iodone); |
321 | DEFINE_BUF_EVENT(xfs_buf_iorequest); | 322 | DEFINE_BUF_EVENT(xfs_buf_iorequest); |
322 | DEFINE_BUF_EVENT(xfs_buf_bawrite); | 323 | DEFINE_BUF_EVENT(xfs_buf_bawrite); |
323 | DEFINE_BUF_EVENT(xfs_buf_bdwrite); | ||
324 | DEFINE_BUF_EVENT(xfs_buf_lock); | 324 | DEFINE_BUF_EVENT(xfs_buf_lock); |
325 | DEFINE_BUF_EVENT(xfs_buf_lock_done); | 325 | DEFINE_BUF_EVENT(xfs_buf_lock_done); |
326 | DEFINE_BUF_EVENT(xfs_buf_trylock); | 326 | DEFINE_BUF_EVENT(xfs_buf_trylock); |
@@ -577,6 +577,7 @@ DEFINE_INODE_EVENT(xfs_vm_bmap); | |||
577 | DEFINE_INODE_EVENT(xfs_file_ioctl); | 577 | DEFINE_INODE_EVENT(xfs_file_ioctl); |
578 | DEFINE_INODE_EVENT(xfs_file_compat_ioctl); | 578 | DEFINE_INODE_EVENT(xfs_file_compat_ioctl); |
579 | DEFINE_INODE_EVENT(xfs_ioctl_setattr); | 579 | DEFINE_INODE_EVENT(xfs_ioctl_setattr); |
580 | DEFINE_INODE_EVENT(xfs_dir_fsync); | ||
580 | DEFINE_INODE_EVENT(xfs_file_fsync); | 581 | DEFINE_INODE_EVENT(xfs_file_fsync); |
581 | DEFINE_INODE_EVENT(xfs_destroy_inode); | 582 | DEFINE_INODE_EVENT(xfs_destroy_inode); |
582 | DEFINE_INODE_EVENT(xfs_write_inode); | 583 | DEFINE_INODE_EVENT(xfs_write_inode); |
@@ -853,6 +854,42 @@ DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_enter); | |||
853 | DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_exit); | 854 | DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_exit); |
854 | DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_sub); | 855 | DEFINE_LOGGRANT_EVENT(xfs_log_ungrant_sub); |
855 | 856 | ||
857 | DECLARE_EVENT_CLASS(xfs_log_item_class, | ||
858 | TP_PROTO(struct xfs_log_item *lip), | ||
859 | TP_ARGS(lip), | ||
860 | TP_STRUCT__entry( | ||
861 | __field(dev_t, dev) | ||
862 | __field(void *, lip) | ||
863 | __field(uint, type) | ||
864 | __field(uint, flags) | ||
865 | __field(xfs_lsn_t, lsn) | ||
866 | ), | ||
867 | TP_fast_assign( | ||
868 | __entry->dev = lip->li_mountp->m_super->s_dev; | ||
869 | __entry->lip = lip; | ||
870 | __entry->type = lip->li_type; | ||
871 | __entry->flags = lip->li_flags; | ||
872 | __entry->lsn = lip->li_lsn; | ||
873 | ), | ||
874 | TP_printk("dev %d:%d lip 0x%p lsn %d/%d type %s flags %s", | ||
875 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
876 | __entry->lip, | ||
877 | CYCLE_LSN(__entry->lsn), BLOCK_LSN(__entry->lsn), | ||
878 | __print_symbolic(__entry->type, XFS_LI_TYPE_DESC), | ||
879 | __print_flags(__entry->flags, "|", XFS_LI_FLAGS)) | ||
880 | ) | ||
881 | |||
882 | #define DEFINE_LOG_ITEM_EVENT(name) \ | ||
883 | DEFINE_EVENT(xfs_log_item_class, name, \ | ||
884 | TP_PROTO(struct xfs_log_item *lip), \ | ||
885 | TP_ARGS(lip)) | ||
886 | DEFINE_LOG_ITEM_EVENT(xfs_ail_push); | ||
887 | DEFINE_LOG_ITEM_EVENT(xfs_ail_pushbuf); | ||
888 | DEFINE_LOG_ITEM_EVENT(xfs_ail_pushbuf_pinned); | ||
889 | DEFINE_LOG_ITEM_EVENT(xfs_ail_pinned); | ||
890 | DEFINE_LOG_ITEM_EVENT(xfs_ail_locked); | ||
891 | |||
892 | |||
856 | DECLARE_EVENT_CLASS(xfs_file_class, | 893 | DECLARE_EVENT_CLASS(xfs_file_class, |
857 | TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags), | 894 | TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags), |
858 | TP_ARGS(ip, count, offset, flags), | 895 | TP_ARGS(ip, count, offset, flags), |
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index efc147f0e9b6..1f35b2feca97 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -1790,9 +1790,7 @@ xfs_trans_commit_cil( | |||
1790 | } | 1790 | } |
1791 | 1791 | ||
1792 | /* | 1792 | /* |
1793 | * xfs_trans_commit | 1793 | * Commit the given transaction to the log. |
1794 | * | ||
1795 | * Commit the given transaction to the log a/synchronously. | ||
1796 | * | 1794 | * |
1797 | * XFS disk error handling mechanism is not based on a typical | 1795 | * XFS disk error handling mechanism is not based on a typical |
1798 | * transaction abort mechanism. Logically after the filesystem | 1796 | * transaction abort mechanism. Logically after the filesystem |
@@ -1804,10 +1802,9 @@ xfs_trans_commit_cil( | |||
1804 | * Do not reference the transaction structure after this call. | 1802 | * Do not reference the transaction structure after this call. |
1805 | */ | 1803 | */ |
1806 | int | 1804 | int |
1807 | _xfs_trans_commit( | 1805 | xfs_trans_commit( |
1808 | struct xfs_trans *tp, | 1806 | struct xfs_trans *tp, |
1809 | uint flags, | 1807 | uint flags) |
1810 | int *log_flushed) | ||
1811 | { | 1808 | { |
1812 | struct xfs_mount *mp = tp->t_mountp; | 1809 | struct xfs_mount *mp = tp->t_mountp; |
1813 | xfs_lsn_t commit_lsn = -1; | 1810 | xfs_lsn_t commit_lsn = -1; |
@@ -1866,7 +1863,7 @@ _xfs_trans_commit( | |||
1866 | if (sync) { | 1863 | if (sync) { |
1867 | if (!error) { | 1864 | if (!error) { |
1868 | error = _xfs_log_force_lsn(mp, commit_lsn, | 1865 | error = _xfs_log_force_lsn(mp, commit_lsn, |
1869 | XFS_LOG_SYNC, log_flushed); | 1866 | XFS_LOG_SYNC, NULL); |
1870 | } | 1867 | } |
1871 | XFS_STATS_INC(xs_trans_sync); | 1868 | XFS_STATS_INC(xs_trans_sync); |
1872 | } else { | 1869 | } else { |
@@ -2021,6 +2018,6 @@ xfs_trans_roll( | |||
2021 | if (error) | 2018 | if (error) |
2022 | return error; | 2019 | return error; |
2023 | 2020 | ||
2024 | xfs_trans_ijoin(trans, dp); | 2021 | xfs_trans_ijoin(trans, dp, 0); |
2025 | return 0; | 2022 | return 0; |
2026 | } | 2023 | } |
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 53597f4db9b5..603f3eb52041 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h | |||
@@ -470,8 +470,7 @@ void xfs_trans_stale_inode_buf(xfs_trans_t *, struct xfs_buf *); | |||
470 | void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint); | 470 | void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint); |
471 | void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *); | 471 | void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *); |
472 | void xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int); | 472 | void xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int); |
473 | void xfs_trans_ijoin_ref(struct xfs_trans *, struct xfs_inode *, uint); | 473 | void xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *, uint); |
474 | void xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *); | ||
475 | void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint); | 474 | void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint); |
476 | void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint); | 475 | void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint); |
477 | struct xfs_efi_log_item *xfs_trans_get_efi(xfs_trans_t *, uint); | 476 | struct xfs_efi_log_item *xfs_trans_get_efi(xfs_trans_t *, uint); |
@@ -487,10 +486,7 @@ void xfs_trans_log_efd_extent(xfs_trans_t *, | |||
487 | struct xfs_efd_log_item *, | 486 | struct xfs_efd_log_item *, |
488 | xfs_fsblock_t, | 487 | xfs_fsblock_t, |
489 | xfs_extlen_t); | 488 | xfs_extlen_t); |
490 | int _xfs_trans_commit(xfs_trans_t *, | 489 | int xfs_trans_commit(xfs_trans_t *, uint flags); |
491 | uint flags, | ||
492 | int *); | ||
493 | #define xfs_trans_commit(tp, flags) _xfs_trans_commit(tp, flags, NULL) | ||
494 | void xfs_trans_cancel(xfs_trans_t *, int); | 490 | void xfs_trans_cancel(xfs_trans_t *, int); |
495 | int xfs_trans_ail_init(struct xfs_mount *); | 491 | int xfs_trans_ail_init(struct xfs_mount *); |
496 | void xfs_trans_ail_destroy(struct xfs_mount *); | 492 | void xfs_trans_ail_destroy(struct xfs_mount *); |
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index 3a1e7ca54c2d..ed9252bcdac9 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
28 | #include "xfs_trans_priv.h" | 28 | #include "xfs_trans_priv.h" |
29 | #include "xfs_trace.h" | ||
29 | #include "xfs_error.h" | 30 | #include "xfs_error.h" |
30 | 31 | ||
31 | #ifdef DEBUG | 32 | #ifdef DEBUG |
@@ -364,12 +365,24 @@ xfsaild_push( | |||
364 | xfs_lsn_t lsn; | 365 | xfs_lsn_t lsn; |
365 | xfs_lsn_t target; | 366 | xfs_lsn_t target; |
366 | long tout = 10; | 367 | long tout = 10; |
367 | int flush_log = 0; | ||
368 | int stuck = 0; | 368 | int stuck = 0; |
369 | int count = 0; | 369 | int count = 0; |
370 | int push_xfsbufd = 0; | 370 | int push_xfsbufd = 0; |
371 | 371 | ||
372 | /* | ||
373 | * If last time we ran we encountered pinned items, force the log first | ||
374 | * and wait for it before pushing again. | ||
375 | */ | ||
372 | spin_lock(&ailp->xa_lock); | 376 | spin_lock(&ailp->xa_lock); |
377 | if (ailp->xa_last_pushed_lsn == 0 && ailp->xa_log_flush && | ||
378 | !list_empty(&ailp->xa_ail)) { | ||
379 | ailp->xa_log_flush = 0; | ||
380 | spin_unlock(&ailp->xa_lock); | ||
381 | XFS_STATS_INC(xs_push_ail_flush); | ||
382 | xfs_log_force(mp, XFS_LOG_SYNC); | ||
383 | spin_lock(&ailp->xa_lock); | ||
384 | } | ||
385 | |||
373 | target = ailp->xa_target; | 386 | target = ailp->xa_target; |
374 | lip = xfs_trans_ail_cursor_first(ailp, &cur, ailp->xa_last_pushed_lsn); | 387 | lip = xfs_trans_ail_cursor_first(ailp, &cur, ailp->xa_last_pushed_lsn); |
375 | if (!lip || XFS_FORCED_SHUTDOWN(mp)) { | 388 | if (!lip || XFS_FORCED_SHUTDOWN(mp)) { |
@@ -413,16 +426,20 @@ xfsaild_push( | |||
413 | switch (lock_result) { | 426 | switch (lock_result) { |
414 | case XFS_ITEM_SUCCESS: | 427 | case XFS_ITEM_SUCCESS: |
415 | XFS_STATS_INC(xs_push_ail_success); | 428 | XFS_STATS_INC(xs_push_ail_success); |
429 | trace_xfs_ail_push(lip); | ||
430 | |||
416 | IOP_PUSH(lip); | 431 | IOP_PUSH(lip); |
417 | ailp->xa_last_pushed_lsn = lsn; | 432 | ailp->xa_last_pushed_lsn = lsn; |
418 | break; | 433 | break; |
419 | 434 | ||
420 | case XFS_ITEM_PUSHBUF: | 435 | case XFS_ITEM_PUSHBUF: |
421 | XFS_STATS_INC(xs_push_ail_pushbuf); | 436 | XFS_STATS_INC(xs_push_ail_pushbuf); |
437 | trace_xfs_ail_pushbuf(lip); | ||
422 | 438 | ||
423 | if (!IOP_PUSHBUF(lip)) { | 439 | if (!IOP_PUSHBUF(lip)) { |
440 | trace_xfs_ail_pushbuf_pinned(lip); | ||
424 | stuck++; | 441 | stuck++; |
425 | flush_log = 1; | 442 | ailp->xa_log_flush++; |
426 | } else { | 443 | } else { |
427 | ailp->xa_last_pushed_lsn = lsn; | 444 | ailp->xa_last_pushed_lsn = lsn; |
428 | } | 445 | } |
@@ -431,12 +448,15 @@ xfsaild_push( | |||
431 | 448 | ||
432 | case XFS_ITEM_PINNED: | 449 | case XFS_ITEM_PINNED: |
433 | XFS_STATS_INC(xs_push_ail_pinned); | 450 | XFS_STATS_INC(xs_push_ail_pinned); |
451 | trace_xfs_ail_pinned(lip); | ||
452 | |||
434 | stuck++; | 453 | stuck++; |
435 | flush_log = 1; | 454 | ailp->xa_log_flush++; |
436 | break; | 455 | break; |
437 | 456 | ||
438 | case XFS_ITEM_LOCKED: | 457 | case XFS_ITEM_LOCKED: |
439 | XFS_STATS_INC(xs_push_ail_locked); | 458 | XFS_STATS_INC(xs_push_ail_locked); |
459 | trace_xfs_ail_locked(lip); | ||
440 | stuck++; | 460 | stuck++; |
441 | break; | 461 | break; |
442 | 462 | ||
@@ -476,16 +496,6 @@ xfsaild_push( | |||
476 | xfs_trans_ail_cursor_done(ailp, &cur); | 496 | xfs_trans_ail_cursor_done(ailp, &cur); |
477 | spin_unlock(&ailp->xa_lock); | 497 | spin_unlock(&ailp->xa_lock); |
478 | 498 | ||
479 | if (flush_log) { | ||
480 | /* | ||
481 | * If something we need to push out was pinned, then | ||
482 | * push out the log so it will become unpinned and | ||
483 | * move forward in the AIL. | ||
484 | */ | ||
485 | XFS_STATS_INC(xs_push_ail_flush); | ||
486 | xfs_log_force(mp, 0); | ||
487 | } | ||
488 | |||
489 | if (push_xfsbufd) { | 499 | if (push_xfsbufd) { |
490 | /* we've got delayed write buffers to flush */ | 500 | /* we've got delayed write buffers to flush */ |
491 | wake_up_process(mp->m_ddev_targp->bt_task); | 501 | wake_up_process(mp->m_ddev_targp->bt_task); |
@@ -496,6 +506,7 @@ out_done: | |||
496 | if (!count) { | 506 | if (!count) { |
497 | /* We're past our target or empty, so idle */ | 507 | /* We're past our target or empty, so idle */ |
498 | ailp->xa_last_pushed_lsn = 0; | 508 | ailp->xa_last_pushed_lsn = 0; |
509 | ailp->xa_log_flush = 0; | ||
499 | 510 | ||
500 | tout = 50; | 511 | tout = 50; |
501 | } else if (XFS_LSN_CMP(lsn, target) >= 0) { | 512 | } else if (XFS_LSN_CMP(lsn, target) >= 0) { |
@@ -514,9 +525,13 @@ out_done: | |||
514 | * were stuck. | 525 | * were stuck. |
515 | * | 526 | * |
516 | * Backoff a bit more to allow some I/O to complete before | 527 | * Backoff a bit more to allow some I/O to complete before |
517 | * continuing from where we were. | 528 | * restarting from the start of the AIL. This prevents us |
529 | * from spinning on the same items, and if they are pinned will | ||
530 | * all the restart to issue a log force to unpin the stuck | ||
531 | * items. | ||
518 | */ | 532 | */ |
519 | tout = 20; | 533 | tout = 20; |
534 | ailp->xa_last_pushed_lsn = 0; | ||
520 | } | 535 | } |
521 | 536 | ||
522 | return tout; | 537 | return tout; |
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 137e2b9e2948..475a4ded4f41 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c | |||
@@ -160,8 +160,10 @@ xfs_trans_get_buf(xfs_trans_t *tp, | |||
160 | bp = xfs_trans_buf_item_match(tp, target_dev, blkno, len); | 160 | bp = xfs_trans_buf_item_match(tp, target_dev, blkno, len); |
161 | if (bp != NULL) { | 161 | if (bp != NULL) { |
162 | ASSERT(xfs_buf_islocked(bp)); | 162 | ASSERT(xfs_buf_islocked(bp)); |
163 | if (XFS_FORCED_SHUTDOWN(tp->t_mountp)) | 163 | if (XFS_FORCED_SHUTDOWN(tp->t_mountp)) { |
164 | XFS_BUF_SUPER_STALE(bp); | 164 | xfs_buf_stale(bp); |
165 | XFS_BUF_DONE(bp); | ||
166 | } | ||
165 | 167 | ||
166 | /* | 168 | /* |
167 | * If the buffer is stale then it was binval'ed | 169 | * If the buffer is stale then it was binval'ed |
@@ -294,8 +296,7 @@ xfs_trans_read_buf( | |||
294 | 296 | ||
295 | if (bp->b_error) { | 297 | if (bp->b_error) { |
296 | error = bp->b_error; | 298 | error = bp->b_error; |
297 | xfs_ioerror_alert("xfs_trans_read_buf", mp, | 299 | xfs_buf_ioerror_alert(bp, __func__); |
298 | bp, blkno); | ||
299 | xfs_buf_relse(bp); | 300 | xfs_buf_relse(bp); |
300 | return error; | 301 | return error; |
301 | } | 302 | } |
@@ -337,8 +338,7 @@ xfs_trans_read_buf( | |||
337 | xfsbdstrat(tp->t_mountp, bp); | 338 | xfsbdstrat(tp->t_mountp, bp); |
338 | error = xfs_buf_iowait(bp); | 339 | error = xfs_buf_iowait(bp); |
339 | if (error) { | 340 | if (error) { |
340 | xfs_ioerror_alert("xfs_trans_read_buf", mp, | 341 | xfs_buf_ioerror_alert(bp, __func__); |
341 | bp, blkno); | ||
342 | xfs_buf_relse(bp); | 342 | xfs_buf_relse(bp); |
343 | /* | 343 | /* |
344 | * We can gracefully recover from most read | 344 | * We can gracefully recover from most read |
@@ -387,9 +387,9 @@ xfs_trans_read_buf( | |||
387 | } | 387 | } |
388 | if (bp->b_error) { | 388 | if (bp->b_error) { |
389 | error = bp->b_error; | 389 | error = bp->b_error; |
390 | XFS_BUF_SUPER_STALE(bp); | 390 | xfs_buf_stale(bp); |
391 | xfs_ioerror_alert("xfs_trans_read_buf", mp, | 391 | XFS_BUF_DONE(bp); |
392 | bp, blkno); | 392 | xfs_buf_ioerror_alert(bp, __func__); |
393 | if (tp->t_flags & XFS_TRANS_DIRTY) | 393 | if (tp->t_flags & XFS_TRANS_DIRTY) |
394 | xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); | 394 | xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); |
395 | xfs_buf_relse(bp); | 395 | xfs_buf_relse(bp); |
@@ -643,13 +643,14 @@ xfs_trans_log_buf(xfs_trans_t *tp, | |||
643 | * inside the b_bdstrat callback so that this won't get written to | 643 | * inside the b_bdstrat callback so that this won't get written to |
644 | * disk. | 644 | * disk. |
645 | */ | 645 | */ |
646 | XFS_BUF_DELAYWRITE(bp); | ||
647 | XFS_BUF_DONE(bp); | 646 | XFS_BUF_DONE(bp); |
648 | 647 | ||
649 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 648 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
650 | bp->b_iodone = xfs_buf_iodone_callbacks; | 649 | bp->b_iodone = xfs_buf_iodone_callbacks; |
651 | bip->bli_item.li_cb = xfs_buf_iodone; | 650 | bip->bli_item.li_cb = xfs_buf_iodone; |
652 | 651 | ||
652 | xfs_buf_delwri_queue(bp); | ||
653 | |||
653 | trace_xfs_trans_log_buf(bip); | 654 | trace_xfs_trans_log_buf(bip); |
654 | 655 | ||
655 | /* | 656 | /* |
@@ -738,8 +739,7 @@ xfs_trans_binval( | |||
738 | * We set the stale bit in the buffer as well since we're getting | 739 | * We set the stale bit in the buffer as well since we're getting |
739 | * rid of it. | 740 | * rid of it. |
740 | */ | 741 | */ |
741 | XFS_BUF_UNDELAYWRITE(bp); | 742 | xfs_buf_stale(bp); |
742 | XFS_BUF_STALE(bp); | ||
743 | bip->bli_flags |= XFS_BLI_STALE; | 743 | bip->bli_flags |= XFS_BLI_STALE; |
744 | bip->bli_flags &= ~(XFS_BLI_INODE_BUF | XFS_BLI_LOGGED | XFS_BLI_DIRTY); | 744 | bip->bli_flags &= ~(XFS_BLI_INODE_BUF | XFS_BLI_LOGGED | XFS_BLI_DIRTY); |
745 | bip->bli_format.blf_flags &= ~XFS_BLF_INODE_BUF; | 745 | bip->bli_format.blf_flags &= ~XFS_BLF_INODE_BUF; |
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c index c8dea2fd7e68..32f0288ae10f 100644 --- a/fs/xfs/xfs_trans_inode.c +++ b/fs/xfs/xfs_trans_inode.c | |||
@@ -47,11 +47,13 @@ xfs_trans_inode_broot_debug( | |||
47 | * Add a locked inode to the transaction. | 47 | * Add a locked inode to the transaction. |
48 | * | 48 | * |
49 | * The inode must be locked, and it cannot be associated with any transaction. | 49 | * The inode must be locked, and it cannot be associated with any transaction. |
50 | * If lock_flags is non-zero the inode will be unlocked on transaction commit. | ||
50 | */ | 51 | */ |
51 | void | 52 | void |
52 | xfs_trans_ijoin( | 53 | xfs_trans_ijoin( |
53 | struct xfs_trans *tp, | 54 | struct xfs_trans *tp, |
54 | struct xfs_inode *ip) | 55 | struct xfs_inode *ip, |
56 | uint lock_flags) | ||
55 | { | 57 | { |
56 | xfs_inode_log_item_t *iip; | 58 | xfs_inode_log_item_t *iip; |
57 | 59 | ||
@@ -59,7 +61,9 @@ xfs_trans_ijoin( | |||
59 | if (ip->i_itemp == NULL) | 61 | if (ip->i_itemp == NULL) |
60 | xfs_inode_item_init(ip, ip->i_mount); | 62 | xfs_inode_item_init(ip, ip->i_mount); |
61 | iip = ip->i_itemp; | 63 | iip = ip->i_itemp; |
64 | |||
62 | ASSERT(iip->ili_lock_flags == 0); | 65 | ASSERT(iip->ili_lock_flags == 0); |
66 | iip->ili_lock_flags = lock_flags; | ||
63 | 67 | ||
64 | /* | 68 | /* |
65 | * Get a log_item_desc to point at the new item. | 69 | * Get a log_item_desc to point at the new item. |
@@ -70,25 +74,6 @@ xfs_trans_ijoin( | |||
70 | } | 74 | } |
71 | 75 | ||
72 | /* | 76 | /* |
73 | * Add a locked inode to the transaction. | ||
74 | * | ||
75 | * | ||
76 | * Grabs a reference to the inode which will be dropped when the transaction | ||
77 | * is committed. The inode will also be unlocked at that point. The inode | ||
78 | * must be locked, and it cannot be associated with any transaction. | ||
79 | */ | ||
80 | void | ||
81 | xfs_trans_ijoin_ref( | ||
82 | struct xfs_trans *tp, | ||
83 | struct xfs_inode *ip, | ||
84 | uint lock_flags) | ||
85 | { | ||
86 | xfs_trans_ijoin(tp, ip); | ||
87 | IHOLD(ip); | ||
88 | ip->i_itemp->ili_lock_flags = lock_flags; | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * Transactional inode timestamp update. Requires the inode to be locked and | 77 | * Transactional inode timestamp update. Requires the inode to be locked and |
93 | * joined to the transaction supplied. Relies on the transaction subsystem to | 78 | * joined to the transaction supplied. Relies on the transaction subsystem to |
94 | * track dirty state and update/writeback the inode accordingly. | 79 | * track dirty state and update/writeback the inode accordingly. |
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h index 22750b5e4a8f..44820b9fcb43 100644 --- a/fs/xfs/xfs_trans_priv.h +++ b/fs/xfs/xfs_trans_priv.h | |||
@@ -70,6 +70,7 @@ struct xfs_ail { | |||
70 | struct list_head xa_cursors; | 70 | struct list_head xa_cursors; |
71 | spinlock_t xa_lock; | 71 | spinlock_t xa_lock; |
72 | xfs_lsn_t xa_last_pushed_lsn; | 72 | xfs_lsn_t xa_last_pushed_lsn; |
73 | int xa_log_flush; | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | /* | 76 | /* |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 51fc429527bc..4ecf2a549060 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -72,8 +72,8 @@ xfs_readlink_bmap( | |||
72 | xfs_buf_t *bp; | 72 | xfs_buf_t *bp; |
73 | int error = 0; | 73 | int error = 0; |
74 | 74 | ||
75 | error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), 0, NULL, 0, | 75 | error = xfs_bmapi_read(ip, 0, XFS_B_TO_FSB(mp, pathlen), mval, &nmaps, |
76 | mval, &nmaps, NULL); | 76 | 0); |
77 | if (error) | 77 | if (error) |
78 | goto out; | 78 | goto out; |
79 | 79 | ||
@@ -87,8 +87,7 @@ xfs_readlink_bmap( | |||
87 | return XFS_ERROR(ENOMEM); | 87 | return XFS_ERROR(ENOMEM); |
88 | error = bp->b_error; | 88 | error = bp->b_error; |
89 | if (error) { | 89 | if (error) { |
90 | xfs_ioerror_alert("xfs_readlink", | 90 | xfs_buf_ioerror_alert(bp, __func__); |
91 | ip->i_mount, bp, XFS_BUF_ADDR(bp)); | ||
92 | xfs_buf_relse(bp); | 91 | xfs_buf_relse(bp); |
93 | goto out; | 92 | goto out; |
94 | } | 93 | } |
@@ -178,8 +177,7 @@ xfs_free_eofblocks( | |||
178 | 177 | ||
179 | nimaps = 1; | 178 | nimaps = 1; |
180 | xfs_ilock(ip, XFS_ILOCK_SHARED); | 179 | xfs_ilock(ip, XFS_ILOCK_SHARED); |
181 | error = xfs_bmapi(NULL, ip, end_fsb, map_len, 0, | 180 | error = xfs_bmapi_read(ip, end_fsb, map_len, &imap, &nimaps, 0); |
182 | NULL, 0, &imap, &nimaps, NULL); | ||
183 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 181 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
184 | 182 | ||
185 | if (!error && (nimaps != 0) && | 183 | if (!error && (nimaps != 0) && |
@@ -220,7 +218,7 @@ xfs_free_eofblocks( | |||
220 | } | 218 | } |
221 | 219 | ||
222 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 220 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
223 | xfs_trans_ijoin(tp, ip); | 221 | xfs_trans_ijoin(tp, ip, 0); |
224 | 222 | ||
225 | error = xfs_itruncate_data(&tp, ip, ip->i_size); | 223 | error = xfs_itruncate_data(&tp, ip, ip->i_size); |
226 | if (error) { | 224 | if (error) { |
@@ -289,7 +287,7 @@ xfs_inactive_symlink_rmt( | |||
289 | xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); | 287 | xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); |
290 | size = (int)ip->i_d.di_size; | 288 | size = (int)ip->i_d.di_size; |
291 | ip->i_d.di_size = 0; | 289 | ip->i_d.di_size = 0; |
292 | xfs_trans_ijoin(tp, ip); | 290 | xfs_trans_ijoin(tp, ip, 0); |
293 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 291 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
294 | /* | 292 | /* |
295 | * Find the block(s) so we can inval and unmap them. | 293 | * Find the block(s) so we can inval and unmap them. |
@@ -297,9 +295,9 @@ xfs_inactive_symlink_rmt( | |||
297 | done = 0; | 295 | done = 0; |
298 | xfs_bmap_init(&free_list, &first_block); | 296 | xfs_bmap_init(&free_list, &first_block); |
299 | nmaps = ARRAY_SIZE(mval); | 297 | nmaps = ARRAY_SIZE(mval); |
300 | if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size), | 298 | error = xfs_bmapi_read(ip, 0, XFS_B_TO_FSB(mp, size), |
301 | XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps, | 299 | mval, &nmaps, 0); |
302 | &free_list))) | 300 | if (error) |
303 | goto error0; | 301 | goto error0; |
304 | /* | 302 | /* |
305 | * Invalidate the block(s). | 303 | * Invalidate the block(s). |
@@ -308,6 +306,10 @@ xfs_inactive_symlink_rmt( | |||
308 | bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, | 306 | bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, |
309 | XFS_FSB_TO_DADDR(mp, mval[i].br_startblock), | 307 | XFS_FSB_TO_DADDR(mp, mval[i].br_startblock), |
310 | XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0); | 308 | XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0); |
309 | if (!bp) { | ||
310 | error = ENOMEM; | ||
311 | goto error1; | ||
312 | } | ||
311 | xfs_trans_binval(tp, bp); | 313 | xfs_trans_binval(tp, bp); |
312 | } | 314 | } |
313 | /* | 315 | /* |
@@ -333,7 +335,7 @@ xfs_inactive_symlink_rmt( | |||
333 | * Mark it dirty so it will be logged and moved forward in the log as | 335 | * Mark it dirty so it will be logged and moved forward in the log as |
334 | * part of every commit. | 336 | * part of every commit. |
335 | */ | 337 | */ |
336 | xfs_trans_ijoin(tp, ip); | 338 | xfs_trans_ijoin(tp, ip, 0); |
337 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 339 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
338 | /* | 340 | /* |
339 | * Get a new, empty transaction to return to our caller. | 341 | * Get a new, empty transaction to return to our caller. |
@@ -466,7 +468,7 @@ xfs_inactive_attrs( | |||
466 | goto error_cancel; | 468 | goto error_cancel; |
467 | 469 | ||
468 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 470 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
469 | xfs_trans_ijoin(tp, ip); | 471 | xfs_trans_ijoin(tp, ip, 0); |
470 | xfs_idestroy_fork(ip, XFS_ATTR_FORK); | 472 | xfs_idestroy_fork(ip, XFS_ATTR_FORK); |
471 | 473 | ||
472 | ASSERT(ip->i_d.di_anextents == 0); | 474 | ASSERT(ip->i_d.di_anextents == 0); |
@@ -647,8 +649,6 @@ xfs_inactive( | |||
647 | if (truncate) { | 649 | if (truncate) { |
648 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | 650 | xfs_ilock(ip, XFS_IOLOCK_EXCL); |
649 | 651 | ||
650 | xfs_ioend_wait(ip); | ||
651 | |||
652 | error = xfs_trans_reserve(tp, 0, | 652 | error = xfs_trans_reserve(tp, 0, |
653 | XFS_ITRUNCATE_LOG_RES(mp), | 653 | XFS_ITRUNCATE_LOG_RES(mp), |
654 | 0, XFS_TRANS_PERM_LOG_RES, | 654 | 0, XFS_TRANS_PERM_LOG_RES, |
@@ -662,7 +662,7 @@ xfs_inactive( | |||
662 | } | 662 | } |
663 | 663 | ||
664 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 664 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
665 | xfs_trans_ijoin(tp, ip); | 665 | xfs_trans_ijoin(tp, ip, 0); |
666 | 666 | ||
667 | error = xfs_itruncate_data(&tp, ip, 0); | 667 | error = xfs_itruncate_data(&tp, ip, 0); |
668 | if (error) { | 668 | if (error) { |
@@ -686,7 +686,7 @@ xfs_inactive( | |||
686 | return VN_INACTIVE_CACHE; | 686 | return VN_INACTIVE_CACHE; |
687 | } | 687 | } |
688 | 688 | ||
689 | xfs_trans_ijoin(tp, ip); | 689 | xfs_trans_ijoin(tp, ip, 0); |
690 | } else { | 690 | } else { |
691 | error = xfs_trans_reserve(tp, 0, | 691 | error = xfs_trans_reserve(tp, 0, |
692 | XFS_IFREE_LOG_RES(mp), | 692 | XFS_IFREE_LOG_RES(mp), |
@@ -699,7 +699,7 @@ xfs_inactive( | |||
699 | } | 699 | } |
700 | 700 | ||
701 | xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | 701 | xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
702 | xfs_trans_ijoin(tp, ip); | 702 | xfs_trans_ijoin(tp, ip, 0); |
703 | } | 703 | } |
704 | 704 | ||
705 | /* | 705 | /* |
@@ -939,7 +939,7 @@ xfs_create( | |||
939 | * the transaction cancel unlocking dp so don't do it explicitly in the | 939 | * the transaction cancel unlocking dp so don't do it explicitly in the |
940 | * error path. | 940 | * error path. |
941 | */ | 941 | */ |
942 | xfs_trans_ijoin_ref(tp, dp, XFS_ILOCK_EXCL); | 942 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); |
943 | unlock_dp_on_error = B_FALSE; | 943 | unlock_dp_on_error = B_FALSE; |
944 | 944 | ||
945 | error = xfs_dir_createname(tp, dp, name, ip->i_ino, | 945 | error = xfs_dir_createname(tp, dp, name, ip->i_ino, |
@@ -1260,8 +1260,8 @@ xfs_remove( | |||
1260 | 1260 | ||
1261 | xfs_lock_two_inodes(dp, ip, XFS_ILOCK_EXCL); | 1261 | xfs_lock_two_inodes(dp, ip, XFS_ILOCK_EXCL); |
1262 | 1262 | ||
1263 | xfs_trans_ijoin_ref(tp, dp, XFS_ILOCK_EXCL); | 1263 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); |
1264 | xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); | 1264 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
1265 | 1265 | ||
1266 | /* | 1266 | /* |
1267 | * If we're removing a directory perform some additional validation. | 1267 | * If we're removing a directory perform some additional validation. |
@@ -1406,8 +1406,8 @@ xfs_link( | |||
1406 | 1406 | ||
1407 | xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL); | 1407 | xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL); |
1408 | 1408 | ||
1409 | xfs_trans_ijoin_ref(tp, sip, XFS_ILOCK_EXCL); | 1409 | xfs_trans_ijoin(tp, sip, XFS_ILOCK_EXCL); |
1410 | xfs_trans_ijoin_ref(tp, tdp, XFS_ILOCK_EXCL); | 1410 | xfs_trans_ijoin(tp, tdp, XFS_ILOCK_EXCL); |
1411 | 1411 | ||
1412 | /* | 1412 | /* |
1413 | * If the source has too many links, we can't make any more to it. | 1413 | * If the source has too many links, we can't make any more to it. |
@@ -1601,7 +1601,7 @@ xfs_symlink( | |||
1601 | * transaction cancel unlocking dp so don't do it explicitly in the | 1601 | * transaction cancel unlocking dp so don't do it explicitly in the |
1602 | * error path. | 1602 | * error path. |
1603 | */ | 1603 | */ |
1604 | xfs_trans_ijoin_ref(tp, dp, XFS_ILOCK_EXCL); | 1604 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); |
1605 | unlock_dp_on_error = B_FALSE; | 1605 | unlock_dp_on_error = B_FALSE; |
1606 | 1606 | ||
1607 | /* | 1607 | /* |
@@ -1632,10 +1632,9 @@ xfs_symlink( | |||
1632 | first_fsb = 0; | 1632 | first_fsb = 0; |
1633 | nmaps = SYMLINK_MAPS; | 1633 | nmaps = SYMLINK_MAPS; |
1634 | 1634 | ||
1635 | error = xfs_bmapi(tp, ip, first_fsb, fs_blocks, | 1635 | error = xfs_bmapi_write(tp, ip, first_fsb, fs_blocks, |
1636 | XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, | 1636 | XFS_BMAPI_METADATA, &first_block, resblks, |
1637 | &first_block, resblks, mval, &nmaps, | 1637 | mval, &nmaps, &free_list); |
1638 | &free_list); | ||
1639 | if (error) | 1638 | if (error) |
1640 | goto error2; | 1639 | goto error2; |
1641 | 1640 | ||
@@ -1650,7 +1649,10 @@ xfs_symlink( | |||
1650 | byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); | 1649 | byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); |
1651 | bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, | 1650 | bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, |
1652 | BTOBB(byte_cnt), 0); | 1651 | BTOBB(byte_cnt), 0); |
1653 | ASSERT(!xfs_buf_geterror(bp)); | 1652 | if (!bp) { |
1653 | error = ENOMEM; | ||
1654 | goto error2; | ||
1655 | } | ||
1654 | if (pathlen < byte_cnt) { | 1656 | if (pathlen < byte_cnt) { |
1655 | byte_cnt = pathlen; | 1657 | byte_cnt = pathlen; |
1656 | } | 1658 | } |
@@ -1732,7 +1734,7 @@ xfs_set_dmattrs( | |||
1732 | return error; | 1734 | return error; |
1733 | } | 1735 | } |
1734 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 1736 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
1735 | xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); | 1737 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
1736 | 1738 | ||
1737 | ip->i_d.di_dmevmask = evmask; | 1739 | ip->i_d.di_dmevmask = evmask; |
1738 | ip->i_d.di_dmstate = state; | 1740 | ip->i_d.di_dmstate = state; |
@@ -1778,7 +1780,6 @@ xfs_alloc_file_space( | |||
1778 | xfs_fileoff_t startoffset_fsb; | 1780 | xfs_fileoff_t startoffset_fsb; |
1779 | xfs_fsblock_t firstfsb; | 1781 | xfs_fsblock_t firstfsb; |
1780 | int nimaps; | 1782 | int nimaps; |
1781 | int bmapi_flag; | ||
1782 | int quota_flag; | 1783 | int quota_flag; |
1783 | int rt; | 1784 | int rt; |
1784 | xfs_trans_t *tp; | 1785 | xfs_trans_t *tp; |
@@ -1806,7 +1807,6 @@ xfs_alloc_file_space( | |||
1806 | count = len; | 1807 | count = len; |
1807 | imapp = &imaps[0]; | 1808 | imapp = &imaps[0]; |
1808 | nimaps = 1; | 1809 | nimaps = 1; |
1809 | bmapi_flag = XFS_BMAPI_WRITE | alloc_type; | ||
1810 | startoffset_fsb = XFS_B_TO_FSBT(mp, offset); | 1810 | startoffset_fsb = XFS_B_TO_FSBT(mp, offset); |
1811 | allocatesize_fsb = XFS_B_TO_FSB(mp, count); | 1811 | allocatesize_fsb = XFS_B_TO_FSB(mp, count); |
1812 | 1812 | ||
@@ -1877,16 +1877,12 @@ xfs_alloc_file_space( | |||
1877 | if (error) | 1877 | if (error) |
1878 | goto error1; | 1878 | goto error1; |
1879 | 1879 | ||
1880 | xfs_trans_ijoin(tp, ip); | 1880 | xfs_trans_ijoin(tp, ip, 0); |
1881 | 1881 | ||
1882 | /* | ||
1883 | * Issue the xfs_bmapi() call to allocate the blocks | ||
1884 | */ | ||
1885 | xfs_bmap_init(&free_list, &firstfsb); | 1882 | xfs_bmap_init(&free_list, &firstfsb); |
1886 | error = xfs_bmapi(tp, ip, startoffset_fsb, | 1883 | error = xfs_bmapi_write(tp, ip, startoffset_fsb, |
1887 | allocatesize_fsb, bmapi_flag, | 1884 | allocatesize_fsb, alloc_type, &firstfsb, |
1888 | &firstfsb, 0, imapp, &nimaps, | 1885 | 0, imapp, &nimaps, &free_list); |
1889 | &free_list); | ||
1890 | if (error) { | 1886 | if (error) { |
1891 | goto error0; | 1887 | goto error0; |
1892 | } | 1888 | } |
@@ -1976,8 +1972,7 @@ xfs_zero_remaining_bytes( | |||
1976 | for (offset = startoff; offset <= endoff; offset = lastoffset + 1) { | 1972 | for (offset = startoff; offset <= endoff; offset = lastoffset + 1) { |
1977 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 1973 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
1978 | nimap = 1; | 1974 | nimap = 1; |
1979 | error = xfs_bmapi(NULL, ip, offset_fsb, 1, 0, | 1975 | error = xfs_bmapi_read(ip, offset_fsb, 1, &imap, &nimap, 0); |
1980 | NULL, 0, &imap, &nimap, NULL); | ||
1981 | if (error || nimap < 1) | 1976 | if (error || nimap < 1) |
1982 | break; | 1977 | break; |
1983 | ASSERT(imap.br_blockcount >= 1); | 1978 | ASSERT(imap.br_blockcount >= 1); |
@@ -1997,8 +1992,8 @@ xfs_zero_remaining_bytes( | |||
1997 | xfsbdstrat(mp, bp); | 1992 | xfsbdstrat(mp, bp); |
1998 | error = xfs_buf_iowait(bp); | 1993 | error = xfs_buf_iowait(bp); |
1999 | if (error) { | 1994 | if (error) { |
2000 | xfs_ioerror_alert("xfs_zero_remaining_bytes(read)", | 1995 | xfs_buf_ioerror_alert(bp, |
2001 | mp, bp, XFS_BUF_ADDR(bp)); | 1996 | "xfs_zero_remaining_bytes(read)"); |
2002 | break; | 1997 | break; |
2003 | } | 1998 | } |
2004 | memset(bp->b_addr + | 1999 | memset(bp->b_addr + |
@@ -2010,8 +2005,8 @@ xfs_zero_remaining_bytes( | |||
2010 | xfsbdstrat(mp, bp); | 2005 | xfsbdstrat(mp, bp); |
2011 | error = xfs_buf_iowait(bp); | 2006 | error = xfs_buf_iowait(bp); |
2012 | if (error) { | 2007 | if (error) { |
2013 | xfs_ioerror_alert("xfs_zero_remaining_bytes(write)", | 2008 | xfs_buf_ioerror_alert(bp, |
2014 | mp, bp, XFS_BUF_ADDR(bp)); | 2009 | "xfs_zero_remaining_bytes(write)"); |
2015 | break; | 2010 | break; |
2016 | } | 2011 | } |
2017 | } | 2012 | } |
@@ -2076,7 +2071,7 @@ xfs_free_file_space( | |||
2076 | if (need_iolock) { | 2071 | if (need_iolock) { |
2077 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | 2072 | xfs_ilock(ip, XFS_IOLOCK_EXCL); |
2078 | /* wait for the completion of any pending DIOs */ | 2073 | /* wait for the completion of any pending DIOs */ |
2079 | xfs_ioend_wait(ip); | 2074 | inode_dio_wait(VFS_I(ip)); |
2080 | } | 2075 | } |
2081 | 2076 | ||
2082 | rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE); | 2077 | rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE); |
@@ -2096,8 +2091,8 @@ xfs_free_file_space( | |||
2096 | */ | 2091 | */ |
2097 | if (rt && !xfs_sb_version_hasextflgbit(&mp->m_sb)) { | 2092 | if (rt && !xfs_sb_version_hasextflgbit(&mp->m_sb)) { |
2098 | nimap = 1; | 2093 | nimap = 1; |
2099 | error = xfs_bmapi(NULL, ip, startoffset_fsb, | 2094 | error = xfs_bmapi_read(ip, startoffset_fsb, 1, |
2100 | 1, 0, NULL, 0, &imap, &nimap, NULL); | 2095 | &imap, &nimap, 0); |
2101 | if (error) | 2096 | if (error) |
2102 | goto out_unlock_iolock; | 2097 | goto out_unlock_iolock; |
2103 | ASSERT(nimap == 0 || nimap == 1); | 2098 | ASSERT(nimap == 0 || nimap == 1); |
@@ -2111,8 +2106,8 @@ xfs_free_file_space( | |||
2111 | startoffset_fsb += mp->m_sb.sb_rextsize - mod; | 2106 | startoffset_fsb += mp->m_sb.sb_rextsize - mod; |
2112 | } | 2107 | } |
2113 | nimap = 1; | 2108 | nimap = 1; |
2114 | error = xfs_bmapi(NULL, ip, endoffset_fsb - 1, | 2109 | error = xfs_bmapi_read(ip, endoffset_fsb - 1, 1, |
2115 | 1, 0, NULL, 0, &imap, &nimap, NULL); | 2110 | &imap, &nimap, 0); |
2116 | if (error) | 2111 | if (error) |
2117 | goto out_unlock_iolock; | 2112 | goto out_unlock_iolock; |
2118 | ASSERT(nimap == 0 || nimap == 1); | 2113 | ASSERT(nimap == 0 || nimap == 1); |
@@ -2180,7 +2175,7 @@ xfs_free_file_space( | |||
2180 | if (error) | 2175 | if (error) |
2181 | goto error1; | 2176 | goto error1; |
2182 | 2177 | ||
2183 | xfs_trans_ijoin(tp, ip); | 2178 | xfs_trans_ijoin(tp, ip, 0); |
2184 | 2179 | ||
2185 | /* | 2180 | /* |
2186 | * issue the bunmapi() call to free the blocks | 2181 | * issue the bunmapi() call to free the blocks |
@@ -2353,8 +2348,7 @@ xfs_change_file_space( | |||
2353 | } | 2348 | } |
2354 | 2349 | ||
2355 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 2350 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
2356 | 2351 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | |
2357 | xfs_trans_ijoin(tp, ip); | ||
2358 | 2352 | ||
2359 | if ((attr_flags & XFS_ATTR_DMI) == 0) { | 2353 | if ((attr_flags & XFS_ATTR_DMI) == 0) { |
2360 | ip->i_d.di_mode &= ~S_ISUID; | 2354 | ip->i_d.di_mode &= ~S_ISUID; |
@@ -2379,10 +2373,5 @@ xfs_change_file_space( | |||
2379 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 2373 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
2380 | if (attr_flags & XFS_ATTR_SYNC) | 2374 | if (attr_flags & XFS_ATTR_SYNC) |
2381 | xfs_trans_set_sync(tp); | 2375 | xfs_trans_set_sync(tp); |
2382 | 2376 | return xfs_trans_commit(tp, 0); | |
2383 | error = xfs_trans_commit(tp, 0); | ||
2384 | |||
2385 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
2386 | |||
2387 | return error; | ||
2388 | } | 2377 | } |