xfs_symlink.c 14.1 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_dir2.h"
31 32 33 34
#include "xfs_inode.h"
#include "xfs_ialloc.h"
#include "xfs_alloc.h"
#include "xfs_bmap.h"
35
#include "xfs_bmap_btree.h"
D
Dave Chinner 已提交
36
#include "xfs_bmap_util.h"
37 38 39 40 41
#include "xfs_error.h"
#include "xfs_quota.h"
#include "xfs_trans_space.h"
#include "xfs_trace.h"
#include "xfs_symlink.h"
42 43
#include "xfs_trans.h"
#include "xfs_log.h"
44
#include "xfs_dinode.h"
45 46 47 48

/* ----- Kernel only functions below ----- */
STATIC int
xfs_readlink_bmap(
49 50
	struct xfs_inode	*ip,
	char			*link)
51
{
52 53 54 55 56 57 58 59 60 61 62 63
	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;
64

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

70
	offset = 0;
71 72 73 74
	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);

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

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

		cur_chunk = bp->b_addr;
		if (xfs_sb_version_hascrc(&mp->m_sb)) {
95
			if (!xfs_symlink_hdr_ok(ip->i_ino, offset,
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
							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);

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

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

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

 out:
	return error;
}

int
xfs_readlink(
127
	struct xfs_inode *ip,
128 129
	char		*link)
{
130
	struct xfs_mount *mp = ip->i_mount;
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
	xfs_fsize_t	pathlen;
	int		error = 0;

	trace_xfs_readlink(ip);

	if (XFS_FORCED_SHUTDOWN(mp))
		return XFS_ERROR(EIO);

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

	*ipp = NULL;

	trace_xfs_symlink(dp, link_name);

	if (XFS_FORCED_SHUTDOWN(mp))
		return XFS_ERROR(EIO);

	/*
	 * Check component lengths of the target path name.
	 */
	pathlen = strlen(target_path);
	if (pathlen >= MAXPATHLEN)      /* total string too long */
		return XFS_ERROR(ENAMETOOLONG);

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

	/*
	 * Make sure that we have allocated dquot(s) on disk.
	 */
220 221 222 223 224
	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);
225 226 227 228 229 230 231 232 233 234 235 236
	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
237
		fs_blocks = xfs_symlink_blocks(mp, pathlen);
238
	resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
239
	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_symlink, resblks, 0);
240 241
	if (error == ENOSPC && fs_blocks == 0) {
		resblks = 0;
242
		error = xfs_trans_reserve(tp, &M_RES(mp)->tr_symlink, 0, 0);
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
	}
	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) {
		error = XFS_ERROR(EPERM);
		goto error_return;
	}

	/*
	 * Reserve disk quota : blocks and inode.
	 */
263 264
	error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
						pdqp, resblks, 1, 0);
265 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
	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.
	 */
302
	xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323

	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 {
324 325
		int	offset;

326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
		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;
341
		offset = 0;
342
		for (n = 0; n < nmaps; n++) {
343
			char	*buf;
344

345 346 347 348 349 350 351 352
			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;
			}
353 354 355
			bp->b_ops = &xfs_symlink_buf_ops;

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

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

			memcpy(buf, cur_chunk, byte_cnt);

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

368
			xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
369 370
			xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) -
							(char *)bp->b_addr);
371
		}
372
		ASSERT(pathlen == 0);
373 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
	}

	/*
	 * 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);
401
	xfs_qm_dqrele(pdqp);
402 403 404 405 406 407 408 409 410 411 412 413 414

	*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);
415
	xfs_qm_dqrele(pdqp);
416 417 418 419 420 421 422 423 424 425

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

/*
 * Free a symlink that has blocks associated with it.
 */
426
STATIC int
427
xfs_inactive_symlink_rmt(
428
	struct xfs_inode *ip)
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
{
	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;
444
	ASSERT(ip->i_df.if_flags & XFS_IFEXTENTS);
445 446 447 448 449 450 451 452 453
	/*
	 * 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);

454 455 456 457 458 459 460 461 462 463
	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);

464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
	/*
	 * 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);
479
	error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size),
480 481
				mval, &nmaps, 0);
	if (error)
482
		goto error_trans_cancel;
483
	/*
484
	 * Invalidate the block(s). No validation is done.
485 486 487 488 489 490 491
	 */
	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;
492
			goto error_bmap_cancel;
493 494 495 496 497 498
		}
		xfs_trans_binval(tp, bp);
	}
	/*
	 * Unmap the dead block(s) to the free_list.
	 */
499 500 501 502
	error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps,
			    &first_block, &free_list, &done);
	if (error)
		goto error_bmap_cancel;
503 504 505 506
	ASSERT(done);
	/*
	 * Commit the first transaction.  This logs the EFI and the inode.
	 */
507 508 509
	error = xfs_bmap_finish(&tp, &free_list, &committed);
	if (error)
		goto error_bmap_cancel;
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
	/*
	 * 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.
	 */
526
	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
527 528
	if (error) {
		ASSERT(XFS_FORCED_SHUTDOWN(mp));
529
		goto error_unlock;
530 531 532 533 534 535 536 537 538
	}

	/*
	 * 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);

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

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

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

	trace_xfs_inactive_symlink(ip);

	if (XFS_FORCED_SHUTDOWN(mp))
		return XFS_ERROR(EIO);

566 567
	xfs_ilock(ip, XFS_ILOCK_EXCL);

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

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

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

594 595
	xfs_iunlock(ip, XFS_ILOCK_EXCL);

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