xfs_attr.c 40.2 KB
Newer Older
D
Dave Chinner 已提交
1
// SPDX-License-Identifier: GPL-2.0
L
Linus Torvalds 已提交
2
/*
3 4
 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
 * All Rights Reserved.
L
Linus Torvalds 已提交
5 6
 */
#include "xfs.h"
7
#include "xfs_fs.h"
8
#include "xfs_shared.h"
9 10 11
#include "xfs_format.h"
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
L
Linus Torvalds 已提交
12
#include "xfs_mount.h"
13
#include "xfs_defer.h"
14
#include "xfs_da_format.h"
15 16
#include "xfs_da_btree.h"
#include "xfs_attr_sf.h"
L
Linus Torvalds 已提交
17
#include "xfs_inode.h"
18
#include "xfs_trans.h"
L
Linus Torvalds 已提交
19
#include "xfs_bmap.h"
20
#include "xfs_bmap_btree.h"
L
Linus Torvalds 已提交
21 22
#include "xfs_attr.h"
#include "xfs_attr_leaf.h"
23
#include "xfs_attr_remote.h"
L
Linus Torvalds 已提交
24 25
#include "xfs_quota.h"
#include "xfs_trans_space.h"
C
Christoph Hellwig 已提交
26
#include "xfs_trace.h"
27
#include "xfs_attr_item.h"
28
#include "xfs_log.h"
29 30 31

struct kmem_cache		*xfs_attri_cache;
struct kmem_cache		*xfs_attrd_cache;
L
Linus Torvalds 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

/*
 * xfs_attr.c
 *
 * Provide the external interfaces to manage attribute lists.
 */

/*========================================================================
 * Function prototypes for the kernel.
 *========================================================================*/

/*
 * Internal routines when attribute list fits inside the inode.
 */
STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);

/*
 * Internal routines when attribute list is one block.
 */
51
STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
L
Linus Torvalds 已提交
52
STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
53
STATIC int xfs_attr_leaf_hasname(struct xfs_da_args *args, struct xfs_buf **bp);
54
STATIC int xfs_attr_leaf_try_add(struct xfs_da_args *args, struct xfs_buf *bp);
L
Linus Torvalds 已提交
55 56 57 58

/*
 * Internal routines when attribute list is more than one block.
 */
59
STATIC int xfs_attr_node_get(xfs_da_args_t *args);
60
STATIC void xfs_attr_restore_rmt_blk(struct xfs_da_args *args);
61
static int xfs_attr_node_try_addname(struct xfs_attr_item *attr);
62
STATIC int xfs_attr_node_addname_find_attr(struct xfs_attr_item *attr);
63
STATIC int xfs_attr_node_remove_attr(struct xfs_attr_item *attr);
64 65
STATIC int xfs_attr_node_hasname(xfs_da_args_t *args,
				 struct xfs_da_state **state);
L
Linus Torvalds 已提交
66

67
int
68 69 70
xfs_inode_hasattr(
	struct xfs_inode	*ip)
{
71 72 73 74 75 76
	if (!XFS_IFORK_Q(ip))
		return 0;
	if (!ip->i_afp)
		return 0;
	if (ip->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
	    ip->i_afp->if_nextents == 0)
77 78 79 80
		return 0;
	return 1;
}

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
/*
 * Returns true if the there is exactly only block in the attr fork, in which
 * case the attribute fork consists of a single leaf block entry.
 */
bool
xfs_attr_is_leaf(
	struct xfs_inode	*ip)
{
	struct xfs_ifork	*ifp = ip->i_afp;
	struct xfs_iext_cursor	icur;
	struct xfs_bmbt_irec	imap;

	if (ifp->if_nextents != 1 || ifp->if_format != XFS_DINODE_FMT_EXTENTS)
		return false;

	xfs_iext_first(ifp, &icur);
	xfs_iext_get_extent(ifp, &icur, &imap);
	return imap.br_startoff == 0 && imap.br_blockcount == 1;
}

D
Dave Chinner 已提交
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 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 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
/*
 * XXX (dchinner): name path state saving and refilling is an optimisation to
 * avoid needing to look up name entries after rolling transactions removing
 * remote xattr blocks between the name entry lookup and name entry removal.
 * This optimisation got sidelined when combining the set and remove state
 * machines, but the code has been left in place because it is worthwhile to
 * restore the optimisation once the combined state machine paths have settled.
 *
 * This comment is a public service announcement to remind Future Dave that he
 * still needs to restore this code to working order.
 */
#if 0
/*
 * Fill in the disk block numbers in the state structure for the buffers
 * that are attached to the state structure.
 * This is done so that we can quickly reattach ourselves to those buffers
 * after some set of transaction commits have released these buffers.
 */
static int
xfs_attr_fillstate(xfs_da_state_t *state)
{
	xfs_da_state_path_t *path;
	xfs_da_state_blk_t *blk;
	int level;

	trace_xfs_attr_fillstate(state->args);

	/*
	 * Roll down the "path" in the state structure, storing the on-disk
	 * block number for those buffers in the "path".
	 */
	path = &state->path;
	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
		if (blk->bp) {
			blk->disk_blkno = xfs_buf_daddr(blk->bp);
			blk->bp = NULL;
		} else {
			blk->disk_blkno = 0;
		}
	}

	/*
	 * Roll down the "altpath" in the state structure, storing the on-disk
	 * block number for those buffers in the "altpath".
	 */
	path = &state->altpath;
	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
		if (blk->bp) {
			blk->disk_blkno = xfs_buf_daddr(blk->bp);
			blk->bp = NULL;
		} else {
			blk->disk_blkno = 0;
		}
	}

	return 0;
}

/*
 * Reattach the buffers to the state structure based on the disk block
 * numbers stored in the state structure.
 * This is done after some set of transaction commits have released those
 * buffers from our grip.
 */
static int
xfs_attr_refillstate(xfs_da_state_t *state)
{
	xfs_da_state_path_t *path;
	xfs_da_state_blk_t *blk;
	int level, error;

	trace_xfs_attr_refillstate(state->args);

	/*
	 * Roll down the "path" in the state structure, storing the on-disk
	 * block number for those buffers in the "path".
	 */
	path = &state->path;
	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
		if (blk->disk_blkno) {
			error = xfs_da3_node_read_mapped(state->args->trans,
					state->args->dp, blk->disk_blkno,
					&blk->bp, XFS_ATTR_FORK);
			if (error)
				return error;
		} else {
			blk->bp = NULL;
		}
	}

	/*
	 * Roll down the "altpath" in the state structure, storing the on-disk
	 * block number for those buffers in the "altpath".
	 */
	path = &state->altpath;
	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
		if (blk->disk_blkno) {
			error = xfs_da3_node_read_mapped(state->args->trans,
					state->args->dp, blk->disk_blkno,
					&blk->bp, XFS_ATTR_FORK);
			if (error)
				return error;
		} else {
			blk->bp = NULL;
		}
	}

	return 0;
}
#else
static int xfs_attr_fillstate(xfs_da_state_t *state) { return 0; }
#endif

L
Linus Torvalds 已提交
218 219 220 221
/*========================================================================
 * Overall external interface routines.
 *========================================================================*/

222 223 224 225
/*
 * Retrieve an extended attribute and its value.  Must have ilock.
 * Returns 0 on successful retrieval, otherwise an error.
 */
226 227 228 229
int
xfs_attr_get_ilocked(
	struct xfs_da_args	*args)
{
230
	ASSERT(xfs_isilocked(args->dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
231

232
	if (!xfs_inode_hasattr(args->dp))
233
		return -ENOATTR;
234

235
	if (args->dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
236
		return xfs_attr_shortform_getvalue(args);
237
	if (xfs_attr_is_leaf(args->dp))
238
		return xfs_attr_leaf_get(args);
239
	return xfs_attr_node_get(args);
240 241
}

242 243 244
/*
 * Retrieve an extended attribute by name, and its value if requested.
 *
C
Christoph Hellwig 已提交
245 246 247
 * If args->valuelen is zero, then the caller does not want the value, just an
 * indication whether the attribute exists and the size of the value if it
 * exists. The size is returned in args.valuelen.
248
 *
249 250 251 252 253
 * If args->value is NULL but args->valuelen is non-zero, allocate the buffer
 * for the value after existence of the attribute has been determined. The
 * caller always has to free args->value if it is set, no matter if this
 * function was successful or not.
 *
254
 * If the attribute is found, but exceeds the size limit set by the caller in
255 256
 * args->valuelen, return -ERANGE with the size of the attribute that was found
 * in args->valuelen.
257
 */
258 259
int
xfs_attr_get(
260
	struct xfs_da_args	*args)
L
Linus Torvalds 已提交
261
{
262 263 264
	uint			lock_mode;
	int			error;

265
	XFS_STATS_INC(args->dp->i_mount, xs_attr_get);
266

267
	if (xfs_is_shutdown(args->dp->i_mount))
D
Dave Chinner 已提交
268
		return -EIO;
L
Linus Torvalds 已提交
269

270 271 272
	args->geo = args->dp->i_mount->m_attr_geo;
	args->whichfork = XFS_ATTR_FORK;
	args->hashval = xfs_da_hashname(args->name, args->namelen);
273

274
	/* Entirely possible to look up a name which doesn't exist */
275
	args->op_flags = XFS_DA_OP_OKNOENT;
L
Linus Torvalds 已提交
276

277
	lock_mode = xfs_ilock_attr_map_shared(args->dp);
278
	error = xfs_attr_get_ilocked(args);
279
	xfs_iunlock(args->dp, lock_mode);
280

281
	return error;
L
Linus Torvalds 已提交
282 283
}

284 285 286
/*
 * Calculate how many blocks we need for the new attribute,
 */
287
int
288
xfs_attr_calc_size(
289
	struct xfs_da_args	*args,
290 291
	int			*local)
{
292
	struct xfs_mount	*mp = args->dp->i_mount;
293 294 295 296 297 298 299
	int			size;
	int			nblks;

	/*
	 * Determine space new attribute will use, and if it would be
	 * "local" or "remote" (note: local != inline).
	 */
300
	size = xfs_attr_leaf_newentsize(args, local);
301 302
	nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
	if (*local) {
303
		if (size > (args->geo->blksize / 2)) {
304 305 306 307 308 309 310 311
			/* Double split possible */
			nblks *= 2;
		}
	} else {
		/*
		 * Out of line attribute, cannot double split, but
		 * make room for the attribute value itself.
		 */
312
		uint	dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen);
313 314 315 316 317 318 319
		nblks += dblocks;
		nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
	}

	return nblks;
}

320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
/* Initialize transaction reservation for attr operations */
void
xfs_init_attr_trans(
	struct xfs_da_args	*args,
	struct xfs_trans_res	*tres,
	unsigned int		*total)
{
	struct xfs_mount	*mp = args->dp->i_mount;

	if (args->value) {
		tres->tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
				 M_RES(mp)->tr_attrsetrt.tr_logres *
				 args->total;
		tres->tr_logcount = XFS_ATTRSET_LOG_COUNT;
		tres->tr_logflags = XFS_TRANS_PERM_LOG_RES;
		*total = args->total;
	} else {
		*tres = M_RES(mp)->tr_attrrm;
		*total = XFS_ATTRRM_SPACE_RES(mp);
	}
}

342 343 344 345 346
/*
 * Add an attr to a shortform fork. If there is no space,
 * xfs_attr_shortform_addname() will convert to leaf format and return -ENOSPC.
 * to use.
 */
347 348 349 350 351 352
STATIC int
xfs_attr_try_sf_addname(
	struct xfs_inode	*dp,
	struct xfs_da_args	*args)
{

353 354 355 356 357 358 359
	int			error;

	/*
	 * Build initial attribute list (if required).
	 */
	if (dp->i_afp->if_format == XFS_DINODE_FMT_EXTENTS)
		xfs_attr_shortform_create(args);
360 361 362 363 364 365 366 367 368

	error = xfs_attr_shortform_addname(args);
	if (error == -ENOSPC)
		return error;

	/*
	 * Commit the shortform mods, and we're done.
	 * NOTE: this is also the error path (EEXIST, etc).
	 */
369
	if (!error && !(args->op_flags & XFS_DA_OP_NOTIME))
370 371
		xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG);

372
	if (xfs_has_wsync(dp->i_mount))
373 374
		xfs_trans_set_sync(args->trans);

375
	return error;
376 377
}

378
static int
379
xfs_attr_sf_addname(
380
	struct xfs_attr_item		*attr)
381
{
382
	struct xfs_da_args		*args = attr->xattri_da_args;
383 384
	struct xfs_inode		*dp = args->dp;
	int				error = 0;
385 386

	error = xfs_attr_try_sf_addname(dp, args);
387 388 389 390 391
	if (error != -ENOSPC) {
		ASSERT(!error || error == -EEXIST);
		attr->xattri_dela_state = XFS_DAS_DONE;
		goto out;
	}
392

393 394 395 396
	/*
	 * It won't fit in the shortform, transform to a leaf block.  GROT:
	 * another possible req'mt for a double-split btree op.
	 */
397
	error = xfs_attr_shortform_to_leaf(args, &attr->xattri_leaf_bp);
398 399 400 401 402 403
	if (error)
		return error;

	/*
	 * Prevent the leaf buffer from being unlocked so that a concurrent AIL
	 * push cannot grab the half-baked leaf buffer and run into problems
404
	 * with the write verifier.
405
	 */
406
	xfs_trans_bhold(args->trans, attr->xattri_leaf_bp);
407 408 409 410
	attr->xattri_dela_state = XFS_DAS_LEAF_ADD;
out:
	trace_xfs_attr_sf_addname_return(attr->xattri_dela_state, args->dp);
	return error;
411 412
}

413
/*
414 415 416 417 418 419 420 421 422
 * Handle the state change on completion of a multi-state attr operation.
 *
 * If the XFS_DA_OP_REPLACE flag is set, this means the operation was the first
 * modification in a attr replace operation and we still have to do the second
 * state, indicated by @replace_state.
 *
 * We consume the XFS_DA_OP_REPLACE flag so that when we are called again on
 * completion of the second half of the attr replace operation we correctly
 * signal that it is done.
423
 */
424 425
static enum xfs_delattr_state
xfs_attr_complete_op(
426
	struct xfs_attr_item	*attr,
427
	enum xfs_delattr_state	replace_state)
428 429
{
	struct xfs_da_args	*args = attr->xattri_da_args;
430
	bool			do_replace = args->op_flags & XFS_DA_OP_REPLACE;
431

432 433 434 435 436 437
	args->op_flags &= ~XFS_DA_OP_REPLACE;
	if (do_replace) {
		args->attr_filter &= ~XFS_ATTR_INCOMPLETE;
		return replace_state;
	}
	return XFS_DAS_DONE;
438 439
}

440
static int
441 442 443 444 445 446
xfs_attr_leaf_addname(
	struct xfs_attr_item	*attr)
{
	struct xfs_da_args	*args = attr->xattri_da_args;
	int			error;

447
	ASSERT(xfs_attr_is_leaf(args->dp));
448

449 450 451 452 453 454 455
	/*
	 * Use the leaf buffer we may already hold locked as a result of
	 * a sf-to-leaf conversion. The held buffer is no longer valid
	 * after this call, regardless of the result.
	 */
	error = xfs_attr_leaf_try_add(args, attr->xattri_leaf_bp);
	attr->xattri_leaf_bp = NULL;
456

457 458
	if (error == -ENOSPC) {
		error = xfs_attr3_leaf_to_node(args);
459 460 461
		if (error)
			return error;

462 463 464 465 466 467
		/*
		 * We're not in leaf format anymore, so roll the transaction and
		 * retry the add to the newly allocated node block.
		 */
		attr->xattri_dela_state = XFS_DAS_NODE_ADD;
		goto out;
468 469 470
	}
	if (error)
		return error;
471

472 473 474 475 476
	/*
	 * We need to commit and roll if we need to allocate remote xattr blocks
	 * or perform more xattr manipulations. Otherwise there is nothing more
	 * to do and we can return success.
	 */
477
	if (args->rmtblkno)
478
		attr->xattri_dela_state = XFS_DAS_LEAF_SET_RMT;
479
	else
480 481
		attr->xattri_dela_state = xfs_attr_complete_op(attr,
							XFS_DAS_LEAF_REPLACE);
482
out:
483
	trace_xfs_attr_leaf_addname_return(attr->xattri_dela_state, args->dp);
484
	return error;
485 486
}

487 488 489 490 491 492 493
/*
 * Add an entry to a node format attr tree.
 *
 * Note that we might still have a leaf here - xfs_attr_is_leaf() cannot tell
 * the difference between leaf + remote attr blocks and a node format tree,
 * so we may still end up having to convert from leaf to node format here.
 */
494 495 496 497 498 499 500 501 502 503 504 505 506 507
static int
xfs_attr_node_addname(
	struct xfs_attr_item	*attr)
{
	struct xfs_da_args	*args = attr->xattri_da_args;
	int			error;

	ASSERT(!attr->xattri_leaf_bp);

	error = xfs_attr_node_addname_find_attr(attr);
	if (error)
		return error;

	error = xfs_attr_node_try_addname(attr);
508 509 510 511 512 513 514 515 516 517
	if (error == -ENOSPC) {
		error = xfs_attr3_leaf_to_node(args);
		if (error)
			return error;
		/*
		 * No state change, we really are in node form now
		 * but we need the transaction rolled to continue.
		 */
		goto out;
	}
518 519 520
	if (error)
		return error;

521
	if (args->rmtblkno)
522
		attr->xattri_dela_state = XFS_DAS_NODE_SET_RMT;
523
	else
524 525
		attr->xattri_dela_state = xfs_attr_complete_op(attr,
							XFS_DAS_NODE_REPLACE);
526
out:
527 528 529 530
	trace_xfs_attr_node_addname_return(attr->xattri_dela_state, args->dp);
	return error;
}

531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
static int
xfs_attr_rmtval_alloc(
	struct xfs_attr_item		*attr)
{
	struct xfs_da_args              *args = attr->xattri_da_args;
	int				error = 0;

	/*
	 * If there was an out-of-line value, allocate the blocks we
	 * identified for its storage and copy the value.  This is done
	 * after we create the attribute so that we don't overflow the
	 * maximum size of a transaction and/or hit a deadlock.
	 */
	if (attr->xattri_blkcnt > 0) {
		error = xfs_attr_rmtval_set_blk(attr);
		if (error)
			return error;
548
		/* Roll the transaction only if there is more to allocate. */
549
		if (attr->xattri_blkcnt > 0)
550
			goto out;
551 552 553 554 555 556
	}

	error = xfs_attr_rmtval_set_value(args);
	if (error)
		return error;

557 558 559 560 561 562 563 564
	attr->xattri_dela_state = xfs_attr_complete_op(attr,
						++attr->xattri_dela_state);
	/*
	 * If we are not doing a rename, we've finished the operation but still
	 * have to clear the incomplete flag protecting the new attr from
	 * exposing partially initialised state if we crash during creation.
	 */
	if (attr->xattri_dela_state == XFS_DAS_DONE)
565 566 567 568 569
		error = xfs_attr3_leaf_clearflag(args);
out:
	trace_xfs_attr_rmtval_alloc(attr->xattri_dela_state, args->dp);
	return error;
}
570

571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
/*
 * Mark an attribute entry INCOMPLETE and save pointers to the relevant buffers
 * for later deletion of the entry.
 */
static int
xfs_attr_leaf_mark_incomplete(
	struct xfs_da_args	*args,
	struct xfs_da_state	*state)
{
	int			error;

	/*
	 * Fill in disk block numbers in the state structure
	 * so that we can get the buffers back after we commit
	 * several transactions in the following calls.
	 */
	error = xfs_attr_fillstate(state);
	if (error)
		return error;

	/*
	 * Mark the attribute as INCOMPLETE
	 */
	return xfs_attr3_leaf_setflag(args);
}

/*
 * Initial setup for xfs_attr_node_removename.  Make sure the attr is there and
 * the blocks are valid.  Attr keys with remote blocks will be marked
 * incomplete.
 */
static
int xfs_attr_node_removename_setup(
	struct xfs_attr_item		*attr)
{
	struct xfs_da_args		*args = attr->xattri_da_args;
607
	struct xfs_da_state		*state;
608 609
	int				error;

610
	error = xfs_attr_node_hasname(args, &attr->xattri_da_state);
611 612 613 614
	if (error != -EEXIST)
		goto out;
	error = 0;

615 616 617
	state = attr->xattri_da_state;
	ASSERT(state->path.blk[state->path.active - 1].bp != NULL);
	ASSERT(state->path.blk[state->path.active - 1].magic ==
618 619
		XFS_ATTR_LEAF_MAGIC);

620
	error = xfs_attr_leaf_mark_incomplete(args, state);
621 622 623
	if (error)
		goto out;
	if (args->rmtblkno > 0)
624 625
		error = xfs_attr_rmtval_invalidate(args);
out:
626 627 628 629
	if (error) {
		xfs_da_state_free(attr->xattri_da_state);
		attr->xattri_da_state = NULL;
	}
630 631 632 633

	return error;
}

634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
/*
 * Remove the original attr we have just replaced. This is dependent on the
 * original lookup and insert placing the old attr in args->blkno/args->index
 * and the new attr in args->blkno2/args->index2.
 */
static int
xfs_attr_leaf_remove_attr(
	struct xfs_attr_item		*attr)
{
	struct xfs_da_args              *args = attr->xattri_da_args;
	struct xfs_inode		*dp = args->dp;
	struct xfs_buf			*bp = NULL;
	int				forkoff;
	int				error;

	error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno,
				   &bp);
	if (error)
		return error;

	xfs_attr3_leaf_remove(bp, args);

	forkoff = xfs_attr_shortform_allfit(bp, dp);
	if (forkoff)
		error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
		/* bp is gone due to xfs_da_shrink_inode */

	return error;
}

/*
 * Shrink an attribute from leaf to shortform. Used by the node format remove
 * path when the node format collapses to a single block and so we have to check
 * if it can be collapsed further.
 */
static int
xfs_attr_leaf_shrink(
D
Dave Chinner 已提交
671
	struct xfs_da_args	*args)
672 673 674
{
	struct xfs_inode	*dp = args->dp;
	struct xfs_buf		*bp;
D
Dave Chinner 已提交
675 676
	int			forkoff;
	int			error;
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695

	if (!xfs_attr_is_leaf(dp))
		return 0;

	error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp);
	if (error)
		return error;

	forkoff = xfs_attr_shortform_allfit(bp, dp);
	if (forkoff) {
		error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
		/* bp is gone due to xfs_da_shrink_inode */
	} else {
		xfs_trans_brelse(args->trans, bp);
	}

	return error;
}

696
/*
697 698 699 700 701 702
 * Run the attribute operation specified in @attr.
 *
 * This routine is meant to function as a delayed operation and will set the
 * state to XFS_DAS_DONE when the operation is complete.  Calling functions will
 * need to handle this, and recall the function until either an error or
 * XFS_DAS_DONE is detected.
703 704
 */
int
705
xfs_attr_set_iter(
706
	struct xfs_attr_item		*attr)
707
{
708
	struct xfs_da_args              *args = attr->xattri_da_args;
709
	int				error = 0;
710 711

	/* State machine switch */
712
next_state:
713
	switch (attr->xattri_dela_state) {
714
	case XFS_DAS_UNINIT:
715 716 717 718 719
		ASSERT(0);
		return -EFSCORRUPTED;
	case XFS_DAS_SF_ADD:
		return xfs_attr_sf_addname(attr);
	case XFS_DAS_LEAF_ADD:
720
		return xfs_attr_leaf_addname(attr);
721 722
	case XFS_DAS_NODE_ADD:
		return xfs_attr_node_addname(attr);
723

724
	case XFS_DAS_SF_REMOVE:
725 726 727 728
		error = xfs_attr_sf_removename(args);
		attr->xattri_dela_state = xfs_attr_complete_op(attr,
						xfs_attr_init_add_state(args));
		break;
729
	case XFS_DAS_LEAF_REMOVE:
730 731 732 733
		error = xfs_attr_leaf_removename(args);
		attr->xattri_dela_state = xfs_attr_complete_op(attr,
						xfs_attr_init_add_state(args));
		break;
734 735
	case XFS_DAS_NODE_REMOVE:
		error = xfs_attr_node_removename_setup(attr);
736 737 738 739 740 741 742
		if (error == -ENOATTR &&
		    (args->op_flags & XFS_DA_OP_RECOVERY)) {
			attr->xattri_dela_state = xfs_attr_complete_op(attr,
						xfs_attr_init_add_state(args));
			error = 0;
			break;
		}
743 744 745 746 747 748 749
		if (error)
			return error;
		attr->xattri_dela_state = XFS_DAS_NODE_REMOVE_RMT;
		if (args->rmtblkno == 0)
			attr->xattri_dela_state++;
		break;

750 751 752 753 754
	case XFS_DAS_LEAF_SET_RMT:
	case XFS_DAS_NODE_SET_RMT:
		error = xfs_attr_rmtval_find_space(attr);
		if (error)
			return error;
755
		attr->xattri_dela_state++;
756
		fallthrough;
757

758
	case XFS_DAS_LEAF_ALLOC_RMT:
759
	case XFS_DAS_NODE_ALLOC_RMT:
760 761
		error = xfs_attr_rmtval_alloc(attr);
		if (error)
762
			return error;
763 764
		if (attr->xattri_dela_state == XFS_DAS_DONE)
			break;
765
		goto next_state;
766

767 768
	case XFS_DAS_LEAF_REPLACE:
	case XFS_DAS_NODE_REPLACE:
769
		/*
770 771
		 * We must "flip" the incomplete flags on the "new" and "old"
		 * attribute/value pairs so that one disappears and one appears
772
		 * atomically.
773
		 */
774 775 776 777
		error = xfs_attr3_leaf_flipflags(args);
		if (error)
			return error;
		/*
778 779
		 * We must commit the flag value change now to make it atomic
		 * and then we can start the next trans in series at REMOVE_OLD.
780
		 */
781
		attr->xattri_dela_state++;
782 783 784 785
		break;

	case XFS_DAS_LEAF_REMOVE_OLD:
	case XFS_DAS_NODE_REMOVE_OLD:
786
		/*
787 788 789 790 791
		 * If we have a remote attr, start the process of removing it
		 * by invalidating any cached buffers.
		 *
		 * If we don't have a remote attr, we skip the remote block
		 * removal state altogether with a second state increment.
792 793 794
		 */
		xfs_attr_restore_rmt_blk(args);
		if (args->rmtblkno) {
795
			error = xfs_attr_rmtval_invalidate(args);
796 797
			if (error)
				return error;
798 799
		} else {
			attr->xattri_dela_state++;
800 801
		}

802 803 804 805 806 807
		attr->xattri_dela_state++;
		goto next_state;

	case XFS_DAS_LEAF_REMOVE_RMT:
	case XFS_DAS_NODE_REMOVE_RMT:
		error = xfs_attr_rmtval_remove(attr);
808 809
		if (error == -EAGAIN) {
			error = 0;
810
			break;
811
		}
812 813 814
		if (error)
			return error;

815
		/*
816 817 818 819 820 821
		 * We've finished removing the remote attr blocks, so commit the
		 * transaction and move on to removing the attr name from the
		 * leaf/node block. Removing the attr might require a full
		 * transaction reservation for btree block freeing, so we
		 * can't do that in the same transaction where we removed the
		 * remote attr blocks.
822 823
		 */
		attr->xattri_dela_state++;
824
		break;
825

826 827
	case XFS_DAS_LEAF_REMOVE_ATTR:
		error = xfs_attr_leaf_remove_attr(attr);
828 829
		attr->xattri_dela_state = xfs_attr_complete_op(attr,
						xfs_attr_init_add_state(args));
830
		break;
831

832 833 834
	case XFS_DAS_NODE_REMOVE_ATTR:
		error = xfs_attr_node_remove_attr(attr);
		if (!error)
D
Dave Chinner 已提交
835
			error = xfs_attr_leaf_shrink(args);
836 837
		attr->xattri_dela_state = xfs_attr_complete_op(attr,
						xfs_attr_init_add_state(args));
838 839
		break;
	default:
840
		ASSERT(0);
841 842
		break;
	}
843 844

	trace_xfs_attr_set_iter_return(attr->xattri_dela_state, args->dp);
845
	return error;
846 847
}

848

849 850 851
/*
 * Return EEXIST if attr is found, or ENOATTR if not
 */
D
Dave Chinner 已提交
852 853
static int
xfs_attr_lookup(
854 855 856 857 858 859 860 861 862
	struct xfs_da_args	*args)
{
	struct xfs_inode	*dp = args->dp;
	struct xfs_buf		*bp = NULL;
	int			error;

	if (!xfs_inode_hasattr(dp))
		return -ENOATTR;

C
Christoph Hellwig 已提交
863
	if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
864 865
		return xfs_attr_sf_findname(args, NULL, NULL);

866
	if (xfs_attr_is_leaf(dp)) {
867 868 869 870 871 872 873 874 875 876 877
		error = xfs_attr_leaf_hasname(args, &bp);

		if (bp)
			xfs_trans_brelse(args->trans, bp);

		return error;
	}

	return xfs_attr_node_hasname(args, NULL);
}

878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906
static int
xfs_attr_item_init(
	struct xfs_da_args	*args,
	unsigned int		op_flags,	/* op flag (set or remove) */
	struct xfs_attr_item	**attr)		/* new xfs_attr_item */
{

	struct xfs_attr_item	*new;

	new = kmem_zalloc(sizeof(struct xfs_attr_item), KM_NOFS);
	new->xattri_op_flags = op_flags;
	new->xattri_da_args = args;

	*attr = new;
	return 0;
}

/* Sets an attribute for an inode as a deferred operation */
static int
xfs_attr_defer_add(
	struct xfs_da_args	*args)
{
	struct xfs_attr_item	*new;
	int			error = 0;

	error = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_SET, &new);
	if (error)
		return error;

907
	new->xattri_dela_state = xfs_attr_init_add_state(args);
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925
	xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);
	trace_xfs_attr_defer_add(new->xattri_dela_state, args->dp);

	return 0;
}

/* Sets an attribute for an inode as a deferred operation */
static int
xfs_attr_defer_replace(
	struct xfs_da_args	*args)
{
	struct xfs_attr_item	*new;
	int			error = 0;

	error = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_REPLACE, &new);
	if (error)
		return error;

926
	new->xattri_dela_state = xfs_attr_init_replace_state(args);
927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945
	xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);
	trace_xfs_attr_defer_replace(new->xattri_dela_state, args->dp);

	return 0;
}

/* Removes an attribute for an inode as a deferred operation */
static int
xfs_attr_defer_remove(
	struct xfs_da_args	*args)
{

	struct xfs_attr_item	*new;
	int			error;

	error  = xfs_attr_item_init(args, XFS_ATTR_OP_FLAGS_REMOVE, &new);
	if (error)
		return error;

946
	new->xattri_dela_state = xfs_attr_init_remove_state(args);
947 948 949 950 951 952
	xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);
	trace_xfs_attr_defer_remove(new->xattri_dela_state, args->dp);

	return 0;
}

953
/*
954
 * Note: If args->value is NULL the attribute will be removed, just like the
955 956
 * Linux ->setattr API.
 */
957 958
int
xfs_attr_set(
959
	struct xfs_da_args	*args)
L
Linus Torvalds 已提交
960
{
961
	struct xfs_inode	*dp = args->dp;
962 963
	struct xfs_mount	*mp = dp->i_mount;
	struct xfs_trans_res	tres;
964
	bool			rsvd = (args->attr_filter & XFS_ATTR_ROOT);
965
	int			error, local;
966
	int			rmt_blks = 0;
967
	unsigned int		total;
968
	int			delayed = xfs_has_larp(mp);
969

970
	if (xfs_is_shutdown(dp->i_mount))
D
Dave Chinner 已提交
971
		return -EIO;
972

973 974 975 976
	error = xfs_qm_dqattach(dp);
	if (error)
		return error;

977 978 979
	args->geo = mp->m_attr_geo;
	args->whichfork = XFS_ATTR_FORK;
	args->hashval = xfs_da_hashname(args->name, args->namelen);
L
Linus Torvalds 已提交
980 981

	/*
982 983 984
	 * We have no control over the attribute names that userspace passes us
	 * to remove, so we have to allow the name lookup prior to attribute
	 * removal to fail as well.
L
Linus Torvalds 已提交
985
	 */
986
	args->op_flags = XFS_DA_OP_OKNOENT;
987

988
	if (args->value) {
989
		XFS_STATS_INC(mp, xs_attr_set);
990
		args->total = xfs_attr_calc_size(args, &local);
991 992 993 994 995 996 997

		/*
		 * If the inode doesn't have an attribute fork, add one.
		 * (inode must not be locked when we call this routine)
		 */
		if (XFS_IFORK_Q(dp) == 0) {
			int sf_size = sizeof(struct xfs_attr_sf_hdr) +
998
				xfs_attr_sf_entsize_byname(args->namelen,
999
						args->valuelen);
1000 1001 1002 1003 1004 1005

			error = xfs_bmap_add_attrfork(dp, sf_size, rsvd);
			if (error)
				return error;
		}

1006 1007
		if (!local)
			rmt_blks = xfs_attr3_rmt_blocks(mp, args->valuelen);
1008 1009
	} else {
		XFS_STATS_INC(mp, xs_attr_remove);
1010
		rmt_blks = xfs_attr3_rmt_blocks(mp, XFS_XATTR_SIZE_MAX);
1011
	}
L
Linus Torvalds 已提交
1012

1013 1014 1015 1016 1017 1018
	if (delayed) {
		error = xfs_attr_use_log_assist(mp);
		if (error)
			return error;
	}

L
Linus Torvalds 已提交
1019 1020 1021 1022
	/*
	 * Root fork attributes can use reserved data blocks for this
	 * operation if necessary
	 */
1023
	xfs_init_attr_trans(args, &tres, &total);
1024
	error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans);
1025
	if (error)
1026
		goto drop_incompat;
L
Linus Torvalds 已提交
1027

1028 1029 1030
	if (args->value || xfs_inode_hasattr(dp)) {
		error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK,
				XFS_IEXT_ATTR_MANIP_CNT(rmt_blks));
1031 1032 1033
		if (error == -EFBIG)
			error = xfs_iext_count_upgrade(args->trans, dp,
					XFS_IEXT_ATTR_MANIP_CNT(rmt_blks));
1034 1035 1036 1037
		if (error)
			goto out_trans_cancel;
	}

D
Dave Chinner 已提交
1038
	error = xfs_attr_lookup(args);
1039 1040 1041 1042 1043 1044 1045 1046 1047
	switch (error) {
	case -EEXIST:
		/* if no value, we are performing a remove operation */
		if (!args->value) {
			error = xfs_attr_defer_remove(args);
			break;
		}
		/* Pure create fails if the attr already exists */
		if (args->attr_flags & XATTR_CREATE)
1048 1049
			goto out_trans_cancel;

1050 1051 1052 1053 1054
		error = xfs_attr_defer_replace(args);
		break;
	case -ENOATTR:
		/* Can't remove what isn't there. */
		if (!args->value)
1055
			goto out_trans_cancel;
1056

1057 1058
		/* Pure replace fails if no existing attr to replace. */
		if (args->attr_flags & XATTR_REPLACE)
1059 1060
			goto out_trans_cancel;

1061 1062 1063 1064
		error = xfs_attr_defer_add(args);
		break;
	default:
		goto out_trans_cancel;
1065
	}
1066 1067
	if (error)
		goto out_trans_cancel;
L
Linus Torvalds 已提交
1068 1069 1070 1071 1072

	/*
	 * If this is a synchronous mount, make sure that the
	 * transaction goes to disk before returning to the user.
	 */
1073
	if (xfs_has_wsync(mp))
1074
		xfs_trans_set_sync(args->trans);
L
Linus Torvalds 已提交
1075

1076
	if (!(args->op_flags & XFS_DA_OP_NOTIME))
1077
		xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG);
1078

L
Linus Torvalds 已提交
1079 1080 1081
	/*
	 * Commit the last in the sequence of transactions.
	 */
1082 1083
	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
	error = xfs_trans_commit(args->trans);
1084
out_unlock:
L
Linus Torvalds 已提交
1085
	xfs_iunlock(dp, XFS_ILOCK_EXCL);
1086 1087 1088
drop_incompat:
	if (delayed)
		xlog_drop_incompat_feat(mp->m_log);
1089
	return error;
L
Linus Torvalds 已提交
1090

1091
out_trans_cancel:
1092 1093
	if (args->trans)
		xfs_trans_cancel(args->trans);
1094
	goto out_unlock;
L
Linus Torvalds 已提交
1095 1096
}

1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
int __init
xfs_attri_init_cache(void)
{
	xfs_attri_cache = kmem_cache_create("xfs_attri",
					    sizeof(struct xfs_attri_log_item),
					    0, 0, NULL);

	return xfs_attri_cache != NULL ? 0 : -ENOMEM;
}

void
xfs_attri_destroy_cache(void)
{
	kmem_cache_destroy(xfs_attri_cache);
	xfs_attri_cache = NULL;
}

int __init
xfs_attrd_init_cache(void)
{
	xfs_attrd_cache = kmem_cache_create("xfs_attrd",
					    sizeof(struct xfs_attrd_log_item),
					    0, 0, NULL);

	return xfs_attrd_cache != NULL ? 0 : -ENOMEM;
}

void
xfs_attrd_destroy_cache(void)
{
	kmem_cache_destroy(xfs_attrd_cache);
	xfs_attrd_cache = NULL;
}

L
Linus Torvalds 已提交
1131 1132 1133 1134
/*========================================================================
 * External routines when attribute list is inside the inode
 *========================================================================*/

1135 1136 1137 1138 1139 1140 1141 1142
static inline int xfs_attr_sf_totsize(struct xfs_inode *dp)
{
	struct xfs_attr_shortform *sf;

	sf = (struct xfs_attr_shortform *)dp->i_afp->if_u1.if_data;
	return be16_to_cpu(sf->hdr.totsize);
}

L
Linus Torvalds 已提交
1143 1144 1145 1146
/*
 * Add a name to the shortform attribute list structure
 * This is the external routine.
 */
1147 1148 1149
static int
xfs_attr_shortform_addname(
	struct xfs_da_args	*args)
L
Linus Torvalds 已提交
1150
{
1151 1152
	int			newsize, forkoff;
	int			error;
L
Linus Torvalds 已提交
1153

1154 1155
	trace_xfs_attr_sf_addname(args);

1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
	error = xfs_attr_shortform_lookup(args);
	switch (error) {
	case -ENOATTR:
		if (args->op_flags & XFS_DA_OP_REPLACE)
			return error;
		break;
	case -EEXIST:
		if (!(args->op_flags & XFS_DA_OP_REPLACE))
			return error;

		error = xfs_attr_sf_removename(args);
		if (error)
			return error;

1170
		/*
1171 1172 1173 1174
		 * Since we have removed the old attr, clear XFS_DA_OP_REPLACE
		 * so that the new attr doesn't fit in shortform format, the
		 * leaf format add routine won't trip over the attr not being
		 * around.
1175
		 */
1176 1177 1178 1179 1180 1181
		args->op_flags &= ~XFS_DA_OP_REPLACE;
		break;
	case 0:
		break;
	default:
		return error;
L
Linus Torvalds 已提交
1182 1183
	}

1184 1185
	if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
	    args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
D
Dave Chinner 已提交
1186
		return -ENOSPC;
1187

1188 1189
	newsize = xfs_attr_sf_totsize(args->dp);
	newsize += xfs_attr_sf_entsize_byname(args->namelen, args->valuelen);
1190 1191 1192

	forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
	if (!forkoff)
D
Dave Chinner 已提交
1193
		return -ENOSPC;
1194 1195

	xfs_attr_shortform_add(args, forkoff);
E
Eric Sandeen 已提交
1196
	return 0;
L
Linus Torvalds 已提交
1197 1198 1199 1200 1201 1202 1203
}


/*========================================================================
 * External routines when attribute list is one block
 *========================================================================*/

1204 1205
/* Save the current remote block info and clear the current pointers. */
static void
1206 1207 1208 1209 1210 1211 1212 1213
xfs_attr_save_rmt_blk(
	struct xfs_da_args	*args)
{
	args->blkno2 = args->blkno;
	args->index2 = args->index;
	args->rmtblkno2 = args->rmtblkno;
	args->rmtblkcnt2 = args->rmtblkcnt;
	args->rmtvaluelen2 = args->rmtvaluelen;
1214 1215 1216
	args->rmtblkno = 0;
	args->rmtblkcnt = 0;
	args->rmtvaluelen = 0;
1217 1218 1219
}

/* Set stored info about a remote block */
1220
static void
1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
xfs_attr_restore_rmt_blk(
	struct xfs_da_args	*args)
{
	args->blkno = args->blkno2;
	args->index = args->index2;
	args->rmtblkno = args->rmtblkno2;
	args->rmtblkcnt = args->rmtblkcnt2;
	args->rmtvaluelen = args->rmtvaluelen2;
}

L
Linus Torvalds 已提交
1231
/*
1232
 * Tries to add an attribute to an inode in leaf form
L
Linus Torvalds 已提交
1233
 *
1234 1235 1236 1237 1238 1239
 * This function is meant to execute as part of a delayed operation and leaves
 * the transaction handling to the caller.  On success the attribute is added
 * and the inode and transaction are left dirty.  If there is not enough space,
 * the attr data is converted to node format and -ENOSPC is returned. Caller is
 * responsible for handling the dirty inode and transaction or adding the attr
 * in node format.
L
Linus Torvalds 已提交
1240
 */
D
David Chinner 已提交
1241
STATIC int
1242 1243 1244
xfs_attr_leaf_try_add(
	struct xfs_da_args	*args,
	struct xfs_buf		*bp)
L
Linus Torvalds 已提交
1245
{
1246
	int			error;
1247

L
Linus Torvalds 已提交
1248
	/*
1249 1250 1251 1252
	 * If the caller provided a buffer to us, it is locked and held in
	 * the transaction because it just did a shortform to leaf conversion.
	 * Hence we don't need to read it again. Otherwise read in the leaf
	 * buffer.
L
Linus Torvalds 已提交
1253
	 */
1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265
	if (bp) {
		xfs_trans_bhold_release(args->trans, bp);
	} else {
		error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp);
		if (error)
			return error;
	}

	/*
	 * Look up the xattr name to set the insertion point for the new xattr.
	 */
	error = xfs_attr3_leaf_lookup_int(bp, args);
1266 1267 1268 1269 1270 1271 1272
	switch (error) {
	case -ENOATTR:
		if (args->op_flags & XFS_DA_OP_REPLACE)
			goto out_brelse;
		break;
	case -EEXIST:
		if (!(args->op_flags & XFS_DA_OP_REPLACE))
1273
			goto out_brelse;
1274 1275

		trace_xfs_attr_leaf_replace(args);
1276
		/*
1277 1278
		 * Save the existing remote attr state so that the current
		 * values reflect the state of the new attribute we are about to
1279 1280
		 * add, not the attribute we just found and will remove later.
		 */
1281 1282 1283 1284 1285 1286
		xfs_attr_save_rmt_blk(args);
		break;
	case 0:
		break;
	default:
		goto out_brelse;
L
Linus Torvalds 已提交
1287 1288
	}

1289 1290
	return xfs_attr3_leaf_add(bp, args);

1291 1292
out_brelse:
	xfs_trans_brelse(args->trans, bp);
1293
	return error;
1294
}
L
Linus Torvalds 已提交
1295

1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
/*
 * Return EEXIST if attr is found, or ENOATTR if not
 */
STATIC int
xfs_attr_leaf_hasname(
	struct xfs_da_args	*args,
	struct xfs_buf		**bp)
{
	int                     error = 0;

	error = xfs_attr3_leaf_read(args->trans, args->dp, 0, bp);
	if (error)
		return error;

	error = xfs_attr3_leaf_lookup_int(*bp, args);
	if (error != -ENOATTR && error != -EEXIST)
		xfs_trans_brelse(args->trans, *bp);

	return error;
}

L
Linus Torvalds 已提交
1317 1318 1319 1320 1321 1322 1323
/*
 * Remove a name from the leaf attribute list structure
 *
 * This leaf block cannot have a "remote" value, we only call this routine
 * if bmap_one_block() says there is only one block (ie: no remote blks).
 */
STATIC int
1324 1325
xfs_attr_leaf_removename(
	struct xfs_da_args	*args)
L
Linus Torvalds 已提交
1326
{
1327 1328 1329
	struct xfs_inode	*dp;
	struct xfs_buf		*bp;
	int			error, forkoff;
L
Linus Torvalds 已提交
1330

1331 1332
	trace_xfs_attr_leaf_removename(args);

L
Linus Torvalds 已提交
1333 1334 1335 1336 1337
	/*
	 * Remove the attribute.
	 */
	dp = args->dp;

1338
	error = xfs_attr_leaf_hasname(args, &bp);
D
Dave Chinner 已提交
1339
	if (error == -ENOATTR) {
1340
		xfs_trans_brelse(args->trans, bp);
1341 1342
		if (args->op_flags & XFS_DA_OP_RECOVERY)
			return 0;
D
Dave Chinner 已提交
1343
		return error;
1344 1345
	} else if (error != -EEXIST)
		return error;
L
Linus Torvalds 已提交
1346

D
Dave Chinner 已提交
1347
	xfs_attr3_leaf_remove(bp, args);
L
Linus Torvalds 已提交
1348 1349 1350 1351

	/*
	 * If the result is small enough, shrink it all into the inode.
	 */
1352 1353 1354
	forkoff = xfs_attr_shortform_allfit(bp, dp);
	if (forkoff)
		return xfs_attr3_leaf_to_shortform(bp, args, forkoff);
L
Linus Torvalds 已提交
1355
		/* bp is gone due to xfs_da_shrink_inode */
1356

D
Dave Chinner 已提交
1357
	return 0;
L
Linus Torvalds 已提交
1358 1359 1360 1361 1362 1363 1364
}

/*
 * Look up a name in a leaf attribute list structure.
 *
 * This leaf block cannot have a "remote" value, we only call this routine
 * if bmap_one_block() says there is only one block (ie: no remote blks).
1365 1366
 *
 * Returns 0 on successful retrieval, otherwise an error.
L
Linus Torvalds 已提交
1367
 */
1368
STATIC int
L
Linus Torvalds 已提交
1369 1370
xfs_attr_leaf_get(xfs_da_args_t *args)
{
1371
	struct xfs_buf *bp;
L
Linus Torvalds 已提交
1372 1373
	int error;

1374 1375
	trace_xfs_attr_leaf_get(args);

1376
	error = xfs_attr_leaf_hasname(args, &bp);
L
Linus Torvalds 已提交
1377

1378
	if (error == -ENOATTR)  {
1379
		xfs_trans_brelse(args->trans, bp);
D
Dave Chinner 已提交
1380
		return error;
1381 1382 1383 1384
	} else if (error != -EEXIST)
		return error;


D
Dave Chinner 已提交
1385
	error = xfs_attr3_leaf_getvalue(bp, args);
1386
	xfs_trans_brelse(args->trans, bp);
1387
	return error;
L
Linus Torvalds 已提交
1388 1389
}

1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404
/*
 * Return EEXIST if attr is found, or ENOATTR if not
 * statep: If not null is set to point at the found state.  Caller will
 *         be responsible for freeing the state in this case.
 */
STATIC int
xfs_attr_node_hasname(
	struct xfs_da_args	*args,
	struct xfs_da_state	**statep)
{
	struct xfs_da_state	*state;
	int			retval, error;

	state = xfs_da_state_alloc(args);
	if (statep != NULL)
1405
		*statep = state;
1406 1407 1408 1409 1410

	/*
	 * Search to see if name exists, and get back a pointer to it.
	 */
	error = xfs_da3_node_lookup_int(state, &retval);
1411 1412
	if (error)
		retval = error;
1413

1414
	if (!statep)
1415
		xfs_da_state_free(state);
1416

1417 1418 1419
	return retval;
}

L
Linus Torvalds 已提交
1420
/*========================================================================
1421
 * External routines when attribute list size > geo->blksize
L
Linus Torvalds 已提交
1422 1423 1424
 *========================================================================*/

STATIC int
1425
xfs_attr_node_addname_find_attr(
1426
	 struct xfs_attr_item	*attr)
L
Linus Torvalds 已提交
1427
{
1428 1429
	struct xfs_da_args	*args = attr->xattri_da_args;
	int			error;
1430

L
Linus Torvalds 已提交
1431 1432 1433 1434
	/*
	 * Search to see if name already exists, and get back a pointer
	 * to where it should go.
	 */
1435 1436 1437 1438 1439 1440 1441 1442
	error = xfs_attr_node_hasname(args, &attr->xattri_da_state);
	switch (error) {
	case -ENOATTR:
		if (args->op_flags & XFS_DA_OP_REPLACE)
			goto error;
		break;
	case -EEXIST:
		if (!(args->op_flags & XFS_DA_OP_REPLACE))
1443
			goto error;
1444

1445

1446
		trace_xfs_attr_node_replace(args);
1447
		/*
1448 1449
		 * Save the existing remote attr state so that the current
		 * values reflect the state of the new attribute we are about to
1450 1451
		 * add, not the attribute we just found and will remove later.
		 */
1452 1453 1454 1455 1456 1457
		xfs_attr_save_rmt_blk(args);
		break;
	case 0:
		break;
	default:
		goto error;
L
Linus Torvalds 已提交
1458 1459
	}

1460 1461
	return 0;
error:
1462
	if (attr->xattri_da_state) {
1463
		xfs_da_state_free(attr->xattri_da_state);
1464 1465
		attr->xattri_da_state = NULL;
	}
1466
	return error;
1467 1468 1469 1470 1471 1472 1473 1474 1475
}

/*
 * Add a name to a Btree-format attribute list.
 *
 * This will involve walking down the Btree, and may involve splitting
 * leaf nodes and even splitting intermediate nodes up to and including
 * the root node (a special case of an intermediate node).
 */
1476 1477
static int
xfs_attr_node_try_addname(
1478
	struct xfs_attr_item		*attr)
1479
{
1480 1481
	struct xfs_da_args		*args = attr->xattri_da_args;
	struct xfs_da_state		*state = attr->xattri_da_state;
1482 1483
	struct xfs_da_state_blk		*blk;
	int				error;
1484 1485 1486 1487 1488 1489

	trace_xfs_attr_node_addname(args);

	blk = &state->path.blk[state->path.active-1];
	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);

1490 1491
	error = xfs_attr3_leaf_add(blk->bp, state->args);
	if (error == -ENOSPC) {
L
Linus Torvalds 已提交
1492 1493 1494 1495
		if (state->path.active == 1) {
			/*
			 * Its really a single leaf node, but it had
			 * out-of-line values so it looked like it *might*
1496
			 * have been a b-tree. Let the caller deal with this.
L
Linus Torvalds 已提交
1497
			 */
1498
			goto out;
L
Linus Torvalds 已提交
1499 1500 1501 1502 1503 1504 1505 1506
		}

		/*
		 * Split as many Btree elements as required.
		 * This code tracks the new and old attr's location
		 * in the index/blkno/rmtblkno/rmtblkcnt fields and
		 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
		 */
1507
		error = xfs_da3_split(state);
1508
		if (error)
1509
			goto out;
L
Linus Torvalds 已提交
1510 1511 1512 1513
	} else {
		/*
		 * Addition succeeded, update Btree hashvals.
		 */
1514
		xfs_da3_fixhashpath(state, &state->path);
L
Linus Torvalds 已提交
1515 1516
	}

1517
out:
1518
	xfs_da_state_free(state);
1519
	attr->xattri_da_state = NULL;
1520
	return error;
1521 1522
}

D
Dave Chinner 已提交
1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540
static int
xfs_attr_node_removename(
	struct xfs_da_args	*args,
	struct xfs_da_state	*state)
{
	struct xfs_da_state_blk	*blk;
	int			retval;

	/*
	 * Remove the name and update the hashvals in the tree.
	 */
	blk = &state->path.blk[state->path.active-1];
	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
	retval = xfs_attr3_leaf_remove(blk->bp, args);
	xfs_da3_fixhashpath(state, &state->path);

	return retval;
}
1541

1542 1543
static int
xfs_attr_node_remove_attr(
1544
	struct xfs_attr_item		*attr)
1545
{
1546
	struct xfs_da_args		*args = attr->xattri_da_args;
1547 1548 1549 1550
	struct xfs_da_state		*state = NULL;
	int				retval = 0;
	int				error = 0;

1551
	/*
1552 1553 1554
	 * The attr we are removing has already been marked incomplete, so
	 * we need to set the filter appropriately to re-find the "old"
	 * attribute entry after any split ops.
1555
	 */
1556
	args->attr_filter |= XFS_ATTR_INCOMPLETE;
1557 1558 1559 1560 1561
	state = xfs_da_state_alloc(args);
	state->inleaf = 0;
	error = xfs_da3_node_lookup_int(state, &retval);
	if (error)
		goto out;
L
Linus Torvalds 已提交
1562

1563
	error = xfs_attr_node_removename(args, state);
L
Linus Torvalds 已提交
1564

1565 1566 1567 1568 1569
	/*
	 * Check to see if the tree needs to be collapsed.
	 */
	if (retval && (state->path.active > 1)) {
		error = xfs_da3_join(state);
L
Linus Torvalds 已提交
1570 1571 1572 1573 1574 1575 1576 1577 1578
		if (error)
			goto out;
	}
	retval = error = 0;

out:
	if (state)
		xfs_da_state_free(state);
	if (error)
E
Eric Sandeen 已提交
1579 1580
		return error;
	return retval;
L
Linus Torvalds 已提交
1581 1582 1583
}

/*
1584
 * Retrieve the attribute data from a node attribute list.
L
Linus Torvalds 已提交
1585 1586 1587 1588
 *
 * This routine gets called for any attribute fork that has more than one
 * block, ie: both true Btree attr lists and for single-leaf-blocks with
 * "remote" values taking up more blocks.
1589 1590
 *
 * Returns 0 on successful retrieval, otherwise an error.
L
Linus Torvalds 已提交
1591
 */
1592
STATIC int
1593 1594
xfs_attr_node_get(
	struct xfs_da_args	*args)
L
Linus Torvalds 已提交
1595
{
1596 1597 1598 1599
	struct xfs_da_state	*state;
	struct xfs_da_state_blk	*blk;
	int			i;
	int			error;
L
Linus Torvalds 已提交
1600

1601 1602
	trace_xfs_attr_node_get(args);

L
Linus Torvalds 已提交
1603 1604 1605
	/*
	 * Search to see if name exists, and get back a pointer to it.
	 */
1606 1607
	error = xfs_attr_node_hasname(args, &state);
	if (error != -EEXIST)
1608 1609 1610 1611 1612 1613
		goto out_release;

	/*
	 * Get the value, local or "remote"
	 */
	blk = &state->path.blk[state->path.active - 1];
1614
	error = xfs_attr3_leaf_getvalue(blk->bp, args);
L
Linus Torvalds 已提交
1615 1616 1617 1618

	/*
	 * If not in a transaction, we have to release all the buffers.
	 */
1619
out_release:
1620
	for (i = 0; state != NULL && i < state->path.active; i++) {
1621
		xfs_trans_brelse(args->trans, state->path.blk[i].bp);
L
Linus Torvalds 已提交
1622 1623 1624
		state->path.blk[i].bp = NULL;
	}

1625 1626 1627
	if (state)
		xfs_da_state_free(state);
	return error;
L
Linus Torvalds 已提交
1628
}
1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645

/* Returns true if the attribute entry name is valid. */
bool
xfs_attr_namecheck(
	const void	*name,
	size_t		length)
{
	/*
	 * MAXNAMELEN includes the trailing null, but (name/length) leave it
	 * out, so use >= for the length check.
	 */
	if (length >= MAXNAMELEN)
		return false;

	/* There shouldn't be any nulls here */
	return !memchr(name, 0, length);
}