xfs_symlink.c 14.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
 * Copyright (c) 2012-2013 Red Hat, Inc.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it would be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write the Free Software Foundation,
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "xfs.h"
20
#include "xfs_shared.h"
21
#include "xfs_fs.h"
22
#include "xfs_format.h"
23 24
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
25 26 27 28
#include "xfs_bit.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_mount.h"
29
#include "xfs_da_format.h"
30
#include "xfs_da_btree.h"
31
#include "xfs_dir2.h"
32 33 34 35
#include "xfs_inode.h"
#include "xfs_ialloc.h"
#include "xfs_alloc.h"
#include "xfs_bmap.h"
36
#include "xfs_bmap_btree.h"
D
Dave Chinner 已提交
37
#include "xfs_bmap_util.h"
38 39 40 41 42
#include "xfs_error.h"
#include "xfs_quota.h"
#include "xfs_trans_space.h"
#include "xfs_trace.h"
#include "xfs_symlink.h"
43 44
#include "xfs_trans.h"
#include "xfs_log.h"
45
#include "xfs_dinode.h"
46 47 48 49

/* ----- Kernel only functions below ----- */
STATIC int
xfs_readlink_bmap(
50 51
	struct xfs_inode	*ip,
	char			*link)
52
{
53 54 55 56 57 58 59 60 61 62 63 64
	struct xfs_mount	*mp = ip->i_mount;
	struct xfs_bmbt_irec	mval[XFS_SYMLINK_MAPS];
	struct xfs_buf		*bp;
	xfs_daddr_t		d;
	char			*cur_chunk;
	int			pathlen = ip->i_d.di_size;
	int			nmaps = XFS_SYMLINK_MAPS;
	int			byte_cnt;
	int			n;
	int			error = 0;
	int			fsblocks = 0;
	int			offset;
65

66 67
	fsblocks = xfs_symlink_blocks(mp, pathlen);
	error = xfs_bmapi_read(ip, 0, fsblocks, mval, &nmaps, 0);
68 69 70
	if (error)
		goto out;

71
	offset = 0;
72 73 74 75
	for (n = 0; n < nmaps; n++) {
		d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
		byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);

76 77
		bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0,
				  &xfs_symlink_buf_ops);
78
		if (!bp)
E
Eric Sandeen 已提交
79
			return ENOMEM;
80 81 82 83
		error = bp->b_error;
		if (error) {
			xfs_buf_ioerror_alert(bp, __func__);
			xfs_buf_relse(bp);
84 85 86 87

			/* bad CRC means corrupted metadata */
			if (error == EFSBADCRC)
				error = EFSCORRUPTED;
88 89
			goto out;
		}
90
		byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
91 92
		if (pathlen < byte_cnt)
			byte_cnt = pathlen;
93 94 95

		cur_chunk = bp->b_addr;
		if (xfs_sb_version_hascrc(&mp->m_sb)) {
96
			if (!xfs_symlink_hdr_ok(ip->i_ino, offset,
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
							byte_cnt, bp)) {
				error = EFSCORRUPTED;
				xfs_alert(mp,
"symlink header does not match required off/len/owner (0x%x/Ox%x,0x%llx)",
					offset, byte_cnt, ip->i_ino);
				xfs_buf_relse(bp);
				goto out;

			}

			cur_chunk += sizeof(struct xfs_dsymlink_hdr);
		}

		memcpy(link + offset, bp->b_addr, byte_cnt);

112
		pathlen -= byte_cnt;
113
		offset += byte_cnt;
114 115 116

		xfs_buf_relse(bp);
	}
117
	ASSERT(pathlen == 0);
118 119 120 121 122 123 124 125 126 127

	link[ip->i_d.di_size] = '\0';
	error = 0;

 out:
	return error;
}

int
xfs_readlink(
128
	struct xfs_inode *ip,
129 130
	char		*link)
{
131
	struct xfs_mount *mp = ip->i_mount;
132 133 134 135 136 137
	xfs_fsize_t	pathlen;
	int		error = 0;

	trace_xfs_readlink(ip);

	if (XFS_FORCED_SHUTDOWN(mp))
E
Eric Sandeen 已提交
138
		return EIO;
139 140 141 142 143 144 145 146 147 148 149 150

	xfs_ilock(ip, XFS_ILOCK_SHARED);

	pathlen = ip->i_d.di_size;
	if (!pathlen)
		goto out;

	if (pathlen < 0 || pathlen > MAXPATHLEN) {
		xfs_alert(mp, "%s: inode (%llu) bad symlink length (%lld)",
			 __func__, (unsigned long long) ip->i_ino,
			 (long long) pathlen);
		ASSERT(0);
E
Eric Sandeen 已提交
151
		error = EFSCORRUPTED;
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
		goto out;
	}


	if (ip->i_df.if_flags & XFS_IFINLINE) {
		memcpy(link, ip->i_df.if_u1.if_data, pathlen);
		link[pathlen] = '\0';
	} else {
		error = xfs_readlink_bmap(ip, link);
	}

 out:
	xfs_iunlock(ip, XFS_ILOCK_SHARED);
	return error;
}

int
xfs_symlink(
170
	struct xfs_inode	*dp,
171 172 173
	struct xfs_name		*link_name,
	const char		*target_path,
	umode_t			mode,
174
	struct xfs_inode	**ipp)
175
{
176 177 178 179
	struct xfs_mount	*mp = dp->i_mount;
	struct xfs_trans	*tp = NULL;
	struct xfs_inode	*ip = NULL;
	int			error = 0;
180
	int			pathlen;
181
	struct xfs_bmap_free	free_list;
182
	xfs_fsblock_t		first_block;
183
	bool			unlock_dp_on_error = false;
184 185 186 187 188
	uint			cancel_flags;
	int			committed;
	xfs_fileoff_t		first_fsb;
	xfs_filblks_t		fs_blocks;
	int			nmaps;
189
	struct xfs_bmbt_irec	mval[XFS_SYMLINK_MAPS];
190 191 192 193 194 195
	xfs_daddr_t		d;
	const char		*cur_chunk;
	int			byte_cnt;
	int			n;
	xfs_buf_t		*bp;
	prid_t			prid;
196 197
	struct xfs_dquot	*udqp = NULL;
	struct xfs_dquot	*gdqp = NULL;
198
	struct xfs_dquot	*pdqp = NULL;
199 200 201 202 203 204 205
	uint			resblks;

	*ipp = NULL;

	trace_xfs_symlink(dp, link_name);

	if (XFS_FORCED_SHUTDOWN(mp))
E
Eric Sandeen 已提交
206
		return EIO;
207 208 209 210 211 212

	/*
	 * Check component lengths of the target path name.
	 */
	pathlen = strlen(target_path);
	if (pathlen >= MAXPATHLEN)      /* total string too long */
E
Eric Sandeen 已提交
213
		return ENAMETOOLONG;
214 215

	udqp = gdqp = NULL;
216
	prid = xfs_get_initial_prid(dp);
217 218 219 220

	/*
	 * Make sure that we have allocated dquot(s) on disk.
	 */
221 222 223 224 225
	error = xfs_qm_vop_dqalloc(dp,
			xfs_kuid_to_uid(current_fsuid()),
			xfs_kgid_to_gid(current_fsgid()), prid,
			XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
			&udqp, &gdqp, &pdqp);
226 227 228 229 230 231 232 233 234 235 236 237
	if (error)
		goto std_return;

	tp = xfs_trans_alloc(mp, XFS_TRANS_SYMLINK);
	cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
	/*
	 * The symlink will fit into the inode data fork?
	 * There can't be any attributes so we get the whole variable part.
	 */
	if (pathlen <= XFS_LITINO(mp, dp->i_d.di_version))
		fs_blocks = 0;
	else
238
		fs_blocks = xfs_symlink_blocks(mp, pathlen);
239
	resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
240
	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_symlink, resblks, 0);
241 242
	if (error == ENOSPC && fs_blocks == 0) {
		resblks = 0;
243
		error = xfs_trans_reserve(tp, &M_RES(mp)->tr_symlink, 0, 0);
244 245 246 247 248 249 250 251 252 253 254 255 256
	}
	if (error) {
		cancel_flags = 0;
		goto error_return;
	}

	xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
	unlock_dp_on_error = true;

	/*
	 * Check whether the directory allows new symlinks or not.
	 */
	if (dp->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) {
E
Eric Sandeen 已提交
257
		error = EPERM;
258 259 260 261 262 263
		goto error_return;
	}

	/*
	 * Reserve disk quota : blocks and inode.
	 */
264 265
	error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
						pdqp, resblks, 1, 0);
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
	if (error)
		goto error_return;

	/*
	 * Check for ability to enter directory entry, if no space reserved.
	 */
	error = xfs_dir_canenter(tp, dp, link_name, resblks);
	if (error)
		goto error_return;
	/*
	 * Initialize the bmap freelist prior to calling either
	 * bmapi or the directory create code.
	 */
	xfs_bmap_init(&free_list, &first_block);

	/*
	 * Allocate an inode for the symlink.
	 */
	error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (mode & ~S_IFMT), 1, 0,
			       prid, resblks > 0, &ip, NULL);
	if (error) {
		if (error == ENOSPC)
			goto error_return;
		goto error1;
	}

	/*
	 * An error after we've joined dp to the transaction will result in the
	 * transaction cancel unlocking dp so don't do it explicitly in the
	 * error path.
	 */
	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
	unlock_dp_on_error = false;

	/*
	 * Also attach the dquot(s) to it, if applicable.
	 */
303
	xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324

	if (resblks)
		resblks -= XFS_IALLOC_SPACE_RES(mp);
	/*
	 * If the symlink will fit into the inode, write it inline.
	 */
	if (pathlen <= XFS_IFORK_DSIZE(ip)) {
		xfs_idata_realloc(ip, pathlen, XFS_DATA_FORK);
		memcpy(ip->i_df.if_u1.if_data, target_path, pathlen);
		ip->i_d.di_size = pathlen;

		/*
		 * The inode was initially created in extent format.
		 */
		ip->i_df.if_flags &= ~(XFS_IFEXTENTS | XFS_IFBROOT);
		ip->i_df.if_flags |= XFS_IFINLINE;

		ip->i_d.di_format = XFS_DINODE_FMT_LOCAL;
		xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);

	} else {
325 326
		int	offset;

327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
		first_fsb = 0;
		nmaps = XFS_SYMLINK_MAPS;

		error = xfs_bmapi_write(tp, ip, first_fsb, fs_blocks,
				  XFS_BMAPI_METADATA, &first_block, resblks,
				  mval, &nmaps, &free_list);
		if (error)
			goto error2;

		if (resblks)
			resblks -= fs_blocks;
		ip->i_d.di_size = pathlen;
		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);

		cur_chunk = target_path;
342
		offset = 0;
343
		for (n = 0; n < nmaps; n++) {
344
			char	*buf;
345

346 347 348 349 350 351 352 353
			d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
			byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
			bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
					       BTOBB(byte_cnt), 0);
			if (!bp) {
				error = ENOMEM;
				goto error2;
			}
354 355 356
			bp->b_ops = &xfs_symlink_buf_ops;

			byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
357
			byte_cnt = min(byte_cnt, pathlen);
358

359 360 361 362 363 364
			buf = bp->b_addr;
			buf += xfs_symlink_hdr_set(mp, ip->i_ino, offset,
						   byte_cnt, bp);

			memcpy(buf, cur_chunk, byte_cnt);

365
			cur_chunk += byte_cnt;
366 367
			pathlen -= byte_cnt;
			offset += byte_cnt;
368

369
			xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
370 371
			xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) -
							(char *)bp->b_addr);
372
		}
373
		ASSERT(pathlen == 0);
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
	}

	/*
	 * Create the directory entry for the symlink.
	 */
	error = xfs_dir_createname(tp, dp, link_name, ip->i_ino,
					&first_block, &free_list, resblks);
	if (error)
		goto error2;
	xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);

	/*
	 * If this is a synchronous mount, make sure that the
	 * symlink transaction goes to disk before returning to
	 * the user.
	 */
	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
		xfs_trans_set_sync(tp);
	}

	error = xfs_bmap_finish(&tp, &free_list, &committed);
	if (error) {
		goto error2;
	}
	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
	xfs_qm_dqrele(udqp);
	xfs_qm_dqrele(gdqp);
402
	xfs_qm_dqrele(pdqp);
403 404 405 406 407 408 409 410 411 412 413 414 415

	*ipp = ip;
	return 0;

 error2:
	IRELE(ip);
 error1:
	xfs_bmap_cancel(&free_list);
	cancel_flags |= XFS_TRANS_ABORT;
 error_return:
	xfs_trans_cancel(tp, cancel_flags);
	xfs_qm_dqrele(udqp);
	xfs_qm_dqrele(gdqp);
416
	xfs_qm_dqrele(pdqp);
417 418 419 420 421 422 423 424 425 426

	if (unlock_dp_on_error)
		xfs_iunlock(dp, XFS_ILOCK_EXCL);
 std_return:
	return error;
}

/*
 * Free a symlink that has blocks associated with it.
 */
427
STATIC int
428
xfs_inactive_symlink_rmt(
429
	struct xfs_inode *ip)
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
{
	xfs_buf_t	*bp;
	int		committed;
	int		done;
	int		error;
	xfs_fsblock_t	first_block;
	xfs_bmap_free_t	free_list;
	int		i;
	xfs_mount_t	*mp;
	xfs_bmbt_irec_t	mval[XFS_SYMLINK_MAPS];
	int		nmaps;
	int		size;
	xfs_trans_t	*tp;

	mp = ip->i_mount;
445
	ASSERT(ip->i_df.if_flags & XFS_IFEXTENTS);
446 447 448 449 450 451 452 453 454
	/*
	 * We're freeing a symlink that has some
	 * blocks allocated to it.  Free the
	 * blocks here.  We know that we've got
	 * either 1 or 2 extents and that we can
	 * free them all in one bunmapi call.
	 */
	ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2);

455 456 457 458 459 460 461 462 463 464
	tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0);
	if (error) {
		xfs_trans_cancel(tp, 0);
		return error;
	}

	xfs_ilock(ip, XFS_ILOCK_EXCL);
	xfs_trans_ijoin(tp, ip, 0);

465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
	/*
	 * Lock the inode, fix the size, and join it to the transaction.
	 * Hold it so in the normal path, we still have it locked for
	 * the second transaction.  In the error paths we need it
	 * held so the cancel won't rele it, see below.
	 */
	size = (int)ip->i_d.di_size;
	ip->i_d.di_size = 0;
	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
	/*
	 * Find the block(s) so we can inval and unmap them.
	 */
	done = 0;
	xfs_bmap_init(&free_list, &first_block);
	nmaps = ARRAY_SIZE(mval);
480
	error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size),
481 482
				mval, &nmaps, 0);
	if (error)
483
		goto error_trans_cancel;
484
	/*
485
	 * Invalidate the block(s). No validation is done.
486 487 488 489 490 491 492
	 */
	for (i = 0; i < nmaps; i++) {
		bp = xfs_trans_get_buf(tp, mp->m_ddev_targp,
			XFS_FSB_TO_DADDR(mp, mval[i].br_startblock),
			XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0);
		if (!bp) {
			error = ENOMEM;
493
			goto error_bmap_cancel;
494 495 496 497 498 499
		}
		xfs_trans_binval(tp, bp);
	}
	/*
	 * Unmap the dead block(s) to the free_list.
	 */
500 501 502 503
	error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps,
			    &first_block, &free_list, &done);
	if (error)
		goto error_bmap_cancel;
504 505 506 507
	ASSERT(done);
	/*
	 * Commit the first transaction.  This logs the EFI and the inode.
	 */
508 509 510
	error = xfs_bmap_finish(&tp, &free_list, &committed);
	if (error)
		goto error_bmap_cancel;
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
	/*
	 * The transaction must have been committed, since there were
	 * actually extents freed by xfs_bunmapi.  See xfs_bmap_finish.
	 * The new tp has the extent freeing and EFDs.
	 */
	ASSERT(committed);
	/*
	 * The first xact was committed, so add the inode to the new one.
	 * Mark it dirty so it will be logged and moved forward in the log as
	 * part of every commit.
	 */
	xfs_trans_ijoin(tp, ip, 0);
	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
	/*
	 * Commit the transaction containing extent freeing and EFDs.
	 */
527
	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
528 529
	if (error) {
		ASSERT(XFS_FORCED_SHUTDOWN(mp));
530
		goto error_unlock;
531 532 533 534 535 536 537 538 539
	}

	/*
	 * Remove the memory for extent descriptions (just bookkeeping).
	 */
	if (ip->i_df.if_bytes)
		xfs_idata_realloc(ip, -ip->i_df.if_bytes, XFS_DATA_FORK);
	ASSERT(ip->i_df.if_bytes == 0);

540
	xfs_iunlock(ip, XFS_ILOCK_EXCL);
541 542
	return 0;

543
error_bmap_cancel:
544
	xfs_bmap_cancel(&free_list);
545 546 547 548
error_trans_cancel:
	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
error_unlock:
	xfs_iunlock(ip, XFS_ILOCK_EXCL);
549 550
	return error;
}
551 552 553 554 555 556

/*
 * xfs_inactive_symlink - free a symlink
 */
int
xfs_inactive_symlink(
557
	struct xfs_inode	*ip)
558 559 560 561 562 563 564
{
	struct xfs_mount	*mp = ip->i_mount;
	int			pathlen;

	trace_xfs_inactive_symlink(ip);

	if (XFS_FORCED_SHUTDOWN(mp))
E
Eric Sandeen 已提交
565
		return EIO;
566

567 568
	xfs_ilock(ip, XFS_ILOCK_EXCL);

569 570 571 572
	/*
	 * Zero length symlinks _can_ exist.
	 */
	pathlen = (int)ip->i_d.di_size;
573 574
	if (!pathlen) {
		xfs_iunlock(ip, XFS_ILOCK_EXCL);
575
		return 0;
576
	}
577 578 579 580

	if (pathlen < 0 || pathlen > MAXPATHLEN) {
		xfs_alert(mp, "%s: inode (0x%llx) bad symlink length (%d)",
			 __func__, (unsigned long long)ip->i_ino, pathlen);
581
		xfs_iunlock(ip, XFS_ILOCK_EXCL);
582
		ASSERT(0);
E
Eric Sandeen 已提交
583
		return EFSCORRUPTED;
584 585 586
	}

	if (ip->i_df.if_flags & XFS_IFINLINE) {
587
		if (ip->i_df.if_bytes > 0) 
588 589
			xfs_idata_realloc(ip, -(ip->i_df.if_bytes),
					  XFS_DATA_FORK);
590
		xfs_iunlock(ip, XFS_ILOCK_EXCL);
591 592 593 594
		ASSERT(ip->i_df.if_bytes == 0);
		return 0;
	}

595 596
	xfs_iunlock(ip, XFS_ILOCK_EXCL);

597
	/* remove the remote symlink */
598
	return xfs_inactive_symlink_rmt(ip);
599
}