Blame view

fs/xfs/xfs_iomap.c 33.1 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
3e57ecf64   Olaf Weber   [XFS] Add paramet...
2
   * Copyright (c) 2000-2006 Silicon Graphics, Inc.
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
3
   * Copyright (c) 2016 Christoph Hellwig.
7b7187698   Nathan Scott   [XFS] Update lice...
4
   * All Rights Reserved.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
   *
7b7187698   Nathan Scott   [XFS] Update lice...
6
7
   * 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
8
9
   * published by the Free Software Foundation.
   *
7b7187698   Nathan Scott   [XFS] Update lice...
10
11
12
13
   * 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
14
   *
7b7187698   Nathan Scott   [XFS] Update lice...
15
16
17
   * 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
18
   */
3b3dce052   Christoph Hellwig   xfs: make xfs_bmb...
19
  #include <linux/iomap.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #include "xfs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
  #include "xfs_fs.h"
70a9883c5   Dave Chinner   xfs: create a sha...
22
  #include "xfs_shared.h"
239880ef6   Dave Chinner   xfs: decouple log...
23
24
25
  #include "xfs_format.h"
  #include "xfs_log_format.h"
  #include "xfs_trans_resv.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
  #include "xfs_mount.h"
3ab78df2a   Darrick J. Wong   xfs: rework xfs_b...
27
  #include "xfs_defer.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  #include "xfs_inode.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
29
  #include "xfs_btree.h"
a4fbe6ab1   Dave Chinner   xfs: decouple ino...
30
  #include "xfs_bmap_btree.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
  #include "xfs_bmap.h"
689881145   Dave Chinner   xfs: create xfs_b...
32
  #include "xfs_bmap_util.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
  #include "xfs_error.h"
a4fbe6ab1   Dave Chinner   xfs: decouple ino...
34
  #include "xfs_trans.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  #include "xfs_trans_space.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
  #include "xfs_iomap.h"
0b1b213fc   Christoph Hellwig   xfs: event tracin...
37
  #include "xfs_trace.h"
27b528679   Brian Foster   xfs: add EOFBLOCK...
38
  #include "xfs_icache.h"
a4fbe6ab1   Dave Chinner   xfs: decouple ino...
39
  #include "xfs_quota.h"
76a4202a3   Brian Foster   xfs: add quota-dr...
40
41
  #include "xfs_dquot_item.h"
  #include "xfs_dquot.h"
2a06705cd   Darrick J. Wong   xfs: create delal...
42
  #include "xfs_reflink.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
46
  
  #define XFS_WRITEIO_ALIGN(mp,off)	(((off) >> mp->m_writeio_log) \
  						<< mp->m_writeio_log)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47

e9c497363   Christoph Hellwig   xfs: move xfs_bmb...
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  void
  xfs_bmbt_to_iomap(
  	struct xfs_inode	*ip,
  	struct iomap		*iomap,
  	struct xfs_bmbt_irec	*imap)
  {
  	struct xfs_mount	*mp = ip->i_mount;
  
  	if (imap->br_startblock == HOLESTARTBLOCK) {
  		iomap->blkno = IOMAP_NULL_BLOCK;
  		iomap->type = IOMAP_HOLE;
  	} else if (imap->br_startblock == DELAYSTARTBLOCK) {
  		iomap->blkno = IOMAP_NULL_BLOCK;
  		iomap->type = IOMAP_DELALLOC;
  	} else {
  		iomap->blkno = xfs_fsb_to_db(ip, imap->br_startblock);
  		if (imap->br_state == XFS_EXT_UNWRITTEN)
  			iomap->type = IOMAP_UNWRITTEN;
  		else
  			iomap->type = IOMAP_MAPPED;
  	}
  	iomap->offset = XFS_FSB_TO_B(mp, imap->br_startoff);
  	iomap->length = XFS_FSB_TO_B(mp, imap->br_blockcount);
  	iomap->bdev = xfs_find_bdev_for_inode(VFS_I(ip));
486aff5e0   Dan Williams   xfs: perform dax_...
72
  	iomap->dax_dev = xfs_find_daxdev_for_inode(VFS_I(ip));
e9c497363   Christoph Hellwig   xfs: move xfs_bmb...
73
  }
f7ca35227   Darrick J. Wong   xfs: create a sep...
74
  xfs_extlen_t
f8e3a8257   Christoph Hellwig   xfs: factor our a...
75
76
77
  xfs_eof_alignment(
  	struct xfs_inode	*ip,
  	xfs_extlen_t		extsize)
dd9f438e3   Nathan Scott   [XFS] Implement t...
78
  {
f8e3a8257   Christoph Hellwig   xfs: factor our a...
79
80
  	struct xfs_mount	*mp = ip->i_mount;
  	xfs_extlen_t		align = 0;
dd9f438e3   Nathan Scott   [XFS] Implement t...
81

bf322d983   Christoph Hellwig   xfs: cleanup xfs_...
82
83
84
85
86
87
88
89
90
91
92
93
94
  	if (!XFS_IS_REALTIME_INODE(ip)) {
  		/*
  		 * Round up the allocation request to a stripe unit
  		 * (m_dalign) boundary if the file size is >= stripe unit
  		 * size, and we are allocating past the allocation eof.
  		 *
  		 * If mounted with the "-o swalloc" option the alignment is
  		 * increased from the strip unit size to the stripe width.
  		 */
  		if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC))
  			align = mp->m_swidth;
  		else if (mp->m_dalign)
  			align = mp->m_dalign;
76b573025   Peter Watkins   xfs: overflow in ...
95
96
  		if (align && XFS_ISIZE(ip) < XFS_FSB_TO_B(mp, align))
  			align = 0;
bf322d983   Christoph Hellwig   xfs: cleanup xfs_...
97
  	}
dd9f438e3   Nathan Scott   [XFS] Implement t...
98
99
100
101
102
103
  
  	/*
  	 * Always round up the allocation request to an extent boundary
  	 * (when file on a real-time subvolume or has di_extsize hint).
  	 */
  	if (extsize) {
76b573025   Peter Watkins   xfs: overflow in ...
104
105
  		if (align)
  			align = roundup_64(align, extsize);
dd9f438e3   Nathan Scott   [XFS] Implement t...
106
107
  		else
  			align = extsize;
dd9f438e3   Nathan Scott   [XFS] Implement t...
108
  	}
f8e3a8257   Christoph Hellwig   xfs: factor our a...
109
110
111
112
113
114
115
116
117
118
  	return align;
  }
  
  STATIC int
  xfs_iomap_eof_align_last_fsb(
  	struct xfs_inode	*ip,
  	xfs_extlen_t		extsize,
  	xfs_fileoff_t		*last_fsb)
  {
  	xfs_extlen_t		align = xfs_eof_alignment(ip, extsize);
76b573025   Peter Watkins   xfs: overflow in ...
119
120
  	if (align) {
  		xfs_fileoff_t	new_last_fsb = roundup_64(*last_fsb, align);
f8e3a8257   Christoph Hellwig   xfs: factor our a...
121
  		int		eof, error;
541d7d3c4   Lachlan McIlroy   [XFS] kill unness...
122
  		error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof);
dd9f438e3   Nathan Scott   [XFS] Implement t...
123
124
125
126
127
128
129
130
131
  		if (error)
  			return error;
  		if (eof)
  			*last_fsb = new_last_fsb;
  	}
  	return 0;
  }
  
  STATIC int
6d4a8ecb3   Dave Chinner   xfs: rename xfs_c...
132
  xfs_alert_fsblock_zero(
572d95f49   Nathan Scott   [XFS] Improve err...
133
134
135
  	xfs_inode_t	*ip,
  	xfs_bmbt_irec_t	*imap)
  {
6a19d9393   Dave Chinner   xfs: convert xfs_...
136
  	xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO,
572d95f49   Nathan Scott   [XFS] Improve err...
137
138
  			"Access to block zero in inode %llu "
  			"start_block: %llx start_off: %llx "
08e96e1a3   Eric Sandeen   xfs: remove newli...
139
  			"blkcnt: %llx extent-state: %x",
572d95f49   Nathan Scott   [XFS] Improve err...
140
141
142
143
144
  		(unsigned long long)ip->i_ino,
  		(unsigned long long)imap->br_startblock,
  		(unsigned long long)imap->br_startoff,
  		(unsigned long long)imap->br_blockcount,
  		imap->br_state);
2451337dd   Dave Chinner   xfs: global error...
145
  	return -EFSCORRUPTED;
572d95f49   Nathan Scott   [XFS] Improve err...
146
  }
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
147
  int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
  xfs_iomap_write_direct(
  	xfs_inode_t	*ip,
f403b7f45   Nathan Scott   [XFS] Cleanup use...
150
  	xfs_off_t	offset,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
  	size_t		count,
3070451ee   Christoph Hellwig   xfs: reduce stack...
152
  	xfs_bmbt_irec_t *imap,
405f80429   Christoph Hellwig   xfs: cleanup the ...
153
  	int		nmaps)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
  {
  	xfs_mount_t	*mp = ip->i_mount;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
  	xfs_fileoff_t	offset_fsb;
  	xfs_fileoff_t	last_fsb;
dd9f438e3   Nathan Scott   [XFS] Implement t...
158
  	xfs_filblks_t	count_fsb, resaligned;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
  	xfs_fsblock_t	firstfsb;
f13eb2055   Christoph Hellwig   xfs: introduce xf...
160
  	xfs_extlen_t	extsz;
0116d9356   Eric Sandeen   [XFS] Remove dead...
161
  	int		nimaps;
06d10dd9c   Nathan Scott   [XFS] Merge fixes...
162
  	int		quota_flag;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
  	int		rt;
  	xfs_trans_t	*tp;
2c3234d1e   Darrick J. Wong   xfs: rename flist...
165
  	struct xfs_defer_ops dfops;
dd9f438e3   Nathan Scott   [XFS] Implement t...
166
  	uint		qblocks, resblks, resrtextents;
dd9f438e3   Nathan Scott   [XFS] Implement t...
167
  	int		error;
009c6e871   Brian Foster   xfs: add missing ...
168
  	int		lockmode;
1ca191576   Dave Chinner   xfs: Don't use un...
169
  	int		bmapi_flags = XFS_BMAPI_PREALLOC;
253f4911f   Christoph Hellwig   xfs: better xfs_t...
170
  	uint		tflags = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171

dd9f438e3   Nathan Scott   [XFS] Implement t...
172
  	rt = XFS_IS_REALTIME_INODE(ip);
957d0ebed   David Chinner   [XFS] Cleanup ino...
173
  	extsz = xfs_get_extsz_hint(ip);
009c6e871   Brian Foster   xfs: add missing ...
174
175
176
  	lockmode = XFS_ILOCK_SHARED;	/* locked by caller */
  
  	ASSERT(xfs_isilocked(ip, lockmode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177

957d0ebed   David Chinner   [XFS] Cleanup ino...
178
179
  	offset_fsb = XFS_B_TO_FSBT(mp, offset);
  	last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
ce7ae151d   Christoph Hellwig   xfs: remove the i...
180
  	if ((offset + count) > XFS_ISIZE(ip)) {
009c6e871   Brian Foster   xfs: add missing ...
181
182
183
184
185
186
187
188
189
  		/*
  		 * Assert that the in-core extent list is present since this can
  		 * call xfs_iread_extents() and we only have the ilock shared.
  		 * This should be safe because the lock was held around a bmapi
  		 * call in the caller and we only need it to access the in-core
  		 * list.
  		 */
  		ASSERT(XFS_IFORK_PTR(ip, XFS_DATA_FORK)->if_flags &
  								XFS_IFEXTENTS);
f8e3a8257   Christoph Hellwig   xfs: factor our a...
190
  		error = xfs_iomap_eof_align_last_fsb(ip, extsz, &last_fsb);
dd9f438e3   Nathan Scott   [XFS] Implement t...
191
  		if (error)
009c6e871   Brian Foster   xfs: add missing ...
192
  			goto out_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
  	} else {
405f80429   Christoph Hellwig   xfs: cleanup the ...
194
  		if (nmaps && (imap->br_startblock == HOLESTARTBLOCK))
dd9f438e3   Nathan Scott   [XFS] Implement t...
195
  			last_fsb = MIN(last_fsb, (xfs_fileoff_t)
3070451ee   Christoph Hellwig   xfs: reduce stack...
196
197
  					imap->br_blockcount +
  					imap->br_startoff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  	}
dd9f438e3   Nathan Scott   [XFS] Implement t...
199
200
  	count_fsb = last_fsb - offset_fsb;
  	ASSERT(count_fsb > 0);
f13eb2055   Christoph Hellwig   xfs: introduce xf...
201
  	resaligned = xfs_aligned_fsb_count(offset_fsb, count_fsb, extsz);
dd9f438e3   Nathan Scott   [XFS] Implement t...
202
203
204
205
  
  	if (unlikely(rt)) {
  		resrtextents = qblocks = resaligned;
  		resrtextents /= mp->m_sb.sb_rextsize;
84e1e99f1   David Chinner   [XFS] Prevent ENO...
206
207
208
209
  		resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
  		quota_flag = XFS_QMOPT_RES_RTBLKS;
  	} else {
  		resrtextents = 0;
dd9f438e3   Nathan Scott   [XFS] Implement t...
210
  		resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned);
84e1e99f1   David Chinner   [XFS] Prevent ENO...
211
212
  		quota_flag = XFS_QMOPT_RES_REGBLKS;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
  
  	/*
009c6e871   Brian Foster   xfs: add missing ...
215
216
217
218
219
220
221
222
223
  	 * Drop the shared lock acquired by the caller, attach the dquot if
  	 * necessary and move on to transaction setup.
  	 */
  	xfs_iunlock(ip, lockmode);
  	error = xfs_qm_dqattach(ip, 0);
  	if (error)
  		return error;
  
  	/*
1ca191576   Dave Chinner   xfs: Don't use un...
224
225
226
227
228
  	 * For DAX, we do not allocate unwritten extents, but instead we zero
  	 * the block before we commit the transaction.  Ideally we'd like to do
  	 * this outside the transaction context, but if we commit and then crash
  	 * we may not have zeroed the blocks and this will be exposed on
  	 * recovery of the allocation. Hence we must zero before commit.
3b0fe4780   Dave Chinner   xfs: Don't use re...
229
  	 *
1ca191576   Dave Chinner   xfs: Don't use un...
230
231
232
  	 * Further, if we are mapping unwritten extents here, we need to zero
  	 * and convert them to written so that we don't need an unwritten extent
  	 * callback for DAX. This also means that we need to be able to dip into
3b0fe4780   Dave Chinner   xfs: Don't use re...
233
234
  	 * the reserve block pool for bmbt block allocation if there is no space
  	 * left but we need to do unwritten extent conversion.
1ca191576   Dave Chinner   xfs: Don't use un...
235
236
237
  	 */
  	if (IS_DAX(VFS_I(ip))) {
  		bmapi_flags = XFS_BMAPI_CONVERT | XFS_BMAPI_ZERO;
63fbb4c18   Christoph Hellwig   xfs: remove the I...
238
  		if (imap->br_state == XFS_EXT_UNWRITTEN) {
253f4911f   Christoph Hellwig   xfs: better xfs_t...
239
  			tflags |= XFS_TRANS_RESERVE;
3b0fe4780   Dave Chinner   xfs: Don't use re...
240
241
  			resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;
  		}
1ca191576   Dave Chinner   xfs: Don't use un...
242
  	}
253f4911f   Christoph Hellwig   xfs: better xfs_t...
243
244
245
  	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, resrtextents,
  			tflags, &tp);
  	if (error)
b474c7ae4   Eric Sandeen   xfs: Nuke XFS_ERR...
246
  		return error;
507630b29   Dave Chinner   xfs: use shared i...
247

009c6e871   Brian Foster   xfs: add missing ...
248
249
  	lockmode = XFS_ILOCK_EXCL;
  	xfs_ilock(ip, lockmode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250

7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
251
  	error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks, 0, quota_flag);
dd9f438e3   Nathan Scott   [XFS] Implement t...
252
  	if (error)
507630b29   Dave Chinner   xfs: use shared i...
253
  		goto out_trans_cancel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254

ddc3415ab   Christoph Hellwig   xfs: simplify xfs...
255
  	xfs_trans_ijoin(tp, ip, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
  	/*
3070451ee   Christoph Hellwig   xfs: reduce stack...
258
259
  	 * From this point onwards we overwrite the imap pointer that the
  	 * caller gave to us.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
  	 */
2c3234d1e   Darrick J. Wong   xfs: rename flist...
261
  	xfs_defer_init(&dfops, &firstfsb);
06d10dd9c   Nathan Scott   [XFS] Merge fixes...
262
  	nimaps = 1;
d531d91d6   Christoph Hellwig   xfs: always use u...
263
  	error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
264e89ad3   Dave Chinner   Merge branch 'xfs...
264
  				bmapi_flags, &firstfsb, resblks, imap,
2c3234d1e   Darrick J. Wong   xfs: rename flist...
265
  				&nimaps, &dfops);
06d10dd9c   Nathan Scott   [XFS] Merge fixes...
266
  	if (error)
507630b29   Dave Chinner   xfs: use shared i...
267
  		goto out_bmap_cancel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
  
  	/*
06d10dd9c   Nathan Scott   [XFS] Merge fixes...
270
  	 * Complete the transaction
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
  	 */
8ad7c629b   Christoph Hellwig   xfs: remove the i...
272
  	error = xfs_defer_finish(&tp, &dfops);
06d10dd9c   Nathan Scott   [XFS] Merge fixes...
273
  	if (error)
507630b29   Dave Chinner   xfs: use shared i...
274
  		goto out_bmap_cancel;
1ca191576   Dave Chinner   xfs: Don't use un...
275

70393313d   Christoph Hellwig   xfs: saner xfs_tr...
276
  	error = xfs_trans_commit(tp);
06d10dd9c   Nathan Scott   [XFS] Merge fixes...
277
  	if (error)
507630b29   Dave Chinner   xfs: use shared i...
278
  		goto out_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279

06d10dd9c   Nathan Scott   [XFS] Merge fixes...
280
281
282
  	/*
  	 * Copy any maps to caller's array and return any error.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
  	if (nimaps == 0) {
2451337dd   Dave Chinner   xfs: global error...
284
  		error = -ENOSPC;
507630b29   Dave Chinner   xfs: use shared i...
285
  		goto out_unlock;
572d95f49   Nathan Scott   [XFS] Improve err...
286
  	}
507630b29   Dave Chinner   xfs: use shared i...
287
  	if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip)))
6d4a8ecb3   Dave Chinner   xfs: rename xfs_c...
288
  		error = xfs_alert_fsblock_zero(ip, imap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289

507630b29   Dave Chinner   xfs: use shared i...
290
  out_unlock:
009c6e871   Brian Foster   xfs: add missing ...
291
  	xfs_iunlock(ip, lockmode);
507630b29   Dave Chinner   xfs: use shared i...
292
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293

507630b29   Dave Chinner   xfs: use shared i...
294
  out_bmap_cancel:
2c3234d1e   Darrick J. Wong   xfs: rename flist...
295
  	xfs_defer_cancel(&dfops);
ea562ed6e   Dave Chinner   xfs: fix delalloc...
296
  	xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag);
507630b29   Dave Chinner   xfs: use shared i...
297
  out_trans_cancel:
4906e2154   Christoph Hellwig   xfs: remove the f...
298
  	xfs_trans_cancel(tp);
507630b29   Dave Chinner   xfs: use shared i...
299
  	goto out_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
  }
76a4202a3   Brian Foster   xfs: add quota-dr...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
  STATIC bool
  xfs_quota_need_throttle(
  	struct xfs_inode *ip,
  	int type,
  	xfs_fsblock_t alloc_blocks)
  {
  	struct xfs_dquot *dq = xfs_inode_dquot(ip, type);
  
  	if (!dq || !xfs_this_quota_on(ip->i_mount, type))
  		return false;
  
  	/* no hi watermark, no throttle */
  	if (!dq->q_prealloc_hi_wmark)
  		return false;
  
  	/* under the lo watermark, no throttle */
  	if (dq->q_res_bcount + alloc_blocks < dq->q_prealloc_lo_wmark)
  		return false;
  
  	return true;
  }
  
  STATIC void
  xfs_quota_calc_throttle(
  	struct xfs_inode *ip,
  	int type,
  	xfs_fsblock_t *qblocks,
f074051ff   Brian Foster   xfs: squash preal...
328
329
  	int *qshift,
  	int64_t	*qfreesp)
76a4202a3   Brian Foster   xfs: add quota-dr...
330
331
332
333
  {
  	int64_t freesp;
  	int shift = 0;
  	struct xfs_dquot *dq = xfs_inode_dquot(ip, type);
5cca3f611   Eric Sandeen   xfs: check for nu...
334
335
  	/* no dq, or over hi wmark, squash the prealloc completely */
  	if (!dq || dq->q_res_bcount >= dq->q_prealloc_hi_wmark) {
76a4202a3   Brian Foster   xfs: add quota-dr...
336
  		*qblocks = 0;
f074051ff   Brian Foster   xfs: squash preal...
337
  		*qfreesp = 0;
76a4202a3   Brian Foster   xfs: add quota-dr...
338
339
340
341
342
343
344
345
346
347
348
  		return;
  	}
  
  	freesp = dq->q_prealloc_hi_wmark - dq->q_res_bcount;
  	if (freesp < dq->q_low_space[XFS_QLOWSP_5_PCNT]) {
  		shift = 2;
  		if (freesp < dq->q_low_space[XFS_QLOWSP_3_PCNT])
  			shift += 2;
  		if (freesp < dq->q_low_space[XFS_QLOWSP_1_PCNT])
  			shift += 2;
  	}
f074051ff   Brian Foster   xfs: squash preal...
349
350
  	if (freesp < *qfreesp)
  		*qfreesp = freesp;
76a4202a3   Brian Foster   xfs: add quota-dr...
351
352
353
354
355
356
  	/* only overwrite the throttle values if we are more aggressive */
  	if ((freesp >> shift) < (*qblocks >> *qshift)) {
  		*qblocks = freesp;
  		*qshift = shift;
  	}
  }
a1e16c266   Dave Chinner   xfs: limit specul...
357
  /*
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
358
359
360
361
   * If we are doing a write at the end of the file and there are no allocations
   * past this one, then extend the allocation out to the file system's write
   * iosize.
   *
055388a31   Dave Chinner   xfs: dynamic spec...
362
   * If we don't have a user specified preallocation size, dynamically increase
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
363
   * the preallocation size as the size of the file grows.  Cap the maximum size
055388a31   Dave Chinner   xfs: dynamic spec...
364
365
   * at a single extent or less if the filesystem is near full. The closer the
   * filesystem is to full, the smaller the maximum prealocation.
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
366
367
368
369
370
371
372
373
   *
   * As an exception we don't do any preallocation at all if the file is smaller
   * than the minimum preallocation and we are using the default dynamic
   * preallocation scheme, as it is likely this is the only write to the file that
   * is going to be done.
   *
   * We clean up any extra space left over when the file is closed in
   * xfs_inactive().
055388a31   Dave Chinner   xfs: dynamic spec...
374
375
376
   */
  STATIC xfs_fsblock_t
  xfs_iomap_prealloc_size(
a1e16c266   Dave Chinner   xfs: limit specul...
377
  	struct xfs_inode	*ip,
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
378
379
  	loff_t			offset,
  	loff_t			count,
656152e55   Christoph Hellwig   xfs: use new exte...
380
  	xfs_extnum_t		idx)
055388a31   Dave Chinner   xfs: dynamic spec...
381
  {
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
382
  	struct xfs_mount	*mp = ip->i_mount;
656152e55   Christoph Hellwig   xfs: use new exte...
383
  	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
384
  	xfs_fileoff_t		offset_fsb = XFS_B_TO_FSBT(mp, offset);
656152e55   Christoph Hellwig   xfs: use new exte...
385
  	struct xfs_bmbt_irec	prev;
3c58b5f80   Brian Foster   xfs: reorganize x...
386
387
  	int			shift = 0;
  	int64_t			freesp;
76a4202a3   Brian Foster   xfs: add quota-dr...
388
389
  	xfs_fsblock_t		qblocks;
  	int			qshift = 0;
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
  	xfs_fsblock_t		alloc_blocks = 0;
  
  	if (offset + count <= XFS_ISIZE(ip))
  		return 0;
  
  	if (!(mp->m_flags & XFS_MOUNT_DFLT_IOSIZE) &&
  	    (XFS_ISIZE(ip) < XFS_FSB_TO_B(mp, mp->m_writeio_blocks)))
  		return 0;
  
  	/*
  	 * If an explicit allocsize is set, the file is small, or we
  	 * are writing behind a hole, then use the minimum prealloc:
  	 */
  	if ((mp->m_flags & XFS_MOUNT_DFLT_IOSIZE) ||
  	    XFS_ISIZE(ip) < XFS_FSB_TO_B(mp, mp->m_dalign) ||
656152e55   Christoph Hellwig   xfs: use new exte...
405
406
  	    !xfs_iext_get_extent(ifp, idx - 1, &prev) ||
  	    prev.br_startoff + prev.br_blockcount < offset_fsb)
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
407
  		return mp->m_writeio_blocks;
055388a31   Dave Chinner   xfs: dynamic spec...
408

51446f5ba   Christoph Hellwig   xfs: rewrite and ...
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
  	/*
  	 * Determine the initial size of the preallocation. We are beyond the
  	 * current EOF here, but we need to take into account whether this is
  	 * a sparse write or an extending write when determining the
  	 * preallocation size.  Hence we need to look up the extent that ends
  	 * at the current write offset and use the result to determine the
  	 * preallocation size.
  	 *
  	 * If the extent is a hole, then preallocation is essentially disabled.
  	 * Otherwise we take the size of the preceding data extent as the basis
  	 * for the preallocation size. If the size of the extent is greater than
  	 * half the maximum extent length, then use the current offset as the
  	 * basis. This ensures that for large files the preallocation size
  	 * always extends to MAXEXTLEN rather than falling short due to things
  	 * like stripe unit/width alignment of real extents.
  	 */
656152e55   Christoph Hellwig   xfs: use new exte...
425
426
  	if (prev.br_blockcount <= (MAXEXTLEN >> 1))
  		alloc_blocks = prev.br_blockcount << 1;
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
427
428
  	else
  		alloc_blocks = XFS_B_TO_FSB(mp, offset);
3c58b5f80   Brian Foster   xfs: reorganize x...
429
430
  	if (!alloc_blocks)
  		goto check_writeio;
76a4202a3   Brian Foster   xfs: add quota-dr...
431
  	qblocks = alloc_blocks;
3c58b5f80   Brian Foster   xfs: reorganize x...
432

c9bdbdc07   Brian Foster   xfs: push rounddo...
433
434
435
436
437
438
439
440
441
  	/*
  	 * MAXEXTLEN is not a power of two value but we round the prealloc down
  	 * to the nearest power of two value after throttling. To prevent the
  	 * round down from unconditionally reducing the maximum supported prealloc
  	 * size, we round up first, apply appropriate throttling, round down and
  	 * cap the value to MAXEXTLEN.
  	 */
  	alloc_blocks = XFS_FILEOFF_MIN(roundup_pow_of_two(MAXEXTLEN),
  				       alloc_blocks);
3c58b5f80   Brian Foster   xfs: reorganize x...
442

0d485ada4   Dave Chinner   xfs: use generic ...
443
  	freesp = percpu_counter_read_positive(&mp->m_fdblocks);
3c58b5f80   Brian Foster   xfs: reorganize x...
444
445
446
447
448
449
450
451
452
453
  	if (freesp < mp->m_low_space[XFS_LOWSP_5_PCNT]) {
  		shift = 2;
  		if (freesp < mp->m_low_space[XFS_LOWSP_4_PCNT])
  			shift++;
  		if (freesp < mp->m_low_space[XFS_LOWSP_3_PCNT])
  			shift++;
  		if (freesp < mp->m_low_space[XFS_LOWSP_2_PCNT])
  			shift++;
  		if (freesp < mp->m_low_space[XFS_LOWSP_1_PCNT])
  			shift++;
055388a31   Dave Chinner   xfs: dynamic spec...
454
  	}
76a4202a3   Brian Foster   xfs: add quota-dr...
455
456
  
  	/*
f074051ff   Brian Foster   xfs: squash preal...
457
458
  	 * Check each quota to cap the prealloc size, provide a shift value to
  	 * throttle with and adjust amount of available space.
76a4202a3   Brian Foster   xfs: add quota-dr...
459
460
  	 */
  	if (xfs_quota_need_throttle(ip, XFS_DQ_USER, alloc_blocks))
f074051ff   Brian Foster   xfs: squash preal...
461
462
  		xfs_quota_calc_throttle(ip, XFS_DQ_USER, &qblocks, &qshift,
  					&freesp);
76a4202a3   Brian Foster   xfs: add quota-dr...
463
  	if (xfs_quota_need_throttle(ip, XFS_DQ_GROUP, alloc_blocks))
f074051ff   Brian Foster   xfs: squash preal...
464
465
  		xfs_quota_calc_throttle(ip, XFS_DQ_GROUP, &qblocks, &qshift,
  					&freesp);
76a4202a3   Brian Foster   xfs: add quota-dr...
466
  	if (xfs_quota_need_throttle(ip, XFS_DQ_PROJ, alloc_blocks))
f074051ff   Brian Foster   xfs: squash preal...
467
468
  		xfs_quota_calc_throttle(ip, XFS_DQ_PROJ, &qblocks, &qshift,
  					&freesp);
76a4202a3   Brian Foster   xfs: add quota-dr...
469
470
471
472
473
474
475
476
477
478
  
  	/*
  	 * The final prealloc size is set to the minimum of free space available
  	 * in each of the quotas and the overall filesystem.
  	 *
  	 * The shift throttle value is set to the maximum value as determined by
  	 * the global low free space values and per-quota low free space values.
  	 */
  	alloc_blocks = MIN(alloc_blocks, qblocks);
  	shift = MAX(shift, qshift);
3c58b5f80   Brian Foster   xfs: reorganize x...
479
480
  	if (shift)
  		alloc_blocks >>= shift;
c9bdbdc07   Brian Foster   xfs: push rounddo...
481
482
483
484
485
486
487
488
  	/*
  	 * rounddown_pow_of_two() returns an undefined result if we pass in
  	 * alloc_blocks = 0.
  	 */
  	if (alloc_blocks)
  		alloc_blocks = rounddown_pow_of_two(alloc_blocks);
  	if (alloc_blocks > MAXEXTLEN)
  		alloc_blocks = MAXEXTLEN;
3c58b5f80   Brian Foster   xfs: reorganize x...
489
490
491
492
493
494
495
496
497
  
  	/*
  	 * If we are still trying to allocate more space than is
  	 * available, squash the prealloc hard. This can happen if we
  	 * have a large file on a small filesystem and the above
  	 * lowspace thresholds are smaller than MAXEXTLEN.
  	 */
  	while (alloc_blocks && alloc_blocks >= freesp)
  		alloc_blocks >>= 4;
3c58b5f80   Brian Foster   xfs: reorganize x...
498
  check_writeio:
055388a31   Dave Chinner   xfs: dynamic spec...
499
500
  	if (alloc_blocks < mp->m_writeio_blocks)
  		alloc_blocks = mp->m_writeio_blocks;
19cb7e385   Brian Foster   xfs: xfs_iomap_pr...
501
502
  	trace_xfs_iomap_prealloc_size(ip, alloc_blocks, shift,
  				      mp->m_writeio_blocks);
055388a31   Dave Chinner   xfs: dynamic spec...
503
504
  	return alloc_blocks;
  }
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
505
506
507
508
509
  static int
  xfs_file_iomap_begin_delay(
  	struct inode		*inode,
  	loff_t			offset,
  	loff_t			count,
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
510
  	struct iomap		*iomap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
  {
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
512
513
514
515
516
517
  	struct xfs_inode	*ip = XFS_I(inode);
  	struct xfs_mount	*mp = ip->i_mount;
  	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
  	xfs_fileoff_t		offset_fsb = XFS_B_TO_FSBT(mp, offset);
  	xfs_fileoff_t		maxbytes_fsb =
  		XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
f782088c9   Brian Foster   xfs: pass post-eo...
518
  	xfs_fileoff_t		end_fsb;
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
519
520
  	int			error = 0, eof = 0;
  	struct xfs_bmbt_irec	got;
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
521
  	xfs_extnum_t		idx;
f782088c9   Brian Foster   xfs: pass post-eo...
522
  	xfs_fsblock_t		prealloc_blocks = 0;
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
523
524
525
  
  	ASSERT(!XFS_IS_REALTIME_INODE(ip));
  	ASSERT(!xfs_get_extsz_hint(ip));
dd9f438e3   Nathan Scott   [XFS] Implement t...
526

51446f5ba   Christoph Hellwig   xfs: rewrite and ...
527
  	xfs_ilock(ip, XFS_ILOCK_EXCL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528

51446f5ba   Christoph Hellwig   xfs: rewrite and ...
529
530
531
  	if (unlikely(XFS_TEST_ERROR(
  	    (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_EXTENTS &&
  	     XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_BTREE),
9e24cfd04   Darrick J. Wong   xfs: remove unnee...
532
  	     mp, XFS_ERRTAG_BMAPIFORMAT))) {
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
533
534
535
536
  		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
  		error = -EFSCORRUPTED;
  		goto out_unlock;
  	}
a1e16c266   Dave Chinner   xfs: limit specul...
537

51446f5ba   Christoph Hellwig   xfs: rewrite and ...
538
  	XFS_STATS_INC(mp, xs_blk_mapw);
055388a31   Dave Chinner   xfs: dynamic spec...
539

51446f5ba   Christoph Hellwig   xfs: rewrite and ...
540
541
542
543
  	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
  		error = xfs_iread_extents(NULL, ip, XFS_DATA_FORK);
  		if (error)
  			goto out_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545

656152e55   Christoph Hellwig   xfs: use new exte...
546
  	eof = !xfs_iext_lookup_extent(ip, ifp, offset_fsb, &idx, &got);
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
547
  	if (!eof && got.br_startoff <= offset_fsb) {
3ba020bef   Christoph Hellwig   xfs: optimize wri...
548
549
550
551
552
553
554
555
556
557
  		if (xfs_is_reflink_inode(ip)) {
  			bool		shared;
  
  			end_fsb = min(XFS_B_TO_FSB(mp, offset + count),
  					maxbytes_fsb);
  			xfs_trim_extent(&got, offset_fsb, end_fsb - offset_fsb);
  			error = xfs_reflink_reserve_cow(ip, &got, &shared);
  			if (error)
  				goto out_unlock;
  		}
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
558
559
  		trace_xfs_iomap_found(ip, offset, count, 0, &got);
  		goto done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
560
  	}
dd9f438e3   Nathan Scott   [XFS] Implement t...
561

51446f5ba   Christoph Hellwig   xfs: rewrite and ...
562
563
564
  	error = xfs_qm_dqattach_locked(ip, 0);
  	if (error)
  		goto out_unlock;
3ed9116e8   Dave Chinner   xfs: limit specua...
565
  	/*
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
566
567
568
569
570
571
572
  	 * We cap the maximum length we map here to MAX_WRITEBACK_PAGES pages
  	 * to keep the chunks of work done where somewhat symmetric with the
  	 * work writeback does. This is a completely arbitrary number pulled
  	 * out of thin air as a best guess for initial testing.
  	 *
  	 * Note that the values needs to be less than 32-bits wide until
  	 * the lower level functions are updated.
3ed9116e8   Dave Chinner   xfs: limit specua...
573
  	 */
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
574
  	count = min_t(loff_t, count, 1024 * PAGE_SIZE);
f782088c9   Brian Foster   xfs: pass post-eo...
575
  	end_fsb = min(XFS_B_TO_FSB(mp, offset + count), maxbytes_fsb);
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
576
577
  
  	if (eof) {
656152e55   Christoph Hellwig   xfs: use new exte...
578
  		prealloc_blocks = xfs_iomap_prealloc_size(ip, offset, count, idx);
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
579
580
581
  		if (prealloc_blocks) {
  			xfs_extlen_t	align;
  			xfs_off_t	end_offset;
f782088c9   Brian Foster   xfs: pass post-eo...
582
  			xfs_fileoff_t	p_end_fsb;
3ed9116e8   Dave Chinner   xfs: limit specua...
583

51446f5ba   Christoph Hellwig   xfs: rewrite and ...
584
  			end_offset = XFS_WRITEIO_ALIGN(mp, offset + count - 1);
f782088c9   Brian Foster   xfs: pass post-eo...
585
586
  			p_end_fsb = XFS_B_TO_FSBT(mp, end_offset) +
  					prealloc_blocks;
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
587
588
589
  
  			align = xfs_eof_alignment(ip, 0);
  			if (align)
f782088c9   Brian Foster   xfs: pass post-eo...
590
  				p_end_fsb = roundup_64(p_end_fsb, align);
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
591

f782088c9   Brian Foster   xfs: pass post-eo...
592
593
594
  			p_end_fsb = min(p_end_fsb, maxbytes_fsb);
  			ASSERT(p_end_fsb > offset_fsb);
  			prealloc_blocks = p_end_fsb - end_fsb;
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
595
596
597
598
  		}
  	}
  
  retry:
be51f8119   Darrick J. Wong   xfs: support bmap...
599
  	error = xfs_bmapi_reserve_delalloc(ip, XFS_DATA_FORK, offset_fsb,
f782088c9   Brian Foster   xfs: pass post-eo...
600
  			end_fsb - offset_fsb, prealloc_blocks, &got, &idx, eof);
055388a31   Dave Chinner   xfs: dynamic spec...
601
602
  	switch (error) {
  	case 0:
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
603
  		break;
2451337dd   Dave Chinner   xfs: global error...
604
605
  	case -ENOSPC:
  	case -EDQUOT:
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
606
  		/* retry without any preallocation */
0b1b213fc   Christoph Hellwig   xfs: event tracin...
607
  		trace_xfs_delalloc_enospc(ip, offset, count);
f782088c9   Brian Foster   xfs: pass post-eo...
608
609
  		if (prealloc_blocks) {
  			prealloc_blocks = 0;
9aa05000f   Dave Chinner   xfs: xfs_sync_dat...
610
  			goto retry;
055388a31   Dave Chinner   xfs: dynamic spec...
611
  		}
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
612
613
614
  		/*FALLTHRU*/
  	default:
  		goto out_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
  	}
f65e6fad2   Brian Foster   xfs: use iomap ne...
616
617
618
619
620
  	/*
  	 * Flag newly allocated delalloc blocks with IOMAP_F_NEW so we punch
  	 * them out if the write happens to fail.
  	 */
  	iomap->flags = IOMAP_F_NEW;
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
  	trace_xfs_iomap_alloc(ip, offset, count, 0, &got);
  done:
  	if (isnullstartblock(got.br_startblock))
  		got.br_startblock = DELAYSTARTBLOCK;
  
  	if (!got.br_startblock) {
  		error = xfs_alert_fsblock_zero(ip, &got);
  		if (error)
  			goto out_unlock;
  	}
  
  	xfs_bmbt_to_iomap(ip, iomap, &got);
  
  out_unlock:
  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
638
639
640
641
642
643
644
  }
  
  /*
   * Pass in a delayed allocate extent, convert it to real extents;
   * return to the caller the extent we create which maps on top of
   * the originating callers request.
   *
   * Called without a lock on the inode.
e4143a1cf   David Chinner   [XFS] Fix transac...
645
646
647
   *
   * We no longer bother to look at the incoming map - all we have to
   * guarantee is that whatever we allocate fills the required range.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
   */
a206c817c   Christoph Hellwig   xfs: kill xfs_iomap
649
  int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
651
  xfs_iomap_write_allocate(
  	xfs_inode_t	*ip,
60b4984fc   Darrick J. Wong   xfs: support allo...
652
  	int		whichfork,
f403b7f45   Nathan Scott   [XFS] Cleanup use...
653
  	xfs_off_t	offset,
405f80429   Christoph Hellwig   xfs: cleanup the ...
654
  	xfs_bmbt_irec_t *imap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
656
  {
  	xfs_mount_t	*mp = ip->i_mount;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
658
659
  	xfs_fileoff_t	offset_fsb, last_block;
  	xfs_fileoff_t	end_fsb, map_start_fsb;
  	xfs_fsblock_t	first_block;
2c3234d1e   Darrick J. Wong   xfs: rename flist...
660
  	struct xfs_defer_ops	dfops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
  	xfs_filblks_t	count_fsb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
  	xfs_trans_t	*tp;
f6106efae   Eric Sandeen   xfs: eliminate co...
663
  	int		nimaps;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
664
  	int		error = 0;
d2b3964a0   Christoph Hellwig   xfs: fix COW writ...
665
  	int		flags = XFS_BMAPI_DELALLOC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
  	int		nres;
60b4984fc   Darrick J. Wong   xfs: support allo...
667
  	if (whichfork == XFS_COW_FORK)
5eda43000   Darrick J. Wong   xfs: mark specula...
668
  		flags |= XFS_BMAPI_COWFORK | XFS_BMAPI_PREALLOC;
60b4984fc   Darrick J. Wong   xfs: support allo...
669

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
671
672
  	/*
  	 * Make sure that the dquots are there.
  	 */
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
673
674
  	error = xfs_qm_dqattach(ip, 0);
  	if (error)
b474c7ae4   Eric Sandeen   xfs: Nuke XFS_ERR...
675
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676

24e17b5fb   Nathan Scott   [XFS] Use the rig...
677
  	offset_fsb = XFS_B_TO_FSBT(mp, offset);
3070451ee   Christoph Hellwig   xfs: reduce stack...
678
679
  	count_fsb = imap->br_blockcount;
  	map_start_fsb = imap->br_startoff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680

ff6d6af23   Bill O'Donnell   xfs: per-filesyst...
681
  	XFS_STATS_ADD(mp, xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
683
684
685
686
687
688
689
690
691
  
  	while (count_fsb != 0) {
  		/*
  		 * Set up a transaction with which to allocate the
  		 * backing store for the file.  Do allocations in a
  		 * loop until we get some space in the range we are
  		 * interested in.  The other space that might be allocated
  		 * is in the delayed allocation extent on which we sit
  		 * but before our buffer starts.
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
693
  		nimaps = 0;
  		while (nimaps == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
  			nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
0af32fb46   Christoph Hellwig   xfs: fix bogus sp...
695
696
697
698
699
700
701
  			/*
  			 * We have already reserved space for the extent and any
  			 * indirect blocks when creating the delalloc extent,
  			 * there is no need to reserve space in this transaction
  			 * again.
  			 */
  			error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0,
253f4911f   Christoph Hellwig   xfs: better xfs_t...
702
703
  					0, XFS_TRANS_RESERVE, &tp);
  			if (error)
b474c7ae4   Eric Sandeen   xfs: Nuke XFS_ERR...
704
  				return error;
253f4911f   Christoph Hellwig   xfs: better xfs_t...
705

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
  			xfs_ilock(ip, XFS_ILOCK_EXCL);
ddc3415ab   Christoph Hellwig   xfs: simplify xfs...
707
  			xfs_trans_ijoin(tp, ip, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708

2c3234d1e   Darrick J. Wong   xfs: rename flist...
709
  			xfs_defer_init(&dfops, &first_block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711
  			/*
e4143a1cf   David Chinner   [XFS] Fix transac...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
  			 * it is possible that the extents have changed since
  			 * we did the read call as we dropped the ilock for a
  			 * while. We have to be careful about truncates or hole
  			 * punchs here - we are not allowed to allocate
  			 * non-delalloc blocks here.
  			 *
  			 * The only protection against truncation is the pages
  			 * for the range we are being asked to convert are
  			 * locked and hence a truncate will block on them
  			 * first.
  			 *
  			 * As a result, if we go beyond the range we really
  			 * need and hit an delalloc extent boundary followed by
  			 * a hole while we have excess blocks in the map, we
  			 * will fill the hole incorrectly and overrun the
  			 * transaction reservation.
  			 *
  			 * Using a single map prevents this as we are forced to
  			 * check each map we look for overlap with the desired
  			 * range and abort as soon as we find it. Also, given
  			 * that we only return a single map, having one beyond
  			 * what we can return is probably a bit silly.
  			 *
  			 * We also need to check that we don't go beyond EOF;
  			 * this is a truncate optimisation as a truncate sets
  			 * the new file size before block on the pages we
  			 * currently have locked under writeback. Because they
  			 * are about to be tossed, we don't need to write them
  			 * back....
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
  			 */
e4143a1cf   David Chinner   [XFS] Fix transac...
742
  			nimaps = 1;
ce7ae151d   Christoph Hellwig   xfs: remove the i...
743
  			end_fsb = XFS_B_TO_FSB(mp, XFS_ISIZE(ip));
7fb2cd4d3   Eric Sandeen   xfs: remove unuse...
744
  			error = xfs_bmap_last_offset(ip, &last_block,
7c9ef85c5   David Chinner   [XFS] Catch error...
745
746
747
  							XFS_DATA_FORK);
  			if (error)
  				goto trans_cancel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
749
750
751
  			last_block = XFS_FILEOFF_MAX(last_block, end_fsb);
  			if ((map_start_fsb + count_fsb) > last_block) {
  				count_fsb = last_block - map_start_fsb;
  				if (count_fsb == 0) {
2451337dd   Dave Chinner   xfs: global error...
752
  					error = -EAGAIN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
753
754
755
  					goto trans_cancel;
  				}
  			}
3070451ee   Christoph Hellwig   xfs: reduce stack...
756
  			/*
3070451ee   Christoph Hellwig   xfs: reduce stack...
757
758
759
  			 * From this point onwards we overwrite the imap
  			 * pointer that the caller gave to us.
  			 */
c0dc7828a   Dave Chinner   xfs: rename xfs_b...
760
  			error = xfs_bmapi_write(tp, ip, map_start_fsb,
60b4984fc   Darrick J. Wong   xfs: support allo...
761
  						count_fsb, flags, &first_block,
dbd5c8c9a   Brian Foster   xfs: pass total b...
762
  						nres, imap, &nimaps,
2c3234d1e   Darrick J. Wong   xfs: rename flist...
763
  						&dfops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
  			if (error)
  				goto trans_cancel;
8ad7c629b   Christoph Hellwig   xfs: remove the i...
766
  			error = xfs_defer_finish(&tp, &dfops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
768
  			if (error)
  				goto trans_cancel;
70393313d   Christoph Hellwig   xfs: saner xfs_tr...
769
  			error = xfs_trans_commit(tp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770
771
772
773
774
775
776
777
778
779
  			if (error)
  				goto error0;
  
  			xfs_iunlock(ip, XFS_ILOCK_EXCL);
  		}
  
  		/*
  		 * See if we were able to allocate an extent that
  		 * covers at least part of the callers request
  		 */
3070451ee   Christoph Hellwig   xfs: reduce stack...
780
  		if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip)))
6d4a8ecb3   Dave Chinner   xfs: rename xfs_c...
781
  			return xfs_alert_fsblock_zero(ip, imap);
86c4d6230   David Chinner   [XFS] Fix check f...
782

3070451ee   Christoph Hellwig   xfs: reduce stack...
783
784
785
  		if ((offset_fsb >= imap->br_startoff) &&
  		    (offset_fsb < (imap->br_startoff +
  				   imap->br_blockcount))) {
ff6d6af23   Bill O'Donnell   xfs: per-filesyst...
786
  			XFS_STATS_INC(mp, xs_xstrat_quick);
e4143a1cf   David Chinner   [XFS] Fix transac...
787
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
  		}
e4143a1cf   David Chinner   [XFS] Fix transac...
789
790
  		/*
  		 * So far we have not mapped the requested part of the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
792
  		 * file, just surrounding data, try again.
  		 */
3070451ee   Christoph Hellwig   xfs: reduce stack...
793
794
  		count_fsb -= imap->br_blockcount;
  		map_start_fsb = imap->br_startoff + imap->br_blockcount;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795
796
797
  	}
  
  trans_cancel:
2c3234d1e   Darrick J. Wong   xfs: rename flist...
798
  	xfs_defer_cancel(&dfops);
4906e2154   Christoph Hellwig   xfs: remove the f...
799
  	xfs_trans_cancel(tp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
801
  error0:
  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
b474c7ae4   Eric Sandeen   xfs: Nuke XFS_ERR...
802
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
804
805
806
807
  }
  
  int
  xfs_iomap_write_unwritten(
  	xfs_inode_t	*ip,
f403b7f45   Nathan Scott   [XFS] Cleanup use...
808
  	xfs_off_t	offset,
ee70daaba   Eryu Guan   xfs: update i_siz...
809
810
  	xfs_off_t	count,
  	bool		update_isize)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811
812
  {
  	xfs_mount_t	*mp = ip->i_mount;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
813
814
815
  	xfs_fileoff_t	offset_fsb;
  	xfs_filblks_t	count_fsb;
  	xfs_filblks_t	numblks_fsb;
dd9f438e3   Nathan Scott   [XFS] Implement t...
816
817
818
819
  	xfs_fsblock_t	firstfsb;
  	int		nimaps;
  	xfs_trans_t	*tp;
  	xfs_bmbt_irec_t imap;
2c3234d1e   Darrick J. Wong   xfs: rename flist...
820
  	struct xfs_defer_ops dfops;
ee70daaba   Eryu Guan   xfs: update i_siz...
821
  	struct inode	*inode = VFS_I(ip);
84803fb78   Christoph Hellwig   xfs: log file siz...
822
  	xfs_fsize_t	i_size;
dd9f438e3   Nathan Scott   [XFS] Implement t...
823
  	uint		resblks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
  	int		error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
825

0b1b213fc   Christoph Hellwig   xfs: event tracin...
826
  	trace_xfs_unwritten_convert(ip, offset, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
828
829
830
  
  	offset_fsb = XFS_B_TO_FSBT(mp, offset);
  	count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
  	count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb);
4ddd8bb1d   Lachlan McIlroy   [XFS] use minleft...
831
832
833
834
835
836
837
838
839
840
  	/*
  	 * Reserve enough blocks in this transaction for two complete extent
  	 * btree splits.  We may be converting the middle part of an unwritten
  	 * extent and in this case we will insert two new extents in the btree
  	 * each of which could cause a full split.
  	 *
  	 * This reservation amount will be used in the first call to
  	 * xfs_bmbt_split() to select an AG with enough space to satisfy the
  	 * rest of the operation.
  	 */
dd9f438e3   Nathan Scott   [XFS] Implement t...
841
  	resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
842

dd9f438e3   Nathan Scott   [XFS] Implement t...
843
  	do {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
844
  		/*
253f4911f   Christoph Hellwig   xfs: better xfs_t...
845
  		 * Set up a transaction to convert the range of extents
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846
847
  		 * from unwritten to real. Do allocations in a loop until
  		 * we have covered the range passed in.
80641dc66   Christoph Hellwig   xfs: I/O completi...
848
  		 *
253f4911f   Christoph Hellwig   xfs: better xfs_t...
849
850
851
  		 * Note that we can't risk to recursing back into the filesystem
  		 * here as we might be asked to write out the same inode that we
  		 * complete here and might deadlock on the iolock.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
  		 */
253f4911f   Christoph Hellwig   xfs: better xfs_t...
853
854
855
  		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0,
  				XFS_TRANS_RESERVE | XFS_TRANS_NOFS, &tp);
  		if (error)
b474c7ae4   Eric Sandeen   xfs: Nuke XFS_ERR...
856
  			return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
857
858
  
  		xfs_ilock(ip, XFS_ILOCK_EXCL);
ddc3415ab   Christoph Hellwig   xfs: simplify xfs...
859
  		xfs_trans_ijoin(tp, ip, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
861
862
863
  
  		/*
  		 * Modify the unwritten extent state of the buffer.
  		 */
2c3234d1e   Darrick J. Wong   xfs: rename flist...
864
  		xfs_defer_init(&dfops, &firstfsb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
865
  		nimaps = 1;
c0dc7828a   Dave Chinner   xfs: rename xfs_b...
866
  		error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
dbd5c8c9a   Brian Foster   xfs: pass total b...
867
  					XFS_BMAPI_CONVERT, &firstfsb, resblks,
2c3234d1e   Darrick J. Wong   xfs: rename flist...
868
  					&imap, &nimaps, &dfops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869
870
  		if (error)
  			goto error_on_bmapi_transaction;
84803fb78   Christoph Hellwig   xfs: log file siz...
871
872
873
874
875
876
877
878
  		/*
  		 * Log the updated inode size as we go.  We have to be careful
  		 * to only log it up to the actual write offset if it is
  		 * halfway into a block.
  		 */
  		i_size = XFS_FSB_TO_B(mp, offset_fsb + count_fsb);
  		if (i_size > offset + count)
  			i_size = offset + count;
ee70daaba   Eryu Guan   xfs: update i_siz...
879
880
  		if (update_isize && i_size > i_size_read(inode))
  			i_size_write(inode, i_size);
84803fb78   Christoph Hellwig   xfs: log file siz...
881
882
883
884
885
  		i_size = xfs_new_eof(ip, i_size);
  		if (i_size) {
  			ip->i_d.di_size = i_size;
  			xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
  		}
8ad7c629b   Christoph Hellwig   xfs: remove the i...
886
  		error = xfs_defer_finish(&tp, &dfops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
887
888
  		if (error)
  			goto error_on_bmapi_transaction;
70393313d   Christoph Hellwig   xfs: saner xfs_tr...
889
  		error = xfs_trans_commit(tp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
890
891
  		xfs_iunlock(ip, XFS_ILOCK_EXCL);
  		if (error)
b474c7ae4   Eric Sandeen   xfs: Nuke XFS_ERR...
892
  			return error;
572d95f49   Nathan Scott   [XFS] Improve err...
893

86c4d6230   David Chinner   [XFS] Fix check f...
894
  		if (!(imap.br_startblock || XFS_IS_REALTIME_INODE(ip)))
6d4a8ecb3   Dave Chinner   xfs: rename xfs_c...
895
  			return xfs_alert_fsblock_zero(ip, &imap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
  
  		if ((numblks_fsb = imap.br_blockcount) == 0) {
  			/*
  			 * The numblks_fsb value should always get
  			 * smaller, otherwise the loop is stuck.
  			 */
  			ASSERT(imap.br_blockcount);
  			break;
  		}
  		offset_fsb += numblks_fsb;
  		count_fsb -= numblks_fsb;
  	} while (count_fsb > 0);
  
  	return 0;
  
  error_on_bmapi_transaction:
2c3234d1e   Darrick J. Wong   xfs: rename flist...
912
  	xfs_defer_cancel(&dfops);
4906e2154   Christoph Hellwig   xfs: remove the f...
913
  	xfs_trans_cancel(tp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
  	xfs_iunlock(ip, XFS_ILOCK_EXCL);
b474c7ae4   Eric Sandeen   xfs: Nuke XFS_ERR...
915
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916
  }
3b3dce052   Christoph Hellwig   xfs: make xfs_bmb...
917

6c31f495d   Christoph Hellwig   xfs: use iomap to...
918
919
  static inline bool imap_needs_alloc(struct inode *inode,
  		struct xfs_bmbt_irec *imap, int nimaps)
68a9f5e70   Christoph Hellwig   xfs: implement io...
920
921
922
  {
  	return !nimaps ||
  		imap->br_startblock == HOLESTARTBLOCK ||
6c31f495d   Christoph Hellwig   xfs: use iomap to...
923
  		imap->br_startblock == DELAYSTARTBLOCK ||
63fbb4c18   Christoph Hellwig   xfs: remove the I...
924
  		(IS_DAX(inode) && imap->br_state == XFS_EXT_UNWRITTEN);
68a9f5e70   Christoph Hellwig   xfs: implement io...
925
  }
acdda3aae   Christoph Hellwig   xfs: use iomap_di...
926
927
928
929
930
931
932
933
934
935
936
937
  static inline bool need_excl_ilock(struct xfs_inode *ip, unsigned flags)
  {
  	/*
  	 * COW writes will allocate delalloc space, so we need to make sure
  	 * to take the lock exclusively here.
  	 */
  	if (xfs_is_reflink_inode(ip) && (flags & (IOMAP_WRITE | IOMAP_ZERO)))
  		return true;
  	if ((flags & IOMAP_DIRECT) && (flags & IOMAP_WRITE))
  		return true;
  	return false;
  }
68a9f5e70   Christoph Hellwig   xfs: implement io...
938
939
940
941
942
943
944
945
946
947
948
949
950
  static int
  xfs_file_iomap_begin(
  	struct inode		*inode,
  	loff_t			offset,
  	loff_t			length,
  	unsigned		flags,
  	struct iomap		*iomap)
  {
  	struct xfs_inode	*ip = XFS_I(inode);
  	struct xfs_mount	*mp = ip->i_mount;
  	struct xfs_bmbt_irec	imap;
  	xfs_fileoff_t		offset_fsb, end_fsb;
  	int			nimaps = 1, error = 0;
3ba020bef   Christoph Hellwig   xfs: optimize wri...
951
  	bool			shared = false, trimmed = false;
66642c5c1   Christoph Hellwig   xfs: take the ilo...
952
  	unsigned		lockmode;
68a9f5e70   Christoph Hellwig   xfs: implement io...
953
954
955
  
  	if (XFS_FORCED_SHUTDOWN(mp))
  		return -EIO;
acdda3aae   Christoph Hellwig   xfs: use iomap_di...
956
957
  	if (((flags & (IOMAP_WRITE | IOMAP_DIRECT)) == IOMAP_WRITE) &&
  			!IS_DAX(inode) && !xfs_get_extsz_hint(ip)) {
2a06705cd   Darrick J. Wong   xfs: create delal...
958
  		/* Reserve delalloc blocks for regular writeback. */
f91fb956f   Eric Sandeen   xfs: remove unuse...
959
  		return xfs_file_iomap_begin_delay(inode, offset, length, iomap);
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
960
  	}
acdda3aae   Christoph Hellwig   xfs: use iomap_di...
961
  	if (need_excl_ilock(ip, flags)) {
3ba020bef   Christoph Hellwig   xfs: optimize wri...
962
963
964
965
966
  		lockmode = XFS_ILOCK_EXCL;
  		xfs_ilock(ip, XFS_ILOCK_EXCL);
  	} else {
  		lockmode = xfs_ilock_data_map_shared(ip);
  	}
68a9f5e70   Christoph Hellwig   xfs: implement io...
967

29a5d29ec   Goldwyn Rodrigues   xfs: nowait aio s...
968
969
970
971
  	if ((flags & IOMAP_NOWAIT) && !(ip->i_df.if_flags & XFS_IFEXTENTS)) {
  		error = -EAGAIN;
  		goto out_unlock;
  	}
68a9f5e70   Christoph Hellwig   xfs: implement io...
972
973
974
975
976
977
978
  	ASSERT(offset <= mp->m_super->s_maxbytes);
  	if ((xfs_fsize_t)offset + length > mp->m_super->s_maxbytes)
  		length = mp->m_super->s_maxbytes - offset;
  	offset_fsb = XFS_B_TO_FSBT(mp, offset);
  	end_fsb = XFS_B_TO_FSB(mp, offset + length);
  
  	error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap,
db1327b16   Darrick J. Wong   xfs: report share...
979
  			       &nimaps, 0);
3ba020bef   Christoph Hellwig   xfs: optimize wri...
980
981
  	if (error)
  		goto out_unlock;
db1327b16   Darrick J. Wong   xfs: report share...
982

3c68d44a2   Christoph Hellwig   xfs: allocate dir...
983
  	if (flags & IOMAP_REPORT) {
5f9268ca5   Christoph Hellwig   xfs: don't bother...
984
985
986
  		/* Trim the mapping to the nearest shared extent boundary. */
  		error = xfs_reflink_trim_around_shared(ip, &imap, &shared,
  				&trimmed);
3ba020bef   Christoph Hellwig   xfs: optimize wri...
987
988
989
990
991
  		if (error)
  			goto out_unlock;
  	}
  
  	if ((flags & (IOMAP_WRITE | IOMAP_ZERO)) && xfs_is_reflink_inode(ip)) {
3c68d44a2   Christoph Hellwig   xfs: allocate dir...
992
  		if (flags & IOMAP_DIRECT) {
29a5d29ec   Goldwyn Rodrigues   xfs: nowait aio s...
993
994
995
996
997
998
999
1000
1001
  			/*
  			 * A reflinked inode will result in CoW alloc.
  			 * FIXME: It could still overwrite on unshared extents
  			 * and not need allocation.
  			 */
  			if (flags & IOMAP_NOWAIT) {
  				error = -EAGAIN;
  				goto out_unlock;
  			}
3c68d44a2   Christoph Hellwig   xfs: allocate dir...
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
  			/* may drop and re-acquire the ilock */
  			error = xfs_reflink_allocate_cow(ip, &imap, &shared,
  					&lockmode);
  			if (error)
  				goto out_unlock;
  		} else {
  			error = xfs_reflink_reserve_cow(ip, &imap, &shared);
  			if (error)
  				goto out_unlock;
  		}
3ba020bef   Christoph Hellwig   xfs: optimize wri...
1012
1013
1014
  
  		end_fsb = imap.br_startoff + imap.br_blockcount;
  		length = XFS_FSB_TO_B(mp, end_fsb) - offset;
68a9f5e70   Christoph Hellwig   xfs: implement io...
1015
  	}
6c31f495d   Christoph Hellwig   xfs: use iomap to...
1016
  	if ((flags & IOMAP_WRITE) && imap_needs_alloc(inode, &imap, nimaps)) {
68a9f5e70   Christoph Hellwig   xfs: implement io...
1017
  		/*
29a5d29ec   Goldwyn Rodrigues   xfs: nowait aio s...
1018
1019
1020
1021
1022
1023
1024
1025
  		 * If nowait is set bail since we are going to make
  		 * allocations.
  		 */
  		if (flags & IOMAP_NOWAIT) {
  			error = -EAGAIN;
  			goto out_unlock;
  		}
  		/*
68a9f5e70   Christoph Hellwig   xfs: implement io...
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
  		 * We cap the maximum length we map here to MAX_WRITEBACK_PAGES
  		 * pages to keep the chunks of work done where somewhat symmetric
  		 * with the work writeback does. This is a completely arbitrary
  		 * number pulled out of thin air as a best guess for initial
  		 * testing.
  		 *
  		 * Note that the values needs to be less than 32-bits wide until
  		 * the lower level functions are updated.
  		 */
  		length = min_t(loff_t, length, 1024 * PAGE_SIZE);
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
1036
1037
1038
1039
  		/*
  		 * xfs_iomap_write_direct() expects the shared lock. It
  		 * is unlocked on return.
  		 */
66642c5c1   Christoph Hellwig   xfs: take the ilo...
1040
1041
  		if (lockmode == XFS_ILOCK_EXCL)
  			xfs_ilock_demote(ip, lockmode);
51446f5ba   Christoph Hellwig   xfs: rewrite and ...
1042
1043
  		error = xfs_iomap_write_direct(ip, offset, length, &imap,
  				nimaps);
68a9f5e70   Christoph Hellwig   xfs: implement io...
1044
1045
  		if (error)
  			return error;
ecd50729f   Christoph Hellwig   iomap: add IOMAP_...
1046
  		iomap->flags = IOMAP_F_NEW;
68a9f5e70   Christoph Hellwig   xfs: implement io...
1047
  		trace_xfs_iomap_alloc(ip, offset, length, 0, &imap);
68a9f5e70   Christoph Hellwig   xfs: implement io...
1048
  	} else {
b95a21271   Christoph Hellwig   xfs: simplify xfs...
1049
  		ASSERT(nimaps);
66642c5c1   Christoph Hellwig   xfs: take the ilo...
1050
  		xfs_iunlock(ip, lockmode);
b95a21271   Christoph Hellwig   xfs: simplify xfs...
1051
  		trace_xfs_iomap_found(ip, offset, length, 0, &imap);
68a9f5e70   Christoph Hellwig   xfs: implement io...
1052
  	}
b95a21271   Christoph Hellwig   xfs: simplify xfs...
1053
  	xfs_bmbt_to_iomap(ip, iomap, &imap);
fa5d932c3   Dan Williams   ext2, ext4, xfs: ...
1054

db1327b16   Darrick J. Wong   xfs: report share...
1055
1056
  	if (shared)
  		iomap->flags |= IOMAP_F_SHARED;
68a9f5e70   Christoph Hellwig   xfs: implement io...
1057
  	return 0;
3ba020bef   Christoph Hellwig   xfs: optimize wri...
1058
1059
1060
  out_unlock:
  	xfs_iunlock(ip, lockmode);
  	return error;
68a9f5e70   Christoph Hellwig   xfs: implement io...
1061
1062
1063
1064
1065
1066
1067
  }
  
  static int
  xfs_file_iomap_end_delalloc(
  	struct xfs_inode	*ip,
  	loff_t			offset,
  	loff_t			length,
f65e6fad2   Brian Foster   xfs: use iomap ne...
1068
1069
  	ssize_t			written,
  	struct iomap		*iomap)
68a9f5e70   Christoph Hellwig   xfs: implement io...
1070
1071
1072
1073
1074
  {
  	struct xfs_mount	*mp = ip->i_mount;
  	xfs_fileoff_t		start_fsb;
  	xfs_fileoff_t		end_fsb;
  	int			error = 0;
f65e6fad2   Brian Foster   xfs: use iomap ne...
1075
1076
1077
1078
  	/*
  	 * Behave as if the write failed if drop writes is enabled. Set the NEW
  	 * flag to force delalloc cleanup.
  	 */
f8c47250b   Darrick J. Wong   xfs: convert drop...
1079
  	if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_DROP_WRITES)) {
f65e6fad2   Brian Foster   xfs: use iomap ne...
1080
  		iomap->flags |= IOMAP_F_NEW;
9dbddd7b0   Brian Foster   xfs: resurrect de...
1081
  		written = 0;
f65e6fad2   Brian Foster   xfs: use iomap ne...
1082
  	}
9dbddd7b0   Brian Foster   xfs: resurrect de...
1083

fa7f138ac   Brian Foster   xfs: clear delall...
1084
1085
1086
1087
1088
1089
1090
1091
1092
  	/*
  	 * start_fsb refers to the first unused block after a short write. If
  	 * nothing was written, round offset down to point at the first block in
  	 * the range.
  	 */
  	if (unlikely(!written))
  		start_fsb = XFS_B_TO_FSBT(mp, offset);
  	else
  		start_fsb = XFS_B_TO_FSB(mp, offset + written);
68a9f5e70   Christoph Hellwig   xfs: implement io...
1093
1094
1095
  	end_fsb = XFS_B_TO_FSB(mp, offset + length);
  
  	/*
f65e6fad2   Brian Foster   xfs: use iomap ne...
1096
1097
  	 * Trim delalloc blocks if they were allocated by this write and we
  	 * didn't manage to write the whole range.
68a9f5e70   Christoph Hellwig   xfs: implement io...
1098
1099
1100
1101
1102
  	 *
  	 * We don't need to care about racing delalloc as we hold i_mutex
  	 * across the reserve/allocate/unreserve calls. If there are delalloc
  	 * blocks in the range, they are ours.
  	 */
f65e6fad2   Brian Foster   xfs: use iomap ne...
1103
  	if ((iomap->flags & IOMAP_F_NEW) && start_fsb < end_fsb) {
fa7f138ac   Brian Foster   xfs: clear delall...
1104
1105
  		truncate_pagecache_range(VFS_I(ip), XFS_FSB_TO_B(mp, start_fsb),
  					 XFS_FSB_TO_B(mp, end_fsb) - 1);
68a9f5e70   Christoph Hellwig   xfs: implement io...
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
  		xfs_ilock(ip, XFS_ILOCK_EXCL);
  		error = xfs_bmap_punch_delalloc_range(ip, start_fsb,
  					       end_fsb - start_fsb);
  		xfs_iunlock(ip, XFS_ILOCK_EXCL);
  
  		if (error && !XFS_FORCED_SHUTDOWN(mp)) {
  			xfs_alert(mp, "%s: unable to clean up ino %lld",
  				__func__, ip->i_ino);
  			return error;
  		}
  	}
  
  	return 0;
  }
  
  static int
  xfs_file_iomap_end(
  	struct inode		*inode,
  	loff_t			offset,
  	loff_t			length,
  	ssize_t			written,
  	unsigned		flags,
  	struct iomap		*iomap)
  {
  	if ((flags & IOMAP_WRITE) && iomap->type == IOMAP_DELALLOC)
  		return xfs_file_iomap_end_delalloc(XFS_I(inode), offset,
f65e6fad2   Brian Foster   xfs: use iomap ne...
1132
  				length, written, iomap);
68a9f5e70   Christoph Hellwig   xfs: implement io...
1133
1134
  	return 0;
  }
8ff6daa17   Christoph Hellwig   iomap: constify s...
1135
  const struct iomap_ops xfs_iomap_ops = {
68a9f5e70   Christoph Hellwig   xfs: implement io...
1136
1137
1138
  	.iomap_begin		= xfs_file_iomap_begin,
  	.iomap_end		= xfs_file_iomap_end,
  };
1d4795e7b   Christoph Hellwig   xfs: (re-)impleme...
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
  
  static int
  xfs_xattr_iomap_begin(
  	struct inode		*inode,
  	loff_t			offset,
  	loff_t			length,
  	unsigned		flags,
  	struct iomap		*iomap)
  {
  	struct xfs_inode	*ip = XFS_I(inode);
  	struct xfs_mount	*mp = ip->i_mount;
  	xfs_fileoff_t		offset_fsb = XFS_B_TO_FSBT(mp, offset);
  	xfs_fileoff_t		end_fsb = XFS_B_TO_FSB(mp, offset + length);
  	struct xfs_bmbt_irec	imap;
  	int			nimaps = 1, error = 0;
  	unsigned		lockmode;
  
  	if (XFS_FORCED_SHUTDOWN(mp))
  		return -EIO;
84358536d   Darrick J. Wong   xfs: actually rep...
1158
  	lockmode = xfs_ilock_attr_map_shared(ip);
1d4795e7b   Christoph Hellwig   xfs: (re-)impleme...
1159
1160
  
  	/* if there are no attribute fork or extents, return ENOENT */
84358536d   Darrick J. Wong   xfs: actually rep...
1161
  	if (!XFS_IFORK_Q(ip) || !ip->i_d.di_anextents) {
1d4795e7b   Christoph Hellwig   xfs: (re-)impleme...
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
  		error = -ENOENT;
  		goto out_unlock;
  	}
  
  	ASSERT(ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL);
  	error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap,
  			       &nimaps, XFS_BMAPI_ENTIRE | XFS_BMAPI_ATTRFORK);
  out_unlock:
  	xfs_iunlock(ip, lockmode);
  
  	if (!error) {
  		ASSERT(nimaps);
  		xfs_bmbt_to_iomap(ip, iomap, &imap);
  	}
  
  	return error;
  }
8ff6daa17   Christoph Hellwig   iomap: constify s...
1179
  const struct iomap_ops xfs_xattr_iomap_ops = {
1d4795e7b   Christoph Hellwig   xfs: (re-)impleme...
1180
1181
  	.iomap_begin		= xfs_xattr_iomap_begin,
  };