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_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 83 84
		if (!bp)
			return XFS_ERROR(ENOMEM);
		error = bp->b_error;
		if (error) {
			xfs_buf_ioerror_alert(bp, __func__);
			xfs_buf_relse(bp);
			goto out;
		}
85
		byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
86 87
		if (pathlen < byte_cnt)
			byte_cnt = pathlen;
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

		cur_chunk = bp->b_addr;
		if (xfs_sb_version_hascrc(&mp->m_sb)) {
			if (!xfs_symlink_hdr_ok(mp, ip->i_ino, offset,
							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);

107
		pathlen -= byte_cnt;
108
		offset += byte_cnt;
109 110 111

		xfs_buf_relse(bp);
	}
112
	ASSERT(pathlen == 0);
113 114 115 116 117 118 119 120 121 122

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

 out:
	return error;
}

int
xfs_readlink(
123
	struct xfs_inode *ip,
124 125
	char		*link)
{
126
	struct xfs_mount *mp = ip->i_mount;
127 128 129 130 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
	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(
165
	struct xfs_inode	*dp,
166 167 168
	struct xfs_name		*link_name,
	const char		*target_path,
	umode_t			mode,
169
	struct xfs_inode	**ipp)
170
{
171 172 173 174
	struct xfs_mount	*mp = dp->i_mount;
	struct xfs_trans	*tp = NULL;
	struct xfs_inode	*ip = NULL;
	int			error = 0;
175
	int			pathlen;
176
	struct xfs_bmap_free	free_list;
177
	xfs_fsblock_t		first_block;
178
	bool			unlock_dp_on_error = false;
179 180 181 182 183
	uint			cancel_flags;
	int			committed;
	xfs_fileoff_t		first_fsb;
	xfs_filblks_t		fs_blocks;
	int			nmaps;
184
	struct xfs_bmbt_irec	mval[XFS_SYMLINK_MAPS];
185 186 187 188 189 190
	xfs_daddr_t		d;
	const char		*cur_chunk;
	int			byte_cnt;
	int			n;
	xfs_buf_t		*bp;
	prid_t			prid;
191 192
	struct xfs_dquot	*udqp = NULL;
	struct xfs_dquot	*gdqp = NULL;
193
	struct xfs_dquot	*pdqp = NULL;
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
	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;
	if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
		prid = xfs_get_projid(dp);
	else
		prid = XFS_PROJID_DEFAULT;

	/*
	 * Make sure that we have allocated dquot(s) on disk.
	 */
219 220 221 222 223
	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);
224 225 226 227 228 229 230 231 232 233 234 235
	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
236
		fs_blocks = xfs_symlink_blocks(mp, pathlen);
237
	resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
238
	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_symlink, resblks, 0);
239 240
	if (error == ENOSPC && fs_blocks == 0) {
		resblks = 0;
241
		error = xfs_trans_reserve(tp, &M_RES(mp)->tr_symlink, 0, 0);
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
	}
	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.
	 */
262 263
	error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
						pdqp, resblks, 1, 0);
264 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
	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.
	 */
301
	xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322

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

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

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

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

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

			memcpy(buf, cur_chunk, byte_cnt);

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

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

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

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

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

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

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

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

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

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

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

/*
 * xfs_inactive_symlink - free a symlink
 */
int
xfs_inactive_symlink(
555
	struct xfs_inode	*ip)
556 557 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))
		return XFS_ERROR(EIO);

565 566
	xfs_ilock(ip, XFS_ILOCK_EXCL);

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

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

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

593 594
	xfs_iunlock(ip, XFS_ILOCK_EXCL);

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