blob: a4f56a42ef90586438effd244f4697e86fafd312 [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.
Nathan Scott7b718762005-11-02 14:58:39 +11003 * All Rights Reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
Nathan Scott7b718762005-11-02 14:58:39 +11005 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 * published by the Free Software Foundation.
8 *
Nathan Scott7b718762005-11-02 14:58:39 +11009 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 *
Nathan Scott7b718762005-11-02 14:58:39 +110014 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 */
Randy Dunlap16f7e0f2006-01-11 12:17:46 -080018
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include "xfs.h"
Nathan Scotta844f452005-11-02 14:38:42 +110020#include "xfs_fs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include "xfs_types.h"
Nathan Scotta844f452005-11-02 14:38:42 +110022#include "xfs_bit.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#include "xfs_log.h"
Nathan Scotta844f452005-11-02 14:38:42 +110024#include "xfs_inum.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include "xfs_trans.h"
26#include "xfs_sb.h"
27#include "xfs_ag.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include "xfs_dir2.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include "xfs_mount.h"
Nathan Scotta844f452005-11-02 14:38:42 +110030#include "xfs_da_btree.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include "xfs_bmap_btree.h"
32#include "xfs_ialloc_btree.h"
Nathan Scotta844f452005-11-02 14:38:42 +110033#include "xfs_dinode.h"
34#include "xfs_inode.h"
35#include "xfs_inode_item.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include "xfs_itable.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include "xfs_ialloc.h"
38#include "xfs_alloc.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include "xfs_bmap.h"
Christoph Hellwigef14f0c2009-06-10 17:07:47 +020040#include "xfs_acl.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include "xfs_attr.h"
42#include "xfs_rw.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 Hellwig993386c12007-08-28 16:12:30 +100050#include "xfs_vnodeops.h"
Christoph Hellwig0b1b2132009-12-14 23:14:59 +000051#include "xfs_trace.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
Linus Torvalds1da177e2005-04-16 15:20:36 -070053/*
Nathan Scott7d4fb402006-06-09 15:27:16 +100054 * The maximum pathlen is 1024 bytes. Since the minimum file system
55 * blocksize is 512 bytes, we can get a max of 2 extents back from
56 * bmapi.
57 */
58#define SYMLINK_MAPS 2
59
Christoph Hellwig804c83c2007-08-28 13:59:03 +100060STATIC int
61xfs_readlink_bmap(
62 xfs_inode_t *ip,
63 char *link)
64{
65 xfs_mount_t *mp = ip->i_mount;
66 int pathlen = ip->i_d.di_size;
67 int nmaps = SYMLINK_MAPS;
68 xfs_bmbt_irec_t mval[SYMLINK_MAPS];
69 xfs_daddr_t d;
70 int byte_cnt;
71 int n;
72 xfs_buf_t *bp;
73 int error = 0;
74
75 error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), 0, NULL, 0,
Christoph Hellwigb4e91812010-06-23 18:11:15 +100076 mval, &nmaps, NULL);
Christoph Hellwig804c83c2007-08-28 13:59:03 +100077 if (error)
78 goto out;
79
80 for (n = 0; n < nmaps; n++) {
81 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
82 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
83
Christoph Hellwig6ad112b2009-11-24 18:02:23 +000084 bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt),
85 XBF_LOCK | XBF_MAPPED | XBF_DONT_BLOCK);
Christoph Hellwig804c83c2007-08-28 13:59:03 +100086 error = XFS_BUF_GETERROR(bp);
87 if (error) {
88 xfs_ioerror_alert("xfs_readlink",
89 ip->i_mount, bp, XFS_BUF_ADDR(bp));
90 xfs_buf_relse(bp);
91 goto out;
92 }
93 if (pathlen < byte_cnt)
94 byte_cnt = pathlen;
95 pathlen -= byte_cnt;
96
97 memcpy(link, XFS_BUF_PTR(bp), byte_cnt);
98 xfs_buf_relse(bp);
99 }
100
101 link[ip->i_d.di_size] = '\0';
102 error = 0;
103
104 out:
105 return error;
106}
107
Christoph Hellwig993386c12007-08-28 16:12:30 +1000108int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109xfs_readlink(
Christoph Hellwig993386c12007-08-28 16:12:30 +1000110 xfs_inode_t *ip,
Christoph Hellwig804c83c2007-08-28 13:59:03 +1000111 char *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112{
Christoph Hellwig804c83c2007-08-28 13:59:03 +1000113 xfs_mount_t *mp = ip->i_mount;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 int pathlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
Christoph Hellwigcca28fb2010-06-24 11:57:09 +1000117 trace_xfs_readlink(ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
119 if (XFS_FORCED_SHUTDOWN(mp))
120 return XFS_ERROR(EIO);
121
122 xfs_ilock(ip, XFS_ILOCK_SHARED);
123
124 ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK);
Christoph Hellwig804c83c2007-08-28 13:59:03 +1000125 ASSERT(ip->i_d.di_size <= MAXPATHLEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
Christoph Hellwig804c83c2007-08-28 13:59:03 +1000127 pathlen = ip->i_d.di_size;
128 if (!pathlen)
129 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
131 if (ip->i_df.if_flags & XFS_IFINLINE) {
Christoph Hellwig804c83c2007-08-28 13:59:03 +1000132 memcpy(link, ip->i_df.if_u1.if_data, pathlen);
133 link[pathlen] = '\0';
134 } else {
135 error = xfs_readlink_bmap(ip, link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 }
137
Christoph Hellwig804c83c2007-08-28 13:59:03 +1000138 out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 xfs_iunlock(ip, XFS_ILOCK_SHARED);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 return error;
141}
142
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143/*
Christoph Hellwigc56c96312009-10-19 04:03:46 +0000144 * Flags for xfs_free_eofblocks
145 */
146#define XFS_FREE_EOF_TRYLOCK (1<<0)
147
148/*
David Chinner92dfe8d2007-05-24 15:22:19 +1000149 * This is called by xfs_inactive to free any blocks beyond eof
150 * when the link count isn't zero and by xfs_dm_punch_hole() when
151 * punching a hole to EOF.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 */
Eric Sandeend96f8f82009-07-02 00:09:33 -0500153STATIC int
David Chinner92dfe8d2007-05-24 15:22:19 +1000154xfs_free_eofblocks(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 xfs_mount_t *mp,
David Chinner92dfe8d2007-05-24 15:22:19 +1000156 xfs_inode_t *ip,
157 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158{
159 xfs_trans_t *tp;
160 int error;
161 xfs_fileoff_t end_fsb;
162 xfs_fileoff_t last_fsb;
163 xfs_filblks_t map_len;
164 int nimaps;
165 xfs_bmbt_irec_t imap;
166
167 /*
168 * Figure out if there are any blocks beyond the end
169 * of the file. If not, then there is nothing to do.
170 */
Lachlan McIlroyba87ea62007-05-08 13:49:46 +1000171 end_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)ip->i_size));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
Kulikov Vasiliy3f348852010-07-20 17:54:28 +1000173 if (last_fsb <= end_fsb)
Jesper Juhl014c2542006-01-15 02:37:08 +0100174 return 0;
Kulikov Vasiliy3f348852010-07-20 17:54:28 +1000175 map_len = last_fsb - end_fsb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176
177 nimaps = 1;
178 xfs_ilock(ip, XFS_ILOCK_SHARED);
Lachlan McIlroy541d7d32007-10-11 17:34:33 +1000179 error = xfs_bmapi(NULL, ip, end_fsb, map_len, 0,
Christoph Hellwigb4e91812010-06-23 18:11:15 +1000180 NULL, 0, &imap, &nimaps, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 xfs_iunlock(ip, XFS_ILOCK_SHARED);
182
183 if (!error && (nimaps != 0) &&
Yingping Lu68bdb6e2006-01-11 15:38:31 +1100184 (imap.br_startblock != HOLESTARTBLOCK ||
185 ip->i_delayed_blks)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 /*
187 * Attach the dquots to the inode up front.
188 */
Christoph Hellwig7d095252009-06-08 15:33:32 +0200189 error = xfs_qm_dqattach(ip, 0);
190 if (error)
Jesper Juhl014c2542006-01-15 02:37:08 +0100191 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
193 /*
194 * There are blocks after the end of file.
195 * Free them up now by truncating the file to
196 * its current size.
197 */
198 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
199
200 /*
201 * Do the xfs_itruncate_start() call before
202 * reserving any log space because
203 * itruncate_start will call into the buffer
204 * cache and we can't
205 * do that within a transaction.
206 */
Christoph Hellwigc56c96312009-10-19 04:03:46 +0000207 if (flags & XFS_FREE_EOF_TRYLOCK) {
208 if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) {
209 xfs_trans_cancel(tp, 0);
210 return 0;
211 }
212 } else {
David Chinner92dfe8d2007-05-24 15:22:19 +1000213 xfs_ilock(ip, XFS_IOLOCK_EXCL);
Christoph Hellwigc56c96312009-10-19 04:03:46 +0000214 }
Lachlan McIlroyd3cf20942007-05-08 13:49:27 +1000215 error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
Lachlan McIlroyba87ea62007-05-08 13:49:46 +1000216 ip->i_size);
Lachlan McIlroyd3cf20942007-05-08 13:49:27 +1000217 if (error) {
Jesper Juhl87ae3c22007-06-28 16:43:14 +1000218 xfs_trans_cancel(tp, 0);
Christoph Hellwigc56c96312009-10-19 04:03:46 +0000219 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
Lachlan McIlroyd3cf20942007-05-08 13:49:27 +1000220 return error;
221 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
223 error = xfs_trans_reserve(tp, 0,
224 XFS_ITRUNCATE_LOG_RES(mp),
225 0, XFS_TRANS_PERM_LOG_RES,
226 XFS_ITRUNCATE_LOG_COUNT);
227 if (error) {
228 ASSERT(XFS_FORCED_SHUTDOWN(mp));
229 xfs_trans_cancel(tp, 0);
230 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
Jesper Juhl014c2542006-01-15 02:37:08 +0100231 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 }
233
234 xfs_ilock(ip, XFS_ILOCK_EXCL);
Christoph Hellwig898621d2010-06-24 11:36:58 +1000235 xfs_trans_ijoin(tp, ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
237 error = xfs_itruncate_finish(&tp, ip,
Lachlan McIlroyba87ea62007-05-08 13:49:46 +1000238 ip->i_size,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 XFS_DATA_FORK,
240 0);
241 /*
242 * If we get an error at this point we
243 * simply don't bother truncating the file.
244 */
245 if (error) {
246 xfs_trans_cancel(tp,
247 (XFS_TRANS_RELEASE_LOG_RES |
248 XFS_TRANS_ABORT));
249 } else {
250 error = xfs_trans_commit(tp,
Eric Sandeen1c72bf92007-05-08 13:48:42 +1000251 XFS_TRANS_RELEASE_LOG_RES);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 }
Christoph Hellwigc56c96312009-10-19 04:03:46 +0000253 xfs_iunlock(ip, XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 }
Jesper Juhl014c2542006-01-15 02:37:08 +0100255 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256}
257
258/*
259 * Free a symlink that has blocks associated with it.
260 */
261STATIC int
262xfs_inactive_symlink_rmt(
263 xfs_inode_t *ip,
264 xfs_trans_t **tpp)
265{
266 xfs_buf_t *bp;
267 int committed;
268 int done;
269 int error;
270 xfs_fsblock_t first_block;
271 xfs_bmap_free_t free_list;
272 int i;
273 xfs_mount_t *mp;
274 xfs_bmbt_irec_t mval[SYMLINK_MAPS];
275 int nmaps;
276 xfs_trans_t *ntp;
277 int size;
278 xfs_trans_t *tp;
279
280 tp = *tpp;
281 mp = ip->i_mount;
282 ASSERT(ip->i_d.di_size > XFS_IFORK_DSIZE(ip));
283 /*
284 * We're freeing a symlink that has some
285 * blocks allocated to it. Free the
286 * blocks here. We know that we've got
287 * either 1 or 2 extents and that we can
288 * free them all in one bunmapi call.
289 */
290 ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2);
291 if ((error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
292 XFS_TRANS_PERM_LOG_RES, XFS_ITRUNCATE_LOG_COUNT))) {
293 ASSERT(XFS_FORCED_SHUTDOWN(mp));
294 xfs_trans_cancel(tp, 0);
295 *tpp = NULL;
296 return error;
297 }
298 /*
299 * Lock the inode, fix the size, and join it to the transaction.
300 * Hold it so in the normal path, we still have it locked for
301 * the second transaction. In the error paths we need it
302 * held so the cancel won't rele it, see below.
303 */
304 xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
305 size = (int)ip->i_d.di_size;
306 ip->i_d.di_size = 0;
Christoph Hellwig898621d2010-06-24 11:36:58 +1000307 xfs_trans_ijoin(tp, ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
309 /*
310 * Find the block(s) so we can inval and unmap them.
311 */
312 done = 0;
Eric Sandeen9d87c312009-01-14 23:22:07 -0600313 xfs_bmap_init(&free_list, &first_block);
Tobias Klausere8c96f82006-03-24 03:15:34 -0800314 nmaps = ARRAY_SIZE(mval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size),
316 XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps,
Christoph Hellwigb4e91812010-06-23 18:11:15 +1000317 &free_list)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 goto error0;
319 /*
320 * Invalidate the block(s).
321 */
322 for (i = 0; i < nmaps; i++) {
323 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp,
324 XFS_FSB_TO_DADDR(mp, mval[i].br_startblock),
325 XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0);
326 xfs_trans_binval(tp, bp);
327 }
328 /*
329 * Unmap the dead block(s) to the free_list.
330 */
331 if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps,
Christoph Hellwigb4e91812010-06-23 18:11:15 +1000332 &first_block, &free_list, &done)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 goto error1;
334 ASSERT(done);
335 /*
336 * Commit the first transaction. This logs the EFI and the inode.
337 */
Eric Sandeenf7c99b62007-02-10 18:37:16 +1100338 if ((error = xfs_bmap_finish(&tp, &free_list, &committed)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 goto error1;
340 /*
341 * The transaction must have been committed, since there were
342 * actually extents freed by xfs_bunmapi. See xfs_bmap_finish.
343 * The new tp has the extent freeing and EFDs.
344 */
345 ASSERT(committed);
346 /*
347 * The first xact was committed, so add the inode to the new one.
348 * Mark it dirty so it will be logged and moved forward in the log as
349 * part of every commit.
350 */
Christoph Hellwig898621d2010-06-24 11:36:58 +1000351 xfs_trans_ijoin(tp, ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
353 /*
354 * Get a new, empty transaction to return to our caller.
355 */
356 ntp = xfs_trans_dup(tp);
357 /*
Nathan Scottc41564b2006-03-29 08:55:14 +1000358 * Commit the transaction containing extent freeing and EFDs.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 * If we get an error on the commit here or on the reserve below,
360 * we need to unlock the inode since the new transaction doesn't
361 * have the inode attached.
362 */
Eric Sandeen1c72bf92007-05-08 13:48:42 +1000363 error = xfs_trans_commit(tp, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 tp = ntp;
365 if (error) {
366 ASSERT(XFS_FORCED_SHUTDOWN(mp));
367 goto error0;
368 }
369 /*
Dave Chinnercc09c0d2008-11-17 17:37:10 +1100370 * transaction commit worked ok so we can drop the extra ticket
371 * reference that we gained in xfs_trans_dup()
372 */
373 xfs_log_ticket_put(tp->t_ticket);
374
375 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 * Remove the memory for extent descriptions (just bookkeeping).
377 */
378 if (ip->i_df.if_bytes)
379 xfs_idata_realloc(ip, -ip->i_df.if_bytes, XFS_DATA_FORK);
380 ASSERT(ip->i_df.if_bytes == 0);
381 /*
382 * Put an itruncate log reservation in the new transaction
383 * for our caller.
384 */
385 if ((error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
386 XFS_TRANS_PERM_LOG_RES, XFS_ITRUNCATE_LOG_COUNT))) {
387 ASSERT(XFS_FORCED_SHUTDOWN(mp));
388 goto error0;
389 }
390 /*
391 * Return with the inode locked but not joined to the transaction.
392 */
393 *tpp = tp;
394 return 0;
395
396 error1:
397 xfs_bmap_cancel(&free_list);
398 error0:
399 /*
400 * Have to come here with the inode locked and either
401 * (held and in the transaction) or (not in the transaction).
402 * If the inode isn't held then cancel would iput it, but
403 * that's wrong since this is inactive and the vnode ref
404 * count is 0 already.
405 * Cancel won't do anything to the inode if held, but it still
406 * needs to be locked until the cancel is done, if it was
407 * joined to the transaction.
408 */
409 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
410 xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
411 *tpp = NULL;
412 return error;
413
414}
415
416STATIC int
417xfs_inactive_symlink_local(
418 xfs_inode_t *ip,
419 xfs_trans_t **tpp)
420{
421 int error;
422
423 ASSERT(ip->i_d.di_size <= XFS_IFORK_DSIZE(ip));
424 /*
425 * We're freeing a symlink which fit into
426 * the inode. Just free the memory used
427 * to hold the old symlink.
428 */
429 error = xfs_trans_reserve(*tpp, 0,
430 XFS_ITRUNCATE_LOG_RES(ip->i_mount),
431 0, XFS_TRANS_PERM_LOG_RES,
432 XFS_ITRUNCATE_LOG_COUNT);
433
434 if (error) {
435 xfs_trans_cancel(*tpp, 0);
436 *tpp = NULL;
Jesper Juhl014c2542006-01-15 02:37:08 +0100437 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 }
439 xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
440
441 /*
442 * Zero length symlinks _can_ exist.
443 */
444 if (ip->i_df.if_bytes > 0) {
445 xfs_idata_realloc(ip,
446 -(ip->i_df.if_bytes),
447 XFS_DATA_FORK);
448 ASSERT(ip->i_df.if_bytes == 0);
449 }
Jesper Juhl014c2542006-01-15 02:37:08 +0100450 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451}
452
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453STATIC int
454xfs_inactive_attrs(
455 xfs_inode_t *ip,
456 xfs_trans_t **tpp)
457{
458 xfs_trans_t *tp;
459 int error;
460 xfs_mount_t *mp;
461
Christoph Hellwig579aa9c2008-04-22 17:34:00 +1000462 ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 tp = *tpp;
464 mp = ip->i_mount;
465 ASSERT(ip->i_d.di_forkoff != 0);
David Chinnere5720ee2008-04-10 12:21:18 +1000466 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 xfs_iunlock(ip, XFS_ILOCK_EXCL);
David Chinnere5720ee2008-04-10 12:21:18 +1000468 if (error)
469 goto error_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
471 error = xfs_attr_inactive(ip);
David Chinnere5720ee2008-04-10 12:21:18 +1000472 if (error)
473 goto error_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474
475 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
476 error = xfs_trans_reserve(tp, 0,
477 XFS_IFREE_LOG_RES(mp),
478 0, XFS_TRANS_PERM_LOG_RES,
479 XFS_INACTIVE_LOG_COUNT);
David Chinnere5720ee2008-04-10 12:21:18 +1000480 if (error)
481 goto error_cancel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
483 xfs_ilock(ip, XFS_ILOCK_EXCL);
Christoph Hellwig898621d2010-06-24 11:36:58 +1000484 xfs_trans_ijoin(tp, ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 xfs_idestroy_fork(ip, XFS_ATTR_FORK);
486
487 ASSERT(ip->i_d.di_anextents == 0);
488
489 *tpp = tp;
Jesper Juhl014c2542006-01-15 02:37:08 +0100490 return 0;
David Chinnere5720ee2008-04-10 12:21:18 +1000491
492error_cancel:
493 ASSERT(XFS_FORCED_SHUTDOWN(mp));
494 xfs_trans_cancel(tp, 0);
495error_unlock:
496 *tpp = NULL;
497 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
498 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499}
500
Christoph Hellwig993386c12007-08-28 16:12:30 +1000501int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502xfs_release(
Christoph Hellwig993386c12007-08-28 16:12:30 +1000503 xfs_inode_t *ip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504{
Christoph Hellwig993386c12007-08-28 16:12:30 +1000505 xfs_mount_t *mp = ip->i_mount;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 int error;
507
Christoph Hellwig42173f62008-04-22 17:33:25 +1000508 if (!S_ISREG(ip->i_d.di_mode) || (ip->i_d.di_mode == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
511 /* If this is a read-only mount, don't do this (would generate I/O) */
Christoph Hellwigbd186aa2007-08-30 17:21:12 +1000512 if (mp->m_flags & XFS_MOUNT_RDONLY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 return 0;
514
David Chinner2a82b8b2007-07-11 11:09:12 +1000515 if (!XFS_FORCED_SHUTDOWN(mp)) {
Christoph Hellwigb3aea4e2007-08-29 11:44:37 +1000516 int truncated;
517
David Chinner2a82b8b2007-07-11 11:09:12 +1000518 /*
519 * If we are using filestreams, and we have an unlinked
520 * file that we are processing the last close on, then nothing
521 * will be able to reopen and write to this file. Purge this
522 * inode from the filestreams cache so that it doesn't delay
523 * teardown of the inode.
524 */
525 if ((ip->i_d.di_nlink == 0) && xfs_inode_is_filestream(ip))
526 xfs_filestream_deassociate(ip);
527
Christoph Hellwigfbf3ce82007-06-28 16:46:47 +1000528 /*
529 * If we previously truncated this file and removed old data
530 * in the process, we want to initiate "early" writeout on
531 * the last close. This is an attempt to combat the notorious
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300532 * NULL files problem which is particularly noticeable from a
Christoph Hellwigfbf3ce82007-06-28 16:46:47 +1000533 * truncate down, buffered (re-)write (delalloc), followed by
534 * a crash. What we are effectively doing here is
535 * significantly reducing the time window where we'd otherwise
536 * be exposed to that problem.
537 */
Christoph Hellwig09262b432007-08-29 11:44:50 +1000538 truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED);
Dave Chinnerdf4368a2011-06-23 01:35:00 +0000539 if (truncated) {
540 xfs_iflags_clear(ip, XFS_IDIRTY_RELEASE);
541 if (VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0)
542 xfs_flush_pages(ip, 0, -1, XBF_ASYNC, FI_NONE);
543 }
Christoph Hellwigfbf3ce82007-06-28 16:46:47 +1000544 }
545
Dave Chinner6e857562010-12-23 12:02:31 +1100546 if (ip->i_d.di_nlink == 0)
547 return 0;
Christoph Hellwigc56c96312009-10-19 04:03:46 +0000548
Dave Chinner6e857562010-12-23 12:02:31 +1100549 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
550 ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 ||
551 ip->i_delayed_blks > 0)) &&
552 (ip->i_df.if_flags & XFS_IFEXTENTS)) &&
553 (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
554
555 /*
556 * If we can't get the iolock just skip truncating the blocks
557 * past EOF because we could deadlock with the mmap_sem
558 * otherwise. We'll get another chance to drop them once the
559 * last reference to the inode is dropped, so we'll never leak
560 * blocks permanently.
561 *
562 * Further, check if the inode is being opened, written and
563 * closed frequently and we have delayed allocation blocks
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300564 * outstanding (e.g. streaming writes from the NFS server),
Dave Chinner6e857562010-12-23 12:02:31 +1100565 * truncating the blocks past EOF will cause fragmentation to
566 * occur.
567 *
568 * In this case don't do the truncation, either, but we have to
569 * be careful how we detect this case. Blocks beyond EOF show
570 * up as i_delayed_blks even when the inode is clean, so we
571 * need to truncate them away first before checking for a dirty
572 * release. Hence on the first dirty close we will still remove
573 * the speculative allocation, but after that we will leave it
574 * in place.
575 */
576 if (xfs_iflags_test(ip, XFS_IDIRTY_RELEASE))
577 return 0;
578
579 error = xfs_free_eofblocks(mp, ip,
580 XFS_FREE_EOF_TRYLOCK);
581 if (error)
582 return error;
583
584 /* delalloc blocks after truncation means it really is dirty */
585 if (ip->i_delayed_blks)
586 xfs_iflags_set(ip, XFS_IDIRTY_RELEASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 return 0;
589}
590
591/*
592 * xfs_inactive
593 *
594 * This is called when the vnode reference count for the vnode
595 * goes to zero. If the file has been unlinked, then it must
596 * now be truncated. Also, we clear all of the read-ahead state
597 * kept for the inode here since the file is now closed.
598 */
Christoph Hellwig993386c12007-08-28 16:12:30 +1000599int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600xfs_inactive(
Christoph Hellwig993386c12007-08-28 16:12:30 +1000601 xfs_inode_t *ip)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602{
Nathan Scott67fcaa72006-06-09 17:00:52 +1000603 xfs_bmap_free_t free_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 xfs_fsblock_t first_block;
605 int committed;
606 xfs_trans_t *tp;
607 xfs_mount_t *mp;
608 int error;
609 int truncate;
610
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 /*
612 * If the inode is already free, then there can be nothing
613 * to clean up here.
614 */
Christoph Hellwigcb4c8cc2009-03-16 08:25:25 +0100615 if (ip->i_d.di_mode == 0 || is_bad_inode(VFS_I(ip))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 ASSERT(ip->i_df.if_real_bytes == 0);
617 ASSERT(ip->i_df.if_broot_bytes == 0);
618 return VN_INACTIVE_CACHE;
619 }
620
621 /*
622 * Only do a truncate if it's a regular file with
623 * some actual space in it. It's OK to look at the
624 * inode's fields without the lock because we're the
625 * only one with a reference to the inode.
626 */
627 truncate = ((ip->i_d.di_nlink == 0) &&
Lachlan McIlroyba87ea62007-05-08 13:49:46 +1000628 ((ip->i_d.di_size != 0) || (ip->i_size != 0) ||
629 (ip->i_d.di_nextents > 0) || (ip->i_delayed_blks > 0)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 ((ip->i_d.di_mode & S_IFMT) == S_IFREG));
631
632 mp = ip->i_mount;
633
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 error = 0;
635
636 /* If this is a read-only mount, don't do this (would generate I/O) */
Christoph Hellwigbd186aa2007-08-30 17:21:12 +1000637 if (mp->m_flags & XFS_MOUNT_RDONLY)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 goto out;
639
640 if (ip->i_d.di_nlink != 0) {
641 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
Christoph Hellwigdf80c932008-08-13 16:22:09 +1000642 ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 ||
Yingping Lu68bdb6e2006-01-11 15:38:31 +1100643 ip->i_delayed_blks > 0)) &&
Nathan Scottdd9f4382006-01-11 15:28:28 +1100644 (ip->i_df.if_flags & XFS_IFEXTENTS) &&
645 (!(ip->i_d.di_flags &
646 (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
647 (ip->i_delayed_blks != 0)))) {
Christoph Hellwigc56c96312009-10-19 04:03:46 +0000648 error = xfs_free_eofblocks(mp, ip, 0);
David Chinner92dfe8d2007-05-24 15:22:19 +1000649 if (error)
Jesper Juhl014c2542006-01-15 02:37:08 +0100650 return VN_INACTIVE_CACHE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 }
652 goto out;
653 }
654
655 ASSERT(ip->i_d.di_nlink == 0);
656
Christoph Hellwig7d095252009-06-08 15:33:32 +0200657 error = xfs_qm_dqattach(ip, 0);
658 if (error)
Jesper Juhl014c2542006-01-15 02:37:08 +0100659 return VN_INACTIVE_CACHE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660
661 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
662 if (truncate) {
663 /*
664 * Do the xfs_itruncate_start() call before
665 * reserving any log space because itruncate_start
666 * will call into the buffer cache and we can't
667 * do that within a transaction.
668 */
669 xfs_ilock(ip, XFS_IOLOCK_EXCL);
670
Lachlan McIlroyd3cf20942007-05-08 13:49:27 +1000671 error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, 0);
672 if (error) {
Jesper Juhl87ae3c22007-06-28 16:43:14 +1000673 xfs_trans_cancel(tp, 0);
Lachlan McIlroyd3cf20942007-05-08 13:49:27 +1000674 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
675 return VN_INACTIVE_CACHE;
676 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
678 error = xfs_trans_reserve(tp, 0,
679 XFS_ITRUNCATE_LOG_RES(mp),
680 0, XFS_TRANS_PERM_LOG_RES,
681 XFS_ITRUNCATE_LOG_COUNT);
682 if (error) {
683 /* Don't call itruncate_cleanup */
684 ASSERT(XFS_FORCED_SHUTDOWN(mp));
685 xfs_trans_cancel(tp, 0);
686 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
Jesper Juhl014c2542006-01-15 02:37:08 +0100687 return VN_INACTIVE_CACHE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 }
689
690 xfs_ilock(ip, XFS_ILOCK_EXCL);
Christoph Hellwig898621d2010-06-24 11:36:58 +1000691 xfs_trans_ijoin(tp, ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
693 /*
694 * normally, we have to run xfs_itruncate_finish sync.
695 * But if filesystem is wsync and we're in the inactive
696 * path, then we know that nlink == 0, and that the
697 * xaction that made nlink == 0 is permanently committed
698 * since xfs_remove runs as a synchronous transaction.
699 */
700 error = xfs_itruncate_finish(&tp, ip, 0, XFS_DATA_FORK,
701 (!(mp->m_flags & XFS_MOUNT_WSYNC) ? 1 : 0));
702
703 if (error) {
704 xfs_trans_cancel(tp,
705 XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
706 xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
Jesper Juhl014c2542006-01-15 02:37:08 +0100707 return VN_INACTIVE_CACHE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 }
709 } else if ((ip->i_d.di_mode & S_IFMT) == S_IFLNK) {
710
711 /*
712 * If we get an error while cleaning up a
713 * symlink we bail out.
714 */
715 error = (ip->i_d.di_size > XFS_IFORK_DSIZE(ip)) ?
716 xfs_inactive_symlink_rmt(ip, &tp) :
717 xfs_inactive_symlink_local(ip, &tp);
718
719 if (error) {
720 ASSERT(tp == NULL);
Jesper Juhl014c2542006-01-15 02:37:08 +0100721 return VN_INACTIVE_CACHE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 }
723
Christoph Hellwig898621d2010-06-24 11:36:58 +1000724 xfs_trans_ijoin(tp, ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 } else {
726 error = xfs_trans_reserve(tp, 0,
727 XFS_IFREE_LOG_RES(mp),
728 0, XFS_TRANS_PERM_LOG_RES,
729 XFS_INACTIVE_LOG_COUNT);
730 if (error) {
731 ASSERT(XFS_FORCED_SHUTDOWN(mp));
732 xfs_trans_cancel(tp, 0);
Jesper Juhl014c2542006-01-15 02:37:08 +0100733 return VN_INACTIVE_CACHE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 }
735
736 xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
Christoph Hellwig898621d2010-06-24 11:36:58 +1000737 xfs_trans_ijoin(tp, ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 }
739
740 /*
741 * If there are attributes associated with the file
742 * then blow them away now. The code calls a routine
743 * that recursively deconstructs the attribute fork.
744 * We need to just commit the current transaction
745 * because we can't use it for xfs_attr_inactive().
746 */
747 if (ip->i_d.di_anextents > 0) {
748 error = xfs_inactive_attrs(ip, &tp);
749 /*
750 * If we got an error, the transaction is already
751 * cancelled, and the inode is unlocked. Just get out.
752 */
753 if (error)
Jesper Juhl014c2542006-01-15 02:37:08 +0100754 return VN_INACTIVE_CACHE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 } else if (ip->i_afp) {
756 xfs_idestroy_fork(ip, XFS_ATTR_FORK);
757 }
758
759 /*
760 * Free the inode.
761 */
Eric Sandeen9d87c312009-01-14 23:22:07 -0600762 xfs_bmap_init(&free_list, &first_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 error = xfs_ifree(tp, ip, &free_list);
764 if (error) {
765 /*
766 * If we fail to free the inode, shut down. The cancel
767 * might do that, we need to make sure. Otherwise the
768 * inode might be lost for a long time or forever.
769 */
770 if (!XFS_FORCED_SHUTDOWN(mp)) {
Dave Chinner0b932cc2011-03-07 10:08:35 +1100771 xfs_notice(mp, "%s: xfs_ifree returned error %d",
772 __func__, error);
Nathan Scott7d04a332006-06-09 14:58:38 +1000773 xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 }
775 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
776 } else {
777 /*
778 * Credit the quota account(s). The inode is gone.
779 */
Christoph Hellwig7d095252009-06-08 15:33:32 +0200780 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_ICOUNT, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781
782 /*
David Chinner78e9da72008-04-10 12:24:17 +1000783 * Just ignore errors at this point. There is nothing we can
784 * do except to try to keep going. Make sure it's not a silent
785 * error.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 */
David Chinner78e9da72008-04-10 12:24:17 +1000787 error = xfs_bmap_finish(&tp, &free_list, &committed);
788 if (error)
Dave Chinner53487782011-03-07 10:05:35 +1100789 xfs_notice(mp, "%s: xfs_bmap_finish returned error %d",
790 __func__, error);
David Chinner78e9da72008-04-10 12:24:17 +1000791 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
792 if (error)
Dave Chinner53487782011-03-07 10:05:35 +1100793 xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
794 __func__, error);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 }
Christoph Hellwig7d095252009-06-08 15:33:32 +0200796
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 /*
798 * Release the dquots held by inode, if any.
799 */
Christoph Hellwig7d095252009-06-08 15:33:32 +0200800 xfs_qm_dqdetach(ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
802
803 out:
804 return VN_INACTIVE_CACHE;
805}
806
Barry Naujok384f3ce2008-05-21 16:58:22 +1000807/*
808 * Lookups up an inode from "name". If ci_name is not NULL, then a CI match
809 * is allowed, otherwise it has to be an exact match. If a CI match is found,
810 * ci_name->name will point to a the actual name (caller must free) or
811 * will be set to NULL if an exact match is found.
812 */
Christoph Hellwig993386c12007-08-28 16:12:30 +1000813int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814xfs_lookup(
Christoph Hellwig993386c12007-08-28 16:12:30 +1000815 xfs_inode_t *dp,
Barry Naujok556b8b12008-04-10 12:22:07 +1000816 struct xfs_name *name,
Barry Naujok384f3ce2008-05-21 16:58:22 +1000817 xfs_inode_t **ipp,
818 struct xfs_name *ci_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819{
Christoph Hellwigeca450b2008-04-22 17:33:52 +1000820 xfs_ino_t inum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 int error;
822 uint lock_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
Christoph Hellwigcca28fb2010-06-24 11:57:09 +1000824 trace_xfs_lookup(dp, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825
826 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
827 return XFS_ERROR(EIO);
828
829 lock_mode = xfs_ilock_map_shared(dp);
Barry Naujok384f3ce2008-05-21 16:58:22 +1000830 error = xfs_dir_lookup(NULL, dp, name, &inum, ci_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 xfs_iunlock_map_shared(dp, lock_mode);
Christoph Hellwigeca450b2008-04-22 17:33:52 +1000832
833 if (error)
834 goto out;
835
Dave Chinner7b6259e2010-06-24 11:35:17 +1000836 error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp);
Christoph Hellwigeca450b2008-04-22 17:33:52 +1000837 if (error)
Barry Naujok384f3ce2008-05-21 16:58:22 +1000838 goto out_free_name;
Christoph Hellwigeca450b2008-04-22 17:33:52 +1000839
Christoph Hellwigeca450b2008-04-22 17:33:52 +1000840 return 0;
841
Barry Naujok384f3ce2008-05-21 16:58:22 +1000842out_free_name:
843 if (ci_name)
844 kmem_free(ci_name->name);
845out:
Christoph Hellwigeca450b2008-04-22 17:33:52 +1000846 *ipp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 return error;
848}
849
Christoph Hellwig993386c12007-08-28 16:12:30 +1000850int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851xfs_create(
Christoph Hellwig993386c12007-08-28 16:12:30 +1000852 xfs_inode_t *dp,
Barry Naujok556b8b12008-04-10 12:22:07 +1000853 struct xfs_name *name,
Christoph Hellwig3e5daf02007-10-11 18:09:12 +1000854 mode_t mode,
855 xfs_dev_t rdev,
Christoph Hellwig6c77b0e2010-10-06 18:41:17 +0000856 xfs_inode_t **ipp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857{
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100858 int is_dir = S_ISDIR(mode);
859 struct xfs_mount *mp = dp->i_mount;
860 struct xfs_inode *ip = NULL;
861 struct xfs_trans *tp = NULL;
Barry Naujok556b8b12008-04-10 12:22:07 +1000862 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 xfs_bmap_free_t free_list;
864 xfs_fsblock_t first_block;
Christoph Hellwig993386c12007-08-28 16:12:30 +1000865 boolean_t unlock_dp_on_error = B_FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 uint cancel_flags;
867 int committed;
Arkadiusz Mi?kiewicz67430992010-09-26 06:10:18 +0000868 prid_t prid;
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100869 struct xfs_dquot *udqp = NULL;
870 struct xfs_dquot *gdqp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 uint resblks;
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100872 uint log_res;
873 uint log_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874
Christoph Hellwigcca28fb2010-06-24 11:57:09 +1000875 trace_xfs_create(dp, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100877 if (XFS_FORCED_SHUTDOWN(mp))
878 return XFS_ERROR(EIO);
879
Nathan Scott365ca832005-06-21 15:39:12 +1000880 if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
Arkadiusz Mi?kiewicz67430992010-09-26 06:10:18 +0000881 prid = xfs_get_projid(dp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 else
Arkadiusz Mi?kiewicz67430992010-09-26 06:10:18 +0000883 prid = XFS_PROJID_DEFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
885 /*
886 * Make sure that we have allocated dquot(s) on disk.
887 */
Christoph Hellwig7d095252009-06-08 15:33:32 +0200888 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100889 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 if (error)
Christoph Hellwigec3ba852011-02-13 13:26:42 +0000891 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100893 if (is_dir) {
894 rdev = 0;
895 resblks = XFS_MKDIR_SPACE_RES(mp, name->len);
896 log_res = XFS_MKDIR_LOG_RES(mp);
897 log_count = XFS_MKDIR_LOG_COUNT;
898 tp = xfs_trans_alloc(mp, XFS_TRANS_MKDIR);
899 } else {
900 resblks = XFS_CREATE_SPACE_RES(mp, name->len);
901 log_res = XFS_CREATE_LOG_RES(mp);
902 log_count = XFS_CREATE_LOG_COUNT;
903 tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE);
904 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100907
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 /*
909 * Initially assume that the file does not exist and
910 * reserve the resources for that case. If that is not
911 * the case we'll drop the one we have and get a more
912 * appropriate transaction later.
913 */
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100914 error = xfs_trans_reserve(tp, resblks, log_res, 0,
915 XFS_TRANS_PERM_LOG_RES, log_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 if (error == ENOSPC) {
Dave Chinner153fec42009-04-06 18:48:30 +0200917 /* flush outstanding delalloc blocks and retry */
918 xfs_flush_inodes(dp);
Christoph Hellwig4734d402009-09-09 18:19:02 -0500919 error = xfs_trans_reserve(tp, resblks, log_res, 0,
920 XFS_TRANS_PERM_LOG_RES, log_count);
Dave Chinner153fec42009-04-06 18:48:30 +0200921 }
922 if (error == ENOSPC) {
923 /* No space at all so try a "no-allocation" reservation */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 resblks = 0;
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100925 error = xfs_trans_reserve(tp, 0, log_res, 0,
926 XFS_TRANS_PERM_LOG_RES, log_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 }
928 if (error) {
929 cancel_flags = 0;
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100930 goto out_trans_cancel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 }
932
Lachlan McIlroyf7c66ce2007-05-08 13:50:19 +1000933 xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
Christoph Hellwig993386c12007-08-28 16:12:30 +1000934 unlock_dp_on_error = B_TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100936 /*
937 * Check for directory link count overflow.
938 */
939 if (is_dir && dp->i_d.di_nlink >= XFS_MAXLINK) {
940 error = XFS_ERROR(EMLINK);
941 goto out_trans_cancel;
942 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100944 xfs_bmap_init(&free_list, &first_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945
946 /*
947 * Reserve disk quota and the inode.
948 */
Christoph Hellwig7d095252009-06-08 15:33:32 +0200949 error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 if (error)
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100951 goto out_trans_cancel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952
Barry Naujok556b8b12008-04-10 12:22:07 +1000953 error = xfs_dir_canenter(tp, dp, name, resblks);
954 if (error)
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100955 goto out_trans_cancel;
956
957 /*
958 * A newly created regular or special file just has one directory
959 * entry pointing to them, but a directory also the "." entry
960 * pointing to itself.
961 */
Christoph Hellwig6c77b0e2010-10-06 18:41:17 +0000962 error = xfs_dir_ialloc(&tp, dp, mode, is_dir ? 2 : 1, rdev,
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100963 prid, resblks > 0, &ip, &committed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 if (error) {
965 if (error == ENOSPC)
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100966 goto out_trans_cancel;
967 goto out_trans_abort;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969
970 /*
Christoph Hellwig993386c12007-08-28 16:12:30 +1000971 * Now we join the directory inode to the transaction. We do not do it
972 * earlier because xfs_dir_ialloc might commit the previous transaction
973 * (and release all the locks). An error from here on will result in
974 * the transaction cancel unlocking dp so don't do it explicitly in the
975 * error path.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 */
Christoph Hellwig898621d2010-06-24 11:36:58 +1000977 xfs_trans_ijoin_ref(tp, dp, XFS_ILOCK_EXCL);
Christoph Hellwig993386c12007-08-28 16:12:30 +1000978 unlock_dp_on_error = B_FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
Barry Naujok556b8b12008-04-10 12:22:07 +1000980 error = xfs_dir_createname(tp, dp, name, ip->i_ino,
Nathan Scottf6c2d1f2006-06-20 13:04:51 +1000981 &first_block, &free_list, resblks ?
982 resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 if (error) {
984 ASSERT(error != ENOSPC);
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100985 goto out_trans_abort;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 }
Dave Chinnerdcd79a12010-09-28 12:27:25 +1000987 xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
989
Christoph Hellwig517b5e82009-02-09 08:38:02 +0100990 if (is_dir) {
991 error = xfs_dir_init(tp, ip, dp);
992 if (error)
993 goto out_bmap_cancel;
994
995 error = xfs_bumplink(tp, dp);
996 if (error)
997 goto out_bmap_cancel;
998 }
999
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 /*
1001 * If this is a synchronous mount, make sure that the
1002 * create transaction goes to disk before returning to
1003 * the user.
1004 */
Christoph Hellwig517b5e82009-02-09 08:38:02 +01001005 if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 xfs_trans_set_sync(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 /*
1009 * Attach the dquot(s) to the inodes and modify them incore.
1010 * These ids of the inode couldn't have changed since the new
1011 * inode has been locked ever since it was created.
1012 */
Christoph Hellwig7d095252009-06-08 15:33:32 +02001013 xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014
Eric Sandeenf7c99b62007-02-10 18:37:16 +11001015 error = xfs_bmap_finish(&tp, &free_list, &committed);
Christoph Hellwig517b5e82009-02-09 08:38:02 +01001016 if (error)
Christoph Hellwigec3ba852011-02-13 13:26:42 +00001017 goto out_bmap_cancel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018
Eric Sandeen1c72bf92007-05-08 13:48:42 +10001019 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
Christoph Hellwigec3ba852011-02-13 13:26:42 +00001020 if (error)
1021 goto out_release_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
Christoph Hellwig7d095252009-06-08 15:33:32 +02001023 xfs_qm_dqrele(udqp);
1024 xfs_qm_dqrele(gdqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
Christoph Hellwig979ebab2008-03-06 13:46:05 +11001026 *ipp = ip;
Christoph Hellwig288699f2010-06-23 18:11:15 +10001027 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
Christoph Hellwig517b5e82009-02-09 08:38:02 +01001029 out_bmap_cancel:
1030 xfs_bmap_cancel(&free_list);
1031 out_trans_abort:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 cancel_flags |= XFS_TRANS_ABORT;
Christoph Hellwig517b5e82009-02-09 08:38:02 +01001033 out_trans_cancel:
1034 xfs_trans_cancel(tp, cancel_flags);
Christoph Hellwigec3ba852011-02-13 13:26:42 +00001035 out_release_inode:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 /*
1037 * Wait until after the current transaction is aborted to
1038 * release the inode. This prevents recursive transactions
1039 * and deadlocks from xfs_inactive.
1040 */
Christoph Hellwigec3ba852011-02-13 13:26:42 +00001041 if (ip)
1042 IRELE(ip);
1043
1044 xfs_qm_dqrele(udqp);
1045 xfs_qm_dqrele(gdqp);
1046
1047 if (unlock_dp_on_error)
1048 xfs_iunlock(dp, XFS_ILOCK_EXCL);
1049 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050}
1051
1052#ifdef DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053int xfs_locked_n;
1054int xfs_small_retries;
1055int xfs_middle_retries;
1056int xfs_lots_retries;
1057int xfs_lock_delays;
1058#endif
1059
1060/*
Lachlan McIlroyf7c66ce2007-05-08 13:50:19 +10001061 * Bump the subclass so xfs_lock_inodes() acquires each lock with
1062 * a different value
1063 */
1064static inline int
1065xfs_lock_inumorder(int lock_mode, int subclass)
1066{
1067 if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL))
David Chinner0f1145c2007-06-29 17:26:09 +10001068 lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_IOLOCK_SHIFT;
Lachlan McIlroyf7c66ce2007-05-08 13:50:19 +10001069 if (lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL))
David Chinner0f1145c2007-06-29 17:26:09 +10001070 lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_ILOCK_SHIFT;
Lachlan McIlroyf7c66ce2007-05-08 13:50:19 +10001071
1072 return lock_mode;
1073}
1074
1075/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 * The following routine will lock n inodes in exclusive mode.
1077 * We assume the caller calls us with the inodes in i_ino order.
1078 *
1079 * We need to detect deadlock where an inode that we lock
1080 * is in the AIL and we start waiting for another inode that is locked
1081 * by a thread in a long running transaction (such as truncate). This can
1082 * result in deadlock since the long running trans might need to wait
1083 * for the inode we just locked in order to push the tail and free space
1084 * in the log.
1085 */
1086void
1087xfs_lock_inodes(
1088 xfs_inode_t **ips,
1089 int inodes,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 uint lock_mode)
1091{
1092 int attempts = 0, i, j, try_lock;
1093 xfs_log_item_t *lp;
1094
1095 ASSERT(ips && (inodes >= 2)); /* we need at least two */
1096
Christoph Hellwigcfa853e2008-04-22 17:34:06 +10001097 try_lock = 0;
1098 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
1100again:
1101 for (; i < inodes; i++) {
1102 ASSERT(ips[i]);
1103
1104 if (i && (ips[i] == ips[i-1])) /* Already locked */
1105 continue;
1106
1107 /*
1108 * If try_lock is not set yet, make sure all locked inodes
1109 * are not in the AIL.
1110 * If any are, set try_lock to be used later.
1111 */
1112
1113 if (!try_lock) {
1114 for (j = (i - 1); j >= 0 && !try_lock; j--) {
1115 lp = (xfs_log_item_t *)ips[j]->i_itemp;
1116 if (lp && (lp->li_flags & XFS_LI_IN_AIL)) {
1117 try_lock++;
1118 }
1119 }
1120 }
1121
1122 /*
1123 * If any of the previous locks we have locked is in the AIL,
1124 * we must TRY to get the second and subsequent locks. If
1125 * we can't get any, we must release all we have
1126 * and try again.
1127 */
1128
1129 if (try_lock) {
1130 /* try_lock must be 0 if i is 0. */
1131 /*
1132 * try_lock means we have an inode locked
1133 * that is in the AIL.
1134 */
1135 ASSERT(i != 0);
Lachlan McIlroyf7c66ce2007-05-08 13:50:19 +10001136 if (!xfs_ilock_nowait(ips[i], xfs_lock_inumorder(lock_mode, i))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 attempts++;
1138
1139 /*
1140 * Unlock all previous guys and try again.
1141 * xfs_iunlock will try to push the tail
1142 * if the inode is in the AIL.
1143 */
1144
1145 for(j = i - 1; j >= 0; j--) {
1146
1147 /*
1148 * Check to see if we've already
1149 * unlocked this one.
1150 * Not the first one going back,
1151 * and the inode ptr is the same.
1152 */
1153 if ((j != (i - 1)) && ips[j] ==
1154 ips[j+1])
1155 continue;
1156
1157 xfs_iunlock(ips[j], lock_mode);
1158 }
1159
1160 if ((attempts % 5) == 0) {
1161 delay(1); /* Don't just spin the CPU */
1162#ifdef DEBUG
1163 xfs_lock_delays++;
1164#endif
1165 }
1166 i = 0;
1167 try_lock = 0;
1168 goto again;
1169 }
1170 } else {
Lachlan McIlroyf7c66ce2007-05-08 13:50:19 +10001171 xfs_ilock(ips[i], xfs_lock_inumorder(lock_mode, i));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 }
1173 }
1174
1175#ifdef DEBUG
1176 if (attempts) {
1177 if (attempts < 5) xfs_small_retries++;
1178 else if (attempts < 100) xfs_middle_retries++;
1179 else xfs_lots_retries++;
1180 } else {
1181 xfs_locked_n++;
1182 }
1183#endif
1184}
1185
David Chinnerf9114eb2008-09-17 16:51:21 +10001186/*
1187 * xfs_lock_two_inodes() can only be used to lock one type of lock
1188 * at a time - the iolock or the ilock, but not both at once. If
1189 * we lock both at once, lockdep will report false positives saying
1190 * we have violated locking orders.
1191 */
Christoph Hellwige1cccd92008-08-13 16:18:07 +10001192void
1193xfs_lock_two_inodes(
1194 xfs_inode_t *ip0,
1195 xfs_inode_t *ip1,
1196 uint lock_mode)
1197{
1198 xfs_inode_t *temp;
1199 int attempts = 0;
1200 xfs_log_item_t *lp;
1201
David Chinnerf9114eb2008-09-17 16:51:21 +10001202 if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL))
1203 ASSERT((lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)) == 0);
Christoph Hellwige1cccd92008-08-13 16:18:07 +10001204 ASSERT(ip0->i_ino != ip1->i_ino);
1205
1206 if (ip0->i_ino > ip1->i_ino) {
1207 temp = ip0;
1208 ip0 = ip1;
1209 ip1 = temp;
1210 }
1211
1212 again:
1213 xfs_ilock(ip0, xfs_lock_inumorder(lock_mode, 0));
1214
1215 /*
1216 * If the first lock we have locked is in the AIL, we must TRY to get
1217 * the second lock. If we can't get it, we must release the first one
1218 * and try again.
1219 */
1220 lp = (xfs_log_item_t *)ip0->i_itemp;
1221 if (lp && (lp->li_flags & XFS_LI_IN_AIL)) {
1222 if (!xfs_ilock_nowait(ip1, xfs_lock_inumorder(lock_mode, 1))) {
1223 xfs_iunlock(ip0, lock_mode);
1224 if ((++attempts % 5) == 0)
1225 delay(1); /* Don't just spin the CPU */
1226 goto again;
1227 }
1228 } else {
1229 xfs_ilock(ip1, xfs_lock_inumorder(lock_mode, 1));
1230 }
1231}
1232
Christoph Hellwig993386c12007-08-28 16:12:30 +10001233int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234xfs_remove(
Christoph Hellwig993386c12007-08-28 16:12:30 +10001235 xfs_inode_t *dp,
Barry Naujok556b8b12008-04-10 12:22:07 +10001236 struct xfs_name *name,
1237 xfs_inode_t *ip)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238{
Christoph Hellwig993386c12007-08-28 16:12:30 +10001239 xfs_mount_t *mp = dp->i_mount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 xfs_trans_t *tp = NULL;
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001241 int is_dir = S_ISDIR(ip->i_d.di_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 int error = 0;
1243 xfs_bmap_free_t free_list;
1244 xfs_fsblock_t first_block;
1245 int cancel_flags;
1246 int committed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 int link_zero;
1248 uint resblks;
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001249 uint log_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250
Christoph Hellwigcca28fb2010-06-24 11:57:09 +10001251 trace_xfs_remove(dp, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 if (XFS_FORCED_SHUTDOWN(mp))
1254 return XFS_ERROR(EIO);
1255
Christoph Hellwig7d095252009-06-08 15:33:32 +02001256 error = xfs_qm_dqattach(dp, 0);
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001257 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 goto std_return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259
Christoph Hellwig7d095252009-06-08 15:33:32 +02001260 error = xfs_qm_dqattach(ip, 0);
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001261 if (error)
1262 goto std_return;
1263
1264 if (is_dir) {
1265 tp = xfs_trans_alloc(mp, XFS_TRANS_RMDIR);
1266 log_count = XFS_DEFAULT_LOG_COUNT;
1267 } else {
1268 tp = xfs_trans_alloc(mp, XFS_TRANS_REMOVE);
1269 log_count = XFS_REMOVE_LOG_COUNT;
1270 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001272
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 /*
1274 * We try to get the real space reservation first,
1275 * allowing for directory btree deletion(s) implying
1276 * possible bmap insert(s). If we can't get the space
1277 * reservation then we use 0 instead, and avoid the bmap
1278 * btree insert(s) in the directory code by, if the bmap
1279 * insert tries to happen, instead trimming the LAST
1280 * block from the directory.
1281 */
1282 resblks = XFS_REMOVE_SPACE_RES(mp);
1283 error = xfs_trans_reserve(tp, resblks, XFS_REMOVE_LOG_RES(mp), 0,
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001284 XFS_TRANS_PERM_LOG_RES, log_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 if (error == ENOSPC) {
1286 resblks = 0;
1287 error = xfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001288 XFS_TRANS_PERM_LOG_RES, log_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 }
1290 if (error) {
1291 ASSERT(error != ENOSPC);
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001292 cancel_flags = 0;
1293 goto out_trans_cancel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 }
1295
Christoph Hellwige1cccd92008-08-13 16:18:07 +10001296 xfs_lock_two_inodes(dp, ip, XFS_ILOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297
Christoph Hellwig898621d2010-06-24 11:36:58 +10001298 xfs_trans_ijoin_ref(tp, dp, XFS_ILOCK_EXCL);
1299 xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300
1301 /*
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001302 * If we're removing a directory perform some additional validation.
1303 */
1304 if (is_dir) {
1305 ASSERT(ip->i_d.di_nlink >= 2);
1306 if (ip->i_d.di_nlink != 2) {
1307 error = XFS_ERROR(ENOTEMPTY);
1308 goto out_trans_cancel;
1309 }
1310 if (!xfs_dir_isempty(ip)) {
1311 error = XFS_ERROR(ENOTEMPTY);
1312 goto out_trans_cancel;
1313 }
1314 }
1315
Eric Sandeen9d87c312009-01-14 23:22:07 -06001316 xfs_bmap_init(&free_list, &first_block);
Barry Naujok556b8b12008-04-10 12:22:07 +10001317 error = xfs_dir_removename(tp, dp, name, ip->i_ino,
Christoph Hellwigd4377d82008-04-22 17:33:46 +10001318 &first_block, &free_list, resblks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 if (error) {
1320 ASSERT(error != ENOENT);
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001321 goto out_bmap_cancel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 }
Dave Chinnerdcd79a12010-09-28 12:27:25 +10001323 xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001325 if (is_dir) {
1326 /*
1327 * Drop the link from ip's "..".
1328 */
1329 error = xfs_droplink(tp, dp);
1330 if (error)
1331 goto out_bmap_cancel;
1332
1333 /*
Christoph Hellwig2b7035f2008-10-30 17:55:18 +11001334 * Drop the "." link from ip to self.
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001335 */
1336 error = xfs_droplink(tp, ip);
1337 if (error)
1338 goto out_bmap_cancel;
1339 } else {
1340 /*
1341 * When removing a non-directory we need to log the parent
Dave Chinner26c52952008-11-28 14:23:37 +11001342 * inode here. For a directory this is done implicitly
1343 * by the xfs_droplink call for the ".." entry.
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001344 */
1345 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 }
1347
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001348 /*
Christoph Hellwig2b7035f2008-10-30 17:55:18 +11001349 * Drop the link from dp to ip.
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001350 */
1351 error = xfs_droplink(tp, ip);
1352 if (error)
1353 goto out_bmap_cancel;
1354
1355 /*
1356 * Determine if this is the last link while
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 * we are in the transaction.
1358 */
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001359 link_zero = (ip->i_d.di_nlink == 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
1361 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 * If this is a synchronous mount, make sure that the
1363 * remove transaction goes to disk before returning to
1364 * the user.
1365 */
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001366 if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 xfs_trans_set_sync(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
Eric Sandeenf7c99b62007-02-10 18:37:16 +11001369 error = xfs_bmap_finish(&tp, &free_list, &committed);
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001370 if (error)
1371 goto out_bmap_cancel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
Eric Sandeen1c72bf92007-05-08 13:48:42 +10001373 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
Christoph Hellwig5df78e72008-04-22 17:34:24 +10001374 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 goto std_return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376
1377 /*
David Chinner2a82b8b2007-07-11 11:09:12 +10001378 * If we are using filestreams, kill the stream association.
1379 * If the file is still open it may get a new one but that
1380 * will get killed on last close in xfs_close() so we don't
1381 * have to worry about that.
1382 */
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001383 if (!is_dir && link_zero && xfs_inode_is_filestream(ip))
David Chinner2a82b8b2007-07-11 11:09:12 +10001384 xfs_filestream_deassociate(ip);
1385
Christoph Hellwig288699f2010-06-23 18:11:15 +10001386 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001388 out_bmap_cancel:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 xfs_bmap_cancel(&free_list);
1390 cancel_flags |= XFS_TRANS_ABORT;
Christoph Hellwig8f112e32008-06-23 13:25:17 +10001391 out_trans_cancel:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 xfs_trans_cancel(tp, cancel_flags);
Christoph Hellwig288699f2010-06-23 18:11:15 +10001393 std_return:
1394 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395}
1396
Christoph Hellwig993386c12007-08-28 16:12:30 +10001397int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398xfs_link(
Christoph Hellwig993386c12007-08-28 16:12:30 +10001399 xfs_inode_t *tdp,
Christoph Hellwiga3da7892008-03-06 13:46:12 +11001400 xfs_inode_t *sip,
Barry Naujok556b8b12008-04-10 12:22:07 +10001401 struct xfs_name *target_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402{
Christoph Hellwig993386c12007-08-28 16:12:30 +10001403 xfs_mount_t *mp = tdp->i_mount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 xfs_trans_t *tp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 int error;
1406 xfs_bmap_free_t free_list;
1407 xfs_fsblock_t first_block;
1408 int cancel_flags;
1409 int committed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 int resblks;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
Christoph Hellwigcca28fb2010-06-24 11:57:09 +10001412 trace_xfs_link(tdp, target_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
Christoph Hellwiga3da7892008-03-06 13:46:12 +11001414 ASSERT(!S_ISDIR(sip->i_d.di_mode));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 if (XFS_FORCED_SHUTDOWN(mp))
1417 return XFS_ERROR(EIO);
1418
Christoph Hellwig7d095252009-06-08 15:33:32 +02001419 error = xfs_qm_dqattach(sip, 0);
Christoph Hellwigcb3f35b2009-02-04 09:34:20 +01001420 if (error)
1421 goto std_return;
1422
Christoph Hellwig7d095252009-06-08 15:33:32 +02001423 error = xfs_qm_dqattach(tdp, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 if (error)
1425 goto std_return;
1426
1427 tp = xfs_trans_alloc(mp, XFS_TRANS_LINK);
1428 cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
Barry Naujok556b8b12008-04-10 12:22:07 +10001429 resblks = XFS_LINK_SPACE_RES(mp, target_name->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 error = xfs_trans_reserve(tp, resblks, XFS_LINK_LOG_RES(mp), 0,
1431 XFS_TRANS_PERM_LOG_RES, XFS_LINK_LOG_COUNT);
1432 if (error == ENOSPC) {
1433 resblks = 0;
1434 error = xfs_trans_reserve(tp, 0, XFS_LINK_LOG_RES(mp), 0,
1435 XFS_TRANS_PERM_LOG_RES, XFS_LINK_LOG_COUNT);
1436 }
1437 if (error) {
1438 cancel_flags = 0;
1439 goto error_return;
1440 }
1441
Christoph Hellwige1cccd92008-08-13 16:18:07 +10001442 xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
Christoph Hellwig898621d2010-06-24 11:36:58 +10001444 xfs_trans_ijoin_ref(tp, sip, XFS_ILOCK_EXCL);
1445 xfs_trans_ijoin_ref(tp, tdp, XFS_ILOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446
1447 /*
1448 * If the source has too many links, we can't make any more to it.
1449 */
1450 if (sip->i_d.di_nlink >= XFS_MAXLINK) {
1451 error = XFS_ERROR(EMLINK);
1452 goto error_return;
1453 }
1454
Nathan Scott365ca832005-06-21 15:39:12 +10001455 /*
1456 * If we are using project inheritance, we only allow hard link
1457 * creation in our tree when the project IDs are the same; else
1458 * the tree quota mechanism could be circumvented.
1459 */
1460 if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
Arkadiusz Mi?kiewicz67430992010-09-26 06:10:18 +00001461 (xfs_get_projid(tdp) != xfs_get_projid(sip)))) {
Nathan Scottb1ecdda2006-05-08 19:51:42 +10001462 error = XFS_ERROR(EXDEV);
Nathan Scott365ca832005-06-21 15:39:12 +10001463 goto error_return;
1464 }
1465
Barry Naujok556b8b12008-04-10 12:22:07 +10001466 error = xfs_dir_canenter(tp, tdp, target_name, resblks);
1467 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 goto error_return;
1469
Eric Sandeen9d87c312009-01-14 23:22:07 -06001470 xfs_bmap_init(&free_list, &first_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
Barry Naujok556b8b12008-04-10 12:22:07 +10001472 error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino,
1473 &first_block, &free_list, resblks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 if (error)
1475 goto abort_return;
Dave Chinnerdcd79a12010-09-28 12:27:25 +10001476 xfs_trans_ichgtime(tp, tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE);
1478
1479 error = xfs_bumplink(tp, sip);
Alexey Dobriyanb71d3002006-06-27 12:45:17 +10001480 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 goto abort_return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
1483 /*
1484 * If this is a synchronous mount, make sure that the
1485 * link transaction goes to disk before returning to
1486 * the user.
1487 */
1488 if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
1489 xfs_trans_set_sync(tp);
1490 }
1491
Eric Sandeenf7c99b62007-02-10 18:37:16 +11001492 error = xfs_bmap_finish (&tp, &free_list, &committed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 if (error) {
1494 xfs_bmap_cancel(&free_list);
1495 goto abort_return;
1496 }
1497
Christoph Hellwig288699f2010-06-23 18:11:15 +10001498 return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499
1500 abort_return:
1501 cancel_flags |= XFS_TRANS_ABORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 error_return:
1503 xfs_trans_cancel(tp, cancel_flags);
Christoph Hellwig288699f2010-06-23 18:11:15 +10001504 std_return:
1505 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506}
Alexey Dobriyanb71d3002006-06-27 12:45:17 +10001507
Christoph Hellwig993386c12007-08-28 16:12:30 +10001508int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509xfs_symlink(
Christoph Hellwig993386c12007-08-28 16:12:30 +10001510 xfs_inode_t *dp,
Barry Naujok556b8b12008-04-10 12:22:07 +10001511 struct xfs_name *link_name,
1512 const char *target_path,
Christoph Hellwig3e5daf02007-10-11 18:09:12 +10001513 mode_t mode,
Christoph Hellwig6c77b0e2010-10-06 18:41:17 +00001514 xfs_inode_t **ipp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515{
Christoph Hellwig993386c12007-08-28 16:12:30 +10001516 xfs_mount_t *mp = dp->i_mount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 xfs_trans_t *tp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 xfs_inode_t *ip;
1519 int error;
1520 int pathlen;
1521 xfs_bmap_free_t free_list;
1522 xfs_fsblock_t first_block;
Christoph Hellwig993386c12007-08-28 16:12:30 +10001523 boolean_t unlock_dp_on_error = B_FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 uint cancel_flags;
1525 int committed;
1526 xfs_fileoff_t first_fsb;
1527 xfs_filblks_t fs_blocks;
1528 int nmaps;
1529 xfs_bmbt_irec_t mval[SYMLINK_MAPS];
1530 xfs_daddr_t d;
Barry Naujok556b8b12008-04-10 12:22:07 +10001531 const char *cur_chunk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 int byte_cnt;
1533 int n;
1534 xfs_buf_t *bp;
Arkadiusz Mi?kiewicz67430992010-09-26 06:10:18 +00001535 prid_t prid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 struct xfs_dquot *udqp, *gdqp;
1537 uint resblks;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538
Christoph Hellwig3937be52008-03-06 13:46:19 +11001539 *ipp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 error = 0;
1541 ip = NULL;
1542 tp = NULL;
1543
Christoph Hellwigcca28fb2010-06-24 11:57:09 +10001544 trace_xfs_symlink(dp, link_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545
1546 if (XFS_FORCED_SHUTDOWN(mp))
1547 return XFS_ERROR(EIO);
1548
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 /*
1550 * Check component lengths of the target path name.
1551 */
1552 pathlen = strlen(target_path);
1553 if (pathlen >= MAXPATHLEN) /* total string too long */
1554 return XFS_ERROR(ENAMETOOLONG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 udqp = gdqp = NULL;
Nathan Scott365ca832005-06-21 15:39:12 +10001557 if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
Arkadiusz Mi?kiewicz67430992010-09-26 06:10:18 +00001558 prid = xfs_get_projid(dp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 else
Arkadiusz Mi?kiewicz67430992010-09-26 06:10:18 +00001560 prid = XFS_PROJID_DEFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561
1562 /*
1563 * Make sure that we have allocated dquot(s) on disk.
1564 */
Christoph Hellwig7d095252009-06-08 15:33:32 +02001565 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
1567 if (error)
1568 goto std_return;
1569
1570 tp = xfs_trans_alloc(mp, XFS_TRANS_SYMLINK);
1571 cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
1572 /*
1573 * The symlink will fit into the inode data fork?
1574 * There can't be any attributes so we get the whole variable part.
1575 */
1576 if (pathlen <= XFS_LITINO(mp))
1577 fs_blocks = 0;
1578 else
1579 fs_blocks = XFS_B_TO_FSB(mp, pathlen);
Barry Naujok556b8b12008-04-10 12:22:07 +10001580 resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 error = xfs_trans_reserve(tp, resblks, XFS_SYMLINK_LOG_RES(mp), 0,
1582 XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT);
1583 if (error == ENOSPC && fs_blocks == 0) {
1584 resblks = 0;
1585 error = xfs_trans_reserve(tp, 0, XFS_SYMLINK_LOG_RES(mp), 0,
1586 XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT);
1587 }
1588 if (error) {
1589 cancel_flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 goto error_return;
1591 }
1592
Lachlan McIlroyf7c66ce2007-05-08 13:50:19 +10001593 xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
Christoph Hellwig993386c12007-08-28 16:12:30 +10001594 unlock_dp_on_error = B_TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595
1596 /*
1597 * Check whether the directory allows new symlinks or not.
1598 */
1599 if (dp->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) {
1600 error = XFS_ERROR(EPERM);
1601 goto error_return;
1602 }
1603
1604 /*
1605 * Reserve disk quota : blocks and inode.
1606 */
Christoph Hellwig7d095252009-06-08 15:33:32 +02001607 error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 if (error)
1609 goto error_return;
1610
1611 /*
1612 * Check for ability to enter directory entry, if no space reserved.
1613 */
Barry Naujok556b8b12008-04-10 12:22:07 +10001614 error = xfs_dir_canenter(tp, dp, link_name, resblks);
1615 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 goto error_return;
1617 /*
1618 * Initialize the bmap freelist prior to calling either
1619 * bmapi or the directory create code.
1620 */
Eric Sandeen9d87c312009-01-14 23:22:07 -06001621 xfs_bmap_init(&free_list, &first_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
1623 /*
1624 * Allocate an inode for the symlink.
1625 */
Christoph Hellwig6c77b0e2010-10-06 18:41:17 +00001626 error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (mode & ~S_IFMT), 1, 0,
1627 prid, resblks > 0, &ip, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 if (error) {
1629 if (error == ENOSPC)
1630 goto error_return;
1631 goto error1;
1632 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
Christoph Hellwig993386c12007-08-28 16:12:30 +10001634 /*
1635 * An error after we've joined dp to the transaction will result in the
1636 * transaction cancel unlocking dp so don't do it explicitly in the
1637 * error path.
1638 */
Christoph Hellwig898621d2010-06-24 11:36:58 +10001639 xfs_trans_ijoin_ref(tp, dp, XFS_ILOCK_EXCL);
Christoph Hellwig993386c12007-08-28 16:12:30 +10001640 unlock_dp_on_error = B_FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641
1642 /*
1643 * Also attach the dquot(s) to it, if applicable.
1644 */
Christoph Hellwig7d095252009-06-08 15:33:32 +02001645 xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646
1647 if (resblks)
1648 resblks -= XFS_IALLOC_SPACE_RES(mp);
1649 /*
1650 * If the symlink will fit into the inode, write it inline.
1651 */
1652 if (pathlen <= XFS_IFORK_DSIZE(ip)) {
1653 xfs_idata_realloc(ip, pathlen, XFS_DATA_FORK);
1654 memcpy(ip->i_df.if_u1.if_data, target_path, pathlen);
1655 ip->i_d.di_size = pathlen;
1656
1657 /*
1658 * The inode was initially created in extent format.
1659 */
1660 ip->i_df.if_flags &= ~(XFS_IFEXTENTS | XFS_IFBROOT);
1661 ip->i_df.if_flags |= XFS_IFINLINE;
1662
1663 ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
1664 xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
1665
1666 } else {
1667 first_fsb = 0;
1668 nmaps = SYMLINK_MAPS;
1669
1670 error = xfs_bmapi(tp, ip, first_fsb, fs_blocks,
1671 XFS_BMAPI_WRITE | XFS_BMAPI_METADATA,
1672 &first_block, resblks, mval, &nmaps,
Christoph Hellwigb4e91812010-06-23 18:11:15 +10001673 &free_list);
Christoph Hellwigec3ba852011-02-13 13:26:42 +00001674 if (error)
1675 goto error2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676
1677 if (resblks)
1678 resblks -= fs_blocks;
1679 ip->i_d.di_size = pathlen;
1680 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1681
1682 cur_chunk = target_path;
1683 for (n = 0; n < nmaps; n++) {
1684 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
1685 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
1686 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
1687 BTOBB(byte_cnt), 0);
1688 ASSERT(bp && !XFS_BUF_GETERROR(bp));
1689 if (pathlen < byte_cnt) {
1690 byte_cnt = pathlen;
1691 }
1692 pathlen -= byte_cnt;
1693
1694 memcpy(XFS_BUF_PTR(bp), cur_chunk, byte_cnt);
1695 cur_chunk += byte_cnt;
1696
1697 xfs_trans_log_buf(tp, bp, 0, byte_cnt - 1);
1698 }
1699 }
1700
1701 /*
1702 * Create the directory entry for the symlink.
1703 */
Barry Naujok556b8b12008-04-10 12:22:07 +10001704 error = xfs_dir_createname(tp, dp, link_name, ip->i_ino,
1705 &first_block, &free_list, resblks);
Nathan Scottf6c2d1f2006-06-20 13:04:51 +10001706 if (error)
Christoph Hellwigec3ba852011-02-13 13:26:42 +00001707 goto error2;
Dave Chinnerdcd79a12010-09-28 12:27:25 +10001708 xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
1710
1711 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 * If this is a synchronous mount, make sure that the
1713 * symlink transaction goes to disk before returning to
1714 * the user.
1715 */
1716 if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
1717 xfs_trans_set_sync(tp);
1718 }
1719
Eric Sandeenf7c99b62007-02-10 18:37:16 +11001720 error = xfs_bmap_finish(&tp, &free_list, &committed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 if (error) {
1722 goto error2;
1723 }
Eric Sandeen1c72bf92007-05-08 13:48:42 +10001724 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
Christoph Hellwig7d095252009-06-08 15:33:32 +02001725 xfs_qm_dqrele(udqp);
1726 xfs_qm_dqrele(gdqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727
Christoph Hellwig288699f2010-06-23 18:11:15 +10001728 *ipp = ip;
1729 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730
1731 error2:
1732 IRELE(ip);
1733 error1:
1734 xfs_bmap_cancel(&free_list);
1735 cancel_flags |= XFS_TRANS_ABORT;
1736 error_return:
1737 xfs_trans_cancel(tp, cancel_flags);
Christoph Hellwig7d095252009-06-08 15:33:32 +02001738 xfs_qm_dqrele(udqp);
1739 xfs_qm_dqrele(gdqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
Christoph Hellwig993386c12007-08-28 16:12:30 +10001741 if (unlock_dp_on_error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 xfs_iunlock(dp, XFS_ILOCK_EXCL);
Christoph Hellwig288699f2010-06-23 18:11:15 +10001743 std_return:
1744 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745}
1746
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747int
Christoph Hellwig993386c12007-08-28 16:12:30 +10001748xfs_set_dmattrs(
1749 xfs_inode_t *ip,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 u_int evmask,
Christoph Hellwig993386c12007-08-28 16:12:30 +10001751 u_int16_t state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752{
Christoph Hellwig993386c12007-08-28 16:12:30 +10001753 xfs_mount_t *mp = ip->i_mount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 xfs_trans_t *tp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 int error;
1756
1757 if (!capable(CAP_SYS_ADMIN))
1758 return XFS_ERROR(EPERM);
1759
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 if (XFS_FORCED_SHUTDOWN(mp))
1761 return XFS_ERROR(EIO);
1762
1763 tp = xfs_trans_alloc(mp, XFS_TRANS_SET_DMATTRS);
1764 error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES (mp), 0, 0, 0);
1765 if (error) {
1766 xfs_trans_cancel(tp, 0);
1767 return error;
1768 }
1769 xfs_ilock(ip, XFS_ILOCK_EXCL);
Christoph Hellwig898621d2010-06-24 11:36:58 +10001770 xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771
Christoph Hellwig613d7042007-10-11 17:44:08 +10001772 ip->i_d.di_dmevmask = evmask;
1773 ip->i_d.di_dmstate = state;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774
1775 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
Eric Sandeen1c72bf92007-05-08 13:48:42 +10001776 error = xfs_trans_commit(tp, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777
1778 return error;
1779}
1780
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781/*
1782 * xfs_alloc_file_space()
1783 * This routine allocates disk space for the given file.
1784 *
1785 * If alloc_type == 0, this request is for an ALLOCSP type
1786 * request which will change the file size. In this case, no
1787 * DMAPI event will be generated by the call. A TRUNCATE event
1788 * will be generated later by xfs_setattr.
1789 *
1790 * If alloc_type != 0, this request is for a RESVSP type
1791 * request, and a DMAPI DM_EVENT_WRITE will be generated if the
1792 * lower block boundary byte address is less than the file's
1793 * length.
1794 *
1795 * RETURNS:
1796 * 0 on success
1797 * errno on error
1798 *
1799 */
Christoph Hellwigba0f32d2005-06-21 15:36:52 +10001800STATIC int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801xfs_alloc_file_space(
1802 xfs_inode_t *ip,
1803 xfs_off_t offset,
1804 xfs_off_t len,
1805 int alloc_type,
1806 int attr_flags)
1807{
Nathan Scottdd9f4382006-01-11 15:28:28 +11001808 xfs_mount_t *mp = ip->i_mount;
1809 xfs_off_t count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 xfs_filblks_t allocated_fsb;
1811 xfs_filblks_t allocatesize_fsb;
Nathan Scottdd9f4382006-01-11 15:28:28 +11001812 xfs_extlen_t extsz, temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 xfs_fileoff_t startoffset_fsb;
Nathan Scottdd9f4382006-01-11 15:28:28 +11001814 xfs_fsblock_t firstfsb;
1815 int nimaps;
1816 int bmapi_flag;
1817 int quota_flag;
1818 int rt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 xfs_trans_t *tp;
Nathan Scottdd9f4382006-01-11 15:28:28 +11001820 xfs_bmbt_irec_t imaps[1], *imapp;
1821 xfs_bmap_free_t free_list;
1822 uint qblocks, resblks, resrtextents;
1823 int committed;
1824 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825
Christoph Hellwigcca28fb2010-06-24 11:57:09 +10001826 trace_xfs_alloc_file_space(ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827
1828 if (XFS_FORCED_SHUTDOWN(mp))
1829 return XFS_ERROR(EIO);
1830
Christoph Hellwig7d095252009-06-08 15:33:32 +02001831 error = xfs_qm_dqattach(ip, 0);
1832 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 return error;
1834
1835 if (len <= 0)
1836 return XFS_ERROR(EINVAL);
1837
David Chinner957d0eb2007-06-18 16:50:37 +10001838 rt = XFS_IS_REALTIME_INODE(ip);
1839 extsz = xfs_get_extsz_hint(ip);
1840
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 count = len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 imapp = &imaps[0];
Nathan Scottdd9f4382006-01-11 15:28:28 +11001843 nimaps = 1;
Dave Chinner44722352010-08-24 12:02:11 +10001844 bmapi_flag = XFS_BMAPI_WRITE | alloc_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
1846 allocatesize_fsb = XFS_B_TO_FSB(mp, count);
1847
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 /*
Nathan Scottdd9f4382006-01-11 15:28:28 +11001849 * Allocate file space until done or until there is an error
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 while (allocatesize_fsb && !error) {
Nathan Scottdd9f4382006-01-11 15:28:28 +11001852 xfs_fileoff_t s, e;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853
Nathan Scottdd9f4382006-01-11 15:28:28 +11001854 /*
Nathan Scott3ddb8fa2006-01-11 15:33:02 +11001855 * Determine space reservations for data/realtime.
Nathan Scottdd9f4382006-01-11 15:28:28 +11001856 */
1857 if (unlikely(extsz)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 s = startoffset_fsb;
Nathan Scottdd9f4382006-01-11 15:28:28 +11001859 do_div(s, extsz);
1860 s *= extsz;
1861 e = startoffset_fsb + allocatesize_fsb;
1862 if ((temp = do_mod(startoffset_fsb, extsz)))
1863 e += temp;
1864 if ((temp = do_mod(e, extsz)))
1865 e += extsz - temp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 } else {
Nathan Scottdd9f4382006-01-11 15:28:28 +11001867 s = 0;
1868 e = allocatesize_fsb;
1869 }
1870
Dave Chinner72656c42010-09-03 12:19:33 +10001871 /*
1872 * The transaction reservation is limited to a 32-bit block
1873 * count, hence we need to limit the number of blocks we are
1874 * trying to reserve to avoid an overflow. We can't allocate
1875 * more than @nimaps extents, and an extent is limited on disk
1876 * to MAXEXTLEN (21 bits), so use that to enforce the limit.
1877 */
1878 resblks = min_t(xfs_fileoff_t, (e - s), (MAXEXTLEN * nimaps));
Nathan Scottdd9f4382006-01-11 15:28:28 +11001879 if (unlikely(rt)) {
Dave Chinner72656c42010-09-03 12:19:33 +10001880 resrtextents = qblocks = resblks;
Nathan Scottdd9f4382006-01-11 15:28:28 +11001881 resrtextents /= mp->m_sb.sb_rextsize;
1882 resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
1883 quota_flag = XFS_QMOPT_RES_RTBLKS;
1884 } else {
1885 resrtextents = 0;
Dave Chinner72656c42010-09-03 12:19:33 +10001886 resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resblks);
Nathan Scottdd9f4382006-01-11 15:28:28 +11001887 quota_flag = XFS_QMOPT_RES_REGBLKS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 }
1889
1890 /*
Nathan Scottdd9f4382006-01-11 15:28:28 +11001891 * Allocate and setup the transaction.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 */
1893 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
Nathan Scottdd9f4382006-01-11 15:28:28 +11001894 error = xfs_trans_reserve(tp, resblks,
1895 XFS_WRITE_LOG_RES(mp), resrtextents,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 XFS_TRANS_PERM_LOG_RES,
1897 XFS_WRITE_LOG_COUNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 /*
Nathan Scottdd9f4382006-01-11 15:28:28 +11001899 * Check for running out of space
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 */
1901 if (error) {
1902 /*
1903 * Free the transaction structure.
1904 */
1905 ASSERT(error == ENOSPC || XFS_FORCED_SHUTDOWN(mp));
1906 xfs_trans_cancel(tp, 0);
1907 break;
1908 }
1909 xfs_ilock(ip, XFS_ILOCK_EXCL);
Christoph Hellwig7d095252009-06-08 15:33:32 +02001910 error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks,
1911 0, quota_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 if (error)
1913 goto error1;
1914
Christoph Hellwig898621d2010-06-24 11:36:58 +10001915 xfs_trans_ijoin(tp, ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916
1917 /*
Nathan Scottdd9f4382006-01-11 15:28:28 +11001918 * Issue the xfs_bmapi() call to allocate the blocks
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 */
Eric Sandeen9d87c312009-01-14 23:22:07 -06001920 xfs_bmap_init(&free_list, &firstfsb);
Lachlan McIlroy541d7d32007-10-11 17:34:33 +10001921 error = xfs_bmapi(tp, ip, startoffset_fsb,
Nathan Scottdd9f4382006-01-11 15:28:28 +11001922 allocatesize_fsb, bmapi_flag,
1923 &firstfsb, 0, imapp, &nimaps,
Christoph Hellwigb4e91812010-06-23 18:11:15 +10001924 &free_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 if (error) {
1926 goto error0;
1927 }
1928
1929 /*
Nathan Scottdd9f4382006-01-11 15:28:28 +11001930 * Complete the transaction
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 */
Eric Sandeenf7c99b62007-02-10 18:37:16 +11001932 error = xfs_bmap_finish(&tp, &free_list, &committed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 if (error) {
1934 goto error0;
1935 }
1936
Eric Sandeen1c72bf92007-05-08 13:48:42 +10001937 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1939 if (error) {
1940 break;
1941 }
1942
1943 allocated_fsb = imapp->br_blockcount;
1944
Nathan Scottdd9f4382006-01-11 15:28:28 +11001945 if (nimaps == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 error = XFS_ERROR(ENOSPC);
1947 break;
1948 }
1949
1950 startoffset_fsb += allocated_fsb;
1951 allocatesize_fsb -= allocated_fsb;
1952 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953
1954 return error;
1955
Nathan Scottdd9f4382006-01-11 15:28:28 +11001956error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957 xfs_bmap_cancel(&free_list);
Christoph Hellwig7d095252009-06-08 15:33:32 +02001958 xfs_trans_unreserve_quota_nblks(tp, ip, qblocks, 0, quota_flag);
Nathan Scottdd9f4382006-01-11 15:28:28 +11001959
1960error1: /* Just cancel transaction */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
1962 xfs_iunlock(ip, XFS_ILOCK_EXCL);
Christoph Hellwig288699f2010-06-23 18:11:15 +10001963 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964}
1965
1966/*
1967 * Zero file bytes between startoff and endoff inclusive.
1968 * The iolock is held exclusive and no blocks are buffered.
Lachlan McIlroy2fd6f6e2008-09-17 16:52:50 +10001969 *
1970 * This function is used by xfs_free_file_space() to zero
1971 * partial blocks when the range to free is not block aligned.
1972 * When unreserving space with boundaries that are not block
1973 * aligned we round up the start and round down the end
1974 * boundaries and then use this function to zero the parts of
1975 * the blocks that got dropped during the rounding.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 */
1977STATIC int
1978xfs_zero_remaining_bytes(
1979 xfs_inode_t *ip,
1980 xfs_off_t startoff,
1981 xfs_off_t endoff)
1982{
1983 xfs_bmbt_irec_t imap;
1984 xfs_fileoff_t offset_fsb;
1985 xfs_off_t lastoffset;
1986 xfs_off_t offset;
1987 xfs_buf_t *bp;
1988 xfs_mount_t *mp = ip->i_mount;
1989 int nimap;
1990 int error = 0;
1991
Lachlan McIlroy2fd6f6e2008-09-17 16:52:50 +10001992 /*
1993 * Avoid doing I/O beyond eof - it's not necessary
1994 * since nothing can read beyond eof. The space will
1995 * be zeroed when the file is extended anyway.
1996 */
1997 if (startoff >= ip->i_size)
1998 return 0;
1999
2000 if (endoff > ip->i_size)
2001 endoff = ip->i_size;
2002
Dave Chinner686865f2010-09-24 20:07:47 +10002003 bp = xfs_buf_get_uncached(XFS_IS_REALTIME_INODE(ip) ?
2004 mp->m_rtdev_targp : mp->m_ddev_targp,
2005 mp->m_sb.sb_blocksize, XBF_DONT_BLOCK);
Lachlan McIlroyc6422612008-12-05 13:16:15 +11002006 if (!bp)
2007 return XFS_ERROR(ENOMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008
2009 for (offset = startoff; offset <= endoff; offset = lastoffset + 1) {
2010 offset_fsb = XFS_B_TO_FSBT(mp, offset);
2011 nimap = 1;
Lachlan McIlroy541d7d32007-10-11 17:34:33 +10002012 error = xfs_bmapi(NULL, ip, offset_fsb, 1, 0,
Christoph Hellwigb4e91812010-06-23 18:11:15 +10002013 NULL, 0, &imap, &nimap, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 if (error || nimap < 1)
2015 break;
2016 ASSERT(imap.br_blockcount >= 1);
2017 ASSERT(imap.br_startoff == offset_fsb);
2018 lastoffset = XFS_FSB_TO_B(mp, imap.br_startoff + 1) - 1;
2019 if (lastoffset > endoff)
2020 lastoffset = endoff;
2021 if (imap.br_startblock == HOLESTARTBLOCK)
2022 continue;
2023 ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
2024 if (imap.br_state == XFS_EXT_UNWRITTEN)
2025 continue;
2026 XFS_BUF_UNDONE(bp);
2027 XFS_BUF_UNWRITE(bp);
2028 XFS_BUF_READ(bp);
Eric Sandeen9d87c312009-01-14 23:22:07 -06002029 XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 xfsbdstrat(mp, bp);
Christoph Hellwig1a1a3e92010-10-06 18:41:18 +00002031 error = xfs_buf_iowait(bp);
David Chinnerd64e31a2008-04-10 12:22:17 +10002032 if (error) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 xfs_ioerror_alert("xfs_zero_remaining_bytes(read)",
2034 mp, bp, XFS_BUF_ADDR(bp));
2035 break;
2036 }
2037 memset(XFS_BUF_PTR(bp) +
2038 (offset - XFS_FSB_TO_B(mp, imap.br_startoff)),
2039 0, lastoffset - offset + 1);
2040 XFS_BUF_UNDONE(bp);
2041 XFS_BUF_UNREAD(bp);
2042 XFS_BUF_WRITE(bp);
2043 xfsbdstrat(mp, bp);
Christoph Hellwig1a1a3e92010-10-06 18:41:18 +00002044 error = xfs_buf_iowait(bp);
David Chinnerd64e31a2008-04-10 12:22:17 +10002045 if (error) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 xfs_ioerror_alert("xfs_zero_remaining_bytes(write)",
2047 mp, bp, XFS_BUF_ADDR(bp));
2048 break;
2049 }
2050 }
2051 xfs_buf_free(bp);
2052 return error;
2053}
2054
2055/*
2056 * xfs_free_file_space()
2057 * This routine frees disk space for the given file.
2058 *
2059 * This routine is only called by xfs_change_file_space
2060 * for an UNRESVSP type call.
2061 *
2062 * RETURNS:
2063 * 0 on success
2064 * errno on error
2065 *
2066 */
2067STATIC int
2068xfs_free_file_space(
2069 xfs_inode_t *ip,
2070 xfs_off_t offset,
2071 xfs_off_t len,
2072 int attr_flags)
2073{
2074 int committed;
2075 int done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 xfs_fileoff_t endoffset_fsb;
2077 int error;
2078 xfs_fsblock_t firstfsb;
2079 xfs_bmap_free_t free_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 xfs_bmbt_irec_t imap;
2081 xfs_off_t ioffset;
2082 xfs_extlen_t mod=0;
2083 xfs_mount_t *mp;
2084 int nimap;
2085 uint resblks;
Nathan Scott673cdf52006-09-28 10:56:26 +10002086 uint rounding;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 int rt;
2088 xfs_fileoff_t startoffset_fsb;
2089 xfs_trans_t *tp;
Dean Roehrich5fcbab32005-05-05 13:27:19 -07002090 int need_iolock = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 mp = ip->i_mount;
2093
Christoph Hellwigcca28fb2010-06-24 11:57:09 +10002094 trace_xfs_free_file_space(ip);
Christoph Hellwigbd5a8762005-06-21 15:47:39 +10002095
Christoph Hellwig7d095252009-06-08 15:33:32 +02002096 error = xfs_qm_dqattach(ip, 0);
2097 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 return error;
2099
2100 error = 0;
2101 if (len <= 0) /* if nothing being freed */
2102 return error;
Eric Sandeen71ddabb2007-11-23 16:29:42 +11002103 rt = XFS_IS_REALTIME_INODE(ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 startoffset_fsb = XFS_B_TO_FSB(mp, offset);
Christoph Hellwig288699f2010-06-23 18:11:15 +10002105 endoffset_fsb = XFS_B_TO_FSBT(mp, offset + len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106
Christoph Hellwig0f285c82008-07-18 17:13:28 +10002107 if (attr_flags & XFS_ATTR_NOLOCK)
Dean Roehrich5fcbab32005-05-05 13:27:19 -07002108 need_iolock = 0;
Yingping Lu9fa80462006-03-22 12:44:35 +11002109 if (need_iolock) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 xfs_ilock(ip, XFS_IOLOCK_EXCL);
Christoph Hellwig25e41b32008-12-03 12:20:39 +01002111 /* wait for the completion of any pending DIOs */
2112 xfs_ioend_wait(ip);
Yingping Lu9fa80462006-03-22 12:44:35 +11002113 }
Dean Roehrich5fcbab32005-05-05 13:27:19 -07002114
Tim Shimmine6a4b372007-11-23 16:30:42 +11002115 rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 ioffset = offset & ~(rounding - 1);
Christoph Hellwigbd5a8762005-06-21 15:47:39 +10002117
Christoph Hellwigdf80c932008-08-13 16:22:09 +10002118 if (VN_CACHED(VFS_I(ip)) != 0) {
Tim Shimmine6a4b372007-11-23 16:30:42 +11002119 error = xfs_flushinval_pages(ip, ioffset, -1, FI_REMAPF_LOCKED);
Lachlan McIlroyd3cf20942007-05-08 13:49:27 +10002120 if (error)
2121 goto out_unlock_iolock;
Christoph Hellwigbd5a8762005-06-21 15:47:39 +10002122 }
2123
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 /*
2125 * Need to zero the stuff we're not freeing, on disk.
Malcolm Parsons9da096f2009-03-29 09:55:42 +02002126 * If it's a realtime file & can't use unwritten extents then we
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 * actually need to zero the extent edges. Otherwise xfs_bunmapi
2128 * will take care of it for us.
2129 */
Eric Sandeen62118702008-03-06 13:44:28 +11002130 if (rt && !xfs_sb_version_hasextflgbit(&mp->m_sb)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 nimap = 1;
Lachlan McIlroy541d7d32007-10-11 17:34:33 +10002132 error = xfs_bmapi(NULL, ip, startoffset_fsb,
Christoph Hellwigb4e91812010-06-23 18:11:15 +10002133 1, 0, NULL, 0, &imap, &nimap, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 if (error)
2135 goto out_unlock_iolock;
2136 ASSERT(nimap == 0 || nimap == 1);
2137 if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
2138 xfs_daddr_t block;
2139
2140 ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
2141 block = imap.br_startblock;
2142 mod = do_div(block, mp->m_sb.sb_rextsize);
2143 if (mod)
2144 startoffset_fsb += mp->m_sb.sb_rextsize - mod;
2145 }
2146 nimap = 1;
Lachlan McIlroy541d7d32007-10-11 17:34:33 +10002147 error = xfs_bmapi(NULL, ip, endoffset_fsb - 1,
Christoph Hellwigb4e91812010-06-23 18:11:15 +10002148 1, 0, NULL, 0, &imap, &nimap, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 if (error)
2150 goto out_unlock_iolock;
2151 ASSERT(nimap == 0 || nimap == 1);
2152 if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
2153 ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
2154 mod++;
2155 if (mod && (mod != mp->m_sb.sb_rextsize))
2156 endoffset_fsb -= mod;
2157 }
2158 }
2159 if ((done = (endoffset_fsb <= startoffset_fsb)))
2160 /*
2161 * One contiguous piece to clear
2162 */
2163 error = xfs_zero_remaining_bytes(ip, offset, offset + len - 1);
2164 else {
2165 /*
2166 * Some full blocks, possibly two pieces to clear
2167 */
2168 if (offset < XFS_FSB_TO_B(mp, startoffset_fsb))
2169 error = xfs_zero_remaining_bytes(ip, offset,
2170 XFS_FSB_TO_B(mp, startoffset_fsb) - 1);
2171 if (!error &&
2172 XFS_FSB_TO_B(mp, endoffset_fsb) < offset + len)
2173 error = xfs_zero_remaining_bytes(ip,
2174 XFS_FSB_TO_B(mp, endoffset_fsb),
2175 offset + len - 1);
2176 }
2177
2178 /*
2179 * free file space until done or until there is an error
2180 */
2181 resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
2182 while (!error && !done) {
2183
2184 /*
David Chinner91ebecc2007-07-19 16:28:30 +10002185 * allocate and setup the transaction. Allow this
2186 * transaction to dip into the reserve blocks to ensure
2187 * the freeing of the space succeeds at ENOSPC.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 */
2189 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
David Chinner91ebecc2007-07-19 16:28:30 +10002190 tp->t_flags |= XFS_TRANS_RESERVE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 error = xfs_trans_reserve(tp,
2192 resblks,
2193 XFS_WRITE_LOG_RES(mp),
2194 0,
2195 XFS_TRANS_PERM_LOG_RES,
2196 XFS_WRITE_LOG_COUNT);
2197
2198 /*
2199 * check for running out of space
2200 */
2201 if (error) {
2202 /*
2203 * Free the transaction structure.
2204 */
2205 ASSERT(error == ENOSPC || XFS_FORCED_SHUTDOWN(mp));
2206 xfs_trans_cancel(tp, 0);
2207 break;
2208 }
2209 xfs_ilock(ip, XFS_ILOCK_EXCL);
Christoph Hellwig7d095252009-06-08 15:33:32 +02002210 error = xfs_trans_reserve_quota(tp, mp,
2211 ip->i_udquot, ip->i_gdquot,
2212 resblks, 0, XFS_QMOPT_RES_REGBLKS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 if (error)
2214 goto error1;
2215
Christoph Hellwig898621d2010-06-24 11:36:58 +10002216 xfs_trans_ijoin(tp, ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217
2218 /*
2219 * issue the bunmapi() call to free the blocks
2220 */
Eric Sandeen9d87c312009-01-14 23:22:07 -06002221 xfs_bmap_init(&free_list, &firstfsb);
Lachlan McIlroy541d7d32007-10-11 17:34:33 +10002222 error = xfs_bunmapi(tp, ip, startoffset_fsb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 endoffset_fsb - startoffset_fsb,
Christoph Hellwigb4e91812010-06-23 18:11:15 +10002224 0, 2, &firstfsb, &free_list, &done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 if (error) {
2226 goto error0;
2227 }
2228
2229 /*
2230 * complete the transaction
2231 */
Eric Sandeenf7c99b62007-02-10 18:37:16 +11002232 error = xfs_bmap_finish(&tp, &free_list, &committed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 if (error) {
2234 goto error0;
2235 }
2236
Eric Sandeen1c72bf92007-05-08 13:48:42 +10002237 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 xfs_iunlock(ip, XFS_ILOCK_EXCL);
2239 }
2240
2241 out_unlock_iolock:
2242 if (need_iolock)
2243 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
2244 return error;
2245
2246 error0:
2247 xfs_bmap_cancel(&free_list);
2248 error1:
2249 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
2250 xfs_iunlock(ip, need_iolock ? (XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL) :
2251 XFS_ILOCK_EXCL);
2252 return error;
2253}
2254
2255/*
2256 * xfs_change_file_space()
2257 * This routine allocates or frees disk space for the given file.
2258 * The user specified parameters are checked for alignment and size
2259 * limitations.
2260 *
2261 * RETURNS:
2262 * 0 on success
2263 * errno on error
2264 *
2265 */
2266int
2267xfs_change_file_space(
Christoph Hellwig993386c12007-08-28 16:12:30 +10002268 xfs_inode_t *ip,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 int cmd,
2270 xfs_flock64_t *bf,
2271 xfs_off_t offset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 int attr_flags)
2273{
Christoph Hellwig993386c12007-08-28 16:12:30 +10002274 xfs_mount_t *mp = ip->i_mount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 int clrprealloc;
2276 int error;
2277 xfs_fsize_t fsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 int setprealloc;
2279 xfs_off_t startoffset;
2280 xfs_off_t llen;
2281 xfs_trans_t *tp;
Christoph Hellwig0f285c82008-07-18 17:13:28 +10002282 struct iattr iattr;
Dave Chinner44722352010-08-24 12:02:11 +10002283 int prealloc_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284
Christoph Hellwig993386c12007-08-28 16:12:30 +10002285 if (!S_ISREG(ip->i_d.di_mode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 return XFS_ERROR(EINVAL);
2287
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 switch (bf->l_whence) {
2289 case 0: /*SEEK_SET*/
2290 break;
2291 case 1: /*SEEK_CUR*/
2292 bf->l_start += offset;
2293 break;
2294 case 2: /*SEEK_END*/
Lachlan McIlroyba87ea62007-05-08 13:49:46 +10002295 bf->l_start += ip->i_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 break;
2297 default:
2298 return XFS_ERROR(EINVAL);
2299 }
2300
2301 llen = bf->l_len > 0 ? bf->l_len - 1 : bf->l_len;
2302
2303 if ( (bf->l_start < 0)
2304 || (bf->l_start > XFS_MAXIOFFSET(mp))
2305 || (bf->l_start + llen < 0)
2306 || (bf->l_start + llen > XFS_MAXIOFFSET(mp)))
2307 return XFS_ERROR(EINVAL);
2308
2309 bf->l_whence = 0;
2310
2311 startoffset = bf->l_start;
Lachlan McIlroyba87ea62007-05-08 13:49:46 +10002312 fsize = ip->i_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313
2314 /*
2315 * XFS_IOC_RESVSP and XFS_IOC_UNRESVSP will reserve or unreserve
2316 * file space.
2317 * These calls do NOT zero the data space allocated to the file,
2318 * nor do they change the file size.
2319 *
2320 * XFS_IOC_ALLOCSP and XFS_IOC_FREESP will allocate and free file
2321 * space.
2322 * These calls cause the new file data to be zeroed and the file
2323 * size to be changed.
2324 */
2325 setprealloc = clrprealloc = 0;
Dave Chinner44722352010-08-24 12:02:11 +10002326 prealloc_type = XFS_BMAPI_PREALLOC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327
2328 switch (cmd) {
Dave Chinner44722352010-08-24 12:02:11 +10002329 case XFS_IOC_ZERO_RANGE:
2330 prealloc_type |= XFS_BMAPI_CONVERT;
2331 xfs_tosspages(ip, startoffset, startoffset + bf->l_len, 0);
2332 /* FALLTHRU */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 case XFS_IOC_RESVSP:
2334 case XFS_IOC_RESVSP64:
2335 error = xfs_alloc_file_space(ip, startoffset, bf->l_len,
Dave Chinner44722352010-08-24 12:02:11 +10002336 prealloc_type, attr_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 if (error)
2338 return error;
2339 setprealloc = 1;
2340 break;
2341
2342 case XFS_IOC_UNRESVSP:
2343 case XFS_IOC_UNRESVSP64:
2344 if ((error = xfs_free_file_space(ip, startoffset, bf->l_len,
2345 attr_flags)))
2346 return error;
2347 break;
2348
2349 case XFS_IOC_ALLOCSP:
2350 case XFS_IOC_ALLOCSP64:
2351 case XFS_IOC_FREESP:
2352 case XFS_IOC_FREESP64:
2353 if (startoffset > fsize) {
2354 error = xfs_alloc_file_space(ip, fsize,
2355 startoffset - fsize, 0, attr_flags);
2356 if (error)
2357 break;
2358 }
2359
Christoph Hellwig0f285c82008-07-18 17:13:28 +10002360 iattr.ia_valid = ATTR_SIZE;
2361 iattr.ia_size = startoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362
Christoph Hellwigc4ed4242011-07-08 14:34:23 +02002363 error = xfs_setattr_size(ip, &iattr, attr_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364
2365 if (error)
2366 return error;
2367
2368 clrprealloc = 1;
2369 break;
2370
2371 default:
2372 ASSERT(0);
2373 return XFS_ERROR(EINVAL);
2374 }
2375
2376 /*
2377 * update the inode timestamp, mode, and prealloc flag bits
2378 */
2379 tp = xfs_trans_alloc(mp, XFS_TRANS_WRITEID);
2380
2381 if ((error = xfs_trans_reserve(tp, 0, XFS_WRITEID_LOG_RES(mp),
2382 0, 0, 0))) {
2383 /* ASSERT(0); */
2384 xfs_trans_cancel(tp, 0);
2385 return error;
2386 }
2387
2388 xfs_ilock(ip, XFS_ILOCK_EXCL);
2389
Christoph Hellwig898621d2010-06-24 11:36:58 +10002390 xfs_trans_ijoin(tp, ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391
Christoph Hellwig0f285c82008-07-18 17:13:28 +10002392 if ((attr_flags & XFS_ATTR_DMI) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 ip->i_d.di_mode &= ~S_ISUID;
2394
2395 /*
2396 * Note that we don't have to worry about mandatory
2397 * file locking being disabled here because we only
2398 * clear the S_ISGID bit if the Group execute bit is
2399 * on, but if it was on then mandatory locking wouldn't
2400 * have been enabled.
2401 */
2402 if (ip->i_d.di_mode & S_IXGRP)
2403 ip->i_d.di_mode &= ~S_ISGID;
2404
Dave Chinnerdcd79a12010-09-28 12:27:25 +10002405 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 }
2407 if (setprealloc)
2408 ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
2409 else if (clrprealloc)
2410 ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC;
2411
2412 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
Dave Chinner82878892011-03-26 09:13:08 +11002413 if (attr_flags & XFS_ATTR_SYNC)
2414 xfs_trans_set_sync(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415
Eric Sandeen1c72bf92007-05-08 13:48:42 +10002416 error = xfs_trans_commit(tp, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417
2418 xfs_iunlock(ip, XFS_ILOCK_EXCL);
2419
2420 return error;
2421}