blob: 221e2e3cec8c4cb807859fe67c916c5594d6c5ad [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Olaf Weber3e57ecf2006-06-09 14:48:12 +10002 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
Dave Chinner19de7352013-04-03 16:11:18 +11003 * Copyright (c) 2012 Red Hat, Inc.
Nathan Scott7b718762005-11-02 14:58:39 +11004 * All Rights Reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
Nathan Scott7b718762005-11-02 14:58:39 +11006 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * published by the Free Software Foundation.
9 *
Nathan Scott7b718762005-11-02 14:58:39 +110010 * This program is distributed in the hope that it would be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 *
Nathan Scott7b718762005-11-02 14:58:39 +110015 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 */
Randy Dunlap16f7e0f2006-01-11 12:17:46 -080019
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include "xfs.h"
Nathan Scotta844f452005-11-02 14:38:42 +110021#include "xfs_fs.h"
Dave Chinner6ca1c902013-08-12 20:49:26 +100022#include "xfs_format.h"
Nathan Scotta844f452005-11-02 14:38:42 +110023#include "xfs_bit.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include "xfs_log.h"
25#include "xfs_trans.h"
26#include "xfs_sb.h"
27#include "xfs_ag.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include "xfs_mount.h"
Nathan Scotta844f452005-11-02 14:38:42 +110029#include "xfs_da_btree.h"
Dave Chinner2b9ab5a2013-08-12 20:49:37 +100030#include "xfs_dir2_format.h"
31#include "xfs_dir2.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include "xfs_bmap_btree.h"
33#include "xfs_ialloc_btree.h"
Nathan Scotta844f452005-11-02 14:38:42 +110034#include "xfs_dinode.h"
35#include "xfs_inode.h"
36#include "xfs_inode_item.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include "xfs_itable.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include "xfs_ialloc.h"
39#include "xfs_alloc.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include "xfs_bmap.h"
Christoph Hellwigef14f0c2009-06-10 17:07:47 +020041#include "xfs_acl.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include "xfs_attr.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include "xfs_error.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include "xfs_quota.h"
45#include "xfs_utils.h"
Nathan Scotta844f452005-11-02 14:38:42 +110046#include "xfs_rtalloc.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include "xfs_trans_space.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#include "xfs_log_priv.h"
David Chinner2a82b8b2007-07-11 11:09:12 +100049#include "xfs_filestream.h"
Christoph Hellwig993386c2007-08-28 16:12:30 +100050#include "xfs_vnodeops.h"
Christoph Hellwig0b1b2132009-12-14 23:14:59 +000051#include "xfs_trace.h"
Dave Chinner33479e02012-10-08 21:56:11 +110052#include "xfs_icache.h"
Dave Chinner19de7352013-04-03 16:11:18 +110053#include "xfs_symlink.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
Linus Torvalds1da177e2005-04-16 15:20:36 -070056/*
David Chinner92dfe8d2007-05-24 15:22:19 +100057 * This is called by xfs_inactive to free any blocks beyond eof
58 * when the link count isn't zero and by xfs_dm_punch_hole() when
59 * punching a hole to EOF.
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 */
Brian Foster40165e22012-11-06 09:50:41 -050061int
David Chinner92dfe8d2007-05-24 15:22:19 +100062xfs_free_eofblocks(
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 xfs_mount_t *mp,
David Chinner92dfe8d2007-05-24 15:22:19 +100064 xfs_inode_t *ip,
Christoph Hellwig5a153222012-07-04 11:13:32 -040065 bool need_iolock)
Linus Torvalds1da177e2005-04-16 15:20:36 -070066{
67 xfs_trans_t *tp;
68 int error;
69 xfs_fileoff_t end_fsb;
70 xfs_fileoff_t last_fsb;
71 xfs_filblks_t map_len;
72 int nimaps;
73 xfs_bmbt_irec_t imap;
74
75 /*
76 * Figure out if there are any blocks beyond the end
77 * of the file. If not, then there is nothing to do.
78 */
Christoph Hellwigce7ae1512011-12-18 20:00:11 +000079 end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip));
Dave Chinner32972382012-06-08 15:44:54 +100080 last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
Kulikov Vasiliy3f348852010-07-20 17:54:28 +100081 if (last_fsb <= end_fsb)
Jesper Juhl014c2542006-01-15 02:37:08 +010082 return 0;
Kulikov Vasiliy3f348852010-07-20 17:54:28 +100083 map_len = last_fsb - end_fsb;
Linus Torvalds1da177e2005-04-16 15:20:36 -070084
85 nimaps = 1;
86 xfs_ilock(ip, XFS_ILOCK_SHARED);
Dave Chinner5c8ed202011-09-18 20:40:45 +000087 error = xfs_bmapi_read(ip, end_fsb, map_len, &imap, &nimaps, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 xfs_iunlock(ip, XFS_ILOCK_SHARED);
89
90 if (!error && (nimaps != 0) &&
Yingping Lu68bdb6e2006-01-11 15:38:31 +110091 (imap.br_startblock != HOLESTARTBLOCK ||
92 ip->i_delayed_blks)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 /*
94 * Attach the dquots to the inode up front.
95 */
Christoph Hellwig7d095252009-06-08 15:33:32 +020096 error = xfs_qm_dqattach(ip, 0);
97 if (error)
Jesper Juhl014c2542006-01-15 02:37:08 +010098 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
100 /*
101 * There are blocks after the end of file.
102 * Free them up now by truncating the file to
103 * its current size.
104 */
105 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
106
Christoph Hellwig5a153222012-07-04 11:13:32 -0400107 if (need_iolock) {
Christoph Hellwigc56c9632009-10-19 04:03:46 +0000108 if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) {
109 xfs_trans_cancel(tp, 0);
Brian Foster40165e22012-11-06 09:50:41 -0500110 return EAGAIN;
Christoph Hellwigc56c9632009-10-19 04:03:46 +0000111 }
Christoph Hellwigc56c9632009-10-19 04:03:46 +0000112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
114 error = xfs_trans_reserve(tp, 0,
115 XFS_ITRUNCATE_LOG_RES(mp),
116 0, XFS_TRANS_PERM_LOG_RES,
117 XFS_ITRUNCATE_LOG_COUNT);
118 if (error) {
119 ASSERT(XFS_FORCED_SHUTDOWN(mp));
120 xfs_trans_cancel(tp, 0);
Christoph Hellwig5a153222012-07-04 11:13:32 -0400121 if (need_iolock)
122 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
Jesper Juhl014c2542006-01-15 02:37:08 +0100123 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 }
125
126 xfs_ilock(ip, XFS_ILOCK_EXCL);
Christoph Hellwigddc34152011-09-19 15:00:54 +0000127 xfs_trans_ijoin(tp, ip, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
Christoph Hellwig673e8e52011-12-18 20:00:04 +0000129 /*
130 * Do not update the on-disk file size. If we update the
131 * on-disk file size and then the system crashes before the
132 * contents of the file are flushed to disk then the files
133 * may be full of holes (ie NULL files bug).
134 */
135 error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK,
Christoph Hellwigce7ae1512011-12-18 20:00:11 +0000136 XFS_ISIZE(ip));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 if (error) {
Christoph Hellwig8f04c472011-07-08 14:34:34 +0200138 /*
139 * If we get an error at this point we simply don't
140 * bother truncating the file.
141 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 xfs_trans_cancel(tp,
143 (XFS_TRANS_RELEASE_LOG_RES |
144 XFS_TRANS_ABORT));
145 } else {
146 error = xfs_trans_commit(tp,
Eric Sandeen1c72bf92007-05-08 13:48:42 +1000147 XFS_TRANS_RELEASE_LOG_RES);
Brian Foster27b52862012-11-06 09:50:38 -0500148 if (!error)
149 xfs_inode_clear_eofblocks_tag(ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 }
Christoph Hellwig5a153222012-07-04 11:13:32 -0400151
152 xfs_iunlock(ip, XFS_ILOCK_EXCL);
153 if (need_iolock)
154 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 }
Jesper Juhl014c2542006-01-15 02:37:08 +0100156 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157}
158
Christoph Hellwig993386c2007-08-28 16:12:30 +1000159int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160xfs_release(
Christoph Hellwig993386c2007-08-28 16:12:30 +1000161 xfs_inode_t *ip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162{
Christoph Hellwig993386c2007-08-28 16:12:30 +1000163 xfs_mount_t *mp = ip->i_mount;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 int error;
165
Christoph Hellwig42173f62008-04-22 17:33:25 +1000166 if (!S_ISREG(ip->i_d.di_mode) || (ip->i_d.di_mode == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168
169 /* If this is a read-only mount, don't do this (would generate I/O) */
Christoph Hellwigbd186aa2007-08-30 17:21:12 +1000170 if (mp->m_flags & XFS_MOUNT_RDONLY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 return 0;
172
David Chinner2a82b8b2007-07-11 11:09:12 +1000173 if (!XFS_FORCED_SHUTDOWN(mp)) {
Christoph Hellwigb3aea4e2007-08-29 11:44:37 +1000174 int truncated;
175
David Chinner2a82b8b2007-07-11 11:09:12 +1000176 /*
177 * If we are using filestreams, and we have an unlinked
178 * file that we are processing the last close on, then nothing
179 * will be able to reopen and write to this file. Purge this
180 * inode from the filestreams cache so that it doesn't delay
181 * teardown of the inode.
182 */
183 if ((ip->i_d.di_nlink == 0) && xfs_inode_is_filestream(ip))
184 xfs_filestream_deassociate(ip);
185
Christoph Hellwigfbf3ce82007-06-28 16:46:47 +1000186 /*
187 * If we previously truncated this file and removed old data
188 * in the process, we want to initiate "early" writeout on
189 * the last close. This is an attempt to combat the notorious
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300190 * NULL files problem which is particularly noticeable from a
Christoph Hellwigfbf3ce82007-06-28 16:46:47 +1000191 * truncate down, buffered (re-)write (delalloc), followed by
192 * a crash. What we are effectively doing here is
193 * significantly reducing the time window where we'd otherwise
194 * be exposed to that problem.
195 */
Christoph Hellwig09262b42007-08-29 11:44:50 +1000196 truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED);
Dave Chinnerdf4368a2011-06-23 01:35:00 +0000197 if (truncated) {
198 xfs_iflags_clear(ip, XFS_IDIRTY_RELEASE);
Dave Chinner4bc1ea62012-11-12 22:53:56 +1100199 if (VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0) {
200 error = -filemap_flush(VFS_I(ip)->i_mapping);
201 if (error)
202 return error;
203 }
Dave Chinnerdf4368a2011-06-23 01:35:00 +0000204 }
Christoph Hellwigfbf3ce82007-06-28 16:46:47 +1000205 }
206
Dave Chinner6e857562010-12-23 12:02:31 +1100207 if (ip->i_d.di_nlink == 0)
208 return 0;
Christoph Hellwigc56c9632009-10-19 04:03:46 +0000209
Brian Foster72b53ef2012-11-06 09:50:40 -0500210 if (xfs_can_free_eofblocks(ip, false)) {
Dave Chinner6e857562010-12-23 12:02:31 +1100211
212 /*
213 * If we can't get the iolock just skip truncating the blocks
214 * past EOF because we could deadlock with the mmap_sem
215 * otherwise. We'll get another chance to drop them once the
216 * last reference to the inode is dropped, so we'll never leak
217 * blocks permanently.
218 *
219 * Further, check if the inode is being opened, written and
220 * closed frequently and we have delayed allocation blocks
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300221 * outstanding (e.g. streaming writes from the NFS server),
Dave Chinner6e857562010-12-23 12:02:31 +1100222 * truncating the blocks past EOF will cause fragmentation to
223 * occur.
224 *
225 * In this case don't do the truncation, either, but we have to
226 * be careful how we detect this case. Blocks beyond EOF show
227 * up as i_delayed_blks even when the inode is clean, so we
228 * need to truncate them away first before checking for a dirty
229 * release. Hence on the first dirty close we will still remove
230 * the speculative allocation, but after that we will leave it
231 * in place.
232 */
233 if (xfs_iflags_test(ip, XFS_IDIRTY_RELEASE))
234 return 0;
235
Christoph Hellwig5a153222012-07-04 11:13:32 -0400236 error = xfs_free_eofblocks(mp, ip, true);
Brian Foster40165e22012-11-06 09:50:41 -0500237 if (error && error != EAGAIN)
Dave Chinner6e857562010-12-23 12:02:31 +1100238 return error;
239
240 /* delalloc blocks after truncation means it really is dirty */
241 if (ip->i_delayed_blks)
242 xfs_iflags_set(ip, XFS_IDIRTY_RELEASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 return 0;
245}
246
247/*
248 * xfs_inactive
249 *
250 * This is called when the vnode reference count for the vnode
251 * goes to zero. If the file has been unlinked, then it must
252 * now be truncated. Also, we clear all of the read-ahead state
253 * kept for the inode here since the file is now closed.
254 */
Christoph Hellwig993386c2007-08-28 16:12:30 +1000255int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256xfs_inactive(
Christoph Hellwig993386c2007-08-28 16:12:30 +1000257 xfs_inode_t *ip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258{
Nathan Scott67fcaa72006-06-09 17:00:52 +1000259 xfs_bmap_free_t free_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 xfs_fsblock_t first_block;
261 int committed;
262 xfs_trans_t *tp;
263 xfs_mount_t *mp;
264 int error;
Christoph Hellwigb373e982012-07-04 11:13:29 -0400265 int truncate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 /*
268 * If the inode is already free, then there can be nothing
269 * to clean up here.
270 */
Christoph Hellwigcb4c8cc2009-03-16 08:25:25 +0100271 if (ip->i_d.di_mode == 0 || is_bad_inode(VFS_I(ip))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 ASSERT(ip->i_df.if_real_bytes == 0);
273 ASSERT(ip->i_df.if_broot_bytes == 0);
274 return VN_INACTIVE_CACHE;
275 }
276
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 mp = ip->i_mount;
278
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 error = 0;
280
281 /* If this is a read-only mount, don't do this (would generate I/O) */
Christoph Hellwigbd186aa2007-08-30 17:21:12 +1000282 if (mp->m_flags & XFS_MOUNT_RDONLY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 goto out;
284
285 if (ip->i_d.di_nlink != 0) {
Brian Foster72b53ef2012-11-06 09:50:40 -0500286 /*
287 * force is true because we are evicting an inode from the
288 * cache. Post-eof blocks must be freed, lest we end up with
289 * broken free space accounting.
290 */
291 if (xfs_can_free_eofblocks(ip, true)) {
Christoph Hellwig5a153222012-07-04 11:13:32 -0400292 error = xfs_free_eofblocks(mp, ip, false);
David Chinner92dfe8d2007-05-24 15:22:19 +1000293 if (error)
Jesper Juhl014c2542006-01-15 02:37:08 +0100294 return VN_INACTIVE_CACHE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 }
296 goto out;
297 }
298
Christoph Hellwigb373e982012-07-04 11:13:29 -0400299 if (S_ISREG(ip->i_d.di_mode) &&
300 (ip->i_d.di_size != 0 || XFS_ISIZE(ip) != 0 ||
301 ip->i_d.di_nextents > 0 || ip->i_delayed_blks > 0))
302 truncate = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
Christoph Hellwig7d095252009-06-08 15:33:32 +0200304 error = xfs_qm_dqattach(ip, 0);
305 if (error)
Jesper Juhl014c2542006-01-15 02:37:08 +0100306 return VN_INACTIVE_CACHE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
308 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
Christoph Hellwigb373e982012-07-04 11:13:29 -0400309 error = xfs_trans_reserve(tp, 0,
310 (truncate || S_ISLNK(ip->i_d.di_mode)) ?
311 XFS_ITRUNCATE_LOG_RES(mp) :
312 XFS_IFREE_LOG_RES(mp),
313 0,
314 XFS_TRANS_PERM_LOG_RES,
315 XFS_ITRUNCATE_LOG_COUNT);
316 if (error) {
317 ASSERT(XFS_FORCED_SHUTDOWN(mp));
318 xfs_trans_cancel(tp, 0);
319 return VN_INACTIVE_CACHE;
320 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
Christoph Hellwig0b561852012-07-04 11:13:31 -0400322 xfs_ilock(ip, XFS_ILOCK_EXCL);
Christoph Hellwigb373e982012-07-04 11:13:29 -0400323 xfs_trans_ijoin(tp, ip, 0);
324
325 if (S_ISLNK(ip->i_d.di_mode)) {
Mark Tinguely725eb1e2013-06-17 15:35:57 -0500326 error = xfs_inactive_symlink(ip, &tp);
327 if (error)
328 goto out_cancel;
Christoph Hellwigb373e982012-07-04 11:13:29 -0400329 } else if (truncate) {
Christoph Hellwig673e8e52011-12-18 20:00:04 +0000330 ip->i_d.di_size = 0;
Christoph Hellwig673e8e52011-12-18 20:00:04 +0000331 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
332
333 error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
Christoph Hellwigb373e982012-07-04 11:13:29 -0400334 if (error)
335 goto out_cancel;
Christoph Hellwig673e8e52011-12-18 20:00:04 +0000336
337 ASSERT(ip->i_d.di_nextents == 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 }
339
340 /*
Christoph Hellwigfe67be02012-07-04 11:13:30 -0400341 * If there are attributes associated with the file then blow them away
342 * now. The code calls a routine that recursively deconstructs the
343 * attribute fork. We need to just commit the current transaction
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 * because we can't use it for xfs_attr_inactive().
345 */
346 if (ip->i_d.di_anextents > 0) {
Christoph Hellwigfe67be02012-07-04 11:13:30 -0400347 ASSERT(ip->i_d.di_forkoff != 0);
348
349 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
Christoph Hellwigfe67be02012-07-04 11:13:30 -0400350 if (error)
Christoph Hellwig0b561852012-07-04 11:13:31 -0400351 goto out_unlock;
352
353 xfs_iunlock(ip, XFS_ILOCK_EXCL);
Christoph Hellwigfe67be02012-07-04 11:13:30 -0400354
355 error = xfs_attr_inactive(ip);
356 if (error)
Christoph Hellwig0b561852012-07-04 11:13:31 -0400357 goto out;
Christoph Hellwigfe67be02012-07-04 11:13:30 -0400358
359 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
360 error = xfs_trans_reserve(tp, 0,
361 XFS_IFREE_LOG_RES(mp),
362 0, XFS_TRANS_PERM_LOG_RES,
363 XFS_INACTIVE_LOG_COUNT);
Christoph Hellwig0b561852012-07-04 11:13:31 -0400364 if (error) {
365 xfs_trans_cancel(tp, 0);
366 goto out;
367 }
Christoph Hellwigfe67be02012-07-04 11:13:30 -0400368
369 xfs_ilock(ip, XFS_ILOCK_EXCL);
370 xfs_trans_ijoin(tp, ip, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 }
372
Christoph Hellwigfe67be02012-07-04 11:13:30 -0400373 if (ip->i_afp)
374 xfs_idestroy_fork(ip, XFS_ATTR_FORK);
375
376 ASSERT(ip->i_d.di_anextents == 0);
377
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 /*
379 * Free the inode.
380 */
Eric Sandeen9d87c312009-01-14 23:22:07 -0600381 xfs_bmap_init(&free_list, &first_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 error = xfs_ifree(tp, ip, &free_list);
383 if (error) {
384 /*
385 * If we fail to free the inode, shut down. The cancel
386 * might do that, we need to make sure. Otherwise the
387 * inode might be lost for a long time or forever.
388 */
389 if (!XFS_FORCED_SHUTDOWN(mp)) {
Dave Chinner0b932cc2011-03-07 10:08:35 +1100390 xfs_notice(mp, "%s: xfs_ifree returned error %d",
391 __func__, error);
Nathan Scott7d04a332006-06-09 14:58:38 +1000392 xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 }
394 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
395 } else {
396 /*
397 * Credit the quota account(s). The inode is gone.
398 */
Christoph Hellwig7d095252009-06-08 15:33:32 +0200399 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_ICOUNT, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
401 /*
David Chinner78e9da72008-04-10 12:24:17 +1000402 * Just ignore errors at this point. There is nothing we can
403 * do except to try to keep going. Make sure it's not a silent
404 * error.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 */
David Chinner78e9da72008-04-10 12:24:17 +1000406 error = xfs_bmap_finish(&tp, &free_list, &committed);
407 if (error)
Dave Chinner53487782011-03-07 10:05:35 +1100408 xfs_notice(mp, "%s: xfs_bmap_finish returned error %d",
409 __func__, error);
David Chinner78e9da72008-04-10 12:24:17 +1000410 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
411 if (error)
Dave Chinner53487782011-03-07 10:05:35 +1100412 xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
413 __func__, error);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 }
Christoph Hellwig7d095252009-06-08 15:33:32 +0200415
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 /*
417 * Release the dquots held by inode, if any.
418 */
Christoph Hellwig7d095252009-06-08 15:33:32 +0200419 xfs_qm_dqdetach(ip);
Christoph Hellwig0b561852012-07-04 11:13:31 -0400420out_unlock:
421 xfs_iunlock(ip, XFS_ILOCK_EXCL);
Christoph Hellwigb373e982012-07-04 11:13:29 -0400422out:
423 return VN_INACTIVE_CACHE;
424out_cancel:
425 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
Christoph Hellwig0b561852012-07-04 11:13:31 -0400426 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427}
428
Barry Naujok384f3ce2008-05-21 16:58:22 +1000429/*
430 * Lookups up an inode from "name". If ci_name is not NULL, then a CI match
431 * is allowed, otherwise it has to be an exact match. If a CI match is found,
432 * ci_name->name will point to a the actual name (caller must free) or
433 * will be set to NULL if an exact match is found.
434 */
Christoph Hellwig993386c2007-08-28 16:12:30 +1000435int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436xfs_lookup(
Christoph Hellwig993386c2007-08-28 16:12:30 +1000437 xfs_inode_t *dp,
Barry Naujok556b8b12008-04-10 12:22:07 +1000438 struct xfs_name *name,
Barry Naujok384f3ce2008-05-21 16:58:22 +1000439 xfs_inode_t **ipp,
440 struct xfs_name *ci_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441{
Christoph Hellwigeca450b2008-04-22 17:33:52 +1000442 xfs_ino_t inum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 int error;
444 uint lock_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445
Christoph Hellwigcca28fb2010-06-24 11:57:09 +1000446 trace_xfs_lookup(dp, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
448 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
449 return XFS_ERROR(EIO);
450
451 lock_mode = xfs_ilock_map_shared(dp);
Barry Naujok384f3ce2008-05-21 16:58:22 +1000452 error = xfs_dir_lookup(NULL, dp, name, &inum, ci_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 xfs_iunlock_map_shared(dp, lock_mode);
Christoph Hellwigeca450b2008-04-22 17:33:52 +1000454
455 if (error)
456 goto out;
457
Dave Chinner7b6259e2010-06-24 11:35:17 +1000458 error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp);
Christoph Hellwigeca450b2008-04-22 17:33:52 +1000459 if (error)
Barry Naujok384f3ce2008-05-21 16:58:22 +1000460 goto out_free_name;
Christoph Hellwigeca450b2008-04-22 17:33:52 +1000461
Christoph Hellwigeca450b2008-04-22 17:33:52 +1000462 return 0;
463
Barry Naujok384f3ce2008-05-21 16:58:22 +1000464out_free_name:
465 if (ci_name)
466 kmem_free(ci_name->name);
467out:
Christoph Hellwigeca450b2008-04-22 17:33:52 +1000468 *ipp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 return error;
470}
471
Christoph Hellwig993386c2007-08-28 16:12:30 +1000472int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473xfs_create(
Christoph Hellwig993386c2007-08-28 16:12:30 +1000474 xfs_inode_t *dp,
Barry Naujok556b8b12008-04-10 12:22:07 +1000475 struct xfs_name *name,
Al Viro576b1d62011-07-26 02:50:15 -0400476 umode_t mode,
Christoph Hellwig3e5daf02007-10-11 18:09:12 +1000477 xfs_dev_t rdev,
Christoph Hellwig6c77b0e2010-10-06 18:41:17 +0000478 xfs_inode_t **ipp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479{
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100480 int is_dir = S_ISDIR(mode);
481 struct xfs_mount *mp = dp->i_mount;
482 struct xfs_inode *ip = NULL;
483 struct xfs_trans *tp = NULL;
Barry Naujok556b8b12008-04-10 12:22:07 +1000484 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 xfs_bmap_free_t free_list;
486 xfs_fsblock_t first_block;
Thiago Farina667a9292012-11-12 21:32:59 -0200487 bool unlock_dp_on_error = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 uint cancel_flags;
489 int committed;
Arkadiusz Mi?kiewicz67430992010-09-26 06:10:18 +0000490 prid_t prid;
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100491 struct xfs_dquot *udqp = NULL;
492 struct xfs_dquot *gdqp = NULL;
Chandra Seetharaman92f8ff72013-07-11 00:00:40 -0500493 struct xfs_dquot *pdqp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 uint resblks;
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100495 uint log_res;
496 uint log_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497
Christoph Hellwigcca28fb2010-06-24 11:57:09 +1000498 trace_xfs_create(dp, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100500 if (XFS_FORCED_SHUTDOWN(mp))
501 return XFS_ERROR(EIO);
502
Nathan Scott365ca832005-06-21 15:39:12 +1000503 if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
Arkadiusz Mi?kiewicz67430992010-09-26 06:10:18 +0000504 prid = xfs_get_projid(dp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 else
Arkadiusz Mi?kiewicz67430992010-09-26 06:10:18 +0000506 prid = XFS_PROJID_DEFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
508 /*
509 * Make sure that we have allocated dquot(s) on disk.
510 */
Christoph Hellwig7d095252009-06-08 15:33:32 +0200511 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
Chandra Seetharaman92f8ff72013-07-11 00:00:40 -0500512 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
513 &udqp, &gdqp, &pdqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 if (error)
Christoph Hellwigec3ba852011-02-13 13:26:42 +0000515 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100517 if (is_dir) {
518 rdev = 0;
519 resblks = XFS_MKDIR_SPACE_RES(mp, name->len);
520 log_res = XFS_MKDIR_LOG_RES(mp);
521 log_count = XFS_MKDIR_LOG_COUNT;
522 tp = xfs_trans_alloc(mp, XFS_TRANS_MKDIR);
523 } else {
524 resblks = XFS_CREATE_SPACE_RES(mp, name->len);
525 log_res = XFS_CREATE_LOG_RES(mp);
526 log_count = XFS_CREATE_LOG_COUNT;
527 tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE);
528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100531
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 /*
533 * Initially assume that the file does not exist and
534 * reserve the resources for that case. If that is not
535 * the case we'll drop the one we have and get a more
536 * appropriate transaction later.
537 */
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100538 error = xfs_trans_reserve(tp, resblks, log_res, 0,
539 XFS_TRANS_PERM_LOG_RES, log_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 if (error == ENOSPC) {
Dave Chinner153fec42009-04-06 18:48:30 +0200541 /* flush outstanding delalloc blocks and retry */
Dave Chinner9aa05002012-10-08 21:56:04 +1100542 xfs_flush_inodes(mp);
Christoph Hellwig4734d402009-09-09 18:19:02 -0500543 error = xfs_trans_reserve(tp, resblks, log_res, 0,
544 XFS_TRANS_PERM_LOG_RES, log_count);
Dave Chinner153fec42009-04-06 18:48:30 +0200545 }
546 if (error == ENOSPC) {
547 /* No space at all so try a "no-allocation" reservation */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 resblks = 0;
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100549 error = xfs_trans_reserve(tp, 0, log_res, 0,
550 XFS_TRANS_PERM_LOG_RES, log_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 }
552 if (error) {
553 cancel_flags = 0;
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100554 goto out_trans_cancel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 }
556
Lachlan McIlroyf7c66ce2007-05-08 13:50:19 +1000557 xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
Thiago Farina667a9292012-11-12 21:32:59 -0200558 unlock_dp_on_error = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100560 xfs_bmap_init(&free_list, &first_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
562 /*
563 * Reserve disk quota and the inode.
564 */
Chandra Seetharaman92f8ff72013-07-11 00:00:40 -0500565 error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
566 pdqp, resblks, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 if (error)
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100568 goto out_trans_cancel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
Barry Naujok556b8b12008-04-10 12:22:07 +1000570 error = xfs_dir_canenter(tp, dp, name, resblks);
571 if (error)
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100572 goto out_trans_cancel;
573
574 /*
575 * A newly created regular or special file just has one directory
576 * entry pointing to them, but a directory also the "." entry
577 * pointing to itself.
578 */
Christoph Hellwig6c77b0e2010-10-06 18:41:17 +0000579 error = xfs_dir_ialloc(&tp, dp, mode, is_dir ? 2 : 1, rdev,
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100580 prid, resblks > 0, &ip, &committed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 if (error) {
582 if (error == ENOSPC)
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100583 goto out_trans_cancel;
584 goto out_trans_abort;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586
587 /*
Christoph Hellwig993386c2007-08-28 16:12:30 +1000588 * Now we join the directory inode to the transaction. We do not do it
589 * earlier because xfs_dir_ialloc might commit the previous transaction
590 * (and release all the locks). An error from here on will result in
591 * the transaction cancel unlocking dp so don't do it explicitly in the
592 * error path.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 */
Christoph Hellwigddc34152011-09-19 15:00:54 +0000594 xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
Thiago Farina667a9292012-11-12 21:32:59 -0200595 unlock_dp_on_error = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
Barry Naujok556b8b12008-04-10 12:22:07 +1000597 error = xfs_dir_createname(tp, dp, name, ip->i_ino,
Nathan Scottf6c2d1f2006-06-20 13:04:51 +1000598 &first_block, &free_list, resblks ?
599 resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 if (error) {
601 ASSERT(error != ENOSPC);
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100602 goto out_trans_abort;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 }
Dave Chinnerdcd79a12010-09-28 12:27:25 +1000604 xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
606
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100607 if (is_dir) {
608 error = xfs_dir_init(tp, ip, dp);
609 if (error)
610 goto out_bmap_cancel;
611
612 error = xfs_bumplink(tp, dp);
613 if (error)
614 goto out_bmap_cancel;
615 }
616
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 /*
618 * If this is a synchronous mount, make sure that the
619 * create transaction goes to disk before returning to
620 * the user.
621 */
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100622 if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 xfs_trans_set_sync(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 /*
626 * Attach the dquot(s) to the inodes and modify them incore.
627 * These ids of the inode couldn't have changed since the new
628 * inode has been locked ever since it was created.
629 */
Chandra Seetharaman92f8ff72013-07-11 00:00:40 -0500630 xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631
Eric Sandeenf7c99b62007-02-10 18:37:16 +1100632 error = xfs_bmap_finish(&tp, &free_list, &committed);
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100633 if (error)
Christoph Hellwigec3ba852011-02-13 13:26:42 +0000634 goto out_bmap_cancel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
Eric Sandeen1c72bf92007-05-08 13:48:42 +1000636 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
Christoph Hellwigec3ba852011-02-13 13:26:42 +0000637 if (error)
638 goto out_release_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639
Christoph Hellwig7d095252009-06-08 15:33:32 +0200640 xfs_qm_dqrele(udqp);
641 xfs_qm_dqrele(gdqp);
Chandra Seetharaman92f8ff72013-07-11 00:00:40 -0500642 xfs_qm_dqrele(pdqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
Christoph Hellwig979ebab2008-03-06 13:46:05 +1100644 *ipp = ip;
Christoph Hellwig288699f2010-06-23 18:11:15 +1000645 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100647 out_bmap_cancel:
648 xfs_bmap_cancel(&free_list);
649 out_trans_abort:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 cancel_flags |= XFS_TRANS_ABORT;
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100651 out_trans_cancel:
652 xfs_trans_cancel(tp, cancel_flags);
Christoph Hellwigec3ba852011-02-13 13:26:42 +0000653 out_release_inode:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 /*
655 * Wait until after the current transaction is aborted to
656 * release the inode. This prevents recursive transactions
657 * and deadlocks from xfs_inactive.
658 */
Christoph Hellwigec3ba852011-02-13 13:26:42 +0000659 if (ip)
660 IRELE(ip);
661
662 xfs_qm_dqrele(udqp);
663 xfs_qm_dqrele(gdqp);
Chandra Seetharaman92f8ff72013-07-11 00:00:40 -0500664 xfs_qm_dqrele(pdqp);
Christoph Hellwigec3ba852011-02-13 13:26:42 +0000665
666 if (unlock_dp_on_error)
667 xfs_iunlock(dp, XFS_ILOCK_EXCL);
668 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669}
670
671#ifdef DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672int xfs_locked_n;
673int xfs_small_retries;
674int xfs_middle_retries;
675int xfs_lots_retries;
676int xfs_lock_delays;
677#endif
678
679/*
Lachlan McIlroyf7c66ce2007-05-08 13:50:19 +1000680 * Bump the subclass so xfs_lock_inodes() acquires each lock with
681 * a different value
682 */
683static inline int
684xfs_lock_inumorder(int lock_mode, int subclass)
685{
686 if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL))
David Chinner0f1145c2007-06-29 17:26:09 +1000687 lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_IOLOCK_SHIFT;
Lachlan McIlroyf7c66ce2007-05-08 13:50:19 +1000688 if (lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL))
David Chinner0f1145c2007-06-29 17:26:09 +1000689 lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_ILOCK_SHIFT;
Lachlan McIlroyf7c66ce2007-05-08 13:50:19 +1000690
691 return lock_mode;
692}
693
694/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 * The following routine will lock n inodes in exclusive mode.
696 * We assume the caller calls us with the inodes in i_ino order.
697 *
698 * We need to detect deadlock where an inode that we lock
699 * is in the AIL and we start waiting for another inode that is locked
700 * by a thread in a long running transaction (such as truncate). This can
701 * result in deadlock since the long running trans might need to wait
702 * for the inode we just locked in order to push the tail and free space
703 * in the log.
704 */
705void
706xfs_lock_inodes(
707 xfs_inode_t **ips,
708 int inodes,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 uint lock_mode)
710{
711 int attempts = 0, i, j, try_lock;
712 xfs_log_item_t *lp;
713
714 ASSERT(ips && (inodes >= 2)); /* we need at least two */
715
Christoph Hellwigcfa853e2008-04-22 17:34:06 +1000716 try_lock = 0;
717 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
719again:
720 for (; i < inodes; i++) {
721 ASSERT(ips[i]);
722
723 if (i && (ips[i] == ips[i-1])) /* Already locked */
724 continue;
725
726 /*
727 * If try_lock is not set yet, make sure all locked inodes
728 * are not in the AIL.
729 * If any are, set try_lock to be used later.
730 */
731
732 if (!try_lock) {
733 for (j = (i - 1); j >= 0 && !try_lock; j--) {
734 lp = (xfs_log_item_t *)ips[j]->i_itemp;
735 if (lp && (lp->li_flags & XFS_LI_IN_AIL)) {
736 try_lock++;
737 }
738 }
739 }
740
741 /*
742 * If any of the previous locks we have locked is in the AIL,
743 * we must TRY to get the second and subsequent locks. If
744 * we can't get any, we must release all we have
745 * and try again.
746 */
747
748 if (try_lock) {
749 /* try_lock must be 0 if i is 0. */
750 /*
751 * try_lock means we have an inode locked
752 * that is in the AIL.
753 */
754 ASSERT(i != 0);
Lachlan McIlroyf7c66ce2007-05-08 13:50:19 +1000755 if (!xfs_ilock_nowait(ips[i], xfs_lock_inumorder(lock_mode, i))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 attempts++;
757
758 /*
759 * Unlock all previous guys and try again.
760 * xfs_iunlock will try to push the tail
761 * if the inode is in the AIL.
762 */
763
764 for(j = i - 1; j >= 0; j--) {
765
766 /*
767 * Check to see if we've already
768 * unlocked this one.
769 * Not the first one going back,
770 * and the inode ptr is the same.
771 */
772 if ((j != (i - 1)) && ips[j] ==
773 ips[j+1])
774 continue;
775
776 xfs_iunlock(ips[j], lock_mode);
777 }
778
779 if ((attempts % 5) == 0) {
780 delay(1); /* Don't just spin the CPU */
781#ifdef DEBUG
782 xfs_lock_delays++;
783#endif
784 }
785 i = 0;
786 try_lock = 0;
787 goto again;
788 }
789 } else {
Lachlan McIlroyf7c66ce2007-05-08 13:50:19 +1000790 xfs_ilock(ips[i], xfs_lock_inumorder(lock_mode, i));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 }
792 }
793
794#ifdef DEBUG
795 if (attempts) {
796 if (attempts < 5) xfs_small_retries++;
797 else if (attempts < 100) xfs_middle_retries++;
798 else xfs_lots_retries++;
799 } else {
800 xfs_locked_n++;
801 }
802#endif
803}
804
David Chinnerf9114eb2008-09-17 16:51:21 +1000805/*
806 * xfs_lock_two_inodes() can only be used to lock one type of lock
807 * at a time - the iolock or the ilock, but not both at once. If
808 * we lock both at once, lockdep will report false positives saying
809 * we have violated locking orders.
810 */
Christoph Hellwige1cccd92008-08-13 16:18:07 +1000811void
812xfs_lock_two_inodes(
813 xfs_inode_t *ip0,
814 xfs_inode_t *ip1,
815 uint lock_mode)
816{
817 xfs_inode_t *temp;
818 int attempts = 0;
819 xfs_log_item_t *lp;
820
David Chinnerf9114eb2008-09-17 16:51:21 +1000821 if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL))
822 ASSERT((lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)) == 0);
Christoph Hellwige1cccd92008-08-13 16:18:07 +1000823 ASSERT(ip0->i_ino != ip1->i_ino);
824
825 if (ip0->i_ino > ip1->i_ino) {
826 temp = ip0;
827 ip0 = ip1;
828 ip1 = temp;
829 }
830
831 again:
832 xfs_ilock(ip0, xfs_lock_inumorder(lock_mode, 0));
833
834 /*
835 * If the first lock we have locked is in the AIL, we must TRY to get
836 * the second lock. If we can't get it, we must release the first one
837 * and try again.
838 */
839 lp = (xfs_log_item_t *)ip0->i_itemp;
840 if (lp && (lp->li_flags & XFS_LI_IN_AIL)) {
841 if (!xfs_ilock_nowait(ip1, xfs_lock_inumorder(lock_mode, 1))) {
842 xfs_iunlock(ip0, lock_mode);
843 if ((++attempts % 5) == 0)
844 delay(1); /* Don't just spin the CPU */
845 goto again;
846 }
847 } else {
848 xfs_ilock(ip1, xfs_lock_inumorder(lock_mode, 1));
849 }
850}
851
Christoph Hellwig993386c2007-08-28 16:12:30 +1000852int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853xfs_remove(
Christoph Hellwig993386c2007-08-28 16:12:30 +1000854 xfs_inode_t *dp,
Barry Naujok556b8b12008-04-10 12:22:07 +1000855 struct xfs_name *name,
856 xfs_inode_t *ip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857{
Christoph Hellwig993386c2007-08-28 16:12:30 +1000858 xfs_mount_t *mp = dp->i_mount;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 xfs_trans_t *tp = NULL;
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000860 int is_dir = S_ISDIR(ip->i_d.di_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 int error = 0;
862 xfs_bmap_free_t free_list;
863 xfs_fsblock_t first_block;
864 int cancel_flags;
865 int committed;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 int link_zero;
867 uint resblks;
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000868 uint log_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869
Christoph Hellwigcca28fb2010-06-24 11:57:09 +1000870 trace_xfs_remove(dp, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 if (XFS_FORCED_SHUTDOWN(mp))
873 return XFS_ERROR(EIO);
874
Christoph Hellwig7d095252009-06-08 15:33:32 +0200875 error = xfs_qm_dqattach(dp, 0);
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000876 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 goto std_return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878
Christoph Hellwig7d095252009-06-08 15:33:32 +0200879 error = xfs_qm_dqattach(ip, 0);
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000880 if (error)
881 goto std_return;
882
883 if (is_dir) {
884 tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR);
885 log_count = XFS_DEFAULT_LOG_COUNT;
886 } else {
887 tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE);
888 log_count = XFS_REMOVE_LOG_COUNT;
889 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000891
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 /*
893 * We try to get the real space reservation first,
894 * allowing for directory btree deletion(s) implying
895 * possible bmap insert(s). If we can't get the space
896 * reservation then we use 0 instead, and avoid the bmap
897 * btree insert(s) in the directory code by, if the bmap
898 * insert tries to happen, instead trimming the LAST
899 * block from the directory.
900 */
901 resblks = XFS_REMOVE_SPACE_RES(mp);
902 error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000903 XFS_TRANS_PERM_LOG_RES, log_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 if (error == ENOSPC) {
905 resblks = 0;
906 error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000907 XFS_TRANS_PERM_LOG_RES, log_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 }
909 if (error) {
910 ASSERT(error != ENOSPC);
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000911 cancel_flags = 0;
912 goto out_trans_cancel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 }
914
Christoph Hellwige1cccd92008-08-13 16:18:07 +1000915 xfs_lock_two_inodes(dp, ip, XFS_ILOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916
Christoph Hellwigddc34152011-09-19 15:00:54 +0000917 xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
918 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
920 /*
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000921 * If we're removing a directory perform some additional validation.
922 */
923 if (is_dir) {
924 ASSERT(ip->i_d.di_nlink >= 2);
925 if (ip->i_d.di_nlink != 2) {
926 error = XFS_ERROR(ENOTEMPTY);
927 goto out_trans_cancel;
928 }
929 if (!xfs_dir_isempty(ip)) {
930 error = XFS_ERROR(ENOTEMPTY);
931 goto out_trans_cancel;
932 }
933 }
934
Eric Sandeen9d87c312009-01-14 23:22:07 -0600935 xfs_bmap_init(&free_list, &first_block);
Barry Naujok556b8b12008-04-10 12:22:07 +1000936 error = xfs_dir_removename(tp, dp, name, ip->i_ino,
Christoph Hellwigd4377d82008-04-22 17:33:46 +1000937 &first_block, &free_list, resblks);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 if (error) {
939 ASSERT(error != ENOENT);
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000940 goto out_bmap_cancel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 }
Dave Chinnerdcd79a12010-09-28 12:27:25 +1000942 xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000944 if (is_dir) {
945 /*
946 * Drop the link from ip's "..".
947 */
948 error = xfs_droplink(tp, dp);
949 if (error)
950 goto out_bmap_cancel;
951
952 /*
Christoph Hellwig2b7035f2008-10-30 17:55:18 +1100953 * Drop the "." link from ip to self.
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000954 */
955 error = xfs_droplink(tp, ip);
956 if (error)
957 goto out_bmap_cancel;
958 } else {
959 /*
960 * When removing a non-directory we need to log the parent
Dave Chinner26c52952008-11-28 14:23:37 +1100961 * inode here. For a directory this is done implicitly
962 * by the xfs_droplink call for the ".." entry.
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000963 */
964 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 }
966
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000967 /*
Christoph Hellwig2b7035f2008-10-30 17:55:18 +1100968 * Drop the link from dp to ip.
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000969 */
970 error = xfs_droplink(tp, ip);
971 if (error)
972 goto out_bmap_cancel;
973
974 /*
975 * Determine if this is the last link while
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 * we are in the transaction.
977 */
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000978 link_zero = (ip->i_d.di_nlink == 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
980 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 * If this is a synchronous mount, make sure that the
982 * remove transaction goes to disk before returning to
983 * the user.
984 */
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000985 if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 xfs_trans_set_sync(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987
Eric Sandeenf7c99b62007-02-10 18:37:16 +1100988 error = xfs_bmap_finish(&tp, &free_list, &committed);
Christoph Hellwig8f112e32008-06-23 13:25:17 +1000989 if (error)
990 goto out_bmap_cancel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
Eric Sandeen1c72bf92007-05-08 13:48:42 +1000992 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
Christoph Hellwig5df78e72008-04-22 17:34:24 +1000993 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 goto std_return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995
996 /*
David Chinner2a82b8b2007-07-11 11:09:12 +1000997 * If we are using filestreams, kill the stream association.
998 * If the file is still open it may get a new one but that
999 * will get killed on last close in xfs_close() so we don't
1000 * have to worry about that.
1001 */
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001002 if (!is_dir && link_zero && xfs_inode_is_filestream(ip))
David Chinner2a82b8b2007-07-11 11:09:12 +10001003 xfs_filestream_deassociate(ip);
1004
Christoph Hellwig288699f2010-06-23 18:11:15 +10001005 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001007 out_bmap_cancel:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 xfs_bmap_cancel(&free_list);
1009 cancel_flags |= XFS_TRANS_ABORT;
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001010 out_trans_cancel:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 xfs_trans_cancel(tp, cancel_flags);
Christoph Hellwig288699f2010-06-23 18:11:15 +10001012 std_return:
1013 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014}
1015
Christoph Hellwig993386c2007-08-28 16:12:30 +10001016int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017xfs_link(
Christoph Hellwig993386c2007-08-28 16:12:30 +10001018 xfs_inode_t *tdp,
Christoph Hellwiga3da7892008-03-06 13:46:12 +11001019 xfs_inode_t *sip,
Barry Naujok556b8b12008-04-10 12:22:07 +10001020 struct xfs_name *target_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021{
Christoph Hellwig993386c2007-08-28 16:12:30 +10001022 xfs_mount_t *mp = tdp->i_mount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 xfs_trans_t *tp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 int error;
1025 xfs_bmap_free_t free_list;
1026 xfs_fsblock_t first_block;
1027 int cancel_flags;
1028 int committed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 int resblks;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030
Christoph Hellwigcca28fb2010-06-24 11:57:09 +10001031 trace_xfs_link(tdp, target_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032
Christoph Hellwiga3da7892008-03-06 13:46:12 +11001033 ASSERT(!S_ISDIR(sip->i_d.di_mode));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 if (XFS_FORCED_SHUTDOWN(mp))
1036 return XFS_ERROR(EIO);
1037
Christoph Hellwig7d095252009-06-08 15:33:32 +02001038 error = xfs_qm_dqattach(sip, 0);
Christoph Hellwigcb3f35b2009-02-04 09:34:20 +01001039 if (error)
1040 goto std_return;
1041
Christoph Hellwig7d095252009-06-08 15:33:32 +02001042 error = xfs_qm_dqattach(tdp, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 if (error)
1044 goto std_return;
1045
1046 tp = xfs_trans_alloc(mp, XFS_TRANS_LINK);
1047 cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
Barry Naujok556b8b12008-04-10 12:22:07 +10001048 resblks = XFS_LINK_SPACE_RES(mp, target_name->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 error = xfs_trans_reserve(tp, resblks, XFS_LINK_LOG_RES(mp), 0,
1050 XFS_TRANS_PERM_LOG_RES, XFS_LINK_LOG_COUNT);
1051 if (error == ENOSPC) {
1052 resblks = 0;
1053 error = xfs_trans_reserve(tp, 0, XFS_LINK_LOG_RES(mp), 0,
1054 XFS_TRANS_PERM_LOG_RES, XFS_LINK_LOG_COUNT);
1055 }
1056 if (error) {
1057 cancel_flags = 0;
1058 goto error_return;
1059 }
1060
Christoph Hellwige1cccd92008-08-13 16:18:07 +10001061 xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
Christoph Hellwigddc34152011-09-19 15:00:54 +00001063 xfs_trans_ijoin(tp, sip, XFS_ILOCK_EXCL);
1064 xfs_trans_ijoin(tp, tdp, XFS_ILOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
1066 /*
Nathan Scott365ca832005-06-21 15:39:12 +10001067 * If we are using project inheritance, we only allow hard link
1068 * creation in our tree when the project IDs are the same; else
1069 * the tree quota mechanism could be circumvented.
1070 */
1071 if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
Arkadiusz Mi?kiewicz67430992010-09-26 06:10:18 +00001072 (xfs_get_projid(tdp) != xfs_get_projid(sip)))) {
Nathan Scottb1ecdda2006-05-08 19:51:42 +10001073 error = XFS_ERROR(EXDEV);
Nathan Scott365ca832005-06-21 15:39:12 +10001074 goto error_return;
1075 }
1076
Barry Naujok556b8b12008-04-10 12:22:07 +10001077 error = xfs_dir_canenter(tp, tdp, target_name, resblks);
1078 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 goto error_return;
1080
Eric Sandeen9d87c312009-01-14 23:22:07 -06001081 xfs_bmap_init(&free_list, &first_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082
Barry Naujok556b8b12008-04-10 12:22:07 +10001083 error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino,
1084 &first_block, &free_list, resblks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 if (error)
1086 goto abort_return;
Dave Chinnerdcd79a12010-09-28 12:27:25 +10001087 xfs_trans_ichgtime(tp, tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE);
1089
1090 error = xfs_bumplink(tp, sip);
Alexey Dobriyanb71d3002006-06-27 12:45:17 +10001091 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 goto abort_return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093
1094 /*
1095 * If this is a synchronous mount, make sure that the
1096 * link transaction goes to disk before returning to
1097 * the user.
1098 */
1099 if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
1100 xfs_trans_set_sync(tp);
1101 }
1102
Eric Sandeenf7c99b62007-02-10 18:37:16 +11001103 error = xfs_bmap_finish (&tp, &free_list, &committed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 if (error) {
1105 xfs_bmap_cancel(&free_list);
1106 goto abort_return;
1107 }
1108
Christoph Hellwig288699f2010-06-23 18:11:15 +10001109 return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110
1111 abort_return:
1112 cancel_flags |= XFS_TRANS_ABORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 error_return:
1114 xfs_trans_cancel(tp, cancel_flags);
Christoph Hellwig288699f2010-06-23 18:11:15 +10001115 std_return:
1116 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117}
Alexey Dobriyanb71d3002006-06-27 12:45:17 +10001118
Christoph Hellwig993386c2007-08-28 16:12:30 +10001119int
Christoph Hellwig993386c2007-08-28 16:12:30 +10001120xfs_set_dmattrs(
1121 xfs_inode_t *ip,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 u_int evmask,
Christoph Hellwig993386c2007-08-28 16:12:30 +10001123 u_int16_t state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124{
Christoph Hellwig993386c2007-08-28 16:12:30 +10001125 xfs_mount_t *mp = ip->i_mount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 xfs_trans_t *tp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 int error;
1128
1129 if (!capable(CAP_SYS_ADMIN))
1130 return XFS_ERROR(EPERM);
1131
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 if (XFS_FORCED_SHUTDOWN(mp))
1133 return XFS_ERROR(EIO);
1134
1135 tp = xfs_trans_alloc(mp, XFS_TRANS_SET_DMATTRS);
1136 error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES (mp), 0, 0, 0);
1137 if (error) {
1138 xfs_trans_cancel(tp, 0);
1139 return error;
1140 }
1141 xfs_ilock(ip, XFS_ILOCK_EXCL);
Christoph Hellwigddc34152011-09-19 15:00:54 +00001142 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143
Christoph Hellwig613d7042007-10-11 17:44:08 +10001144 ip->i_d.di_dmevmask = evmask;
1145 ip->i_d.di_dmstate = state;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146
1147 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
Eric Sandeen1c72bf92007-05-08 13:48:42 +10001148 error = xfs_trans_commit(tp, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149
1150 return error;
1151}
1152
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153/*
1154 * xfs_alloc_file_space()
1155 * This routine allocates disk space for the given file.
1156 *
1157 * If alloc_type == 0, this request is for an ALLOCSP type
1158 * request which will change the file size. In this case, no
1159 * DMAPI event will be generated by the call. A TRUNCATE event
1160 * will be generated later by xfs_setattr.
1161 *
1162 * If alloc_type != 0, this request is for a RESVSP type
1163 * request, and a DMAPI DM_EVENT_WRITE will be generated if the
1164 * lower block boundary byte address is less than the file's
1165 * length.
1166 *
1167 * RETURNS:
1168 * 0 on success
1169 * errno on error
1170 *
1171 */
Christoph Hellwigba0f32d2005-06-21 15:36:52 +10001172STATIC int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173xfs_alloc_file_space(
1174 xfs_inode_t *ip,
1175 xfs_off_t offset,
1176 xfs_off_t len,
1177 int alloc_type,
1178 int attr_flags)
1179{
Nathan Scottdd9f4382006-01-11 15:28:28 +11001180 xfs_mount_t *mp = ip->i_mount;
1181 xfs_off_t count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 xfs_filblks_t allocated_fsb;
1183 xfs_filblks_t allocatesize_fsb;
Nathan Scottdd9f4382006-01-11 15:28:28 +11001184 xfs_extlen_t extsz, temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 xfs_fileoff_t startoffset_fsb;
Nathan Scottdd9f4382006-01-11 15:28:28 +11001186 xfs_fsblock_t firstfsb;
1187 int nimaps;
Nathan Scottdd9f4382006-01-11 15:28:28 +11001188 int quota_flag;
1189 int rt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 xfs_trans_t *tp;
Nathan Scottdd9f4382006-01-11 15:28:28 +11001191 xfs_bmbt_irec_t imaps[1], *imapp;
1192 xfs_bmap_free_t free_list;
1193 uint qblocks, resblks, resrtextents;
1194 int committed;
1195 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196
Christoph Hellwigcca28fb2010-06-24 11:57:09 +10001197 trace_xfs_alloc_file_space(ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198
1199 if (XFS_FORCED_SHUTDOWN(mp))
1200 return XFS_ERROR(EIO);
1201
Christoph Hellwig7d095252009-06-08 15:33:32 +02001202 error = xfs_qm_dqattach(ip, 0);
1203 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 return error;
1205
1206 if (len <= 0)
1207 return XFS_ERROR(EINVAL);
1208
David Chinner957d0eb2007-06-18 16:50:37 +10001209 rt = XFS_IS_REALTIME_INODE(ip);
1210 extsz = xfs_get_extsz_hint(ip);
1211
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 count = len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 imapp = &imaps[0];
Nathan Scottdd9f4382006-01-11 15:28:28 +11001214 nimaps = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
1216 allocatesize_fsb = XFS_B_TO_FSB(mp, count);
1217
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 /*
Nathan Scottdd9f4382006-01-11 15:28:28 +11001219 * Allocate file space until done or until there is an error
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 while (allocatesize_fsb && !error) {
Nathan Scottdd9f4382006-01-11 15:28:28 +11001222 xfs_fileoff_t s, e;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
Nathan Scottdd9f4382006-01-11 15:28:28 +11001224 /*
Nathan Scott3ddb8fa2006-01-11 15:33:02 +11001225 * Determine space reservations for data/realtime.
Nathan Scottdd9f4382006-01-11 15:28:28 +11001226 */
1227 if (unlikely(extsz)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 s = startoffset_fsb;
Nathan Scottdd9f4382006-01-11 15:28:28 +11001229 do_div(s, extsz);
1230 s *= extsz;
1231 e = startoffset_fsb + allocatesize_fsb;
1232 if ((temp = do_mod(startoffset_fsb, extsz)))
1233 e += temp;
1234 if ((temp = do_mod(e, extsz)))
1235 e += extsz - temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 } else {
Nathan Scottdd9f4382006-01-11 15:28:28 +11001237 s = 0;
1238 e = allocatesize_fsb;
1239 }
1240
Dave Chinner72656c42010-09-03 12:19:33 +10001241 /*
1242 * The transaction reservation is limited to a 32-bit block
1243 * count, hence we need to limit the number of blocks we are
1244 * trying to reserve to avoid an overflow. We can't allocate
1245 * more than @nimaps extents, and an extent is limited on disk
1246 * to MAXEXTLEN (21 bits), so use that to enforce the limit.
1247 */
1248 resblks = min_t(xfs_fileoff_t, (e - s), (MAXEXTLEN * nimaps));
Nathan Scottdd9f4382006-01-11 15:28:28 +11001249 if (unlikely(rt)) {
Dave Chinner72656c42010-09-03 12:19:33 +10001250 resrtextents = qblocks = resblks;
Nathan Scottdd9f4382006-01-11 15:28:28 +11001251 resrtextents /= mp->m_sb.sb_rextsize;
1252 resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
1253 quota_flag = XFS_QMOPT_RES_RTBLKS;
1254 } else {
1255 resrtextents = 0;
Dave Chinner72656c42010-09-03 12:19:33 +10001256 resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resblks);
Nathan Scottdd9f4382006-01-11 15:28:28 +11001257 quota_flag = XFS_QMOPT_RES_REGBLKS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 }
1259
1260 /*
Nathan Scottdd9f4382006-01-11 15:28:28 +11001261 * Allocate and setup the transaction.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 */
1263 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
Nathan Scottdd9f4382006-01-11 15:28:28 +11001264 error = xfs_trans_reserve(tp, resblks,
1265 XFS_WRITE_LOG_RES(mp), resrtextents,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 XFS_TRANS_PERM_LOG_RES,
1267 XFS_WRITE_LOG_COUNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 /*
Nathan Scottdd9f4382006-01-11 15:28:28 +11001269 * Check for running out of space
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 */
1271 if (error) {
1272 /*
1273 * Free the transaction structure.
1274 */
1275 ASSERT(error == ENOSPC || XFS_FORCED_SHUTDOWN(mp));
1276 xfs_trans_cancel(tp, 0);
1277 break;
1278 }
1279 xfs_ilock(ip, XFS_ILOCK_EXCL);
Christoph Hellwig7d095252009-06-08 15:33:32 +02001280 error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks,
1281 0, quota_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 if (error)
1283 goto error1;
1284
Christoph Hellwigddc34152011-09-19 15:00:54 +00001285 xfs_trans_ijoin(tp, ip, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286
Eric Sandeen9d87c312009-01-14 23:22:07 -06001287 xfs_bmap_init(&free_list, &firstfsb);
Dave Chinnerc0dc7822011-09-18 20:40:52 +00001288 error = xfs_bmapi_write(tp, ip, startoffset_fsb,
1289 allocatesize_fsb, alloc_type, &firstfsb,
1290 0, imapp, &nimaps, &free_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 if (error) {
1292 goto error0;
1293 }
1294
1295 /*
Nathan Scottdd9f4382006-01-11 15:28:28 +11001296 * Complete the transaction
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 */
Eric Sandeenf7c99b62007-02-10 18:37:16 +11001298 error = xfs_bmap_finish(&tp, &free_list, &committed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 if (error) {
1300 goto error0;
1301 }
1302
Eric Sandeen1c72bf92007-05-08 13:48:42 +10001303 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1305 if (error) {
1306 break;
1307 }
1308
1309 allocated_fsb = imapp->br_blockcount;
1310
Nathan Scottdd9f4382006-01-11 15:28:28 +11001311 if (nimaps == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 error = XFS_ERROR(ENOSPC);
1313 break;
1314 }
1315
1316 startoffset_fsb += allocated_fsb;
1317 allocatesize_fsb -= allocated_fsb;
1318 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319
1320 return error;
1321
Nathan Scottdd9f4382006-01-11 15:28:28 +11001322error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 xfs_bmap_cancel(&free_list);
Dave Chinnerea562ed2012-05-08 20:48:53 +10001324 xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag);
Nathan Scottdd9f4382006-01-11 15:28:28 +11001325
1326error1: /* Just cancel transaction */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
1328 xfs_iunlock(ip, XFS_ILOCK_EXCL);
Christoph Hellwig288699f2010-06-23 18:11:15 +10001329 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330}
1331
1332/*
1333 * Zero file bytes between startoff and endoff inclusive.
1334 * The iolock is held exclusive and no blocks are buffered.
Lachlan McIlroy2fd6f6e2008-09-17 16:52:50 +10001335 *
1336 * This function is used by xfs_free_file_space() to zero
1337 * partial blocks when the range to free is not block aligned.
1338 * When unreserving space with boundaries that are not block
1339 * aligned we round up the start and round down the end
1340 * boundaries and then use this function to zero the parts of
1341 * the blocks that got dropped during the rounding.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 */
1343STATIC int
1344xfs_zero_remaining_bytes(
1345 xfs_inode_t *ip,
1346 xfs_off_t startoff,
1347 xfs_off_t endoff)
1348{
1349 xfs_bmbt_irec_t imap;
1350 xfs_fileoff_t offset_fsb;
1351 xfs_off_t lastoffset;
1352 xfs_off_t offset;
1353 xfs_buf_t *bp;
1354 xfs_mount_t *mp = ip->i_mount;
1355 int nimap;
1356 int error = 0;
1357
Lachlan McIlroy2fd6f6e2008-09-17 16:52:50 +10001358 /*
1359 * Avoid doing I/O beyond eof - it's not necessary
1360 * since nothing can read beyond eof. The space will
1361 * be zeroed when the file is extended anyway.
1362 */
Christoph Hellwigce7ae1512011-12-18 20:00:11 +00001363 if (startoff >= XFS_ISIZE(ip))
Lachlan McIlroy2fd6f6e2008-09-17 16:52:50 +10001364 return 0;
1365
Christoph Hellwigce7ae1512011-12-18 20:00:11 +00001366 if (endoff > XFS_ISIZE(ip))
1367 endoff = XFS_ISIZE(ip);
Lachlan McIlroy2fd6f6e2008-09-17 16:52:50 +10001368
Dave Chinner686865f2010-09-24 20:07:47 +10001369 bp = xfs_buf_get_uncached(XFS_IS_REALTIME_INODE(ip) ?
1370 mp->m_rtdev_targp : mp->m_ddev_targp,
Dave Chinneraa5c1582012-04-23 15:58:56 +10001371 BTOBB(mp->m_sb.sb_blocksize), 0);
Lachlan McIlroyc6422612008-12-05 13:16:15 +11001372 if (!bp)
1373 return XFS_ERROR(ENOMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
Christoph Hellwigc8da0fa2011-07-08 14:36:25 +02001375 xfs_buf_unlock(bp);
1376
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 for (offset = startoff; offset <= endoff; offset = lastoffset + 1) {
1378 offset_fsb = XFS_B_TO_FSBT(mp, offset);
1379 nimap = 1;
Dave Chinner5c8ed202011-09-18 20:40:45 +00001380 error = xfs_bmapi_read(ip, offset_fsb, 1, &imap, &nimap, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 if (error || nimap < 1)
1382 break;
1383 ASSERT(imap.br_blockcount >= 1);
1384 ASSERT(imap.br_startoff == offset_fsb);
1385 lastoffset = XFS_FSB_TO_B(mp, imap.br_startoff + 1) - 1;
1386 if (lastoffset > endoff)
1387 lastoffset = endoff;
1388 if (imap.br_startblock == HOLESTARTBLOCK)
1389 continue;
1390 ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
1391 if (imap.br_state == XFS_EXT_UNWRITTEN)
1392 continue;
1393 XFS_BUF_UNDONE(bp);
1394 XFS_BUF_UNWRITE(bp);
1395 XFS_BUF_READ(bp);
Eric Sandeen9d87c312009-01-14 23:22:07 -06001396 XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 xfsbdstrat(mp, bp);
Christoph Hellwig1a1a3e92010-10-06 18:41:18 +00001398 error = xfs_buf_iowait(bp);
David Chinnerd64e31a2008-04-10 12:22:17 +10001399 if (error) {
Christoph Hellwig901796a2011-10-10 16:52:49 +00001400 xfs_buf_ioerror_alert(bp,
1401 "xfs_zero_remaining_bytes(read)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 break;
1403 }
Chandra Seetharaman62926042011-07-22 23:40:15 +00001404 memset(bp->b_addr +
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 (offset - XFS_FSB_TO_B(mp, imap.br_startoff)),
1406 0, lastoffset - offset + 1);
1407 XFS_BUF_UNDONE(bp);
1408 XFS_BUF_UNREAD(bp);
1409 XFS_BUF_WRITE(bp);
1410 xfsbdstrat(mp, bp);
Christoph Hellwig1a1a3e92010-10-06 18:41:18 +00001411 error = xfs_buf_iowait(bp);
David Chinnerd64e31a2008-04-10 12:22:17 +10001412 if (error) {
Christoph Hellwig901796a2011-10-10 16:52:49 +00001413 xfs_buf_ioerror_alert(bp,
1414 "xfs_zero_remaining_bytes(write)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 break;
1416 }
1417 }
1418 xfs_buf_free(bp);
1419 return error;
1420}
1421
1422/*
1423 * xfs_free_file_space()
1424 * This routine frees disk space for the given file.
1425 *
1426 * This routine is only called by xfs_change_file_space
1427 * for an UNRESVSP type call.
1428 *
1429 * RETURNS:
1430 * 0 on success
1431 * errno on error
1432 *
1433 */
1434STATIC int
1435xfs_free_file_space(
1436 xfs_inode_t *ip,
1437 xfs_off_t offset,
1438 xfs_off_t len,
1439 int attr_flags)
1440{
1441 int committed;
1442 int done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 xfs_fileoff_t endoffset_fsb;
1444 int error;
1445 xfs_fsblock_t firstfsb;
1446 xfs_bmap_free_t free_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 xfs_bmbt_irec_t imap;
1448 xfs_off_t ioffset;
1449 xfs_extlen_t mod=0;
1450 xfs_mount_t *mp;
1451 int nimap;
1452 uint resblks;
Dave Chinner28ca4892013-05-20 09:51:09 +10001453 xfs_off_t rounding;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 int rt;
1455 xfs_fileoff_t startoffset_fsb;
1456 xfs_trans_t *tp;
Dean Roehrich5fcbab32005-05-05 13:27:19 -07001457 int need_iolock = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459 mp = ip->i_mount;
1460
Christoph Hellwigcca28fb2010-06-24 11:57:09 +10001461 trace_xfs_free_file_space(ip);
Christoph Hellwigbd5a8762005-06-21 15:47:39 +10001462
Christoph Hellwig7d095252009-06-08 15:33:32 +02001463 error = xfs_qm_dqattach(ip, 0);
1464 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 return error;
1466
1467 error = 0;
1468 if (len <= 0) /* if nothing being freed */
1469 return error;
Eric Sandeen71ddabb2007-11-23 16:29:42 +11001470 rt = XFS_IS_REALTIME_INODE(ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 startoffset_fsb = XFS_B_TO_FSB(mp, offset);
Christoph Hellwig288699f2010-06-23 18:11:15 +10001472 endoffset_fsb = XFS_B_TO_FSBT(mp, offset + len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473
Christoph Hellwig0f285c82008-07-18 17:13:28 +10001474 if (attr_flags & XFS_ATTR_NOLOCK)
Dean Roehrich5fcbab32005-05-05 13:27:19 -07001475 need_iolock = 0;
Yingping Lu9fa80462006-03-22 12:44:35 +11001476 if (need_iolock) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 xfs_ilock(ip, XFS_IOLOCK_EXCL);
Christoph Hellwig25e41b32008-12-03 12:20:39 +01001478 /* wait for the completion of any pending DIOs */
Christoph Hellwig4a06fd22011-08-23 08:28:13 +00001479 inode_dio_wait(VFS_I(ip));
Yingping Lu9fa80462006-03-22 12:44:35 +11001480 }
Dean Roehrich5fcbab32005-05-05 13:27:19 -07001481
Dave Chinner28ca4892013-05-20 09:51:09 +10001482 rounding = max_t(xfs_off_t, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 ioffset = offset & ~(rounding - 1);
Dave Chinnerfb595812012-11-12 22:53:57 +11001484 error = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
1485 ioffset, -1);
1486 if (error)
1487 goto out_unlock_iolock;
1488 truncate_pagecache_range(VFS_I(ip), ioffset, -1);
Christoph Hellwigbd5a8762005-06-21 15:47:39 +10001489
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 /*
1491 * Need to zero the stuff we're not freeing, on disk.
Malcolm Parsons9da096f2009-03-29 09:55:42 +02001492 * If it's a realtime file & can't use unwritten extents then we
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 * actually need to zero the extent edges. Otherwise xfs_bunmapi
1494 * will take care of it for us.
1495 */
Eric Sandeen62118702008-03-06 13:44:28 +11001496 if (rt && !xfs_sb_version_hasextflgbit(&mp->m_sb)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 nimap = 1;
Dave Chinner5c8ed202011-09-18 20:40:45 +00001498 error = xfs_bmapi_read(ip, startoffset_fsb, 1,
1499 &imap, &nimap, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 if (error)
1501 goto out_unlock_iolock;
1502 ASSERT(nimap == 0 || nimap == 1);
1503 if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
1504 xfs_daddr_t block;
1505
1506 ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
1507 block = imap.br_startblock;
1508 mod = do_div(block, mp->m_sb.sb_rextsize);
1509 if (mod)
1510 startoffset_fsb += mp->m_sb.sb_rextsize - mod;
1511 }
1512 nimap = 1;
Dave Chinner5c8ed202011-09-18 20:40:45 +00001513 error = xfs_bmapi_read(ip, endoffset_fsb - 1, 1,
1514 &imap, &nimap, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 if (error)
1516 goto out_unlock_iolock;
1517 ASSERT(nimap == 0 || nimap == 1);
1518 if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
1519 ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
1520 mod++;
1521 if (mod && (mod != mp->m_sb.sb_rextsize))
1522 endoffset_fsb -= mod;
1523 }
1524 }
1525 if ((done = (endoffset_fsb <= startoffset_fsb)))
1526 /*
1527 * One contiguous piece to clear
1528 */
1529 error = xfs_zero_remaining_bytes(ip, offset, offset + len - 1);
1530 else {
1531 /*
1532 * Some full blocks, possibly two pieces to clear
1533 */
1534 if (offset < XFS_FSB_TO_B(mp, startoffset_fsb))
1535 error = xfs_zero_remaining_bytes(ip, offset,
1536 XFS_FSB_TO_B(mp, startoffset_fsb) - 1);
1537 if (!error &&
1538 XFS_FSB_TO_B(mp, endoffset_fsb) < offset + len)
1539 error = xfs_zero_remaining_bytes(ip,
1540 XFS_FSB_TO_B(mp, endoffset_fsb),
1541 offset + len - 1);
1542 }
1543
1544 /*
1545 * free file space until done or until there is an error
1546 */
1547 resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
1548 while (!error && !done) {
1549
1550 /*
David Chinner91ebecc2007-07-19 16:28:30 +10001551 * allocate and setup the transaction. Allow this
1552 * transaction to dip into the reserve blocks to ensure
1553 * the freeing of the space succeeds at ENOSPC.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 */
1555 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
David Chinner91ebecc2007-07-19 16:28:30 +10001556 tp->t_flags |= XFS_TRANS_RESERVE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 error = xfs_trans_reserve(tp,
1558 resblks,
1559 XFS_WRITE_LOG_RES(mp),
1560 0,
1561 XFS_TRANS_PERM_LOG_RES,
1562 XFS_WRITE_LOG_COUNT);
1563
1564 /*
1565 * check for running out of space
1566 */
1567 if (error) {
1568 /*
1569 * Free the transaction structure.
1570 */
1571 ASSERT(error == ENOSPC || XFS_FORCED_SHUTDOWN(mp));
1572 xfs_trans_cancel(tp, 0);
1573 break;
1574 }
1575 xfs_ilock(ip, XFS_ILOCK_EXCL);
Christoph Hellwig7d095252009-06-08 15:33:32 +02001576 error = xfs_trans_reserve_quota(tp, mp,
Chandra Seetharaman92f8ff72013-07-11 00:00:40 -05001577 ip->i_udquot, ip->i_gdquot, ip->i_pdquot,
Christoph Hellwig7d095252009-06-08 15:33:32 +02001578 resblks, 0, XFS_QMOPT_RES_REGBLKS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 if (error)
1580 goto error1;
1581
Christoph Hellwigddc34152011-09-19 15:00:54 +00001582 xfs_trans_ijoin(tp, ip, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
1584 /*
1585 * issue the bunmapi() call to free the blocks
1586 */
Eric Sandeen9d87c312009-01-14 23:22:07 -06001587 xfs_bmap_init(&free_list, &firstfsb);
Lachlan McIlroy541d7d32007-10-11 17:34:33 +10001588 error = xfs_bunmapi(tp, ip, startoffset_fsb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 endoffset_fsb - startoffset_fsb,
Christoph Hellwigb4e91812010-06-23 18:11:15 +10001590 0, 2, &firstfsb, &free_list, &done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 if (error) {
1592 goto error0;
1593 }
1594
1595 /*
1596 * complete the transaction
1597 */
Eric Sandeenf7c99b62007-02-10 18:37:16 +11001598 error = xfs_bmap_finish(&tp, &free_list, &committed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 if (error) {
1600 goto error0;
1601 }
1602
Eric Sandeen1c72bf92007-05-08 13:48:42 +10001603 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1605 }
1606
1607 out_unlock_iolock:
1608 if (need_iolock)
1609 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1610 return error;
1611
1612 error0:
1613 xfs_bmap_cancel(&free_list);
1614 error1:
1615 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
1616 xfs_iunlock(ip, need_iolock ? (XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL) :
1617 XFS_ILOCK_EXCL);
1618 return error;
1619}
1620
Dave Chinneref9d8732012-11-29 15:26:33 +11001621
1622STATIC int
1623xfs_zero_file_space(
1624 struct xfs_inode *ip,
1625 xfs_off_t offset,
1626 xfs_off_t len,
1627 int attr_flags)
1628{
1629 struct xfs_mount *mp = ip->i_mount;
1630 uint granularity;
1631 xfs_off_t start_boundary;
1632 xfs_off_t end_boundary;
1633 int error;
1634
1635 granularity = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
1636
1637 /*
1638 * Round the range of extents we are going to convert inwards. If the
1639 * offset is aligned, then it doesn't get changed so we zero from the
1640 * start of the block offset points to.
1641 */
1642 start_boundary = round_up(offset, granularity);
1643 end_boundary = round_down(offset + len, granularity);
1644
1645 ASSERT(start_boundary >= offset);
1646 ASSERT(end_boundary <= offset + len);
1647
1648 if (!(attr_flags & XFS_ATTR_NOLOCK))
1649 xfs_ilock(ip, XFS_IOLOCK_EXCL);
1650
1651 if (start_boundary < end_boundary - 1) {
1652 /* punch out the page cache over the conversion range */
1653 truncate_pagecache_range(VFS_I(ip), start_boundary,
1654 end_boundary - 1);
1655 /* convert the blocks */
1656 error = xfs_alloc_file_space(ip, start_boundary,
1657 end_boundary - start_boundary - 1,
1658 XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT,
1659 attr_flags);
1660 if (error)
1661 goto out_unlock;
1662
1663 /* We've handled the interior of the range, now for the edges */
1664 if (start_boundary != offset)
1665 error = xfs_iozero(ip, offset, start_boundary - offset);
1666 if (error)
1667 goto out_unlock;
1668
1669 if (end_boundary != offset + len)
1670 error = xfs_iozero(ip, end_boundary,
1671 offset + len - end_boundary);
1672
1673 } else {
1674 /*
1675 * It's either a sub-granularity range or the range spanned lies
1676 * partially across two adjacent blocks.
1677 */
1678 error = xfs_iozero(ip, offset, len);
1679 }
1680
1681out_unlock:
1682 if (!(attr_flags & XFS_ATTR_NOLOCK))
1683 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1684 return error;
1685
1686}
1687
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688/*
1689 * xfs_change_file_space()
1690 * This routine allocates or frees disk space for the given file.
1691 * The user specified parameters are checked for alignment and size
1692 * limitations.
1693 *
1694 * RETURNS:
1695 * 0 on success
1696 * errno on error
1697 *
1698 */
1699int
1700xfs_change_file_space(
Christoph Hellwig993386c2007-08-28 16:12:30 +10001701 xfs_inode_t *ip,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 int cmd,
1703 xfs_flock64_t *bf,
1704 xfs_off_t offset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 int attr_flags)
1706{
Christoph Hellwig993386c2007-08-28 16:12:30 +10001707 xfs_mount_t *mp = ip->i_mount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 int clrprealloc;
1709 int error;
1710 xfs_fsize_t fsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 int setprealloc;
1712 xfs_off_t startoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 xfs_trans_t *tp;
Christoph Hellwig0f285c82008-07-18 17:13:28 +10001714 struct iattr iattr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715
Christoph Hellwig993386c2007-08-28 16:12:30 +10001716 if (!S_ISREG(ip->i_d.di_mode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 return XFS_ERROR(EINVAL);
1718
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 switch (bf->l_whence) {
1720 case 0: /*SEEK_SET*/
1721 break;
1722 case 1: /*SEEK_CUR*/
1723 bf->l_start += offset;
1724 break;
1725 case 2: /*SEEK_END*/
Christoph Hellwigce7ae1512011-12-18 20:00:11 +00001726 bf->l_start += XFS_ISIZE(ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 break;
1728 default:
1729 return XFS_ERROR(EINVAL);
1730 }
1731
Dave Chinnerf5b89112012-11-14 17:42:47 +11001732 /*
1733 * length of <= 0 for resv/unresv/zero is invalid. length for
1734 * alloc/free is ignored completely and we have no idea what userspace
1735 * might have set it to, so set it to zero to allow range
1736 * checks to pass.
1737 */
1738 switch (cmd) {
1739 case XFS_IOC_ZERO_RANGE:
1740 case XFS_IOC_RESVSP:
1741 case XFS_IOC_RESVSP64:
1742 case XFS_IOC_UNRESVSP:
1743 case XFS_IOC_UNRESVSP64:
1744 if (bf->l_len <= 0)
1745 return XFS_ERROR(EINVAL);
1746 break;
1747 default:
1748 bf->l_len = 0;
1749 break;
1750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751
Dave Chinner32972382012-06-08 15:44:54 +10001752 if (bf->l_start < 0 ||
1753 bf->l_start > mp->m_super->s_maxbytes ||
Dave Chinnerf5b89112012-11-14 17:42:47 +11001754 bf->l_start + bf->l_len < 0 ||
1755 bf->l_start + bf->l_len >= mp->m_super->s_maxbytes)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 return XFS_ERROR(EINVAL);
1757
1758 bf->l_whence = 0;
1759
1760 startoffset = bf->l_start;
Christoph Hellwigce7ae1512011-12-18 20:00:11 +00001761 fsize = XFS_ISIZE(ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 setprealloc = clrprealloc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 switch (cmd) {
Dave Chinner44722352010-08-24 12:02:11 +10001765 case XFS_IOC_ZERO_RANGE:
Dave Chinneref9d8732012-11-29 15:26:33 +11001766 error = xfs_zero_file_space(ip, startoffset, bf->l_len,
1767 attr_flags);
1768 if (error)
1769 return error;
1770 setprealloc = 1;
1771 break;
1772
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 case XFS_IOC_RESVSP:
1774 case XFS_IOC_RESVSP64:
1775 error = xfs_alloc_file_space(ip, startoffset, bf->l_len,
Dave Chinneref9d8732012-11-29 15:26:33 +11001776 XFS_BMAPI_PREALLOC, attr_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 if (error)
1778 return error;
1779 setprealloc = 1;
1780 break;
1781
1782 case XFS_IOC_UNRESVSP:
1783 case XFS_IOC_UNRESVSP64:
1784 if ((error = xfs_free_file_space(ip, startoffset, bf->l_len,
1785 attr_flags)))
1786 return error;
1787 break;
1788
1789 case XFS_IOC_ALLOCSP:
1790 case XFS_IOC_ALLOCSP64:
1791 case XFS_IOC_FREESP:
1792 case XFS_IOC_FREESP64:
Dave Chinnerbc4010ec2012-04-23 15:58:57 +10001793 /*
1794 * These operations actually do IO when extending the file, but
1795 * the allocation is done seperately to the zeroing that is
1796 * done. This set of operations need to be serialised against
1797 * other IO operations, such as truncate and buffered IO. We
1798 * need to take the IOLOCK here to serialise the allocation and
1799 * zeroing IO to prevent other IOLOCK holders (e.g. getbmap,
1800 * truncate, direct IO) from racing against the transient
1801 * allocated but not written state we can have here.
1802 */
1803 xfs_ilock(ip, XFS_IOLOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 if (startoffset > fsize) {
1805 error = xfs_alloc_file_space(ip, fsize,
Dave Chinnerbc4010ec2012-04-23 15:58:57 +10001806 startoffset - fsize, 0,
1807 attr_flags | XFS_ATTR_NOLOCK);
1808 if (error) {
1809 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 break;
Dave Chinnerbc4010ec2012-04-23 15:58:57 +10001811 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 }
1813
Christoph Hellwig0f285c82008-07-18 17:13:28 +10001814 iattr.ia_valid = ATTR_SIZE;
1815 iattr.ia_size = startoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816
Dave Chinnerbc4010ec2012-04-23 15:58:57 +10001817 error = xfs_setattr_size(ip, &iattr,
1818 attr_flags | XFS_ATTR_NOLOCK);
1819 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
1821 if (error)
1822 return error;
1823
1824 clrprealloc = 1;
1825 break;
1826
1827 default:
1828 ASSERT(0);
1829 return XFS_ERROR(EINVAL);
1830 }
1831
1832 /*
1833 * update the inode timestamp, mode, and prealloc flag bits
1834 */
1835 tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID);
1836
1837 if ((error = xfs_trans_reserve(tp, 0, XFS_WRITEID_LOG_RES(mp),
1838 0, 0, 0))) {
1839 /* ASSERT(0); */
1840 xfs_trans_cancel(tp, 0);
1841 return error;
1842 }
1843
1844 xfs_ilock(ip, XFS_ILOCK_EXCL);
Christoph Hellwigddc34152011-09-19 15:00:54 +00001845 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846
Christoph Hellwig0f285c82008-07-18 17:13:28 +10001847 if ((attr_flags & XFS_ATTR_DMI) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 ip->i_d.di_mode &= ~S_ISUID;
1849
1850 /*
1851 * Note that we don't have to worry about mandatory
1852 * file locking being disabled here because we only
1853 * clear the S_ISGID bit if the Group execute bit is
1854 * on, but if it was on then mandatory locking wouldn't
1855 * have been enabled.
1856 */
1857 if (ip->i_d.di_mode & S_IXGRP)
1858 ip->i_d.di_mode &= ~S_ISGID;
1859
Dave Chinnerdcd79a12010-09-28 12:27:25 +10001860 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 }
1862 if (setprealloc)
1863 ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
1864 else if (clrprealloc)
1865 ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC;
1866
1867 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
Dave Chinner82878892011-03-26 09:13:08 +11001868 if (attr_flags & XFS_ATTR_SYNC)
1869 xfs_trans_set_sync(tp);
Christoph Hellwig23bb0be2011-09-18 20:47:51 +00001870 return xfs_trans_commit(tp, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871}