Blame view

fs/xfs/xfs_aops.c 35.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
7b7187698   Nathan Scott   [XFS] Update lice...
2
3
   * Copyright (c) 2000-2005 Silicon Graphics, Inc.
   * All Rights Reserved.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
   *
7b7187698   Nathan Scott   [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   Linus Torvalds   Linux-2.6.12-rc2
7
8
   * published by the Free Software Foundation.
   *
7b7187698   Nathan Scott   [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   Linus Torvalds   Linux-2.6.12-rc2
13
   *
7b7187698   Nathan Scott   [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   Linus Torvalds   Linux-2.6.12-rc2
17
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include "xfs.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
19
  #include "xfs_bit.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #include "xfs_log.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
21
  #include "xfs_inum.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #include "xfs_sb.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
23
  #include "xfs_ag.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
  #include "xfs_trans.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
  #include "xfs_mount.h"
  #include "xfs_bmap_btree.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
  #include "xfs_dinode.h"
  #include "xfs_inode.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
29
  #include "xfs_alloc.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
  #include "xfs_error.h"
  #include "xfs_rw.h"
  #include "xfs_iomap.h"
739bfb2a7   Christoph Hellwig   [XFS] call common...
33
  #include "xfs_vnodeops.h"
0b1b213fc   Christoph Hellwig   xfs: event tracin...
34
  #include "xfs_trace.h"
3ed3a4343   Dave Chinner   xfs: truncate del...
35
  #include "xfs_bmap.h"
5a0e3ad6a   Tejun Heo   include cleanup: ...
36
  #include <linux/gfp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
  #include <linux/mpage.h>
10ce44442   Christoph Hellwig   [XFS] use pagevec...
38
  #include <linux/pagevec.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
  #include <linux/writeback.h>
0b1b213fc   Christoph Hellwig   xfs: event tracin...
40
  void
f51623b21   Nathan Scott   [XFS] Move some c...
41
42
43
  xfs_count_page_state(
  	struct page		*page,
  	int			*delalloc,
f51623b21   Nathan Scott   [XFS] Move some c...
44
45
46
  	int			*unwritten)
  {
  	struct buffer_head	*bh, *head;
20cb52ebd   Christoph Hellwig   xfs: simplify xfs...
47
  	*delalloc = *unwritten = 0;
f51623b21   Nathan Scott   [XFS] Move some c...
48
49
50
  
  	bh = head = page_buffers(page);
  	do {
20cb52ebd   Christoph Hellwig   xfs: simplify xfs...
51
  		if (buffer_unwritten(bh))
f51623b21   Nathan Scott   [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   Christoph Hellwig   [XFS] kill BMAPI_...
57
58
  STATIC struct block_device *
  xfs_find_bdev_for_inode(
046f1685b   Christoph Hellwig   xfs: remove iomap...
59
  	struct inode		*inode)
6214ed446   Christoph Hellwig   [XFS] kill BMAPI_...
60
  {
046f1685b   Christoph Hellwig   xfs: remove iomap...
61
  	struct xfs_inode	*ip = XFS_I(inode);
6214ed446   Christoph Hellwig   [XFS] kill BMAPI_...
62
  	struct xfs_mount	*mp = ip->i_mount;
71ddabb94   Eric Sandeen   [XFS] optimize XF...
63
  	if (XFS_IS_REALTIME_INODE(ip))
6214ed446   Christoph Hellwig   [XFS] kill BMAPI_...
64
65
66
67
  		return mp->m_rtdev_targp->bt_bdev;
  	else
  		return mp->m_ddev_targp->bt_bdev;
  }
0829c3602   Christoph Hellwig   [XFS] Add infrast...
68
  /*
f6d6d4fcd   Christoph Hellwig   [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   Christoph Hellwig   [XFS] Add infrast...
74
75
76
77
  STATIC void
  xfs_destroy_ioend(
  	xfs_ioend_t		*ioend)
  {
f6d6d4fcd   Christoph Hellwig   [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   Nathan Scott   [XFS] Shutdown th...
82
  		bh->b_end_io(bh, !ioend->io_error);
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
83
  	}
583fa586f   Christoph Hellwig   kill vn_ioerror
84

c859cdd1d   Christoph Hellwig   xfs: defer AIO/DI...
85
  	if (ioend->io_iocb) {
04f658ee2   Christoph Hellwig   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   Christoph Hellwig   xfs: defer AIO/DI...
90
91
  		inode_dio_done(ioend->io_inode);
  	}
4a06fd262   Christoph Hellwig   xfs: remove i_ioc...
92

0829c3602   Christoph Hellwig   [XFS] Add infrast...
93
94
95
96
  	mempool_free(ioend, xfs_ioend_pool);
  }
  
  /*
932640e8a   Dave Chinner   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   Christoph Hellwig   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   Dave Chinner   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   Lachlan McIlroy   [XFS] Fix to prev...
133
   */
77d7a0c2e   Dave Chinner   xfs: Non-blocking...
134
  STATIC int
ba87ea699   Lachlan McIlroy   [XFS] Fix to prev...
135
136
137
  xfs_setfilesize(
  	xfs_ioend_t		*ioend)
  {
b677c210c   Christoph Hellwig   [XFS] move v_ioco...
138
  	xfs_inode_t		*ip = XFS_I(ioend->io_inode);
ba87ea699   Lachlan McIlroy   [XFS] Fix to prev...
139
  	xfs_fsize_t		isize;
ba87ea699   Lachlan McIlroy   [XFS] Fix to prev...
140

77d7a0c2e   Dave Chinner   xfs: Non-blocking...
141
142
  	if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL))
  		return EAGAIN;
ba87ea699   Lachlan McIlroy   [XFS] Fix to prev...
143

932640e8a   Dave Chinner   xfs: mark inodes ...
144
145
  	isize = xfs_ioend_new_eof(ioend);
  	if (isize) {
55fb25d5b   Dave Chinner   xfs: add size upd...
146
  		trace_xfs_setfilesize(ip, ioend->io_offset, ioend->io_size);
ba87ea699   Lachlan McIlroy   [XFS] Fix to prev...
147
  		ip->i_d.di_size = isize;
66d834ea6   Christoph Hellwig   xfs: implement op...
148
  		xfs_mark_inode_dirty(ip);
ba87ea699   Lachlan McIlroy   [XFS] Fix to prev...
149
150
151
  	}
  
  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
77d7a0c2e   Dave Chinner   xfs: Non-blocking...
152
153
154
155
  	return 0;
  }
  
  /*
209fb87a2   Christoph Hellwig   xfs simplify and ...
156
   * Schedule IO completion handling on the final put of an ioend.
fc0063c44   Christoph Hellwig   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   Dave Chinner   xfs: Non-blocking...
160
161
162
   */
  STATIC void
  xfs_finish_ioend(
209fb87a2   Christoph Hellwig   xfs simplify and ...
163
  	struct xfs_ioend	*ioend)
77d7a0c2e   Dave Chinner   xfs: Non-blocking...
164
165
  {
  	if (atomic_dec_and_test(&ioend->io_remaining)) {
209fb87a2   Christoph Hellwig   xfs simplify and ...
166
167
  		if (ioend->io_type == IO_UNWRITTEN)
  			queue_work(xfsconvertd_workqueue, &ioend->io_work);
fc0063c44   Christoph Hellwig   xfs: reduce ioend...
168
  		else if (xfs_ioend_is_append(ioend))
209fb87a2   Christoph Hellwig   xfs simplify and ...
169
  			queue_work(xfsdatad_workqueue, &ioend->io_work);
fc0063c44   Christoph Hellwig   xfs: reduce ioend...
170
171
  		else
  			xfs_destroy_ioend(ioend);
77d7a0c2e   Dave Chinner   xfs: Non-blocking...
172
  	}
ba87ea699   Lachlan McIlroy   [XFS] Fix to prev...
173
174
175
  }
  
  /*
5ec4fabb0   Christoph Hellwig   xfs: cleanup data...
176
   * IO write completion.
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
177
178
   */
  STATIC void
5ec4fabb0   Christoph Hellwig   xfs: cleanup data...
179
  xfs_end_io(
77d7a0c2e   Dave Chinner   xfs: Non-blocking...
180
  	struct work_struct *work)
0829c3602   Christoph Hellwig   [XFS] Add infrast...
181
  {
77d7a0c2e   Dave Chinner   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   Dave Chinner   xfs: Fix a build ...
184
  	int		error = 0;
ba87ea699   Lachlan McIlroy   [XFS] Fix to prev...
185

04f658ee2   Christoph Hellwig   xfs: improve ioen...
186
  	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
810627d9a   Christoph Hellwig   xfs: fix force sh...
187
  		ioend->io_error = -EIO;
04f658ee2   Christoph Hellwig   xfs: improve ioen...
188
189
190
191
  		goto done;
  	}
  	if (ioend->io_error)
  		goto done;
5ec4fabb0   Christoph Hellwig   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   Christoph Hellwig   xfs: improve ioen...
196
  	if (ioend->io_type == IO_UNWRITTEN) {
5ec4fabb0   Christoph Hellwig   xfs: cleanup data...
197
198
  		error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
  						 ioend->io_size);
04f658ee2   Christoph Hellwig   xfs: improve ioen...
199
200
201
202
  		if (error) {
  			ioend->io_error = -error;
  			goto done;
  		}
5ec4fabb0   Christoph Hellwig   xfs: cleanup data...
203
  	}
ba87ea699   Lachlan McIlroy   [XFS] Fix to prev...
204

5ec4fabb0   Christoph Hellwig   xfs: cleanup data...
205
206
207
208
  	/*
  	 * We might have to update the on-disk file size after extending
  	 * writes.
  	 */
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
209
210
  	error = xfs_setfilesize(ioend);
  	ASSERT(!error || error == EAGAIN);
77d7a0c2e   Dave Chinner   xfs: Non-blocking...
211

04f658ee2   Christoph Hellwig   xfs: improve ioen...
212
  done:
77d7a0c2e   Dave Chinner   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   Christoph Hellwig   xfs simplify and ...
220
  		xfs_finish_ioend(ioend);
77d7a0c2e   Dave Chinner   xfs: Non-blocking...
221
222
  		/* ensure we don't spin on blocked ioends */
  		delay(1);
fb511f215   Christoph Hellwig   xfs: move aio com...
223
  	} else {
77d7a0c2e   Dave Chinner   xfs: Non-blocking...
224
  		xfs_destroy_ioend(ioend);
fb511f215   Christoph Hellwig   xfs: move aio com...
225
  	}
c626d174c   Dave Chinner   xfs: prevent unwr...
226
227
228
  }
  
  /*
209fb87a2   Christoph Hellwig   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   Christoph Hellwig   [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   Christoph Hellwig   [XFS] Initial pas...
247
248
  	struct inode		*inode,
  	unsigned int		type)
0829c3602   Christoph Hellwig   [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   Christoph Hellwig   xfs: defer AIO/DI...
260
  	ioend->io_isasync = 0;
7d04a335b   Nathan Scott   [XFS] Shutdown th...
261
  	ioend->io_error = 0;
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
262
263
  	ioend->io_list = NULL;
  	ioend->io_type = type;
b677c210c   Christoph Hellwig   [XFS] move v_ioco...
264
  	ioend->io_inode = inode;
c1a073bdf   Christoph Hellwig   [XFS] Delay I/O c...
265
  	ioend->io_buffer_head = NULL;
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
266
  	ioend->io_buffer_tail = NULL;
0829c3602   Christoph Hellwig   [XFS] Add infrast...
267
268
  	ioend->io_offset = 0;
  	ioend->io_size = 0;
fb511f215   Christoph Hellwig   xfs: move aio com...
269
270
  	ioend->io_iocb = NULL;
  	ioend->io_result = 0;
0829c3602   Christoph Hellwig   [XFS] Add infrast...
271

5ec4fabb0   Christoph Hellwig   xfs: cleanup data...
272
  	INIT_WORK(&ioend->io_work, xfs_end_io);
0829c3602   Christoph Hellwig   [XFS] Add infrast...
273
274
  	return ioend;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
276
277
278
  STATIC int
  xfs_map_blocks(
  	struct inode		*inode,
  	loff_t			offset,
207d04160   Christoph Hellwig   xfs: kill struct ...
279
  	struct xfs_bmbt_irec	*imap,
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
280
281
  	int			type,
  	int			nonblocking)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
  {
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
283
284
  	struct xfs_inode	*ip = XFS_I(inode);
  	struct xfs_mount	*mp = ip->i_mount;
ed1e7b7e4   Christoph Hellwig   xfs: remove xfs_p...
285
  	ssize_t			count = 1 << inode->i_blkbits;
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
286
287
  	xfs_fileoff_t		offset_fsb, end_fsb;
  	int			error = 0;
a206c817c   Christoph Hellwig   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   Christoph Hellwig   xfs: simplify xfs...
293
  	if (type == IO_UNWRITTEN)
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
294
  		bmapi_flags |= XFS_BMAPI_IGSTATE;
8ff2957d5   Christoph Hellwig   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   Christoph Hellwig   xfs: kill xfs_iomap
300
  	}
8ff2957d5   Christoph Hellwig   xfs: simplify xfs...
301
302
  	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
  	       (ip->i_df.if_flags & XFS_IFEXTENTS));
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
303
  	ASSERT(offset <= mp->m_maxioffset);
8ff2957d5   Christoph Hellwig   xfs: simplify xfs...
304

a206c817c   Christoph Hellwig   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   Dave Chinner   xfs: introduce xf...
309
310
  	error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
  				imap, &nimaps, bmapi_flags);
8ff2957d5   Christoph Hellwig   xfs: simplify xfs...
311
  	xfs_iunlock(ip, XFS_ILOCK_SHARED);
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
312

8ff2957d5   Christoph Hellwig   xfs: simplify xfs...
313
314
  	if (error)
  		return -XFS_ERROR(error);
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
315

8ff2957d5   Christoph Hellwig   xfs: simplify xfs...
316
317
  	if (type == IO_DELALLOC &&
  	    (!nimaps || isnullstartblock(imap->br_startblock))) {
a206c817c   Christoph Hellwig   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   Christoph Hellwig   xfs: simplify xfs...
321
  		return -XFS_ERROR(error);
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
322
  	}
8ff2957d5   Christoph Hellwig   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   Linus Torvalds   Linux-2.6.12-rc2
333
  }
b8f82a4a6   Christoph Hellwig   xfs: kill the STA...
334
  STATIC int
558e68916   Christoph Hellwig   xfs: clean up xfs...
335
  xfs_imap_valid(
8699bb0a4   Christoph Hellwig   xfs: report iomap...
336
  	struct inode		*inode,
207d04160   Christoph Hellwig   xfs: kill struct ...
337
  	struct xfs_bmbt_irec	*imap,
558e68916   Christoph Hellwig   xfs: clean up xfs...
338
  	xfs_off_t		offset)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  {
558e68916   Christoph Hellwig   xfs: clean up xfs...
340
  	offset >>= inode->i_blkbits;
8699bb0a4   Christoph Hellwig   xfs: report iomap...
341

558e68916   Christoph Hellwig   xfs: clean up xfs...
342
343
  	return offset >= imap->br_startoff &&
  		offset < imap->br_startoff + imap->br_blockcount;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
  }
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
345
346
347
  /*
   * BIO completion handler for buffered IO.
   */
782e3b3b3   Al Viro   Fix up more bio f...
348
  STATIC void
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
349
350
  xfs_end_bio(
  	struct bio		*bio,
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
351
352
353
  	int			error)
  {
  	xfs_ioend_t		*ioend = bio->bi_private;
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
354
  	ASSERT(atomic_read(&bio->bi_cnt) >= 1);
7d04a335b   Nathan Scott   [XFS] Shutdown th...
355
  	ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error;
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
356
357
  
  	/* Toss bio and pass work off to an xfsdatad thread */
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
358
359
  	bio->bi_private = NULL;
  	bio->bi_end_io = NULL;
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
360
  	bio_put(bio);
7d04a335b   Nathan Scott   [XFS] Shutdown th...
361

209fb87a2   Christoph Hellwig   xfs simplify and ...
362
  	xfs_finish_ioend(ioend);
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
363
364
365
366
  }
  
  STATIC void
  xfs_submit_ioend_bio(
06342cf8a   Christoph Hellwig   xfs: use WRITE_SY...
367
368
369
  	struct writeback_control *wbc,
  	xfs_ioend_t		*ioend,
  	struct bio		*bio)
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
370
371
  {
  	atomic_inc(&ioend->io_remaining);
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
372
373
  	bio->bi_private = ioend;
  	bio->bi_end_io = xfs_end_bio;
932640e8a   Dave Chinner   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   Christoph Hellwig   xfs: implement op...
379
  		xfs_mark_inode_dirty(XFS_I(ioend->io_inode));
932640e8a   Dave Chinner   xfs: mark inodes ...
380

721a9602e   Jens Axboe   block: kill off R...
381
  	submit_bio(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE, bio);
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
382
383
384
385
386
387
  }
  
  STATIC struct bio *
  xfs_alloc_ioend_bio(
  	struct buffer_head	*bh)
  {
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
388
  	int			nvecs = bio_get_nr_vecs(bh->b_bdev);
221cb2517   Christoph Hellwig   xfs: remove some ...
389
  	struct bio		*bio = bio_alloc(GFP_NOIO, nvecs);
f6d6d4fcd   Christoph Hellwig   [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   Christoph Hellwig   [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   Christoph Hellwig   [XFS] Initial pas...
414
415
416
417
418
  	int			clear_dirty,
  	int			buffers)
  {
  	ASSERT(PageLocked(page));
  	ASSERT(!PageWriteback(page));
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
419
  	if (clear_dirty)
921320210   David Chinner   [PATCH] Fix XFS a...
420
421
  		clear_page_dirty_for_io(page);
  	set_page_writeback(page);
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
422
  	unlock_page(page);
1f7decf6d   Fengguang Wu   writeback: remove...
423
424
  	/* If no buffers on the page are to be written, finish it here */
  	if (!buffers)
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
425
  		end_page_writeback(page);
f6d6d4fcd   Christoph Hellwig   [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   David Chinner   [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   Nathan Scott   [XFS] We really s...
448
   * buffer_heads, and then submit them for I/O on the second pass.
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
449
450
451
   */
  STATIC void
  xfs_submit_ioend(
06342cf8a   Christoph Hellwig   xfs: use WRITE_SY...
452
  	struct writeback_control *wbc,
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
453
454
  	xfs_ioend_t		*ioend)
  {
d88992f66   David Chinner   [XFS] Fix a race ...
455
  	xfs_ioend_t		*head = ioend;
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
456
457
458
459
  	xfs_ioend_t		*next;
  	struct buffer_head	*bh;
  	struct bio		*bio;
  	sector_t		lastblock = 0;
d88992f66   David Chinner   [XFS] Fix a race ...
460
461
462
  	/* Pass 1 - start writeback */
  	do {
  		next = ioend->io_list;
221cb2517   Christoph Hellwig   xfs: remove some ...
463
  		for (bh = ioend->io_buffer_head; bh; bh = bh->b_private)
d88992f66   David Chinner   [XFS] Fix a race ...
464
  			xfs_start_buffer_writeback(bh);
d88992f66   David Chinner   [XFS] Fix a race ...
465
466
467
468
  	} while ((ioend = next) != NULL);
  
  	/* Pass 2 - submit I/O */
  	ioend = head;
f6d6d4fcd   Christoph Hellwig   [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   Christoph Hellwig   [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   Christoph Hellwig   xfs: use WRITE_SY...
479
  				xfs_submit_ioend_bio(wbc, ioend, bio);
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
480
481
482
483
  				goto retry;
  			}
  
  			if (bio_add_buffer(bio, bh) != bh->b_size) {
06342cf8a   Christoph Hellwig   xfs: use WRITE_SY...
484
  				xfs_submit_ioend_bio(wbc, ioend, bio);
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
485
486
487
488
489
490
  				goto retry;
  			}
  
  			lastblock = bh->b_blocknr;
  		}
  		if (bio)
06342cf8a   Christoph Hellwig   xfs: use WRITE_SY...
491
  			xfs_submit_ioend_bio(wbc, ioend, bio);
209fb87a2   Christoph Hellwig   xfs simplify and ...
492
  		xfs_finish_ioend(ioend);
f6d6d4fcd   Christoph Hellwig   [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   Christoph Hellwig   [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   Christoph Hellwig   [XFS] pass full 6...
530
  	xfs_off_t		offset,
f6d6d4fcd   Christoph Hellwig   [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   Christoph Hellwig   [XFS] Initial pas...
539

f6d6d4fcd   Christoph Hellwig   [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   Linus Torvalds   Linux-2.6.12-rc2
555
  STATIC void
87cbc49cd   Nathan Scott   [XFS] Add xfs_map...
556
  xfs_map_buffer(
046f1685b   Christoph Hellwig   xfs: remove iomap...
557
  	struct inode		*inode,
87cbc49cd   Nathan Scott   [XFS] Add xfs_map...
558
  	struct buffer_head	*bh,
207d04160   Christoph Hellwig   xfs: kill struct ...
559
  	struct xfs_bmbt_irec	*imap,
046f1685b   Christoph Hellwig   xfs: remove iomap...
560
  	xfs_off_t		offset)
87cbc49cd   Nathan Scott   [XFS] Add xfs_map...
561
562
  {
  	sector_t		bn;
8699bb0a4   Christoph Hellwig   xfs: report iomap...
563
  	struct xfs_mount	*m = XFS_I(inode)->i_mount;
207d04160   Christoph Hellwig   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   Nathan Scott   [XFS] Add xfs_map...
566

207d04160   Christoph Hellwig   xfs: kill struct ...
567
568
  	ASSERT(imap->br_startblock != HOLESTARTBLOCK);
  	ASSERT(imap->br_startblock != DELAYSTARTBLOCK);
87cbc49cd   Nathan Scott   [XFS] Add xfs_map...
569

e513182d4   Christoph Hellwig   xfs: report iomap...
570
  	bn = (iomap_bn >> (inode->i_blkbits - BBSHIFT)) +
8699bb0a4   Christoph Hellwig   xfs: report iomap...
571
  	      ((offset - iomap_offset) >> inode->i_blkbits);
87cbc49cd   Nathan Scott   [XFS] Add xfs_map...
572

046f1685b   Christoph Hellwig   xfs: remove iomap...
573
  	ASSERT(bn || XFS_IS_REALTIME_INODE(XFS_I(inode)));
87cbc49cd   Nathan Scott   [XFS] Add xfs_map...
574
575
576
577
578
579
  
  	bh->b_blocknr = bn;
  	set_buffer_mapped(bh);
  }
  
  STATIC void
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  xfs_map_at_offset(
046f1685b   Christoph Hellwig   xfs: remove iomap...
581
  	struct inode		*inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
  	struct buffer_head	*bh,
207d04160   Christoph Hellwig   xfs: kill struct ...
583
  	struct xfs_bmbt_irec	*imap,
046f1685b   Christoph Hellwig   xfs: remove iomap...
584
  	xfs_off_t		offset)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
  {
207d04160   Christoph Hellwig   xfs: kill struct ...
586
587
  	ASSERT(imap->br_startblock != HOLESTARTBLOCK);
  	ASSERT(imap->br_startblock != DELAYSTARTBLOCK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588

207d04160   Christoph Hellwig   xfs: kill struct ...
589
  	xfs_map_buffer(inode, bh, imap, offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
591
  	set_buffer_mapped(bh);
  	clear_buffer_delay(bh);
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
592
  	clear_buffer_unwritten(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
594
595
  }
  
  /*
10ce44442   Christoph Hellwig   [XFS] use pagevec...
596
597
   * Test if a given page is suitable for writing as part of an unwritten
   * or delayed allocate extent.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
   */
10ce44442   Christoph Hellwig   [XFS] use pagevec...
599
600
601
  STATIC int
  xfs_is_delayed_page(
  	struct page		*page,
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
602
  	unsigned int		type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
  	if (PageWriteback(page))
10ce44442   Christoph Hellwig   [XFS] use pagevec...
605
  		return 0;
1da177e4c   Linus Torvalds   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   Christoph Hellwig   [XFS] Initial pas...
613
  			if (buffer_unwritten(bh))
34a52c6c0   Christoph Hellwig   xfs: move I/O typ...
614
  				acceptable = (type == IO_UNWRITTEN);
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
615
  			else if (buffer_delay(bh))
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
616
  				acceptable = (type == IO_DELALLOC);
2ddee844e   David Chinner   [XFS] Check that ...
617
  			else if (buffer_dirty(bh) && buffer_mapped(bh))
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
618
  				acceptable = (type == IO_OVERWRITE);
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
619
  			else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
620
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
621
622
623
  		} while ((bh = bh->b_this_page) != head);
  
  		if (acceptable)
10ce44442   Christoph Hellwig   [XFS] use pagevec...
624
  			return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
  	}
10ce44442   Christoph Hellwig   [XFS] use pagevec...
626
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
  }
1da177e4c   Linus Torvalds   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   Christoph Hellwig   [XFS] Initial pas...
634
  STATIC int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
636
637
  xfs_convert_page(
  	struct inode		*inode,
  	struct page		*page,
10ce44442   Christoph Hellwig   [XFS] use pagevec...
638
  	loff_t			tindex,
207d04160   Christoph Hellwig   xfs: kill struct ...
639
  	struct xfs_bmbt_irec	*imap,
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
640
  	xfs_ioend_t		**ioendp,
2fa24f925   Christoph Hellwig   xfs: remove the a...
641
  	struct writeback_control *wbc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
  {
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
643
  	struct buffer_head	*bh, *head;
9260dc6b2   Christoph Hellwig   [XFS] various fix...
644
645
  	xfs_off_t		end_offset;
  	unsigned long		p_offset;
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
646
  	unsigned int		type;
24e17b5fb   Nathan Scott   [XFS] Use the rig...
647
  	int			len, page_dirty;
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
648
  	int			count = 0, done = 0, uptodate = 1;
9260dc6b2   Christoph Hellwig   [XFS] various fix...
649
   	xfs_off_t		offset = page_offset(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650

10ce44442   Christoph Hellwig   [XFS] use pagevec...
651
652
  	if (page->index != tindex)
  		goto fail;
529ae9aaa   Nick Piggin   mm: rename page t...
653
  	if (!trylock_page(page))
10ce44442   Christoph Hellwig   [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   Nathan Scott   [XFS] Use the rig...
661
662
  	/*
  	 * page_dirty is initially a count of buffers on the page before
c41564b5a   Nathan Scott   [XFS] We really s...
663
  	 * EOF and is decremented as we move each into a cleanable state.
9260dc6b2   Christoph Hellwig   [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   Nathan Scott   [XFS] Use the rig...
673
  	 */
9260dc6b2   Christoph Hellwig   [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   Nathan Scott   [XFS] Use the rig...
677
  	len = 1 << inode->i_blkbits;
9260dc6b2   Christoph Hellwig   [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   Nathan Scott   [XFS] Use the rig...
682

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683
684
  	bh = head = page_buffers(page);
  	do {
9260dc6b2   Christoph Hellwig   [XFS] various fix...
685
  		if (offset >= end_offset)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
  			break;
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
687
688
689
690
  		if (!buffer_uptodate(bh))
  			uptodate = 0;
  		if (!(PageUptodate(page) || buffer_uptodate(bh))) {
  			done = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
  			continue;
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
692
  		}
2fa24f925   Christoph Hellwig   xfs: remove the a...
693
694
  		if (buffer_unwritten(bh) || buffer_delay(bh) ||
  		    buffer_mapped(bh)) {
9260dc6b2   Christoph Hellwig   [XFS] various fix...
695
  			if (buffer_unwritten(bh))
34a52c6c0   Christoph Hellwig   xfs: move I/O typ...
696
  				type = IO_UNWRITTEN;
2fa24f925   Christoph Hellwig   xfs: remove the a...
697
  			else if (buffer_delay(bh))
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
698
  				type = IO_DELALLOC;
2fa24f925   Christoph Hellwig   xfs: remove the a...
699
700
  			else
  				type = IO_OVERWRITE;
9260dc6b2   Christoph Hellwig   [XFS] various fix...
701

558e68916   Christoph Hellwig   xfs: clean up xfs...
702
  			if (!xfs_imap_valid(inode, imap, offset)) {
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
703
  				done = 1;
9260dc6b2   Christoph Hellwig   [XFS] various fix...
704
705
  				continue;
  			}
ecff71e67   Christoph Hellwig   xfs: simplify xfs...
706
707
  			lock_buffer(bh);
  			if (type != IO_OVERWRITE)
2fa24f925   Christoph Hellwig   xfs: remove the a...
708
  				xfs_map_at_offset(inode, bh, imap, offset);
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
709
710
  			xfs_add_to_ioend(inode, bh, offset, type,
  					 ioendp, done);
9260dc6b2   Christoph Hellwig   [XFS] various fix...
711
712
713
  			page_dirty--;
  			count++;
  		} else {
2fa24f925   Christoph Hellwig   xfs: remove the a...
714
  			done = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
  		}
7336cea8c   Christoph Hellwig   [XFS] pass full 6...
716
  	} while (offset += len, (bh = bh->b_this_page) != head);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717

f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
718
719
  	if (uptodate && bh == head)
  		SetPageUptodate(page);
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
720
  	if (count) {
efceab1d5   Dave Chinner   xfs: handle negat...
721
722
  		if (--wbc->nr_to_write <= 0 &&
  		    wbc->sync_mode == WB_SYNC_NONE)
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
723
  			done = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724
  	}
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
725
  	xfs_start_page_writeback(page, !page_dirty, count);
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
726
727
  
  	return done;
10ce44442   Christoph Hellwig   [XFS] use pagevec...
728
729
730
731
   fail_unlock_page:
  	unlock_page(page);
   fail:
  	return 1;
1da177e4c   Linus Torvalds   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   Christoph Hellwig   xfs: kill struct ...
742
  	struct xfs_bmbt_irec	*imap,
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
743
  	xfs_ioend_t		**ioendp,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
  	struct writeback_control *wbc,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
746
  	pgoff_t			tlast)
  {
10ce44442   Christoph Hellwig   [XFS] use pagevec...
747
748
  	struct pagevec		pvec;
  	int			done = 0, i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749

10ce44442   Christoph Hellwig   [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   Linus Torvalds   Linux-2.6.12-rc2
755
  			break;
10ce44442   Christoph Hellwig   [XFS] use pagevec...
756
757
758
  
  		for (i = 0; i < pagevec_count(&pvec); i++) {
  			done = xfs_convert_page(inode, pvec.pages[i], tindex++,
2fa24f925   Christoph Hellwig   xfs: remove the a...
759
  					imap, ioendp, wbc);
10ce44442   Christoph Hellwig   [XFS] use pagevec...
760
761
762
763
764
765
  			if (done)
  				break;
  		}
  
  		pagevec_release(&pvec);
  		cond_resched();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
766
767
  	}
  }
3ed3a4343   Dave Chinner   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   Dave Chinner   xfs: truncate del...
801

a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
802
  	if (!xfs_is_delayed_page(page, IO_DELALLOC))
3ed3a4343   Dave Chinner   xfs: truncate del...
803
  		goto out_invalidate;
e8c3753ce   Dave Chinner   xfs: don't warn a...
804
805
  	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
  		goto out_invalidate;
4f10700a2   Dave Chinner   xfs: Convert linu...
806
  	xfs_alert(ip->i_mount,
3ed3a4343   Dave Chinner   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   Dave Chinner   xfs: truncate del...
813
  		int		error;
c726de440   Dave Chinner   xfs: fix failed w...
814
  		xfs_fileoff_t	start_fsb;
3ed3a4343   Dave Chinner   xfs: truncate del...
815
816
817
  
  		if (!buffer_delay(bh))
  			goto next_buffer;
c726de440   Dave Chinner   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   Dave Chinner   xfs: truncate del...
820
821
  		if (error) {
  			/* something screwed, just bail */
e8c3753ce   Dave Chinner   xfs: don't warn a...
822
  			if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
4f10700a2   Dave Chinner   xfs: Convert linu...
823
  				xfs_alert(ip->i_mount,
3ed3a4343   Dave Chinner   xfs: truncate del...
824
  			"page discard unable to remove delalloc mapping.");
e8c3753ce   Dave Chinner   xfs: don't warn a...
825
  			}
3ed3a4343   Dave Chinner   xfs: truncate del...
826
827
828
  			break;
  		}
  next_buffer:
c726de440   Dave Chinner   xfs: fix failed w...
829
  		offset += 1 << inode->i_blkbits;
3ed3a4343   Dave Chinner   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   Linus Torvalds   Linux-2.6.12-rc2
838
  /*
89f3b3639   Christoph Hellwig   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   Christoph Hellwig   xfs: simplify xfs...
844
   * For any other dirty buffer heads on the page we should flush them.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846
  STATIC int
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
847
848
849
  xfs_vm_writepage(
  	struct page		*page,
  	struct writeback_control *wbc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
850
  {
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
851
  	struct inode		*inode = page->mapping->host;
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
852
  	struct buffer_head	*bh, *head;
207d04160   Christoph Hellwig   xfs: kill struct ...
853
  	struct xfs_bmbt_irec	imap;
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
854
  	xfs_ioend_t		*ioend = NULL, *iohead = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
  	loff_t			offset;
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
856
  	unsigned int		type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
857
  	__uint64_t              end_offset;
bd1556a14   Christoph Hellwig   xfs: clean up end...
858
  	pgoff_t                 end_index, last_index;
ed1e7b7e4   Christoph Hellwig   xfs: remove xfs_p...
859
  	ssize_t			len;
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
860
  	int			err, imap_valid = 0, uptodate = 1;
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
861
  	int			count = 0;
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
862
  	int			nonblocking = 0;
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
863
864
  
  	trace_xfs_writepage(inode, page, 0);
20cb52ebd   Christoph Hellwig   xfs: simplify xfs...
865
  	ASSERT(page_has_buffers(page));
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
866
867
868
  	/*
  	 * Refuse to write the page out if we are called from reclaim context.
  	 *
d4f7a5cbd   Christoph Hellwig   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   Christoph Hellwig   xfs: simplify xfs...
872
  	 *
94054fa3f   Mel Gorman   xfs: warn if dire...
873
874
  	 * This should never happen except in the case of a VM regression so
  	 * warn about it.
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
875
  	 */
94054fa3f   Mel Gorman   xfs: warn if dire...
876
877
  	if (WARN_ON_ONCE((current->flags & (PF_MEMALLOC|PF_KSWAPD)) ==
  			PF_MEMALLOC))
b5420f235   Christoph Hellwig   xfs: do not disca...
878
  		goto redirty;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879

89f3b3639   Christoph Hellwig   xfs: simplify xfs...
880
  	/*
680a647b4   Christoph Hellwig   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   Christoph Hellwig   xfs: simplify xfs...
883
  	 */
680a647b4   Christoph Hellwig   xfs: PF_FSTRANS s...
884
  	if (WARN_ON(current->flags & PF_FSTRANS))
b5420f235   Christoph Hellwig   xfs: do not disca...
885
  		goto redirty;
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
886

1da177e4c   Linus Torvalds   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   Christoph Hellwig   xfs: simplify xfs...
894
  			unlock_page(page);
19d5bcf37   Nathan Scott   [XFS] Ensure fsyn...
895
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
896
897
  		}
  	}
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
898
  	end_offset = min_t(unsigned long long,
20cb52ebd   Christoph Hellwig   xfs: simplify xfs...
899
900
  			(xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT,
  			offset);
24e17b5fb   Nathan Scott   [XFS] Use the rig...
901
  	len = 1 << inode->i_blkbits;
24e17b5fb   Nathan Scott   [XFS] Use the rig...
902

24e17b5fb   Nathan Scott   [XFS] Use the rig...
903
  	bh = head = page_buffers(page);
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
904
  	offset = page_offset(page);
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
905
  	type = IO_OVERWRITE;
dbcdde3e7   Christoph Hellwig   xfs: re-enable no...
906
  	if (wbc->sync_mode == WB_SYNC_NONE)
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
907
  		nonblocking = 1;
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
908

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
909
  	do {
6ac7248ec   Christoph Hellwig   xfs: a few small ...
910
  		int new_ioend = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
911
912
913
914
  		if (offset >= end_offset)
  			break;
  		if (!buffer_uptodate(bh))
  			uptodate = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
915

3d9b02e3c   Eric Sandeen   xfs: fix corrupti...
916
  		/*
ece413f59   Christoph Hellwig   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   Eric Sandeen   xfs: fix corrupti...
921
922
  		 */
  		if (!buffer_mapped(bh) && buffer_uptodate(bh)) {
3d9b02e3c   Eric Sandeen   xfs: fix corrupti...
923
924
925
  			imap_valid = 0;
  			continue;
  		}
aeea1b1f8   Christoph Hellwig   xfs: refactor xfs...
926
927
928
929
  		if (buffer_unwritten(bh)) {
  			if (type != IO_UNWRITTEN) {
  				type = IO_UNWRITTEN;
  				imap_valid = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
  			}
aeea1b1f8   Christoph Hellwig   xfs: refactor xfs...
931
932
933
934
  		} else if (buffer_delay(bh)) {
  			if (type != IO_DELALLOC) {
  				type = IO_DELALLOC;
  				imap_valid = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
935
  			}
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
936
  		} else if (buffer_uptodate(bh)) {
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
937
938
  			if (type != IO_OVERWRITE) {
  				type = IO_OVERWRITE;
85da94c6b   Christoph Hellwig   xfs: improve mapp...
939
940
  				imap_valid = 0;
  			}
aeea1b1f8   Christoph Hellwig   xfs: refactor xfs...
941
942
943
944
  		} else {
  			if (PageUptodate(page)) {
  				ASSERT(buffer_mapped(bh));
  				imap_valid = 0;
6c4fe19f6   Christoph Hellwig   [XFS] cluster rew...
945
  			}
aeea1b1f8   Christoph Hellwig   xfs: refactor xfs...
946
947
  			continue;
  		}
d5cb48aaa   Christoph Hellwig   [XFS] consolidate...
948

aeea1b1f8   Christoph Hellwig   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   Christoph Hellwig   xfs: simplify xfs...
968
969
  			lock_buffer(bh);
  			if (type != IO_OVERWRITE)
aeea1b1f8   Christoph Hellwig   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   Linus Torvalds   Linux-2.6.12-rc2
974
  		}
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
975
976
977
978
979
  
  		if (!iohead)
  			iohead = ioend;
  
  	} while (offset += len, ((bh = bh->b_this_page) != head));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
982
  
  	if (uptodate && bh == head)
  		SetPageUptodate(page);
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
983
  	xfs_start_page_writeback(page, 1, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
984

558e68916   Christoph Hellwig   xfs: clean up xfs...
985
  	if (ioend && imap_valid) {
bd1556a14   Christoph Hellwig   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   Christoph Hellwig   xfs: report iomap...
999

207d04160   Christoph Hellwig   xfs: kill struct ...
1000
  		xfs_cluster_write(inode, page->index + 1, &imap, &ioend,
2fa24f925   Christoph Hellwig   xfs: remove the a...
1001
  				  wbc, end_index);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1002
  	}
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
1003
  	if (iohead)
06342cf8a   Christoph Hellwig   xfs: use WRITE_SY...
1004
  		xfs_submit_ioend(wbc, iohead);
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
1005

89f3b3639   Christoph Hellwig   xfs: simplify xfs...
1006
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1007
1008
  
  error:
f6d6d4fcd   Christoph Hellwig   [XFS] Initial pas...
1009
1010
  	if (iohead)
  		xfs_cancel_ioend(iohead);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1011

b5420f235   Christoph Hellwig   xfs: do not disca...
1012
1013
  	if (err == -EAGAIN)
  		goto redirty;
20cb52ebd   Christoph Hellwig   xfs: simplify xfs...
1014
  	xfs_aops_discard_page(page);
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
1015
1016
  	ClearPageUptodate(page);
  	unlock_page(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1017
  	return err;
f51623b21   Nathan Scott   [XFS] Move some c...
1018

b5420f235   Christoph Hellwig   xfs: do not disca...
1019
  redirty:
f51623b21   Nathan Scott   [XFS] Move some c...
1020
1021
1022
  	redirty_page_for_writepage(wbc, page);
  	unlock_page(page);
  	return 0;
f51623b21   Nathan Scott   [XFS] Move some c...
1023
  }
7d4fb40ad   Nathan Scott   [XFS] Start write...
1024
1025
1026
1027
1028
  STATIC int
  xfs_vm_writepages(
  	struct address_space	*mapping,
  	struct writeback_control *wbc)
  {
b3aea4edc   Christoph Hellwig   [XFS] kill the v_...
1029
  	xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);
7d4fb40ad   Nathan Scott   [XFS] Start write...
1030
1031
  	return generic_writepages(mapping, wbc);
  }
f51623b21   Nathan Scott   [XFS] Move some c...
1032
1033
  /*
   * Called to move a page into cleanable state - and from there
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
1034
   * to be released. The page should already be clean. We always
f51623b21   Nathan Scott   [XFS] Move some c...
1035
1036
   * have buffer heads in this call.
   *
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
1037
   * Returns 1 if the page is ok to release, 0 otherwise.
f51623b21   Nathan Scott   [XFS] Move some c...
1038
1039
   */
  STATIC int
238f4c546   Nathan Scott   [XFS] Make couple...
1040
  xfs_vm_releasepage(
f51623b21   Nathan Scott   [XFS] Move some c...
1041
1042
1043
  	struct page		*page,
  	gfp_t			gfp_mask)
  {
20cb52ebd   Christoph Hellwig   xfs: simplify xfs...
1044
  	int			delalloc, unwritten;
f51623b21   Nathan Scott   [XFS] Move some c...
1045

89f3b3639   Christoph Hellwig   xfs: simplify xfs...
1046
  	trace_xfs_releasepage(page->mapping->host, page, 0);
238f4c546   Nathan Scott   [XFS] Make couple...
1047

20cb52ebd   Christoph Hellwig   xfs: simplify xfs...
1048
  	xfs_count_page_state(page, &delalloc, &unwritten);
f51623b21   Nathan Scott   [XFS] Move some c...
1049

89f3b3639   Christoph Hellwig   xfs: simplify xfs...
1050
  	if (WARN_ON(delalloc))
f51623b21   Nathan Scott   [XFS] Move some c...
1051
  		return 0;
89f3b3639   Christoph Hellwig   xfs: simplify xfs...
1052
  	if (WARN_ON(unwritten))
f51623b21   Nathan Scott   [XFS] Move some c...
1053
  		return 0;
f51623b21   Nathan Scott   [XFS] Move some c...
1054
1055
  	return try_to_free_buffers(page);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1056
  STATIC int
c25366680   Nathan Scott   [XFS] Cleanup in ...
1057
  __xfs_get_blocks(
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1058
1059
  	struct inode		*inode,
  	sector_t		iblock,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1060
1061
  	struct buffer_head	*bh_result,
  	int			create,
f2bde9b89   Christoph Hellwig   xfs: small cleanu...
1062
  	int			direct)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1063
  {
a206c817c   Christoph Hellwig   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   Christoph Hellwig   xfs: kill struct ...
1069
  	struct xfs_bmbt_irec	imap;
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
1070
  	int			nimaps = 1;
fdc7ed75c   Nathan Scott   [XFS] Fix boundar...
1071
1072
  	xfs_off_t		offset;
  	ssize_t			size;
207d04160   Christoph Hellwig   xfs: kill struct ...
1073
  	int			new = 0;
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
1074
1075
1076
  
  	if (XFS_FORCED_SHUTDOWN(mp))
  		return -XFS_ERROR(EIO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1077

fdc7ed75c   Nathan Scott   [XFS] Fix boundar...
1078
  	offset = (xfs_off_t)iblock << inode->i_blkbits;
c25366680   Nathan Scott   [XFS] Cleanup in ...
1079
1080
  	ASSERT(bh_result->b_size >= (1 << inode->i_blkbits));
  	size = bh_result->b_size;
364f358a7   Lachlan McIlroy   [XFS] Prevent dir...
1081
1082
1083
  
  	if (!create && direct && offset >= i_size_read(inode))
  		return 0;
a206c817c   Christoph Hellwig   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   Christoph Hellwig   xfs: small cleanu...
1090

a206c817c   Christoph Hellwig   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   Dave Chinner   xfs: introduce xf...
1096
1097
  	error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
  				&imap, &nimaps, XFS_BMAPI_ENTIRE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1098
  	if (error)
a206c817c   Christoph Hellwig   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   Linus Torvalds   Linux-2.6.12-rc2
1122

207d04160   Christoph Hellwig   xfs: kill struct ...
1123
1124
  	if (imap.br_startblock != HOLESTARTBLOCK &&
  	    imap.br_startblock != DELAYSTARTBLOCK) {
87cbc49cd   Nathan Scott   [XFS] Add xfs_map...
1125
1126
  		/*
  		 * For unwritten extents do not report a disk address on
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1127
1128
  		 * the read case (treat as if we're reading into a hole).
  		 */
207d04160   Christoph Hellwig   xfs: kill struct ...
1129
1130
1131
  		if (create || !ISUNWRITTEN(&imap))
  			xfs_map_buffer(inode, bh_result, &imap, offset);
  		if (create && ISUNWRITTEN(&imap)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1132
1133
1134
  			if (direct)
  				bh_result->b_private = inode;
  			set_buffer_unwritten(bh_result);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135
1136
  		}
  	}
c25366680   Nathan Scott   [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   Christoph Hellwig   xfs: remove iomap...
1141
  	bh_result->b_bdev = xfs_find_bdev_for_inode(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1142

c25366680   Nathan Scott   [XFS] Cleanup in ...
1143
  	/*
549054afa   David Chinner   [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   Linus Torvalds   Linux-2.6.12-rc2
1151
1152
1153
  	 */
  	if (create &&
  	    ((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) ||
549054afa   David Chinner   [XFS] Fix sub-blo...
1154
  	     (offset >= i_size_read(inode)) ||
207d04160   Christoph Hellwig   xfs: kill struct ...
1155
  	     (new || ISUNWRITTEN(&imap))))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1156
  		set_buffer_new(bh_result);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1157

207d04160   Christoph Hellwig   xfs: kill struct ...
1158
  	if (imap.br_startblock == DELAYSTARTBLOCK) {
1da177e4c   Linus Torvalds   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   Christoph Hellwig   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   Nathan Scott   [XFS] Cleanup in ...
1170
  	if (direct || size > (1 << inode->i_blkbits)) {
2b8f12b7e   Christoph Hellwig   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   Linus Torvalds   Linux-2.6.12-rc2
1183
1184
1185
  	}
  
  	return 0;
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
1186
1187
1188
1189
  
  out_unlock:
  	xfs_iunlock(ip, lockmode);
  	return -error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190
1191
1192
  }
  
  int
c25366680   Nathan Scott   [XFS] Cleanup in ...
1193
  xfs_get_blocks(
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1194
1195
1196
1197
1198
  	struct inode		*inode,
  	sector_t		iblock,
  	struct buffer_head	*bh_result,
  	int			create)
  {
f2bde9b89   Christoph Hellwig   xfs: small cleanu...
1199
  	return __xfs_get_blocks(inode, iblock, bh_result, create, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1200
1201
1202
  }
  
  STATIC int
e4c573bb6   Nathan Scott   [XFS] Switch over...
1203
  xfs_get_blocks_direct(
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1204
1205
  	struct inode		*inode,
  	sector_t		iblock,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1206
1207
1208
  	struct buffer_head	*bh_result,
  	int			create)
  {
f2bde9b89   Christoph Hellwig   xfs: small cleanu...
1209
  	return __xfs_get_blocks(inode, iblock, bh_result, create, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1210
  }
209fb87a2   Christoph Hellwig   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   Lucas De Marchi   Fix common misspe...
1217
   * to do this and we are done.  But in case this was a successful AIO
209fb87a2   Christoph Hellwig   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   Christoph Hellwig   [XFS] Delay direc...
1222
  STATIC void
209fb87a2   Christoph Hellwig   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   Christoph Hellwig   [XFS] Delay direc...
1230
  {
209fb87a2   Christoph Hellwig   xfs simplify and ...
1231
  	struct xfs_ioend	*ioend = iocb->private;
f09738638   Christoph Hellwig   [XFS] Delay direc...
1232
1233
  
  	/*
209fb87a2   Christoph Hellwig   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   Christoph Hellwig   [XFS] Delay direc...
1237
  	 */
209fb87a2   Christoph Hellwig   xfs simplify and ...
1238
  	iocb->private = NULL;
ba87ea699   Lachlan McIlroy   [XFS] Fix to prev...
1239
1240
  	ioend->io_offset = offset;
  	ioend->io_size = size;
c859cdd1d   Christoph Hellwig   xfs: defer AIO/DI...
1241
1242
  	ioend->io_iocb = iocb;
  	ioend->io_result = ret;
209fb87a2   Christoph Hellwig   xfs simplify and ...
1243
1244
1245
1246
  	if (private && size > 0)
  		ioend->io_type = IO_UNWRITTEN;
  
  	if (is_async) {
c859cdd1d   Christoph Hellwig   xfs: defer AIO/DI...
1247
  		ioend->io_isasync = 1;
209fb87a2   Christoph Hellwig   xfs simplify and ...
1248
  		xfs_finish_ioend(ioend);
f09738638   Christoph Hellwig   [XFS] Delay direc...
1249
  	} else {
209fb87a2   Christoph Hellwig   xfs simplify and ...
1250
  		xfs_finish_ioend_sync(ioend);
f09738638   Christoph Hellwig   [XFS] Delay direc...
1251
  	}
f09738638   Christoph Hellwig   [XFS] Delay direc...
1252
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1253
  STATIC ssize_t
e4c573bb6   Nathan Scott   [XFS] Switch over...
1254
  xfs_vm_direct_IO(
1da177e4c   Linus Torvalds   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   Christoph Hellwig   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   Christoph Hellwig   xfs: kill xfs_iomap
1266
  		iocb->private = xfs_alloc_ioend(inode, IO_DIRECT);
209fb87a2   Christoph Hellwig   xfs simplify and ...
1267

eafdc7d19   Christoph Hellwig   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   Christoph Hellwig   xfs simplify and ...
1272
1273
1274
  		if (ret != -EIOCBQUEUED && iocb->private)
  			xfs_destroy_ioend(iocb->private);
  	} else {
eafdc7d19   Christoph Hellwig   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   Christoph Hellwig   xfs simplify and ...
1279
  	}
f09738638   Christoph Hellwig   [XFS] Delay direc...
1280

f09738638   Christoph Hellwig   [XFS] Delay direc...
1281
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1282
  }
fa9b227e9   Christoph Hellwig   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   Dave Chinner   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   Dave Chinner   xfs: Convert linu...
1321
  				xfs_alert(ip->i_mount,
c726de440   Dave Chinner   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   Christoph Hellwig   xfs: new truncate...
1327
1328
  	}
  }
f51623b21   Nathan Scott   [XFS] Move some c...
1329
  STATIC int
d79689c70   Nick Piggin   xfs: convert to n...
1330
  xfs_vm_write_begin(
f51623b21   Nathan Scott   [XFS] Move some c...
1331
  	struct file		*file,
d79689c70   Nick Piggin   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   Nathan Scott   [XFS] Move some c...
1338
  {
155130a4f   Christoph Hellwig   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   Christoph Hellwig   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   Christoph Hellwig   get rid of block_...
1359

fa9b227e9   Christoph Hellwig   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   Christoph Hellwig   get rid of block_...
1363
  	return ret;
f51623b21   Nathan Scott   [XFS] Move some c...
1364
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1365
1366
  
  STATIC sector_t
e4c573bb6   Nathan Scott   [XFS] Switch over...
1367
  xfs_vm_bmap(
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1368
1369
1370
1371
  	struct address_space	*mapping,
  	sector_t		block)
  {
  	struct inode		*inode = (struct inode *)mapping->host;
739bfb2a7   Christoph Hellwig   [XFS] call common...
1372
  	struct xfs_inode	*ip = XFS_I(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1373

cca28fb83   Christoph Hellwig   xfs: split xfs_it...
1374
  	trace_xfs_vm_bmap(XFS_I(inode));
126468b11   Christoph Hellwig   [XFS] kill xfs_rw...
1375
  	xfs_ilock(ip, XFS_IOLOCK_SHARED);
739bfb2a7   Christoph Hellwig   [XFS] call common...
1376
  	xfs_flush_pages(ip, (xfs_off_t)0, -1, 0, FI_REMAPF);
126468b11   Christoph Hellwig   [XFS] kill xfs_rw...
1377
  	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
c25366680   Nathan Scott   [XFS] Cleanup in ...
1378
  	return generic_block_bmap(mapping, block, xfs_get_blocks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1379
1380
1381
  }
  
  STATIC int
e4c573bb6   Nathan Scott   [XFS] Switch over...
1382
  xfs_vm_readpage(
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1383
1384
1385
  	struct file		*unused,
  	struct page		*page)
  {
c25366680   Nathan Scott   [XFS] Cleanup in ...
1386
  	return mpage_readpage(page, xfs_get_blocks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1387
1388
1389
  }
  
  STATIC int
e4c573bb6   Nathan Scott   [XFS] Switch over...
1390
  xfs_vm_readpages(
1da177e4c   Linus Torvalds   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   Nathan Scott   [XFS] Cleanup in ...
1396
  	return mpage_readpages(mapping, pages, nr_pages, xfs_get_blocks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1397
  }
f5e54d6e5   Christoph Hellwig   [PATCH] mark addr...
1398
  const struct address_space_operations xfs_address_space_operations = {
e4c573bb6   Nathan Scott   [XFS] Switch over...
1399
1400
1401
  	.readpage		= xfs_vm_readpage,
  	.readpages		= xfs_vm_readpages,
  	.writepage		= xfs_vm_writepage,
7d4fb40ad   Nathan Scott   [XFS] Start write...
1402
  	.writepages		= xfs_vm_writepages,
238f4c546   Nathan Scott   [XFS] Make couple...
1403
1404
  	.releasepage		= xfs_vm_releasepage,
  	.invalidatepage		= xfs_vm_invalidatepage,
d79689c70   Nick Piggin   xfs: convert to n...
1405
  	.write_begin		= xfs_vm_write_begin,
fa9b227e9   Christoph Hellwig   xfs: new truncate...
1406
  	.write_end		= xfs_vm_write_end,
e4c573bb6   Nathan Scott   [XFS] Switch over...
1407
1408
  	.bmap			= xfs_vm_bmap,
  	.direct_IO		= xfs_vm_direct_IO,
e965f9630   Christoph Lameter   [PATCH] Direct Mi...
1409
  	.migratepage		= buffer_migrate_page,
bddaafa11   Hisashi Hifumi   xfs: pagecache us...
1410
  	.is_partially_uptodate  = block_is_partially_uptodate,
aa261f549   Andi Kleen   HWPOISON: Enable ...
1411
  	.error_remove_page	= generic_error_remove_page,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1412
  };