Blame view
fs/xfs/xfs_aops.c
35.3 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
7b7187698 [XFS] Update lice... |
2 3 |
* Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. |
1da177e4c Linux-2.6.12-rc2 |
4 |
* |
7b7187698 [XFS] Update lice... |
5 6 |
* This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as |
1da177e4c Linux-2.6.12-rc2 |
7 8 |
* published by the Free Software Foundation. * |
7b7187698 [XFS] Update lice... |
9 10 11 12 |
* This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. |
1da177e4c Linux-2.6.12-rc2 |
13 |
* |
7b7187698 [XFS] Update lice... |
14 15 16 |
* You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1da177e4c Linux-2.6.12-rc2 |
17 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
18 |
#include "xfs.h" |
a844f4510 [XFS] Remove xfs_... |
19 |
#include "xfs_bit.h" |
1da177e4c Linux-2.6.12-rc2 |
20 |
#include "xfs_log.h" |
a844f4510 [XFS] Remove xfs_... |
21 |
#include "xfs_inum.h" |
1da177e4c Linux-2.6.12-rc2 |
22 |
#include "xfs_sb.h" |
a844f4510 [XFS] Remove xfs_... |
23 |
#include "xfs_ag.h" |
1da177e4c Linux-2.6.12-rc2 |
24 |
#include "xfs_trans.h" |
1da177e4c Linux-2.6.12-rc2 |
25 26 |
#include "xfs_mount.h" #include "xfs_bmap_btree.h" |
1da177e4c Linux-2.6.12-rc2 |
27 28 |
#include "xfs_dinode.h" #include "xfs_inode.h" |
a844f4510 [XFS] Remove xfs_... |
29 |
#include "xfs_alloc.h" |
1da177e4c Linux-2.6.12-rc2 |
30 31 32 |
#include "xfs_error.h" #include "xfs_rw.h" #include "xfs_iomap.h" |
739bfb2a7 [XFS] call common... |
33 |
#include "xfs_vnodeops.h" |
0b1b213fc xfs: event tracin... |
34 |
#include "xfs_trace.h" |
3ed3a4343 xfs: truncate del... |
35 |
#include "xfs_bmap.h" |
5a0e3ad6a include cleanup: ... |
36 |
#include <linux/gfp.h> |
1da177e4c Linux-2.6.12-rc2 |
37 |
#include <linux/mpage.h> |
10ce44442 [XFS] use pagevec... |
38 |
#include <linux/pagevec.h> |
1da177e4c Linux-2.6.12-rc2 |
39 |
#include <linux/writeback.h> |
0b1b213fc xfs: event tracin... |
40 |
void |
f51623b21 [XFS] Move some c... |
41 42 43 |
xfs_count_page_state( struct page *page, int *delalloc, |
f51623b21 [XFS] Move some c... |
44 45 46 |
int *unwritten) { struct buffer_head *bh, *head; |
20cb52ebd xfs: simplify xfs... |
47 |
*delalloc = *unwritten = 0; |
f51623b21 [XFS] Move some c... |
48 49 50 |
bh = head = page_buffers(page); do { |
20cb52ebd xfs: simplify xfs... |
51 |
if (buffer_unwritten(bh)) |
f51623b21 [XFS] Move some c... |
52 53 54 55 56 |
(*unwritten) = 1; else if (buffer_delay(bh)) (*delalloc) = 1; } while ((bh = bh->b_this_page) != head); } |
6214ed446 [XFS] kill BMAPI_... |
57 58 |
STATIC struct block_device * xfs_find_bdev_for_inode( |
046f1685b xfs: remove iomap... |
59 |
struct inode *inode) |
6214ed446 [XFS] kill BMAPI_... |
60 |
{ |
046f1685b xfs: remove iomap... |
61 |
struct xfs_inode *ip = XFS_I(inode); |
6214ed446 [XFS] kill BMAPI_... |
62 |
struct xfs_mount *mp = ip->i_mount; |
71ddabb94 [XFS] optimize XF... |
63 |
if (XFS_IS_REALTIME_INODE(ip)) |
6214ed446 [XFS] kill BMAPI_... |
64 65 66 67 |
return mp->m_rtdev_targp->bt_bdev; else return mp->m_ddev_targp->bt_bdev; } |
0829c3602 [XFS] Add infrast... |
68 |
/* |
f6d6d4fcd [XFS] Initial pas... |
69 70 71 72 73 |
* We're now finished for good with this ioend structure. * Update the page state via the associated buffer_heads, * release holds on the inode and bio, and finally free * up memory. Do not use the ioend after this. */ |
0829c3602 [XFS] Add infrast... |
74 75 76 77 |
STATIC void xfs_destroy_ioend( xfs_ioend_t *ioend) { |
f6d6d4fcd [XFS] Initial pas... |
78 79 80 81 |
struct buffer_head *bh, *next; for (bh = ioend->io_buffer_head; bh; bh = next) { next = bh->b_private; |
7d04a335b [XFS] Shutdown th... |
82 |
bh->b_end_io(bh, !ioend->io_error); |
f6d6d4fcd [XFS] Initial pas... |
83 |
} |
583fa586f kill vn_ioerror |
84 |
|
c859cdd1d xfs: defer AIO/DI... |
85 |
if (ioend->io_iocb) { |
04f658ee2 xfs: improve ioen... |
86 87 88 89 |
if (ioend->io_isasync) { aio_complete(ioend->io_iocb, ioend->io_error ? ioend->io_error : ioend->io_result, 0); } |
c859cdd1d xfs: defer AIO/DI... |
90 91 |
inode_dio_done(ioend->io_inode); } |
4a06fd262 xfs: remove i_ioc... |
92 |
|
0829c3602 [XFS] Add infrast... |
93 94 95 96 |
mempool_free(ioend, xfs_ioend_pool); } /* |
932640e8a xfs: mark inodes ... |
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
* If the end of the current ioend is beyond the current EOF, * return the new EOF value, otherwise zero. */ STATIC xfs_fsize_t xfs_ioend_new_eof( xfs_ioend_t *ioend) { xfs_inode_t *ip = XFS_I(ioend->io_inode); xfs_fsize_t isize; xfs_fsize_t bsize; bsize = ioend->io_offset + ioend->io_size; isize = MAX(ip->i_size, ip->i_new_size); isize = MIN(isize, bsize); return isize > ip->i_d.di_size ? isize : 0; } /* |
fc0063c44 xfs: reduce ioend... |
115 116 117 118 119 120 121 122 123 |
* Fast and loose check if this write could update the on-disk inode size. */ static inline bool xfs_ioend_is_append(struct xfs_ioend *ioend) { return ioend->io_offset + ioend->io_size > XFS_I(ioend->io_inode)->i_d.di_size; } /* |
77d7a0c2e xfs: Non-blocking... |
124 125 126 127 128 129 130 131 132 |
* Update on-disk file size now that data has been written to disk. The * current in-memory file size is i_size. If a write is beyond eof i_new_size * will be the intended file size until i_size is updated. If this write does * not extend all the way to the valid file size then restrict this update to * the end of the write. * * This function does not block as blocking on the inode lock in IO completion * can lead to IO completion order dependency deadlocks.. If it can't get the * inode ilock it will return EAGAIN. Callers must handle this. |
ba87ea699 [XFS] Fix to prev... |
133 |
*/ |
77d7a0c2e xfs: Non-blocking... |
134 |
STATIC int |
ba87ea699 [XFS] Fix to prev... |
135 136 137 |
xfs_setfilesize( xfs_ioend_t *ioend) { |
b677c210c [XFS] move v_ioco... |
138 |
xfs_inode_t *ip = XFS_I(ioend->io_inode); |
ba87ea699 [XFS] Fix to prev... |
139 |
xfs_fsize_t isize; |
ba87ea699 [XFS] Fix to prev... |
140 |
|
77d7a0c2e xfs: Non-blocking... |
141 142 |
if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) return EAGAIN; |
ba87ea699 [XFS] Fix to prev... |
143 |
|
932640e8a xfs: mark inodes ... |
144 145 |
isize = xfs_ioend_new_eof(ioend); if (isize) { |
55fb25d5b xfs: add size upd... |
146 |
trace_xfs_setfilesize(ip, ioend->io_offset, ioend->io_size); |
ba87ea699 [XFS] Fix to prev... |
147 |
ip->i_d.di_size = isize; |
66d834ea6 xfs: implement op... |
148 |
xfs_mark_inode_dirty(ip); |
ba87ea699 [XFS] Fix to prev... |
149 150 151 |
} xfs_iunlock(ip, XFS_ILOCK_EXCL); |
77d7a0c2e xfs: Non-blocking... |
152 153 154 155 |
return 0; } /* |
209fb87a2 xfs simplify and ... |
156 |
* Schedule IO completion handling on the final put of an ioend. |
fc0063c44 xfs: reduce ioend... |
157 158 159 |
* * If there is no work to do we might as well call it a day and free the * ioend right now. |
77d7a0c2e xfs: Non-blocking... |
160 161 162 |
*/ STATIC void xfs_finish_ioend( |
209fb87a2 xfs simplify and ... |
163 |
struct xfs_ioend *ioend) |
77d7a0c2e xfs: Non-blocking... |
164 165 |
{ if (atomic_dec_and_test(&ioend->io_remaining)) { |
209fb87a2 xfs simplify and ... |
166 167 |
if (ioend->io_type == IO_UNWRITTEN) queue_work(xfsconvertd_workqueue, &ioend->io_work); |
fc0063c44 xfs: reduce ioend... |
168 |
else if (xfs_ioend_is_append(ioend)) |
209fb87a2 xfs simplify and ... |
169 |
queue_work(xfsdatad_workqueue, &ioend->io_work); |
fc0063c44 xfs: reduce ioend... |
170 171 |
else xfs_destroy_ioend(ioend); |
77d7a0c2e xfs: Non-blocking... |
172 |
} |
ba87ea699 [XFS] Fix to prev... |
173 174 175 |
} /* |
5ec4fabb0 xfs: cleanup data... |
176 |
* IO write completion. |
f6d6d4fcd [XFS] Initial pas... |
177 178 |
*/ STATIC void |
5ec4fabb0 xfs: cleanup data... |
179 |
xfs_end_io( |
77d7a0c2e xfs: Non-blocking... |
180 |
struct work_struct *work) |
0829c3602 [XFS] Add infrast... |
181 |
{ |
77d7a0c2e xfs: Non-blocking... |
182 183 |
xfs_ioend_t *ioend = container_of(work, xfs_ioend_t, io_work); struct xfs_inode *ip = XFS_I(ioend->io_inode); |
694189328 xfs: Fix a build ... |
184 |
int error = 0; |
ba87ea699 [XFS] Fix to prev... |
185 |
|
04f658ee2 xfs: improve ioen... |
186 |
if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { |
810627d9a xfs: fix force sh... |
187 |
ioend->io_error = -EIO; |
04f658ee2 xfs: improve ioen... |
188 189 190 191 |
goto done; } if (ioend->io_error) goto done; |
5ec4fabb0 xfs: cleanup data... |
192 193 194 195 |
/* * For unwritten extents we need to issue transactions to convert a * range to normal written extens after the data I/O has finished. */ |
04f658ee2 xfs: improve ioen... |
196 |
if (ioend->io_type == IO_UNWRITTEN) { |
5ec4fabb0 xfs: cleanup data... |
197 198 |
error = xfs_iomap_write_unwritten(ip, ioend->io_offset, ioend->io_size); |
04f658ee2 xfs: improve ioen... |
199 200 201 202 |
if (error) { ioend->io_error = -error; goto done; } |
5ec4fabb0 xfs: cleanup data... |
203 |
} |
ba87ea699 [XFS] Fix to prev... |
204 |
|
5ec4fabb0 xfs: cleanup data... |
205 206 207 208 |
/* * We might have to update the on-disk file size after extending * writes. */ |
a206c817c xfs: kill xfs_iomap |
209 210 |
error = xfs_setfilesize(ioend); ASSERT(!error || error == EAGAIN); |
77d7a0c2e xfs: Non-blocking... |
211 |
|
04f658ee2 xfs: improve ioen... |
212 |
done: |
77d7a0c2e xfs: Non-blocking... |
213 214 215 216 217 218 219 |
/* * If we didn't complete processing of the ioend, requeue it to the * tail of the workqueue for another attempt later. Otherwise destroy * it. */ if (error == EAGAIN) { atomic_inc(&ioend->io_remaining); |
209fb87a2 xfs simplify and ... |
220 |
xfs_finish_ioend(ioend); |
77d7a0c2e xfs: Non-blocking... |
221 222 |
/* ensure we don't spin on blocked ioends */ delay(1); |
fb511f215 xfs: move aio com... |
223 |
} else { |
77d7a0c2e xfs: Non-blocking... |
224 |
xfs_destroy_ioend(ioend); |
fb511f215 xfs: move aio com... |
225 |
} |
c626d174c xfs: prevent unwr... |
226 227 228 |
} /* |
209fb87a2 xfs simplify and ... |
229 230 231 232 233 234 235 236 237 238 239 |
* Call IO completion handling in caller context on the final put of an ioend. */ STATIC void xfs_finish_ioend_sync( struct xfs_ioend *ioend) { if (atomic_dec_and_test(&ioend->io_remaining)) xfs_end_io(&ioend->io_work); } /* |
0829c3602 [XFS] Add infrast... |
240 241 242 243 244 245 246 |
* Allocate and initialise an IO completion structure. * We need to track unwritten extent write completion here initially. * We'll need to extend this for updating the ondisk inode size later * (vs. incore size). */ STATIC xfs_ioend_t * xfs_alloc_ioend( |
f6d6d4fcd [XFS] Initial pas... |
247 248 |
struct inode *inode, unsigned int type) |
0829c3602 [XFS] Add infrast... |
249 250 251 252 253 254 255 256 257 258 259 |
{ xfs_ioend_t *ioend; ioend = mempool_alloc(xfs_ioend_pool, GFP_NOFS); /* * Set the count to 1 initially, which will prevent an I/O * completion callback from happening before we have started * all the I/O from calling the completion routine too early. */ atomic_set(&ioend->io_remaining, 1); |
c859cdd1d xfs: defer AIO/DI... |
260 |
ioend->io_isasync = 0; |
7d04a335b [XFS] Shutdown th... |
261 |
ioend->io_error = 0; |
f6d6d4fcd [XFS] Initial pas... |
262 263 |
ioend->io_list = NULL; ioend->io_type = type; |
b677c210c [XFS] move v_ioco... |
264 |
ioend->io_inode = inode; |
c1a073bdf [XFS] Delay I/O c... |
265 |
ioend->io_buffer_head = NULL; |
f6d6d4fcd [XFS] Initial pas... |
266 |
ioend->io_buffer_tail = NULL; |
0829c3602 [XFS] Add infrast... |
267 268 |
ioend->io_offset = 0; ioend->io_size = 0; |
fb511f215 xfs: move aio com... |
269 270 |
ioend->io_iocb = NULL; ioend->io_result = 0; |
0829c3602 [XFS] Add infrast... |
271 |
|
5ec4fabb0 xfs: cleanup data... |
272 |
INIT_WORK(&ioend->io_work, xfs_end_io); |
0829c3602 [XFS] Add infrast... |
273 274 |
return ioend; } |
1da177e4c Linux-2.6.12-rc2 |
275 276 277 278 |
STATIC int xfs_map_blocks( struct inode *inode, loff_t offset, |
207d04160 xfs: kill struct ... |
279 |
struct xfs_bmbt_irec *imap, |
a206c817c xfs: kill xfs_iomap |
280 281 |
int type, int nonblocking) |
1da177e4c Linux-2.6.12-rc2 |
282 |
{ |
a206c817c xfs: kill xfs_iomap |
283 284 |
struct xfs_inode *ip = XFS_I(inode); struct xfs_mount *mp = ip->i_mount; |
ed1e7b7e4 xfs: remove xfs_p... |
285 |
ssize_t count = 1 << inode->i_blkbits; |
a206c817c xfs: kill xfs_iomap |
286 287 |
xfs_fileoff_t offset_fsb, end_fsb; int error = 0; |
a206c817c xfs: kill xfs_iomap |
288 289 290 291 292 |
int bmapi_flags = XFS_BMAPI_ENTIRE; int nimaps = 1; if (XFS_FORCED_SHUTDOWN(mp)) return -XFS_ERROR(EIO); |
8ff2957d5 xfs: simplify xfs... |
293 |
if (type == IO_UNWRITTEN) |
a206c817c xfs: kill xfs_iomap |
294 |
bmapi_flags |= XFS_BMAPI_IGSTATE; |
8ff2957d5 xfs: simplify xfs... |
295 296 297 298 299 |
if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) { if (nonblocking) return -XFS_ERROR(EAGAIN); xfs_ilock(ip, XFS_ILOCK_SHARED); |
a206c817c xfs: kill xfs_iomap |
300 |
} |
8ff2957d5 xfs: simplify xfs... |
301 302 |
ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || (ip->i_df.if_flags & XFS_IFEXTENTS)); |
a206c817c xfs: kill xfs_iomap |
303 |
ASSERT(offset <= mp->m_maxioffset); |
8ff2957d5 xfs: simplify xfs... |
304 |
|
a206c817c xfs: kill xfs_iomap |
305 306 307 308 |
if (offset + count > mp->m_maxioffset) count = mp->m_maxioffset - offset; end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); offset_fsb = XFS_B_TO_FSBT(mp, offset); |
5c8ed2021 xfs: introduce xf... |
309 310 |
error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, imap, &nimaps, bmapi_flags); |
8ff2957d5 xfs: simplify xfs... |
311 |
xfs_iunlock(ip, XFS_ILOCK_SHARED); |
a206c817c xfs: kill xfs_iomap |
312 |
|
8ff2957d5 xfs: simplify xfs... |
313 314 |
if (error) return -XFS_ERROR(error); |
a206c817c xfs: kill xfs_iomap |
315 |
|
8ff2957d5 xfs: simplify xfs... |
316 317 |
if (type == IO_DELALLOC && (!nimaps || isnullstartblock(imap->br_startblock))) { |
a206c817c xfs: kill xfs_iomap |
318 319 320 |
error = xfs_iomap_write_allocate(ip, offset, count, imap); if (!error) trace_xfs_map_blocks_alloc(ip, offset, count, type, imap); |
8ff2957d5 xfs: simplify xfs... |
321 |
return -XFS_ERROR(error); |
a206c817c xfs: kill xfs_iomap |
322 |
} |
8ff2957d5 xfs: simplify xfs... |
323 324 325 326 327 328 329 330 331 332 |
#ifdef DEBUG if (type == IO_UNWRITTEN) { ASSERT(nimaps); ASSERT(imap->br_startblock != HOLESTARTBLOCK); ASSERT(imap->br_startblock != DELAYSTARTBLOCK); } #endif if (nimaps) trace_xfs_map_blocks_found(ip, offset, count, type, imap); return 0; |
1da177e4c Linux-2.6.12-rc2 |
333 |
} |
b8f82a4a6 xfs: kill the STA... |
334 |
STATIC int |
558e68916 xfs: clean up xfs... |
335 |
xfs_imap_valid( |
8699bb0a4 xfs: report iomap... |
336 |
struct inode *inode, |
207d04160 xfs: kill struct ... |
337 |
struct xfs_bmbt_irec *imap, |
558e68916 xfs: clean up xfs... |
338 |
xfs_off_t offset) |
1da177e4c Linux-2.6.12-rc2 |
339 |
{ |
558e68916 xfs: clean up xfs... |
340 |
offset >>= inode->i_blkbits; |
8699bb0a4 xfs: report iomap... |
341 |
|
558e68916 xfs: clean up xfs... |
342 343 |
return offset >= imap->br_startoff && offset < imap->br_startoff + imap->br_blockcount; |
1da177e4c Linux-2.6.12-rc2 |
344 |
} |
f6d6d4fcd [XFS] Initial pas... |
345 346 347 |
/* * BIO completion handler for buffered IO. */ |
782e3b3b3 Fix up more bio f... |
348 |
STATIC void |
f6d6d4fcd [XFS] Initial pas... |
349 350 |
xfs_end_bio( struct bio *bio, |
f6d6d4fcd [XFS] Initial pas... |
351 352 353 |
int error) { xfs_ioend_t *ioend = bio->bi_private; |
f6d6d4fcd [XFS] Initial pas... |
354 |
ASSERT(atomic_read(&bio->bi_cnt) >= 1); |
7d04a335b [XFS] Shutdown th... |
355 |
ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error; |
f6d6d4fcd [XFS] Initial pas... |
356 357 |
/* Toss bio and pass work off to an xfsdatad thread */ |
f6d6d4fcd [XFS] Initial pas... |
358 359 |
bio->bi_private = NULL; bio->bi_end_io = NULL; |
f6d6d4fcd [XFS] Initial pas... |
360 |
bio_put(bio); |
7d04a335b [XFS] Shutdown th... |
361 |
|
209fb87a2 xfs simplify and ... |
362 |
xfs_finish_ioend(ioend); |
f6d6d4fcd [XFS] Initial pas... |
363 364 365 366 |
} STATIC void xfs_submit_ioend_bio( |
06342cf8a xfs: use WRITE_SY... |
367 368 369 |
struct writeback_control *wbc, xfs_ioend_t *ioend, struct bio *bio) |
f6d6d4fcd [XFS] Initial pas... |
370 371 |
{ atomic_inc(&ioend->io_remaining); |
f6d6d4fcd [XFS] Initial pas... |
372 373 |
bio->bi_private = ioend; bio->bi_end_io = xfs_end_bio; |
932640e8a xfs: mark inodes ... |
374 375 376 377 378 |
/* * If the I/O is beyond EOF we mark the inode dirty immediately * but don't update the inode size until I/O completion. */ if (xfs_ioend_new_eof(ioend)) |
66d834ea6 xfs: implement op... |
379 |
xfs_mark_inode_dirty(XFS_I(ioend->io_inode)); |
932640e8a xfs: mark inodes ... |
380 |
|
721a9602e block: kill off R... |
381 |
submit_bio(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE, bio); |
f6d6d4fcd [XFS] Initial pas... |
382 383 384 385 386 387 |
} STATIC struct bio * xfs_alloc_ioend_bio( struct buffer_head *bh) { |
f6d6d4fcd [XFS] Initial pas... |
388 |
int nvecs = bio_get_nr_vecs(bh->b_bdev); |
221cb2517 xfs: remove some ... |
389 |
struct bio *bio = bio_alloc(GFP_NOIO, nvecs); |
f6d6d4fcd [XFS] Initial pas... |
390 391 392 393 |
ASSERT(bio->bi_private == NULL); bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9); bio->bi_bdev = bh->b_bdev; |
f6d6d4fcd [XFS] Initial pas... |
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
return bio; } STATIC void xfs_start_buffer_writeback( struct buffer_head *bh) { ASSERT(buffer_mapped(bh)); ASSERT(buffer_locked(bh)); ASSERT(!buffer_delay(bh)); ASSERT(!buffer_unwritten(bh)); mark_buffer_async_write(bh); set_buffer_uptodate(bh); clear_buffer_dirty(bh); } STATIC void xfs_start_page_writeback( struct page *page, |
f6d6d4fcd [XFS] Initial pas... |
414 415 416 417 418 |
int clear_dirty, int buffers) { ASSERT(PageLocked(page)); ASSERT(!PageWriteback(page)); |
f6d6d4fcd [XFS] Initial pas... |
419 |
if (clear_dirty) |
921320210 [PATCH] Fix XFS a... |
420 421 |
clear_page_dirty_for_io(page); set_page_writeback(page); |
f6d6d4fcd [XFS] Initial pas... |
422 |
unlock_page(page); |
1f7decf6d writeback: remove... |
423 424 |
/* If no buffers on the page are to be written, finish it here */ if (!buffers) |
f6d6d4fcd [XFS] Initial pas... |
425 |
end_page_writeback(page); |
f6d6d4fcd [XFS] Initial pas... |
426 427 428 429 430 431 432 433 |
} static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh) { return bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh)); } /* |
d88992f66 [XFS] Fix a race ... |
434 435 436 437 438 439 440 441 442 443 444 445 446 447 |
* Submit all of the bios for all of the ioends we have saved up, covering the * initial writepage page and also any probed pages. * * Because we may have multiple ioends spanning a page, we need to start * writeback on all the buffers before we submit them for I/O. If we mark the * buffers as we got, then we can end up with a page that only has buffers * marked async write and I/O complete on can occur before we mark the other * buffers async write. * * The end result of this is that we trip a bug in end_page_writeback() because * we call it twice for the one page as the code in end_buffer_async_write() * assumes that all buffers on the page are started at the same time. * * The fix is two passes across the ioend list - one to start writeback on the |
c41564b5a [XFS] We really s... |
448 |
* buffer_heads, and then submit them for I/O on the second pass. |
f6d6d4fcd [XFS] Initial pas... |
449 450 451 |
*/ STATIC void xfs_submit_ioend( |
06342cf8a xfs: use WRITE_SY... |
452 |
struct writeback_control *wbc, |
f6d6d4fcd [XFS] Initial pas... |
453 454 |
xfs_ioend_t *ioend) { |
d88992f66 [XFS] Fix a race ... |
455 |
xfs_ioend_t *head = ioend; |
f6d6d4fcd [XFS] Initial pas... |
456 457 458 459 |
xfs_ioend_t *next; struct buffer_head *bh; struct bio *bio; sector_t lastblock = 0; |
d88992f66 [XFS] Fix a race ... |
460 461 462 |
/* Pass 1 - start writeback */ do { next = ioend->io_list; |
221cb2517 xfs: remove some ... |
463 |
for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) |
d88992f66 [XFS] Fix a race ... |
464 |
xfs_start_buffer_writeback(bh); |
d88992f66 [XFS] Fix a race ... |
465 466 467 468 |
} while ((ioend = next) != NULL); /* Pass 2 - submit I/O */ ioend = head; |
f6d6d4fcd [XFS] Initial pas... |
469 470 471 472 473 |
do { next = ioend->io_list; bio = NULL; for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) { |
f6d6d4fcd [XFS] Initial pas... |
474 475 476 477 478 |
if (!bio) { retry: bio = xfs_alloc_ioend_bio(bh); } else if (bh->b_blocknr != lastblock + 1) { |
06342cf8a xfs: use WRITE_SY... |
479 |
xfs_submit_ioend_bio(wbc, ioend, bio); |
f6d6d4fcd [XFS] Initial pas... |
480 481 482 483 |
goto retry; } if (bio_add_buffer(bio, bh) != bh->b_size) { |
06342cf8a xfs: use WRITE_SY... |
484 |
xfs_submit_ioend_bio(wbc, ioend, bio); |
f6d6d4fcd [XFS] Initial pas... |
485 486 487 488 489 490 |
goto retry; } lastblock = bh->b_blocknr; } if (bio) |
06342cf8a xfs: use WRITE_SY... |
491 |
xfs_submit_ioend_bio(wbc, ioend, bio); |
209fb87a2 xfs simplify and ... |
492 |
xfs_finish_ioend(ioend); |
f6d6d4fcd [XFS] Initial pas... |
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 |
} while ((ioend = next) != NULL); } /* * Cancel submission of all buffer_heads so far in this endio. * Toss the endio too. Only ever called for the initial page * in a writepage request, so only ever one page. */ STATIC void xfs_cancel_ioend( xfs_ioend_t *ioend) { xfs_ioend_t *next; struct buffer_head *bh, *next_bh; do { next = ioend->io_list; bh = ioend->io_buffer_head; do { next_bh = bh->b_private; clear_buffer_async_write(bh); unlock_buffer(bh); } while ((bh = next_bh) != NULL); |
f6d6d4fcd [XFS] Initial pas... |
516 517 518 519 520 521 522 523 524 525 526 527 528 529 |
mempool_free(ioend, xfs_ioend_pool); } while ((ioend = next) != NULL); } /* * Test to see if we've been building up a completion structure for * earlier buffers -- if so, we try to append to this ioend if we * can, otherwise we finish off any current ioend and start another. * Return true if we've finished the given ioend. */ STATIC void xfs_add_to_ioend( struct inode *inode, struct buffer_head *bh, |
7336cea8c [XFS] pass full 6... |
530 |
xfs_off_t offset, |
f6d6d4fcd [XFS] Initial pas... |
531 532 533 534 535 536 537 538 |
unsigned int type, xfs_ioend_t **result, int need_ioend) { xfs_ioend_t *ioend = *result; if (!ioend || need_ioend || type != ioend->io_type) { xfs_ioend_t *previous = *result; |
f6d6d4fcd [XFS] Initial pas... |
539 |
|
f6d6d4fcd [XFS] Initial pas... |
540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 |
ioend = xfs_alloc_ioend(inode, type); ioend->io_offset = offset; ioend->io_buffer_head = bh; ioend->io_buffer_tail = bh; if (previous) previous->io_list = ioend; *result = ioend; } else { ioend->io_buffer_tail->b_private = bh; ioend->io_buffer_tail = bh; } bh->b_private = NULL; ioend->io_size += bh->b_size; } |
1da177e4c Linux-2.6.12-rc2 |
555 |
STATIC void |
87cbc49cd [XFS] Add xfs_map... |
556 |
xfs_map_buffer( |
046f1685b xfs: remove iomap... |
557 |
struct inode *inode, |
87cbc49cd [XFS] Add xfs_map... |
558 |
struct buffer_head *bh, |
207d04160 xfs: kill struct ... |
559 |
struct xfs_bmbt_irec *imap, |
046f1685b xfs: remove iomap... |
560 |
xfs_off_t offset) |
87cbc49cd [XFS] Add xfs_map... |
561 562 |
{ sector_t bn; |
8699bb0a4 xfs: report iomap... |
563 |
struct xfs_mount *m = XFS_I(inode)->i_mount; |
207d04160 xfs: kill struct ... |
564 565 |
xfs_off_t iomap_offset = XFS_FSB_TO_B(m, imap->br_startoff); xfs_daddr_t iomap_bn = xfs_fsb_to_db(XFS_I(inode), imap->br_startblock); |
87cbc49cd [XFS] Add xfs_map... |
566 |
|
207d04160 xfs: kill struct ... |
567 568 |
ASSERT(imap->br_startblock != HOLESTARTBLOCK); ASSERT(imap->br_startblock != DELAYSTARTBLOCK); |
87cbc49cd [XFS] Add xfs_map... |
569 |
|
e513182d4 xfs: report iomap... |
570 |
bn = (iomap_bn >> (inode->i_blkbits - BBSHIFT)) + |
8699bb0a4 xfs: report iomap... |
571 |
((offset - iomap_offset) >> inode->i_blkbits); |
87cbc49cd [XFS] Add xfs_map... |
572 |
|
046f1685b xfs: remove iomap... |
573 |
ASSERT(bn || XFS_IS_REALTIME_INODE(XFS_I(inode))); |
87cbc49cd [XFS] Add xfs_map... |
574 575 576 577 578 579 |
bh->b_blocknr = bn; set_buffer_mapped(bh); } STATIC void |
1da177e4c Linux-2.6.12-rc2 |
580 |
xfs_map_at_offset( |
046f1685b xfs: remove iomap... |
581 |
struct inode *inode, |
1da177e4c Linux-2.6.12-rc2 |
582 |
struct buffer_head *bh, |
207d04160 xfs: kill struct ... |
583 |
struct xfs_bmbt_irec *imap, |
046f1685b xfs: remove iomap... |
584 |
xfs_off_t offset) |
1da177e4c Linux-2.6.12-rc2 |
585 |
{ |
207d04160 xfs: kill struct ... |
586 587 |
ASSERT(imap->br_startblock != HOLESTARTBLOCK); ASSERT(imap->br_startblock != DELAYSTARTBLOCK); |
1da177e4c Linux-2.6.12-rc2 |
588 |
|
207d04160 xfs: kill struct ... |
589 |
xfs_map_buffer(inode, bh, imap, offset); |
1da177e4c Linux-2.6.12-rc2 |
590 591 |
set_buffer_mapped(bh); clear_buffer_delay(bh); |
f6d6d4fcd [XFS] Initial pas... |
592 |
clear_buffer_unwritten(bh); |
1da177e4c Linux-2.6.12-rc2 |
593 594 595 |
} /* |
10ce44442 [XFS] use pagevec... |
596 597 |
* Test if a given page is suitable for writing as part of an unwritten * or delayed allocate extent. |
1da177e4c Linux-2.6.12-rc2 |
598 |
*/ |
10ce44442 [XFS] use pagevec... |
599 600 601 |
STATIC int xfs_is_delayed_page( struct page *page, |
f6d6d4fcd [XFS] Initial pas... |
602 |
unsigned int type) |
1da177e4c Linux-2.6.12-rc2 |
603 |
{ |
1da177e4c Linux-2.6.12-rc2 |
604 |
if (PageWriteback(page)) |
10ce44442 [XFS] use pagevec... |
605 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
606 607 608 609 610 611 612 |
if (page->mapping && page_has_buffers(page)) { struct buffer_head *bh, *head; int acceptable = 0; bh = head = page_buffers(page); do { |
f6d6d4fcd [XFS] Initial pas... |
613 |
if (buffer_unwritten(bh)) |
34a52c6c0 xfs: move I/O typ... |
614 |
acceptable = (type == IO_UNWRITTEN); |
f6d6d4fcd [XFS] Initial pas... |
615 |
else if (buffer_delay(bh)) |
a206c817c xfs: kill xfs_iomap |
616 |
acceptable = (type == IO_DELALLOC); |
2ddee844e [XFS] Check that ... |
617 |
else if (buffer_dirty(bh) && buffer_mapped(bh)) |
a206c817c xfs: kill xfs_iomap |
618 |
acceptable = (type == IO_OVERWRITE); |
f6d6d4fcd [XFS] Initial pas... |
619 |
else |
1da177e4c Linux-2.6.12-rc2 |
620 |
break; |
1da177e4c Linux-2.6.12-rc2 |
621 622 623 |
} while ((bh = bh->b_this_page) != head); if (acceptable) |
10ce44442 [XFS] use pagevec... |
624 |
return 1; |
1da177e4c Linux-2.6.12-rc2 |
625 |
} |
10ce44442 [XFS] use pagevec... |
626 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
627 |
} |
1da177e4c Linux-2.6.12-rc2 |
628 629 630 631 632 633 |
/* * Allocate & map buffers for page given the extent map. Write it out. * except for the original page of a writepage, this is called on * delalloc/unwritten pages only, for the original page it is possible * that the page has no mapping at all. */ |
f6d6d4fcd [XFS] Initial pas... |
634 |
STATIC int |
1da177e4c Linux-2.6.12-rc2 |
635 636 637 |
xfs_convert_page( struct inode *inode, struct page *page, |
10ce44442 [XFS] use pagevec... |
638 |
loff_t tindex, |
207d04160 xfs: kill struct ... |
639 |
struct xfs_bmbt_irec *imap, |
f6d6d4fcd [XFS] Initial pas... |
640 |
xfs_ioend_t **ioendp, |
2fa24f925 xfs: remove the a... |
641 |
struct writeback_control *wbc) |
1da177e4c Linux-2.6.12-rc2 |
642 |
{ |
f6d6d4fcd [XFS] Initial pas... |
643 |
struct buffer_head *bh, *head; |
9260dc6b2 [XFS] various fix... |
644 645 |
xfs_off_t end_offset; unsigned long p_offset; |
f6d6d4fcd [XFS] Initial pas... |
646 |
unsigned int type; |
24e17b5fb [XFS] Use the rig... |
647 |
int len, page_dirty; |
f6d6d4fcd [XFS] Initial pas... |
648 |
int count = 0, done = 0, uptodate = 1; |
9260dc6b2 [XFS] various fix... |
649 |
xfs_off_t offset = page_offset(page); |
1da177e4c Linux-2.6.12-rc2 |
650 |
|
10ce44442 [XFS] use pagevec... |
651 652 |
if (page->index != tindex) goto fail; |
529ae9aaa mm: rename page t... |
653 |
if (!trylock_page(page)) |
10ce44442 [XFS] use pagevec... |
654 655 656 657 658 659 660 |
goto fail; if (PageWriteback(page)) goto fail_unlock_page; if (page->mapping != inode->i_mapping) goto fail_unlock_page; if (!xfs_is_delayed_page(page, (*ioendp)->io_type)) goto fail_unlock_page; |
24e17b5fb [XFS] Use the rig... |
661 662 |
/* * page_dirty is initially a count of buffers on the page before |
c41564b5a [XFS] We really s... |
663 |
* EOF and is decremented as we move each into a cleanable state. |
9260dc6b2 [XFS] various fix... |
664 665 666 667 668 669 670 671 672 |
* * Derivation: * * End offset is the highest offset that this page should represent. * If we are on the last page, (end_offset & (PAGE_CACHE_SIZE - 1)) * will evaluate non-zero and be less than PAGE_CACHE_SIZE and * hence give us the correct page_dirty count. On any other page, * it will be zero and in that case we need page_dirty to be the * count of buffers on the page. |
24e17b5fb [XFS] Use the rig... |
673 |
*/ |
9260dc6b2 [XFS] various fix... |
674 675 676 |
end_offset = min_t(unsigned long long, (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT, i_size_read(inode)); |
24e17b5fb [XFS] Use the rig... |
677 |
len = 1 << inode->i_blkbits; |
9260dc6b2 [XFS] various fix... |
678 679 680 681 |
p_offset = min_t(unsigned long, end_offset & (PAGE_CACHE_SIZE - 1), PAGE_CACHE_SIZE); p_offset = p_offset ? roundup(p_offset, len) : PAGE_CACHE_SIZE; page_dirty = p_offset / len; |
24e17b5fb [XFS] Use the rig... |
682 |
|
1da177e4c Linux-2.6.12-rc2 |
683 684 |
bh = head = page_buffers(page); do { |
9260dc6b2 [XFS] various fix... |
685 |
if (offset >= end_offset) |
1da177e4c Linux-2.6.12-rc2 |
686 |
break; |
f6d6d4fcd [XFS] Initial pas... |
687 688 689 690 |
if (!buffer_uptodate(bh)) uptodate = 0; if (!(PageUptodate(page) || buffer_uptodate(bh))) { done = 1; |
1da177e4c Linux-2.6.12-rc2 |
691 |
continue; |
f6d6d4fcd [XFS] Initial pas... |
692 |
} |
2fa24f925 xfs: remove the a... |
693 694 |
if (buffer_unwritten(bh) || buffer_delay(bh) || buffer_mapped(bh)) { |
9260dc6b2 [XFS] various fix... |
695 |
if (buffer_unwritten(bh)) |
34a52c6c0 xfs: move I/O typ... |
696 |
type = IO_UNWRITTEN; |
2fa24f925 xfs: remove the a... |
697 |
else if (buffer_delay(bh)) |
a206c817c xfs: kill xfs_iomap |
698 |
type = IO_DELALLOC; |
2fa24f925 xfs: remove the a... |
699 700 |
else type = IO_OVERWRITE; |
9260dc6b2 [XFS] various fix... |
701 |
|
558e68916 xfs: clean up xfs... |
702 |
if (!xfs_imap_valid(inode, imap, offset)) { |
f6d6d4fcd [XFS] Initial pas... |
703 |
done = 1; |
9260dc6b2 [XFS] various fix... |
704 705 |
continue; } |
ecff71e67 xfs: simplify xfs... |
706 707 |
lock_buffer(bh); if (type != IO_OVERWRITE) |
2fa24f925 xfs: remove the a... |
708 |
xfs_map_at_offset(inode, bh, imap, offset); |
89f3b3639 xfs: simplify xfs... |
709 710 |
xfs_add_to_ioend(inode, bh, offset, type, ioendp, done); |
9260dc6b2 [XFS] various fix... |
711 712 713 |
page_dirty--; count++; } else { |
2fa24f925 xfs: remove the a... |
714 |
done = 1; |
1da177e4c Linux-2.6.12-rc2 |
715 |
} |
7336cea8c [XFS] pass full 6... |
716 |
} while (offset += len, (bh = bh->b_this_page) != head); |
1da177e4c Linux-2.6.12-rc2 |
717 |
|
f6d6d4fcd [XFS] Initial pas... |
718 719 |
if (uptodate && bh == head) SetPageUptodate(page); |
89f3b3639 xfs: simplify xfs... |
720 |
if (count) { |
efceab1d5 xfs: handle negat... |
721 722 |
if (--wbc->nr_to_write <= 0 && wbc->sync_mode == WB_SYNC_NONE) |
89f3b3639 xfs: simplify xfs... |
723 |
done = 1; |
1da177e4c Linux-2.6.12-rc2 |
724 |
} |
89f3b3639 xfs: simplify xfs... |
725 |
xfs_start_page_writeback(page, !page_dirty, count); |
f6d6d4fcd [XFS] Initial pas... |
726 727 |
return done; |
10ce44442 [XFS] use pagevec... |
728 729 730 731 |
fail_unlock_page: unlock_page(page); fail: return 1; |
1da177e4c Linux-2.6.12-rc2 |
732 733 734 735 736 737 738 739 740 741 |
} /* * Convert & write out a cluster of pages in the same extent as defined * by mp and following the start page. */ STATIC void xfs_cluster_write( struct inode *inode, pgoff_t tindex, |
207d04160 xfs: kill struct ... |
742 |
struct xfs_bmbt_irec *imap, |
f6d6d4fcd [XFS] Initial pas... |
743 |
xfs_ioend_t **ioendp, |
1da177e4c Linux-2.6.12-rc2 |
744 |
struct writeback_control *wbc, |
1da177e4c Linux-2.6.12-rc2 |
745 746 |
pgoff_t tlast) { |
10ce44442 [XFS] use pagevec... |
747 748 |
struct pagevec pvec; int done = 0, i; |
1da177e4c Linux-2.6.12-rc2 |
749 |
|
10ce44442 [XFS] use pagevec... |
750 751 752 753 754 |
pagevec_init(&pvec, 0); while (!done && tindex <= tlast) { unsigned len = min_t(pgoff_t, PAGEVEC_SIZE, tlast - tindex + 1); if (!pagevec_lookup(&pvec, inode->i_mapping, tindex, len)) |
1da177e4c Linux-2.6.12-rc2 |
755 |
break; |
10ce44442 [XFS] use pagevec... |
756 757 758 |
for (i = 0; i < pagevec_count(&pvec); i++) { done = xfs_convert_page(inode, pvec.pages[i], tindex++, |
2fa24f925 xfs: remove the a... |
759 |
imap, ioendp, wbc); |
10ce44442 [XFS] use pagevec... |
760 761 762 763 764 765 |
if (done) break; } pagevec_release(&pvec); cond_resched(); |
1da177e4c Linux-2.6.12-rc2 |
766 767 |
} } |
3ed3a4343 xfs: truncate del... |
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 |
STATIC void xfs_vm_invalidatepage( struct page *page, unsigned long offset) { trace_xfs_invalidatepage(page->mapping->host, page, offset); block_invalidatepage(page, offset); } /* * If the page has delalloc buffers on it, we need to punch them out before we * invalidate the page. If we don't, we leave a stale delalloc mapping on the * inode that can trip a BUG() in xfs_get_blocks() later on if a direct IO read * is done on that same region - the delalloc extent is returned when none is * supposed to be there. * * We prevent this by truncating away the delalloc regions on the page before * invalidating it. Because they are delalloc, we can do this without needing a * transaction. Indeed - if we get ENOSPC errors, we have to be able to do this * truncation without a transaction as there is no space left for block * reservation (typically why we see a ENOSPC in writeback). * * This is not a performance critical path, so for now just do the punching a * buffer head at a time. */ STATIC void xfs_aops_discard_page( struct page *page) { struct inode *inode = page->mapping->host; struct xfs_inode *ip = XFS_I(inode); struct buffer_head *bh, *head; loff_t offset = page_offset(page); |
3ed3a4343 xfs: truncate del... |
801 |
|
a206c817c xfs: kill xfs_iomap |
802 |
if (!xfs_is_delayed_page(page, IO_DELALLOC)) |
3ed3a4343 xfs: truncate del... |
803 |
goto out_invalidate; |
e8c3753ce xfs: don't warn a... |
804 805 |
if (XFS_FORCED_SHUTDOWN(ip->i_mount)) goto out_invalidate; |
4f10700a2 xfs: Convert linu... |
806 |
xfs_alert(ip->i_mount, |
3ed3a4343 xfs: truncate del... |
807 808 809 810 811 812 |
"page discard on page %p, inode 0x%llx, offset %llu.", page, ip->i_ino, offset); xfs_ilock(ip, XFS_ILOCK_EXCL); bh = head = page_buffers(page); do { |
3ed3a4343 xfs: truncate del... |
813 |
int error; |
c726de440 xfs: fix failed w... |
814 |
xfs_fileoff_t start_fsb; |
3ed3a4343 xfs: truncate del... |
815 816 817 |
if (!buffer_delay(bh)) goto next_buffer; |
c726de440 xfs: fix failed w... |
818 819 |
start_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); error = xfs_bmap_punch_delalloc_range(ip, start_fsb, 1); |
3ed3a4343 xfs: truncate del... |
820 821 |
if (error) { /* something screwed, just bail */ |
e8c3753ce xfs: don't warn a... |
822 |
if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { |
4f10700a2 xfs: Convert linu... |
823 |
xfs_alert(ip->i_mount, |
3ed3a4343 xfs: truncate del... |
824 |
"page discard unable to remove delalloc mapping."); |
e8c3753ce xfs: don't warn a... |
825 |
} |
3ed3a4343 xfs: truncate del... |
826 827 828 |
break; } next_buffer: |
c726de440 xfs: fix failed w... |
829 |
offset += 1 << inode->i_blkbits; |
3ed3a4343 xfs: truncate del... |
830 831 832 833 834 835 836 837 |
} while ((bh = bh->b_this_page) != head); xfs_iunlock(ip, XFS_ILOCK_EXCL); out_invalidate: xfs_vm_invalidatepage(page, 0); return; } |
1da177e4c Linux-2.6.12-rc2 |
838 |
/* |
89f3b3639 xfs: simplify xfs... |
839 840 841 842 843 |
* Write out a dirty page. * * For delalloc space on the page we need to allocate space and flush it. * For unwritten space on the page we need to start the conversion to * regular allocated space. |
89f3b3639 xfs: simplify xfs... |
844 |
* For any other dirty buffer heads on the page we should flush them. |
1da177e4c Linux-2.6.12-rc2 |
845 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
846 |
STATIC int |
89f3b3639 xfs: simplify xfs... |
847 848 849 |
xfs_vm_writepage( struct page *page, struct writeback_control *wbc) |
1da177e4c Linux-2.6.12-rc2 |
850 |
{ |
89f3b3639 xfs: simplify xfs... |
851 |
struct inode *inode = page->mapping->host; |
f6d6d4fcd [XFS] Initial pas... |
852 |
struct buffer_head *bh, *head; |
207d04160 xfs: kill struct ... |
853 |
struct xfs_bmbt_irec imap; |
f6d6d4fcd [XFS] Initial pas... |
854 |
xfs_ioend_t *ioend = NULL, *iohead = NULL; |
1da177e4c Linux-2.6.12-rc2 |
855 |
loff_t offset; |
f6d6d4fcd [XFS] Initial pas... |
856 |
unsigned int type; |
1da177e4c Linux-2.6.12-rc2 |
857 |
__uint64_t end_offset; |
bd1556a14 xfs: clean up end... |
858 |
pgoff_t end_index, last_index; |
ed1e7b7e4 xfs: remove xfs_p... |
859 |
ssize_t len; |
a206c817c xfs: kill xfs_iomap |
860 |
int err, imap_valid = 0, uptodate = 1; |
89f3b3639 xfs: simplify xfs... |
861 |
int count = 0; |
a206c817c xfs: kill xfs_iomap |
862 |
int nonblocking = 0; |
89f3b3639 xfs: simplify xfs... |
863 864 |
trace_xfs_writepage(inode, page, 0); |
20cb52ebd xfs: simplify xfs... |
865 |
ASSERT(page_has_buffers(page)); |
89f3b3639 xfs: simplify xfs... |
866 867 868 |
/* * Refuse to write the page out if we are called from reclaim context. * |
d4f7a5cbd xfs: allow writeb... |
869 870 871 |
* This avoids stack overflows when called from deeply used stacks in * random callers for direct reclaim or memcg reclaim. We explicitly * allow reclaim from kswapd as the stack usage there is relatively low. |
89f3b3639 xfs: simplify xfs... |
872 |
* |
94054fa3f xfs: warn if dire... |
873 874 |
* This should never happen except in the case of a VM regression so * warn about it. |
89f3b3639 xfs: simplify xfs... |
875 |
*/ |
94054fa3f xfs: warn if dire... |
876 877 |
if (WARN_ON_ONCE((current->flags & (PF_MEMALLOC|PF_KSWAPD)) == PF_MEMALLOC)) |
b5420f235 xfs: do not disca... |
878 |
goto redirty; |
1da177e4c Linux-2.6.12-rc2 |
879 |
|
89f3b3639 xfs: simplify xfs... |
880 |
/* |
680a647b4 xfs: PF_FSTRANS s... |
881 882 |
* Given that we do not allow direct reclaim to call us, we should * never be called while in a filesystem transaction. |
89f3b3639 xfs: simplify xfs... |
883 |
*/ |
680a647b4 xfs: PF_FSTRANS s... |
884 |
if (WARN_ON(current->flags & PF_FSTRANS)) |
b5420f235 xfs: do not disca... |
885 |
goto redirty; |
89f3b3639 xfs: simplify xfs... |
886 |
|
1da177e4c Linux-2.6.12-rc2 |
887 888 889 890 891 892 893 |
/* Is this page beyond the end of the file? */ offset = i_size_read(inode); end_index = offset >> PAGE_CACHE_SHIFT; last_index = (offset - 1) >> PAGE_CACHE_SHIFT; if (page->index >= end_index) { if ((page->index >= end_index + 1) || !(i_size_read(inode) & (PAGE_CACHE_SIZE - 1))) { |
89f3b3639 xfs: simplify xfs... |
894 |
unlock_page(page); |
19d5bcf37 [XFS] Ensure fsyn... |
895 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
896 897 |
} } |
f6d6d4fcd [XFS] Initial pas... |
898 |
end_offset = min_t(unsigned long long, |
20cb52ebd xfs: simplify xfs... |
899 900 |
(xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT, offset); |
24e17b5fb [XFS] Use the rig... |
901 |
len = 1 << inode->i_blkbits; |
24e17b5fb [XFS] Use the rig... |
902 |
|
24e17b5fb [XFS] Use the rig... |
903 |
bh = head = page_buffers(page); |
f6d6d4fcd [XFS] Initial pas... |
904 |
offset = page_offset(page); |
a206c817c xfs: kill xfs_iomap |
905 |
type = IO_OVERWRITE; |
dbcdde3e7 xfs: re-enable no... |
906 |
if (wbc->sync_mode == WB_SYNC_NONE) |
a206c817c xfs: kill xfs_iomap |
907 |
nonblocking = 1; |
f6d6d4fcd [XFS] Initial pas... |
908 |
|
1da177e4c Linux-2.6.12-rc2 |
909 |
do { |
6ac7248ec xfs: a few small ... |
910 |
int new_ioend = 0; |
1da177e4c Linux-2.6.12-rc2 |
911 912 913 914 |
if (offset >= end_offset) break; if (!buffer_uptodate(bh)) uptodate = 0; |
1da177e4c Linux-2.6.12-rc2 |
915 |
|
3d9b02e3c xfs: fix corrupti... |
916 |
/* |
ece413f59 xfs: remove incor... |
917 918 919 920 |
* set_page_dirty dirties all buffers in a page, independent * of their state. The dirty state however is entirely * meaningless for holes (!mapped && uptodate), so skip * buffers covering holes here. |
3d9b02e3c xfs: fix corrupti... |
921 922 |
*/ if (!buffer_mapped(bh) && buffer_uptodate(bh)) { |
3d9b02e3c xfs: fix corrupti... |
923 924 925 |
imap_valid = 0; continue; } |
aeea1b1f8 xfs: refactor xfs... |
926 927 928 929 |
if (buffer_unwritten(bh)) { if (type != IO_UNWRITTEN) { type = IO_UNWRITTEN; imap_valid = 0; |
1da177e4c Linux-2.6.12-rc2 |
930 |
} |
aeea1b1f8 xfs: refactor xfs... |
931 932 933 934 |
} else if (buffer_delay(bh)) { if (type != IO_DELALLOC) { type = IO_DELALLOC; imap_valid = 0; |
1da177e4c Linux-2.6.12-rc2 |
935 |
} |
89f3b3639 xfs: simplify xfs... |
936 |
} else if (buffer_uptodate(bh)) { |
a206c817c xfs: kill xfs_iomap |
937 938 |
if (type != IO_OVERWRITE) { type = IO_OVERWRITE; |
85da94c6b xfs: improve mapp... |
939 940 |
imap_valid = 0; } |
aeea1b1f8 xfs: refactor xfs... |
941 942 943 944 |
} else { if (PageUptodate(page)) { ASSERT(buffer_mapped(bh)); imap_valid = 0; |
6c4fe19f6 [XFS] cluster rew... |
945 |
} |
aeea1b1f8 xfs: refactor xfs... |
946 947 |
continue; } |
d5cb48aaa [XFS] consolidate... |
948 |
|
aeea1b1f8 xfs: refactor xfs... |
949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 |
if (imap_valid) imap_valid = xfs_imap_valid(inode, &imap, offset); if (!imap_valid) { /* * If we didn't have a valid mapping then we need to * put the new mapping into a separate ioend structure. * This ensures non-contiguous extents always have * separate ioends, which is particularly important * for unwritten extent conversion at I/O completion * time. */ new_ioend = 1; err = xfs_map_blocks(inode, offset, &imap, type, nonblocking); if (err) goto error; imap_valid = xfs_imap_valid(inode, &imap, offset); } if (imap_valid) { |
ecff71e67 xfs: simplify xfs... |
968 969 |
lock_buffer(bh); if (type != IO_OVERWRITE) |
aeea1b1f8 xfs: refactor xfs... |
970 971 972 973 |
xfs_map_at_offset(inode, bh, &imap, offset); xfs_add_to_ioend(inode, bh, offset, type, &ioend, new_ioend); count++; |
1da177e4c Linux-2.6.12-rc2 |
974 |
} |
f6d6d4fcd [XFS] Initial pas... |
975 976 977 978 979 |
if (!iohead) iohead = ioend; } while (offset += len, ((bh = bh->b_this_page) != head)); |
1da177e4c Linux-2.6.12-rc2 |
980 981 982 |
if (uptodate && bh == head) SetPageUptodate(page); |
89f3b3639 xfs: simplify xfs... |
983 |
xfs_start_page_writeback(page, 1, count); |
1da177e4c Linux-2.6.12-rc2 |
984 |
|
558e68916 xfs: clean up xfs... |
985 |
if (ioend && imap_valid) { |
bd1556a14 xfs: clean up end... |
986 987 988 989 990 991 992 993 994 995 996 997 998 |
xfs_off_t end_index; end_index = imap.br_startoff + imap.br_blockcount; /* to bytes */ end_index <<= inode->i_blkbits; /* to pages */ end_index = (end_index - 1) >> PAGE_CACHE_SHIFT; /* check against file size */ if (end_index > last_index) end_index = last_index; |
8699bb0a4 xfs: report iomap... |
999 |
|
207d04160 xfs: kill struct ... |
1000 |
xfs_cluster_write(inode, page->index + 1, &imap, &ioend, |
2fa24f925 xfs: remove the a... |
1001 |
wbc, end_index); |
1da177e4c Linux-2.6.12-rc2 |
1002 |
} |
f6d6d4fcd [XFS] Initial pas... |
1003 |
if (iohead) |
06342cf8a xfs: use WRITE_SY... |
1004 |
xfs_submit_ioend(wbc, iohead); |
f6d6d4fcd [XFS] Initial pas... |
1005 |
|
89f3b3639 xfs: simplify xfs... |
1006 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1007 1008 |
error: |
f6d6d4fcd [XFS] Initial pas... |
1009 1010 |
if (iohead) xfs_cancel_ioend(iohead); |
1da177e4c Linux-2.6.12-rc2 |
1011 |
|
b5420f235 xfs: do not disca... |
1012 1013 |
if (err == -EAGAIN) goto redirty; |
20cb52ebd xfs: simplify xfs... |
1014 |
xfs_aops_discard_page(page); |
89f3b3639 xfs: simplify xfs... |
1015 1016 |
ClearPageUptodate(page); unlock_page(page); |
1da177e4c Linux-2.6.12-rc2 |
1017 |
return err; |
f51623b21 [XFS] Move some c... |
1018 |
|
b5420f235 xfs: do not disca... |
1019 |
redirty: |
f51623b21 [XFS] Move some c... |
1020 1021 1022 |
redirty_page_for_writepage(wbc, page); unlock_page(page); return 0; |
f51623b21 [XFS] Move some c... |
1023 |
} |
7d4fb40ad [XFS] Start write... |
1024 1025 1026 1027 1028 |
STATIC int xfs_vm_writepages( struct address_space *mapping, struct writeback_control *wbc) { |
b3aea4edc [XFS] kill the v_... |
1029 |
xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED); |
7d4fb40ad [XFS] Start write... |
1030 1031 |
return generic_writepages(mapping, wbc); } |
f51623b21 [XFS] Move some c... |
1032 1033 |
/* * Called to move a page into cleanable state - and from there |
89f3b3639 xfs: simplify xfs... |
1034 |
* to be released. The page should already be clean. We always |
f51623b21 [XFS] Move some c... |
1035 1036 |
* have buffer heads in this call. * |
89f3b3639 xfs: simplify xfs... |
1037 |
* Returns 1 if the page is ok to release, 0 otherwise. |
f51623b21 [XFS] Move some c... |
1038 1039 |
*/ STATIC int |
238f4c546 [XFS] Make couple... |
1040 |
xfs_vm_releasepage( |
f51623b21 [XFS] Move some c... |
1041 1042 1043 |
struct page *page, gfp_t gfp_mask) { |
20cb52ebd xfs: simplify xfs... |
1044 |
int delalloc, unwritten; |
f51623b21 [XFS] Move some c... |
1045 |
|
89f3b3639 xfs: simplify xfs... |
1046 |
trace_xfs_releasepage(page->mapping->host, page, 0); |
238f4c546 [XFS] Make couple... |
1047 |
|
20cb52ebd xfs: simplify xfs... |
1048 |
xfs_count_page_state(page, &delalloc, &unwritten); |
f51623b21 [XFS] Move some c... |
1049 |
|
89f3b3639 xfs: simplify xfs... |
1050 |
if (WARN_ON(delalloc)) |
f51623b21 [XFS] Move some c... |
1051 |
return 0; |
89f3b3639 xfs: simplify xfs... |
1052 |
if (WARN_ON(unwritten)) |
f51623b21 [XFS] Move some c... |
1053 |
return 0; |
f51623b21 [XFS] Move some c... |
1054 1055 |
return try_to_free_buffers(page); } |
1da177e4c Linux-2.6.12-rc2 |
1056 |
STATIC int |
c25366680 [XFS] Cleanup in ... |
1057 |
__xfs_get_blocks( |
1da177e4c Linux-2.6.12-rc2 |
1058 1059 |
struct inode *inode, sector_t iblock, |
1da177e4c Linux-2.6.12-rc2 |
1060 1061 |
struct buffer_head *bh_result, int create, |
f2bde9b89 xfs: small cleanu... |
1062 |
int direct) |
1da177e4c Linux-2.6.12-rc2 |
1063 |
{ |
a206c817c xfs: kill xfs_iomap |
1064 1065 1066 1067 1068 |
struct xfs_inode *ip = XFS_I(inode); struct xfs_mount *mp = ip->i_mount; xfs_fileoff_t offset_fsb, end_fsb; int error = 0; int lockmode = 0; |
207d04160 xfs: kill struct ... |
1069 |
struct xfs_bmbt_irec imap; |
a206c817c xfs: kill xfs_iomap |
1070 |
int nimaps = 1; |
fdc7ed75c [XFS] Fix boundar... |
1071 1072 |
xfs_off_t offset; ssize_t size; |
207d04160 xfs: kill struct ... |
1073 |
int new = 0; |
a206c817c xfs: kill xfs_iomap |
1074 1075 1076 |
if (XFS_FORCED_SHUTDOWN(mp)) return -XFS_ERROR(EIO); |
1da177e4c Linux-2.6.12-rc2 |
1077 |
|
fdc7ed75c [XFS] Fix boundar... |
1078 |
offset = (xfs_off_t)iblock << inode->i_blkbits; |
c25366680 [XFS] Cleanup in ... |
1079 1080 |
ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); size = bh_result->b_size; |
364f358a7 [XFS] Prevent dir... |
1081 1082 1083 |
if (!create && direct && offset >= i_size_read(inode)) return 0; |
a206c817c xfs: kill xfs_iomap |
1084 1085 1086 1087 1088 1089 |
if (create) { lockmode = XFS_ILOCK_EXCL; xfs_ilock(ip, lockmode); } else { lockmode = xfs_ilock_map_shared(ip); } |
f2bde9b89 xfs: small cleanu... |
1090 |
|
a206c817c xfs: kill xfs_iomap |
1091 1092 1093 1094 1095 |
ASSERT(offset <= mp->m_maxioffset); if (offset + size > mp->m_maxioffset) size = mp->m_maxioffset - offset; end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size); offset_fsb = XFS_B_TO_FSBT(mp, offset); |
5c8ed2021 xfs: introduce xf... |
1096 1097 |
error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap, &nimaps, XFS_BMAPI_ENTIRE); |
1da177e4c Linux-2.6.12-rc2 |
1098 |
if (error) |
a206c817c xfs: kill xfs_iomap |
1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 |
goto out_unlock; if (create && (!nimaps || (imap.br_startblock == HOLESTARTBLOCK || imap.br_startblock == DELAYSTARTBLOCK))) { if (direct) { error = xfs_iomap_write_direct(ip, offset, size, &imap, nimaps); } else { error = xfs_iomap_write_delay(ip, offset, size, &imap); } if (error) goto out_unlock; trace_xfs_get_blocks_alloc(ip, offset, size, 0, &imap); } else if (nimaps) { trace_xfs_get_blocks_found(ip, offset, size, 0, &imap); } else { trace_xfs_get_blocks_notfound(ip, offset, size); goto out_unlock; } xfs_iunlock(ip, lockmode); |
1da177e4c Linux-2.6.12-rc2 |
1122 |
|
207d04160 xfs: kill struct ... |
1123 1124 |
if (imap.br_startblock != HOLESTARTBLOCK && imap.br_startblock != DELAYSTARTBLOCK) { |
87cbc49cd [XFS] Add xfs_map... |
1125 1126 |
/* * For unwritten extents do not report a disk address on |
1da177e4c Linux-2.6.12-rc2 |
1127 1128 |
* the read case (treat as if we're reading into a hole). */ |
207d04160 xfs: kill struct ... |
1129 1130 1131 |
if (create || !ISUNWRITTEN(&imap)) xfs_map_buffer(inode, bh_result, &imap, offset); if (create && ISUNWRITTEN(&imap)) { |
1da177e4c Linux-2.6.12-rc2 |
1132 1133 1134 |
if (direct) bh_result->b_private = inode; set_buffer_unwritten(bh_result); |
1da177e4c Linux-2.6.12-rc2 |
1135 1136 |
} } |
c25366680 [XFS] Cleanup in ... |
1137 1138 1139 1140 |
/* * If this is a realtime file, data may be on a different device. * to that pointed to from the buffer_head b_bdev currently. */ |
046f1685b xfs: remove iomap... |
1141 |
bh_result->b_bdev = xfs_find_bdev_for_inode(inode); |
1da177e4c Linux-2.6.12-rc2 |
1142 |
|
c25366680 [XFS] Cleanup in ... |
1143 |
/* |
549054afa [XFS] Fix sub-blo... |
1144 1145 1146 1147 1148 1149 1150 |
* If we previously allocated a block out beyond eof and we are now * coming back to use it then we will need to flag it as new even if it * has a disk address. * * With sub-block writes into unwritten extents we also need to mark * the buffer as new so that the unwritten parts of the buffer gets * correctly zeroed. |
1da177e4c Linux-2.6.12-rc2 |
1151 1152 1153 |
*/ if (create && ((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) || |
549054afa [XFS] Fix sub-blo... |
1154 |
(offset >= i_size_read(inode)) || |
207d04160 xfs: kill struct ... |
1155 |
(new || ISUNWRITTEN(&imap)))) |
1da177e4c Linux-2.6.12-rc2 |
1156 |
set_buffer_new(bh_result); |
1da177e4c Linux-2.6.12-rc2 |
1157 |
|
207d04160 xfs: kill struct ... |
1158 |
if (imap.br_startblock == DELAYSTARTBLOCK) { |
1da177e4c Linux-2.6.12-rc2 |
1159 1160 1161 1162 1163 1164 1165 |
BUG_ON(direct); if (create) { set_buffer_uptodate(bh_result); set_buffer_mapped(bh_result); set_buffer_delay(bh_result); } } |
2b8f12b7e xfs: clean up map... |
1166 1167 1168 1169 |
/* * If this is O_DIRECT or the mpage code calling tell them how large * the mapping is, so that we can avoid repeated get_blocks calls. */ |
c25366680 [XFS] Cleanup in ... |
1170 |
if (direct || size > (1 << inode->i_blkbits)) { |
2b8f12b7e xfs: clean up map... |
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 |
xfs_off_t mapping_size; mapping_size = imap.br_startoff + imap.br_blockcount - iblock; mapping_size <<= inode->i_blkbits; ASSERT(mapping_size > 0); if (mapping_size > size) mapping_size = size; if (mapping_size > LONG_MAX) mapping_size = LONG_MAX; bh_result->b_size = mapping_size; |
1da177e4c Linux-2.6.12-rc2 |
1183 1184 1185 |
} return 0; |
a206c817c xfs: kill xfs_iomap |
1186 1187 1188 1189 |
out_unlock: xfs_iunlock(ip, lockmode); return -error; |
1da177e4c Linux-2.6.12-rc2 |
1190 1191 1192 |
} int |
c25366680 [XFS] Cleanup in ... |
1193 |
xfs_get_blocks( |
1da177e4c Linux-2.6.12-rc2 |
1194 1195 1196 1197 1198 |
struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) { |
f2bde9b89 xfs: small cleanu... |
1199 |
return __xfs_get_blocks(inode, iblock, bh_result, create, 0); |
1da177e4c Linux-2.6.12-rc2 |
1200 1201 1202 |
} STATIC int |
e4c573bb6 [XFS] Switch over... |
1203 |
xfs_get_blocks_direct( |
1da177e4c Linux-2.6.12-rc2 |
1204 1205 |
struct inode *inode, sector_t iblock, |
1da177e4c Linux-2.6.12-rc2 |
1206 1207 1208 |
struct buffer_head *bh_result, int create) { |
f2bde9b89 xfs: small cleanu... |
1209 |
return __xfs_get_blocks(inode, iblock, bh_result, create, 1); |
1da177e4c Linux-2.6.12-rc2 |
1210 |
} |
209fb87a2 xfs simplify and ... |
1211 1212 1213 1214 1215 1216 |
/* * Complete a direct I/O write request. * * If the private argument is non-NULL __xfs_get_blocks signals us that we * need to issue a transaction to convert the range from unwritten to written * extents. In case this is regular synchronous I/O we just call xfs_end_io |
25985edce Fix common misspe... |
1217 |
* to do this and we are done. But in case this was a successful AIO |
209fb87a2 xfs simplify and ... |
1218 1219 1220 1221 |
* request this handler is called from interrupt context, from which we * can't start transactions. In that case offload the I/O completion to * the workqueues we also use for buffered I/O completion. */ |
f09738638 [XFS] Delay direc... |
1222 |
STATIC void |
209fb87a2 xfs simplify and ... |
1223 1224 1225 1226 1227 1228 1229 |
xfs_end_io_direct_write( struct kiocb *iocb, loff_t offset, ssize_t size, void *private, int ret, bool is_async) |
f09738638 [XFS] Delay direc... |
1230 |
{ |
209fb87a2 xfs simplify and ... |
1231 |
struct xfs_ioend *ioend = iocb->private; |
f09738638 [XFS] Delay direc... |
1232 1233 |
/* |
209fb87a2 xfs simplify and ... |
1234 1235 1236 |
* blockdev_direct_IO can return an error even after the I/O * completion handler was called. Thus we need to protect * against double-freeing. |
f09738638 [XFS] Delay direc... |
1237 |
*/ |
209fb87a2 xfs simplify and ... |
1238 |
iocb->private = NULL; |
ba87ea699 [XFS] Fix to prev... |
1239 1240 |
ioend->io_offset = offset; ioend->io_size = size; |
c859cdd1d xfs: defer AIO/DI... |
1241 1242 |
ioend->io_iocb = iocb; ioend->io_result = ret; |
209fb87a2 xfs simplify and ... |
1243 1244 1245 1246 |
if (private && size > 0) ioend->io_type = IO_UNWRITTEN; if (is_async) { |
c859cdd1d xfs: defer AIO/DI... |
1247 |
ioend->io_isasync = 1; |
209fb87a2 xfs simplify and ... |
1248 |
xfs_finish_ioend(ioend); |
f09738638 [XFS] Delay direc... |
1249 |
} else { |
209fb87a2 xfs simplify and ... |
1250 |
xfs_finish_ioend_sync(ioend); |
f09738638 [XFS] Delay direc... |
1251 |
} |
f09738638 [XFS] Delay direc... |
1252 |
} |
1da177e4c Linux-2.6.12-rc2 |
1253 |
STATIC ssize_t |
e4c573bb6 [XFS] Switch over... |
1254 |
xfs_vm_direct_IO( |
1da177e4c Linux-2.6.12-rc2 |
1255 1256 1257 1258 1259 1260 |
int rw, struct kiocb *iocb, const struct iovec *iov, loff_t offset, unsigned long nr_segs) { |
209fb87a2 xfs simplify and ... |
1261 1262 1263 1264 1265 |
struct inode *inode = iocb->ki_filp->f_mapping->host; struct block_device *bdev = xfs_find_bdev_for_inode(inode); ssize_t ret; if (rw & WRITE) { |
a206c817c xfs: kill xfs_iomap |
1266 |
iocb->private = xfs_alloc_ioend(inode, IO_DIRECT); |
209fb87a2 xfs simplify and ... |
1267 |
|
eafdc7d19 sort out blockdev... |
1268 1269 1270 1271 |
ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, nr_segs, xfs_get_blocks_direct, xfs_end_io_direct_write, NULL, 0); |
209fb87a2 xfs simplify and ... |
1272 1273 1274 |
if (ret != -EIOCBQUEUED && iocb->private) xfs_destroy_ioend(iocb->private); } else { |
eafdc7d19 sort out blockdev... |
1275 1276 1277 1278 |
ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, nr_segs, xfs_get_blocks_direct, NULL, NULL, 0); |
209fb87a2 xfs simplify and ... |
1279 |
} |
f09738638 [XFS] Delay direc... |
1280 |
|
f09738638 [XFS] Delay direc... |
1281 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
1282 |
} |
fa9b227e9 xfs: new truncate... |
1283 1284 1285 1286 1287 1288 1289 1290 |
STATIC void xfs_vm_write_failed( struct address_space *mapping, loff_t to) { struct inode *inode = mapping->host; if (to > inode->i_size) { |
c726de440 xfs: fix failed w... |
1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 |
/* * punch out the delalloc blocks we have already allocated. We * don't call xfs_setattr() to do this as we may be in the * middle of a multi-iovec write and so the vfs inode->i_size * will not match the xfs ip->i_size and so it will zero too * much. Hence we jus truncate the page cache to zero what is * necessary and punch the delalloc blocks directly. */ struct xfs_inode *ip = XFS_I(inode); xfs_fileoff_t start_fsb; xfs_fileoff_t end_fsb; int error; truncate_pagecache(inode, to, inode->i_size); /* * Check if there are any blocks that are outside of i_size * that need to be trimmed back. */ start_fsb = XFS_B_TO_FSB(ip->i_mount, inode->i_size) + 1; end_fsb = XFS_B_TO_FSB(ip->i_mount, to); if (end_fsb <= start_fsb) return; xfs_ilock(ip, XFS_ILOCK_EXCL); error = xfs_bmap_punch_delalloc_range(ip, start_fsb, end_fsb - start_fsb); if (error) { /* something screwed, just bail */ if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { |
4f10700a2 xfs: Convert linu... |
1321 |
xfs_alert(ip->i_mount, |
c726de440 xfs: fix failed w... |
1322 1323 1324 1325 1326 |
"xfs_vm_write_failed: unable to clean up ino %lld", ip->i_ino); } } xfs_iunlock(ip, XFS_ILOCK_EXCL); |
fa9b227e9 xfs: new truncate... |
1327 1328 |
} } |
f51623b21 [XFS] Move some c... |
1329 |
STATIC int |
d79689c70 xfs: convert to n... |
1330 |
xfs_vm_write_begin( |
f51623b21 [XFS] Move some c... |
1331 |
struct file *file, |
d79689c70 xfs: convert to n... |
1332 1333 1334 1335 1336 1337 |
struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) |
f51623b21 [XFS] Move some c... |
1338 |
{ |
155130a4f get rid of block_... |
1339 1340 1341 1342 |
int ret; ret = block_write_begin(mapping, pos, len, flags | AOP_FLAG_NOFS, pagep, xfs_get_blocks); |
fa9b227e9 xfs: new truncate... |
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 |
if (unlikely(ret)) xfs_vm_write_failed(mapping, pos + len); return ret; } STATIC int xfs_vm_write_end( struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata) { int ret; |
155130a4f get rid of block_... |
1359 |
|
fa9b227e9 xfs: new truncate... |
1360 1361 1362 |
ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata); if (unlikely(ret < len)) xfs_vm_write_failed(mapping, pos + len); |
155130a4f get rid of block_... |
1363 |
return ret; |
f51623b21 [XFS] Move some c... |
1364 |
} |
1da177e4c Linux-2.6.12-rc2 |
1365 1366 |
STATIC sector_t |
e4c573bb6 [XFS] Switch over... |
1367 |
xfs_vm_bmap( |
1da177e4c Linux-2.6.12-rc2 |
1368 1369 1370 1371 |
struct address_space *mapping, sector_t block) { struct inode *inode = (struct inode *)mapping->host; |
739bfb2a7 [XFS] call common... |
1372 |
struct xfs_inode *ip = XFS_I(inode); |
1da177e4c Linux-2.6.12-rc2 |
1373 |
|
cca28fb83 xfs: split xfs_it... |
1374 |
trace_xfs_vm_bmap(XFS_I(inode)); |
126468b11 [XFS] kill xfs_rw... |
1375 |
xfs_ilock(ip, XFS_IOLOCK_SHARED); |
739bfb2a7 [XFS] call common... |
1376 |
xfs_flush_pages(ip, (xfs_off_t)0, -1, 0, FI_REMAPF); |
126468b11 [XFS] kill xfs_rw... |
1377 |
xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
c25366680 [XFS] Cleanup in ... |
1378 |
return generic_block_bmap(mapping, block, xfs_get_blocks); |
1da177e4c Linux-2.6.12-rc2 |
1379 1380 1381 |
} STATIC int |
e4c573bb6 [XFS] Switch over... |
1382 |
xfs_vm_readpage( |
1da177e4c Linux-2.6.12-rc2 |
1383 1384 1385 |
struct file *unused, struct page *page) { |
c25366680 [XFS] Cleanup in ... |
1386 |
return mpage_readpage(page, xfs_get_blocks); |
1da177e4c Linux-2.6.12-rc2 |
1387 1388 1389 |
} STATIC int |
e4c573bb6 [XFS] Switch over... |
1390 |
xfs_vm_readpages( |
1da177e4c Linux-2.6.12-rc2 |
1391 1392 1393 1394 1395 |
struct file *unused, struct address_space *mapping, struct list_head *pages, unsigned nr_pages) { |
c25366680 [XFS] Cleanup in ... |
1396 |
return mpage_readpages(mapping, pages, nr_pages, xfs_get_blocks); |
1da177e4c Linux-2.6.12-rc2 |
1397 |
} |
f5e54d6e5 [PATCH] mark addr... |
1398 |
const struct address_space_operations xfs_address_space_operations = { |
e4c573bb6 [XFS] Switch over... |
1399 1400 1401 |
.readpage = xfs_vm_readpage, .readpages = xfs_vm_readpages, .writepage = xfs_vm_writepage, |
7d4fb40ad [XFS] Start write... |
1402 |
.writepages = xfs_vm_writepages, |
238f4c546 [XFS] Make couple... |
1403 1404 |
.releasepage = xfs_vm_releasepage, .invalidatepage = xfs_vm_invalidatepage, |
d79689c70 xfs: convert to n... |
1405 |
.write_begin = xfs_vm_write_begin, |
fa9b227e9 xfs: new truncate... |
1406 |
.write_end = xfs_vm_write_end, |
e4c573bb6 [XFS] Switch over... |
1407 1408 |
.bmap = xfs_vm_bmap, .direct_IO = xfs_vm_direct_IO, |
e965f9630 [PATCH] Direct Mi... |
1409 |
.migratepage = buffer_migrate_page, |
bddaafa11 xfs: pagecache us... |
1410 |
.is_partially_uptodate = block_is_partially_uptodate, |
aa261f549 HWPOISON: Enable ... |
1411 |
.error_remove_page = generic_error_remove_page, |
1da177e4c Linux-2.6.12-rc2 |
1412 |
}; |