xfs_attr.c 42.8 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 62 63
STATIC int xfs_attr_node_addname(struct xfs_attr_item *attr);
STATIC int xfs_attr_node_addname_find_attr(struct xfs_attr_item *attr);
STATIC int xfs_attr_node_addname_clear_incomplete(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
STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
68 69
STATIC int xfs_attr_node_removename(struct xfs_da_args *args,
				    struct xfs_da_state *state);
L
Linus Torvalds 已提交
70

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

82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
/*
 * 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;
}

L
Linus Torvalds 已提交
102 103 104 105
/*========================================================================
 * Overall external interface routines.
 *========================================================================*/

106 107 108 109
/*
 * Retrieve an extended attribute and its value.  Must have ilock.
 * Returns 0 on successful retrieval, otherwise an error.
 */
110 111 112 113
int
xfs_attr_get_ilocked(
	struct xfs_da_args	*args)
{
114
	ASSERT(xfs_isilocked(args->dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
115

116
	if (!xfs_inode_hasattr(args->dp))
117
		return -ENOATTR;
118

119
	if (args->dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
120
		return xfs_attr_shortform_getvalue(args);
121
	if (xfs_attr_is_leaf(args->dp))
122
		return xfs_attr_leaf_get(args);
123
	return xfs_attr_node_get(args);
124 125
}

126 127 128
/*
 * Retrieve an extended attribute by name, and its value if requested.
 *
C
Christoph Hellwig 已提交
129 130 131
 * 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.
132
 *
133 134 135 136 137
 * 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.
 *
138
 * If the attribute is found, but exceeds the size limit set by the caller in
139 140
 * args->valuelen, return -ERANGE with the size of the attribute that was found
 * in args->valuelen.
141
 */
142 143
int
xfs_attr_get(
144
	struct xfs_da_args	*args)
L
Linus Torvalds 已提交
145
{
146 147 148
	uint			lock_mode;
	int			error;

149
	XFS_STATS_INC(args->dp->i_mount, xs_attr_get);
150

151
	if (xfs_is_shutdown(args->dp->i_mount))
D
Dave Chinner 已提交
152
		return -EIO;
L
Linus Torvalds 已提交
153

154 155 156
	args->geo = args->dp->i_mount->m_attr_geo;
	args->whichfork = XFS_ATTR_FORK;
	args->hashval = xfs_da_hashname(args->name, args->namelen);
157

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

161
	lock_mode = xfs_ilock_attr_map_shared(args->dp);
162
	error = xfs_attr_get_ilocked(args);
163
	xfs_iunlock(args->dp, lock_mode);
164

165
	return error;
L
Linus Torvalds 已提交
166 167
}

168 169 170
/*
 * Calculate how many blocks we need for the new attribute,
 */
171
int
172
xfs_attr_calc_size(
173
	struct xfs_da_args	*args,
174 175
	int			*local)
{
176
	struct xfs_mount	*mp = args->dp->i_mount;
177 178 179 180 181 182 183
	int			size;
	int			nblks;

	/*
	 * Determine space new attribute will use, and if it would be
	 * "local" or "remote" (note: local != inline).
	 */
184
	size = xfs_attr_leaf_newentsize(args, local);
185 186
	nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
	if (*local) {
187
		if (size > (args->geo->blksize / 2)) {
188 189 190 191 192 193 194 195
			/* Double split possible */
			nblks *= 2;
		}
	} else {
		/*
		 * Out of line attribute, cannot double split, but
		 * make room for the attribute value itself.
		 */
196
		uint	dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen);
197 198 199 200 201 202 203
		nblks += dblocks;
		nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
	}

	return nblks;
}

204 205 206 207 208 209
STATIC int
xfs_attr_try_sf_addname(
	struct xfs_inode	*dp,
	struct xfs_da_args	*args)
{

210 211 212 213 214 215 216
	int			error;

	/*
	 * Build initial attribute list (if required).
	 */
	if (dp->i_afp->if_format == XFS_DINODE_FMT_EXTENTS)
		xfs_attr_shortform_create(args);
217 218 219 220 221 222 223 224 225

	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).
	 */
226
	if (!error && !(args->op_flags & XFS_DA_OP_NOTIME))
227 228
		xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG);

229
	if (xfs_has_wsync(dp->i_mount))
230 231
		xfs_trans_set_sync(args->trans);

232
	return error;
233 234
}

235 236 237 238 239 240 241 242 243 244 245 246 247 248
/*
 * Check to see if the attr should be upgraded from non-existent or shortform to
 * single-leaf-block attribute list.
 */
static inline bool
xfs_attr_is_shortform(
	struct xfs_inode    *ip)
{
	return ip->i_afp->if_format == XFS_DINODE_FMT_LOCAL ||
	       (ip->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
		ip->i_afp->if_nextents == 0);
}

STATIC int
249
xfs_attr_sf_addname(
250
	struct xfs_attr_item		*attr)
251
{
252
	struct xfs_da_args		*args = attr->xattri_da_args;
253 254
	struct xfs_inode		*dp = args->dp;
	int				error = 0;
255 256 257 258 259

	/*
	 * Try to add the attr to the attribute list in the inode.
	 */
	error = xfs_attr_try_sf_addname(dp, args);
260 261 262 263

	/* Should only be 0, -EEXIST or -ENOSPC */
	if (error != -ENOSPC)
		return error;
264

265 266 267 268
	/*
	 * It won't fit in the shortform, transform to a leaf block.  GROT:
	 * another possible req'mt for a double-split btree op.
	 */
269
	error = xfs_attr_shortform_to_leaf(args, &attr->xattri_leaf_bp);
270 271 272 273 274 275
	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
276
	 * with the write verifier.
277
	 */
278
	xfs_trans_bhold(args->trans, attr->xattri_leaf_bp);
279

280 281 282 283 284
	/*
	 * We're still in XFS_DAS_UNINIT state here.  We've converted
	 * the attr fork to leaf format and will restart with the leaf
	 * add.
	 */
285
	trace_xfs_attr_sf_addname_return(XFS_DAS_UNINIT, args->dp);
286
	return -EAGAIN;
287 288
}

289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
STATIC int
xfs_attr_leaf_addname(
	struct xfs_attr_item	*attr)
{
	struct xfs_da_args	*args = attr->xattri_da_args;
	struct xfs_inode	*dp = args->dp;
	int			error;

	if (xfs_attr_is_leaf(dp)) {
		error = xfs_attr_leaf_try_add(args, attr->xattri_leaf_bp);
		if (error == -ENOSPC) {
			error = xfs_attr3_leaf_to_node(args);
			if (error)
				return error;

			/*
			 * Finish any deferred work items and roll the
			 * transaction once more.  The goal here is to call
			 * node_addname with the inode and transaction in the
			 * same state (inode locked and joined, transaction
			 * clean) no matter how we got to this step.
			 *
			 * At this point, we are still in XFS_DAS_UNINIT, but
			 * when we come back, we'll be a node, so we'll fall
			 * down into the node handling code below
			 */
			trace_xfs_attr_set_iter_return(
				attr->xattri_dela_state, args->dp);
			return -EAGAIN;
		}

		if (error)
			return error;

		attr->xattri_dela_state = XFS_DAS_FOUND_LBLK;
	} else {
		error = xfs_attr_node_addname_find_attr(attr);
		if (error)
			return error;

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

		/*
		 * If addname was successful, and we dont need to alloc or
		 * remove anymore blks, we're done.
		 */
		if (!args->rmtblkno &&
		    !(args->op_flags & XFS_DA_OP_RENAME))
			return 0;

		attr->xattri_dela_state = XFS_DAS_FOUND_NBLK;
	}

	trace_xfs_attr_leaf_addname_return(attr->xattri_dela_state, args->dp);
	return -EAGAIN;
}

348 349
/*
 * Set the attribute specified in @args.
350 351 352 353
 * This routine is meant to function as a delayed operation, and may return
 * -EAGAIN when the transaction needs to be rolled.  Calling functions will need
 * to handle this, and recall the function until a successful error code is
 * returned.
354 355
 */
int
356
xfs_attr_set_iter(
357
	struct xfs_attr_item		*attr)
358
{
359
	struct xfs_da_args              *args = attr->xattri_da_args;
360 361 362
	struct xfs_inode		*dp = args->dp;
	struct xfs_buf			*bp = NULL;
	int				forkoff, error = 0;
363
	struct xfs_mount		*mp = args->dp->i_mount;
364 365

	/* State machine switch */
366
	switch (attr->xattri_dela_state) {
367 368 369 370 371 372 373 374 375
	case XFS_DAS_UNINIT:
		/*
		 * If the fork is shortform, attempt to add the attr. If there
		 * is no space, this converts to leaf format and returns
		 * -EAGAIN with the leaf buffer held across the roll. The caller
		 * will deal with a transaction roll error, but otherwise
		 * release the hold once we return with a clean transaction.
		 */
		if (xfs_attr_is_shortform(dp))
376 377 378 379 380
			return xfs_attr_sf_addname(attr);
		if (attr->xattri_leaf_bp != NULL) {
			xfs_trans_bhold_release(args->trans,
						attr->xattri_leaf_bp);
			attr->xattri_leaf_bp = NULL;
381
		}
382

383
		return xfs_attr_leaf_addname(attr);
384

385
	case XFS_DAS_FOUND_LBLK:
386 387 388 389 390 391
		/*
		 * 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.
		 */
392 393

		/* Open coded xfs_attr_rmtval_set without trans handling */
394 395
		if ((attr->xattri_flags & XFS_DAC_LEAF_ADDNAME_INIT) == 0) {
			attr->xattri_flags |= XFS_DAC_LEAF_ADDNAME_INIT;
396
			if (args->rmtblkno > 0) {
397
				error = xfs_attr_rmtval_find_space(attr);
398 399 400 401 402 403 404 405 406
				if (error)
					return error;
			}
		}

		/*
		 * Repeat allocating remote blocks for the attr value until
		 * blkcnt drops to zero.
		 */
407 408
		if (attr->xattri_blkcnt > 0) {
			error = xfs_attr_rmtval_set_blk(attr);
409 410
			if (error)
				return error;
411
			trace_xfs_attr_set_iter_return(attr->xattri_dela_state,
412
						       args->dp);
413
			return -EAGAIN;
414 415
		}

416 417 418 419 420 421 422 423
		error = xfs_attr_rmtval_set_value(args);
		if (error)
			return error;

		/*
		 * If this is not a rename, clear the incomplete flag and we're
		 * done.
		 */
424 425 426
		if (!(args->op_flags & XFS_DA_OP_RENAME)) {
			if (args->rmtblkno > 0)
				error = xfs_attr3_leaf_clearflag(args);
427
			return error;
428
		}
429

430 431 432 433 434 435 436 437 438
		/*
		 * If this is an atomic rename operation, we must "flip" the
		 * incomplete flags on the "new" and "old" attribute/value pairs
		 * so that one disappears and one appears atomically.  Then we
		 * must remove the "old" attribute/value pair.
		 *
		 * In a separate transaction, set the incomplete flag on the
		 * "old" attr and clear the incomplete flag on the "new" attr.
		 */
439 440 441 442 443 444 445 446
		if (!xfs_has_larp(mp)) {
			error = xfs_attr3_leaf_flipflags(args);
			if (error)
				return error;
			/*
			 * Commit the flag value change and start the next trans
			 * in series.
			 */
447 448
			attr->xattri_dela_state = XFS_DAS_FLIP_LFLAG;
			trace_xfs_attr_set_iter_return(attr->xattri_dela_state,
449 450 451 452 453
						       args->dp);
			return -EAGAIN;
		}

		fallthrough;
454
	case XFS_DAS_FLIP_LFLAG:
455 456 457 458 459
		/*
		 * Dismantle the "old" attribute/value pair by removing a
		 * "remote" value (if it exists).
		 */
		xfs_attr_restore_rmt_blk(args);
460 461 462
		error = xfs_attr_rmtval_invalidate(args);
		if (error)
			return error;
463

464
		fallthrough;
465 466
	case XFS_DAS_RM_LBLK:
		/* Set state in case xfs_attr_rmtval_remove returns -EAGAIN */
467
		attr->xattri_dela_state = XFS_DAS_RM_LBLK;
468
		if (args->rmtblkno) {
469
			error = xfs_attr_rmtval_remove(attr);
470 471
			if (error == -EAGAIN)
				trace_xfs_attr_set_iter_return(
472
					attr->xattri_dela_state, args->dp);
473 474 475
			if (error)
				return error;

476 477 478
			attr->xattri_dela_state = XFS_DAS_RD_LEAF;
			trace_xfs_attr_set_iter_return(attr->xattri_dela_state,
						       args->dp);
479
			return -EAGAIN;
480 481
		}

482
		fallthrough;
483
	case XFS_DAS_RD_LEAF:
484
		/*
485 486 487
		 * This is the last step for leaf format. Read the block with
		 * the old attr, remove the old attr, check for shortform
		 * conversion and return.
488 489 490 491 492 493 494 495 496 497 498 499 500 501
		 */
		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;
502

503 504 505 506 507 508
	case XFS_DAS_FOUND_NBLK:
		/*
		 * Find space for remote blocks and fall into the allocation
		 * state.
		 */
		if (args->rmtblkno > 0) {
509
			error = xfs_attr_rmtval_find_space(attr);
510 511 512
			if (error)
				return error;
		}
513

514
		fallthrough;
515 516 517 518 519 520 521
	case XFS_DAS_ALLOC_NODE:
		/*
		 * 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.
		 */
522
		attr->xattri_dela_state = XFS_DAS_ALLOC_NODE;
523
		if (args->rmtblkno > 0) {
524 525
			if (attr->xattri_blkcnt > 0) {
				error = xfs_attr_rmtval_set_blk(attr);
526 527
				if (error)
					return error;
528
				trace_xfs_attr_set_iter_return(
529
					attr->xattri_dela_state, args->dp);
530 531 532 533 534 535 536
				return -EAGAIN;
			}

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

538 539 540 541 542 543 544 545 546
		/*
		 * If this was not a rename, clear the incomplete flag and we're
		 * done.
		 */
		if (!(args->op_flags & XFS_DA_OP_RENAME)) {
			if (args->rmtblkno > 0)
				error = xfs_attr3_leaf_clearflag(args);
			goto out;
		}
547

548 549 550 551 552 553 554 555 556
		/*
		 * If this is an atomic rename operation, we must "flip" the
		 * incomplete flags on the "new" and "old" attribute/value pairs
		 * so that one disappears and one appears atomically.  Then we
		 * must remove the "old" attribute/value pair.
		 *
		 * In a separate transaction, set the incomplete flag on the
		 * "old" attr and clear the incomplete flag on the "new" attr.
		 */
557 558 559 560 561 562 563 564
		if (!xfs_has_larp(mp)) {
			error = xfs_attr3_leaf_flipflags(args);
			if (error)
				goto out;
			/*
			 * Commit the flag value change and start the next trans
			 * in series
			 */
565 566
			attr->xattri_dela_state = XFS_DAS_FLIP_NFLAG;
			trace_xfs_attr_set_iter_return(attr->xattri_dela_state,
567 568 569
						       args->dp);
			return -EAGAIN;
		}
570

571
		fallthrough;
572 573 574 575 576 577
	case XFS_DAS_FLIP_NFLAG:
		/*
		 * Dismantle the "old" attribute/value pair by removing a
		 * "remote" value (if it exists).
		 */
		xfs_attr_restore_rmt_blk(args);
578 579 580 581 582

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

583
		fallthrough;
584 585
	case XFS_DAS_RM_NBLK:
		/* Set state in case xfs_attr_rmtval_remove returns -EAGAIN */
586
		attr->xattri_dela_state = XFS_DAS_RM_NBLK;
587
		if (args->rmtblkno) {
588
			error = xfs_attr_rmtval_remove(attr);
589 590
			if (error == -EAGAIN)
				trace_xfs_attr_set_iter_return(
591
					attr->xattri_dela_state, args->dp);
592

593 594 595
			if (error)
				return error;

596 597 598
			attr->xattri_dela_state = XFS_DAS_CLR_FLAG;
			trace_xfs_attr_set_iter_return(attr->xattri_dela_state,
						       args->dp);
599 600
			return -EAGAIN;
		}
601

602
		fallthrough;
603 604 605 606 607
	case XFS_DAS_CLR_FLAG:
		/*
		 * The last state for node format. Look up the old attr and
		 * remove it.
		 */
608
		error = xfs_attr_node_addname_clear_incomplete(attr);
609 610
		break;
	default:
611
		ASSERT(0);
612 613
		break;
	}
614
out:
615
	return error;
616 617
}

618

619 620 621
/*
 * Return EEXIST if attr is found, or ENOATTR if not
 */
D
Dave Chinner 已提交
622 623
static int
xfs_attr_lookup(
624 625 626 627 628 629 630 631 632
	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 已提交
633
	if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
634 635
		return xfs_attr_sf_findname(args, NULL, NULL);

636
	if (xfs_attr_is_leaf(dp)) {
637 638 639 640 641 642 643 644 645 646 647
		error = xfs_attr_leaf_hasname(args, &bp);

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

		return error;
	}

	return xfs_attr_node_hasname(args, NULL);
}

648
/*
649
 * Note: If args->value is NULL the attribute will be removed, just like the
650 651
 * Linux ->setattr API.
 */
652 653
int
xfs_attr_set(
654
	struct xfs_da_args	*args)
L
Linus Torvalds 已提交
655
{
656
	struct xfs_inode	*dp = args->dp;
657 658
	struct xfs_mount	*mp = dp->i_mount;
	struct xfs_trans_res	tres;
659
	bool			rsvd = (args->attr_filter & XFS_ATTR_ROOT);
660
	int			error, local;
661
	int			rmt_blks = 0;
662
	unsigned int		total;
663
	int			delayed = xfs_has_larp(mp);
664

665
	if (xfs_is_shutdown(dp->i_mount))
D
Dave Chinner 已提交
666
		return -EIO;
667

668 669 670 671
	error = xfs_qm_dqattach(dp);
	if (error)
		return error;

672 673 674
	args->geo = mp->m_attr_geo;
	args->whichfork = XFS_ATTR_FORK;
	args->hashval = xfs_da_hashname(args->name, args->namelen);
L
Linus Torvalds 已提交
675 676

	/*
677 678 679
	 * 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 已提交
680
	 */
681
	args->op_flags = XFS_DA_OP_OKNOENT;
682

683
	if (args->value) {
684 685
		XFS_STATS_INC(mp, xs_attr_set);

686 687
		args->op_flags |= XFS_DA_OP_ADDNAME;
		args->total = xfs_attr_calc_size(args, &local);
688 689 690 691 692 693 694

		/*
		 * 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) +
695
				xfs_attr_sf_entsize_byname(args->namelen,
696
						args->valuelen);
697 698 699 700 701 702 703

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

		tres.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
704 705
				 M_RES(mp)->tr_attrsetrt.tr_logres *
					args->total;
706 707
		tres.tr_logcount = XFS_ATTRSET_LOG_COUNT;
		tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
708
		total = args->total;
709 710 711

		if (!local)
			rmt_blks = xfs_attr3_rmt_blocks(mp, args->valuelen);
712 713
	} else {
		XFS_STATS_INC(mp, xs_attr_remove);
L
Linus Torvalds 已提交
714

715 716
		tres = M_RES(mp)->tr_attrrm;
		total = XFS_ATTRRM_SPACE_RES(mp);
717
		rmt_blks = xfs_attr3_rmt_blocks(mp, XFS_XATTR_SIZE_MAX);
718
	}
L
Linus Torvalds 已提交
719

720 721 722 723 724 725
	if (delayed) {
		error = xfs_attr_use_log_assist(mp);
		if (error)
			return error;
	}

L
Linus Torvalds 已提交
726 727 728 729
	/*
	 * Root fork attributes can use reserved data blocks for this
	 * operation if necessary
	 */
730
	error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans);
731
	if (error)
732
		goto drop_incompat;
L
Linus Torvalds 已提交
733

734 735 736
	if (args->value || xfs_inode_hasattr(dp)) {
		error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK,
				XFS_IEXT_ATTR_MANIP_CNT(rmt_blks));
737 738 739
		if (error == -EFBIG)
			error = xfs_iext_count_upgrade(args->trans, dp,
					XFS_IEXT_ATTR_MANIP_CNT(rmt_blks));
740 741 742 743
		if (error)
			goto out_trans_cancel;
	}

D
Dave Chinner 已提交
744
	error = xfs_attr_lookup(args);
745
	if (args->value) {
746 747 748 749 750 751 752
		if (error == -EEXIST && (args->attr_flags & XATTR_CREATE))
			goto out_trans_cancel;
		if (error == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
			goto out_trans_cancel;
		if (error != -ENOATTR && error != -EEXIST)
			goto out_trans_cancel;

753
		error = xfs_attr_set_deferred(args);
754 755
		if (error)
			goto out_trans_cancel;
756

757
		/* shortform attribute has already been committed */
758
		if (!args->trans)
759 760
			goto out_unlock;
	} else {
761 762 763
		if (error != -EEXIST)
			goto out_trans_cancel;

764
		error = xfs_attr_remove_deferred(args);
765 766
		if (error)
			goto out_trans_cancel;
767
	}
L
Linus Torvalds 已提交
768 769 770 771 772

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

776
	if (!(args->op_flags & XFS_DA_OP_NOTIME))
777
		xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG);
778

L
Linus Torvalds 已提交
779 780 781
	/*
	 * Commit the last in the sequence of transactions.
	 */
782 783
	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
	error = xfs_trans_commit(args->trans);
784
out_unlock:
L
Linus Torvalds 已提交
785
	xfs_iunlock(dp, XFS_ILOCK_EXCL);
786 787 788
drop_incompat:
	if (delayed)
		xlog_drop_incompat_feat(mp->m_log);
789
	return error;
L
Linus Torvalds 已提交
790

791
out_trans_cancel:
792 793
	if (args->trans)
		xfs_trans_cancel(args->trans);
794
	goto out_unlock;
L
Linus Torvalds 已提交
795 796
}

797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830
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;
}

831 832 833 834 835 836 837 838 839 840 841
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;
842
	new->xattri_da_args = args;
843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882

	*attr = new;
	return 0;
}

/* Sets an attribute for an inode as a deferred operation */
int
xfs_attr_set_deferred(
	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;

	xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);

	return 0;
}

/* Removes an attribute for an inode as a deferred operation */
int
xfs_attr_remove_deferred(
	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;

	xfs_defer_add(args->trans, XFS_DEFER_OPS_TYPE_ATTR, &new->xattri_list);

	return 0;
}

L
Linus Torvalds 已提交
883 884 885 886
/*========================================================================
 * External routines when attribute list is inside the inode
 *========================================================================*/

887 888 889 890 891 892 893 894
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 已提交
895 896 897 898 899 900 901
/*
 * Add a name to the shortform attribute list structure
 * This is the external routine.
 */
STATIC int
xfs_attr_shortform_addname(xfs_da_args_t *args)
{
902
	int newsize, forkoff, retval;
L
Linus Torvalds 已提交
903

904 905
	trace_xfs_attr_sf_addname(args);

L
Linus Torvalds 已提交
906
	retval = xfs_attr_shortform_lookup(args);
907
	if (retval == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
E
Eric Sandeen 已提交
908
		return retval;
909
	if (retval == -EEXIST) {
910
		if (args->attr_flags & XATTR_CREATE)
E
Eric Sandeen 已提交
911
			return retval;
912
		retval = xfs_attr_sf_removename(args);
913 914 915 916 917 918 919
		if (retval)
			return retval;
		/*
		 * Since we have removed the old attr, clear ATTR_REPLACE so
		 * that the leaf format add routine won't trip over the attr
		 * not being around.
		 */
920
		args->attr_flags &= ~XATTR_REPLACE;
L
Linus Torvalds 已提交
921 922
	}

923 924
	if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
	    args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
D
Dave Chinner 已提交
925
		return -ENOSPC;
926

927 928
	newsize = xfs_attr_sf_totsize(args->dp);
	newsize += xfs_attr_sf_entsize_byname(args->namelen, args->valuelen);
929 930 931

	forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
	if (!forkoff)
D
Dave Chinner 已提交
932
		return -ENOSPC;
933 934

	xfs_attr_shortform_add(args, forkoff);
E
Eric Sandeen 已提交
935
	return 0;
L
Linus Torvalds 已提交
936 937 938 939 940 941 942
}


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

943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966
/* Store info about a remote block */
STATIC void
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;
}

/* Set stored info about a remote block */
STATIC void
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 已提交
967
/*
968
 * Tries to add an attribute to an inode in leaf form
L
Linus Torvalds 已提交
969
 *
970 971 972 973 974 975
 * 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 已提交
976
 */
D
David Chinner 已提交
977
STATIC int
978 979 980
xfs_attr_leaf_try_add(
	struct xfs_da_args	*args,
	struct xfs_buf		*bp)
L
Linus Torvalds 已提交
981
{
982
	int			retval;
983

L
Linus Torvalds 已提交
984 985 986 987
	/*
	 * Look up the given attribute in the leaf block.  Figure out if
	 * the given flags produce an error or call for an atomic rename.
	 */
988 989 990
	retval = xfs_attr_leaf_hasname(args, &bp);
	if (retval != -ENOATTR && retval != -EEXIST)
		return retval;
991
	if (retval == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
992 993
		goto out_brelse;
	if (retval == -EEXIST) {
994
		if (args->attr_flags & XATTR_CREATE)
995
			goto out_brelse;
996 997 998

		trace_xfs_attr_leaf_replace(args);

999
		/* save the attribute state for later removal*/
1000
		args->op_flags |= XFS_DA_OP_RENAME;	/* an atomic rename */
1001
		xfs_attr_save_rmt_blk(args);
1002 1003 1004 1005 1006 1007 1008 1009 1010

		/*
		 * clear the remote attr state now that it is saved so that the
		 * values reflect the state of the attribute we are about to
		 * add, not the attribute we just found and will remove later.
		 */
		args->rmtblkno = 0;
		args->rmtblkcnt = 0;
		args->rmtvaluelen = 0;
L
Linus Torvalds 已提交
1011 1012 1013
	}

	/*
1014
	 * Add the attribute to the leaf block
L
Linus Torvalds 已提交
1015
	 */
1016 1017
	return xfs_attr3_leaf_add(bp, args);

1018 1019 1020 1021
out_brelse:
	xfs_trans_brelse(args->trans, bp);
	return retval;
}
L
Linus Torvalds 已提交
1022

1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
/*
 * 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 已提交
1044 1045 1046 1047 1048 1049 1050
/*
 * 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
1051 1052
xfs_attr_leaf_removename(
	struct xfs_da_args	*args)
L
Linus Torvalds 已提交
1053
{
1054 1055 1056
	struct xfs_inode	*dp;
	struct xfs_buf		*bp;
	int			error, forkoff;
L
Linus Torvalds 已提交
1057

1058 1059
	trace_xfs_attr_leaf_removename(args);

L
Linus Torvalds 已提交
1060 1061 1062 1063 1064
	/*
	 * Remove the attribute.
	 */
	dp = args->dp;

1065 1066
	error = xfs_attr_leaf_hasname(args, &bp);

D
Dave Chinner 已提交
1067
	if (error == -ENOATTR) {
1068
		xfs_trans_brelse(args->trans, bp);
D
Dave Chinner 已提交
1069
		return error;
1070 1071
	} else if (error != -EEXIST)
		return error;
L
Linus Torvalds 已提交
1072

D
Dave Chinner 已提交
1073
	xfs_attr3_leaf_remove(bp, args);
L
Linus Torvalds 已提交
1074 1075 1076 1077

	/*
	 * If the result is small enough, shrink it all into the inode.
	 */
1078 1079 1080
	forkoff = xfs_attr_shortform_allfit(bp, dp);
	if (forkoff)
		return xfs_attr3_leaf_to_shortform(bp, args, forkoff);
L
Linus Torvalds 已提交
1081
		/* bp is gone due to xfs_da_shrink_inode */
1082

D
Dave Chinner 已提交
1083
	return 0;
L
Linus Torvalds 已提交
1084 1085 1086 1087 1088 1089 1090
}

/*
 * 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).
1091 1092
 *
 * Returns 0 on successful retrieval, otherwise an error.
L
Linus Torvalds 已提交
1093
 */
1094
STATIC int
L
Linus Torvalds 已提交
1095 1096
xfs_attr_leaf_get(xfs_da_args_t *args)
{
1097
	struct xfs_buf *bp;
L
Linus Torvalds 已提交
1098 1099
	int error;

1100 1101
	trace_xfs_attr_leaf_get(args);

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

1104
	if (error == -ENOATTR)  {
1105
		xfs_trans_brelse(args->trans, bp);
D
Dave Chinner 已提交
1106
		return error;
1107 1108 1109 1110
	} else if (error != -EEXIST)
		return error;


D
Dave Chinner 已提交
1111
	error = xfs_attr3_leaf_getvalue(bp, args);
1112
	xfs_trans_brelse(args->trans, bp);
1113
	return error;
L
Linus Torvalds 已提交
1114 1115
}

1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
/*
 * 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)
1131
		*statep = state;
1132 1133 1134 1135 1136

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

1140
	if (!statep)
1141
		xfs_da_state_free(state);
1142

1143 1144 1145
	return retval;
}

L
Linus Torvalds 已提交
1146
/*========================================================================
1147
 * External routines when attribute list size > geo->blksize
L
Linus Torvalds 已提交
1148 1149 1150
 *========================================================================*/

STATIC int
1151
xfs_attr_node_addname_find_attr(
1152
	 struct xfs_attr_item		*attr)
L
Linus Torvalds 已提交
1153
{
1154
	struct xfs_da_args		*args = attr->xattri_da_args;
1155
	int				retval;
1156

L
Linus Torvalds 已提交
1157 1158 1159 1160
	/*
	 * Search to see if name already exists, and get back a pointer
	 * to where it should go.
	 */
1161
	retval = xfs_attr_node_hasname(args, &attr->xattri_da_state);
1162
	if (retval != -ENOATTR && retval != -EEXIST)
1163
		goto error;
1164

1165
	if (retval == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
1166
		goto error;
1167
	if (retval == -EEXIST) {
1168
		if (args->attr_flags & XATTR_CREATE)
1169
			goto error;
1170 1171 1172

		trace_xfs_attr_node_replace(args);

1173
		/* save the attribute state for later removal*/
1174
		args->op_flags |= XFS_DA_OP_RENAME;	/* atomic rename op */
1175
		xfs_attr_save_rmt_blk(args);
1176 1177 1178 1179 1180 1181

		/*
		 * clear the remote attr state now that it is saved so that the
		 * values reflect the state of the attribute we are about to
		 * add, not the attribute we just found and will remove later.
		 */
L
Linus Torvalds 已提交
1182 1183
		args->rmtblkno = 0;
		args->rmtblkcnt = 0;
1184
		args->rmtvaluelen = 0;
L
Linus Torvalds 已提交
1185 1186
	}

1187 1188
	return 0;
error:
1189 1190
	if (attr->xattri_da_state)
		xfs_da_state_free(attr->xattri_da_state);
1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
	return retval;
}

/*
 * 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).
 *
 * "Remote" attribute values confuse the issue and atomic rename operations
 * add a whole extra layer of confusion on top of that.
1203 1204 1205 1206 1207
 *
 * This routine is meant to function as a delayed operation, and may return
 * -EAGAIN when the transaction needs to be rolled.  Calling functions will need
 * to handle this, and recall the function until a successful error code is
 *returned.
1208 1209 1210
 */
STATIC int
xfs_attr_node_addname(
1211
	struct xfs_attr_item		*attr)
1212
{
1213 1214
	struct xfs_da_args		*args = attr->xattri_da_args;
	struct xfs_da_state		*state = attr->xattri_da_state;
1215 1216
	struct xfs_da_state_blk		*blk;
	int				error;
1217 1218 1219 1220 1221 1222

	trace_xfs_attr_node_addname(args);

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

1223 1224
	error = xfs_attr3_leaf_add(blk->bp, state->args);
	if (error == -ENOSPC) {
L
Linus Torvalds 已提交
1225 1226 1227 1228 1229 1230 1231
		if (state->path.active == 1) {
			/*
			 * Its really a single leaf node, but it had
			 * out-of-line values so it looked like it *might*
			 * have been a b-tree.
			 */
			xfs_da_state_free(state);
1232
			state = NULL;
D
Dave Chinner 已提交
1233
			error = xfs_attr3_leaf_to_node(args);
1234
			if (error)
1235
				goto out;
L
Linus Torvalds 已提交
1236 1237

			/*
1238 1239 1240 1241 1242
			 * Now that we have converted the leaf to a node, we can
			 * roll the transaction, and try xfs_attr3_leaf_add
			 * again on re-entry.  No need to set dela_state to do
			 * this. dela_state is still unset by this function at
			 * this point.
L
Linus Torvalds 已提交
1243
			 */
1244
			trace_xfs_attr_node_addname_return(
1245
					attr->xattri_dela_state, args->dp);
1246
			return -EAGAIN;
L
Linus Torvalds 已提交
1247 1248 1249 1250 1251 1252 1253 1254
		}

		/*
		 * 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.
		 */
1255
		error = xfs_da3_split(state);
1256
		if (error)
1257
			goto out;
L
Linus Torvalds 已提交
1258 1259 1260 1261
	} else {
		/*
		 * Addition succeeded, update Btree hashvals.
		 */
1262
		xfs_da3_fixhashpath(state, &state->path);
L
Linus Torvalds 已提交
1263 1264
	}

1265 1266 1267
out:
	if (state)
		xfs_da_state_free(state);
1268
	return error;
1269 1270 1271 1272 1273
}


STATIC int
xfs_attr_node_addname_clear_incomplete(
1274
	struct xfs_attr_item		*attr)
1275
{
1276
	struct xfs_da_args		*args = attr->xattri_da_args;
1277
	struct xfs_da_state		*state = NULL;
1278
	struct xfs_mount		*mp = args->dp->i_mount;
1279 1280 1281
	int				retval = 0;
	int				error = 0;

1282 1283 1284 1285
	/*
	 * Re-find the "old" attribute entry after any split ops. The INCOMPLETE
	 * flag means that we will find the "old" attr, not the "new" one.
	 */
1286 1287
	if (!xfs_has_larp(mp))
		args->attr_filter |= XFS_ATTR_INCOMPLETE;
1288 1289 1290 1291 1292
	state = xfs_da_state_alloc(args);
	state->inleaf = 0;
	error = xfs_da3_node_lookup_int(state, &retval);
	if (error)
		goto out;
L
Linus Torvalds 已提交
1293

1294
	error = xfs_attr_node_removename(args, state);
L
Linus Torvalds 已提交
1295

1296 1297 1298 1299 1300
	/*
	 * Check to see if the tree needs to be collapsed.
	 */
	if (retval && (state->path.active > 1)) {
		error = xfs_da3_join(state);
L
Linus Torvalds 已提交
1301 1302 1303 1304 1305 1306 1307 1308 1309
		if (error)
			goto out;
	}
	retval = error = 0;

out:
	if (state)
		xfs_da_state_free(state);
	if (error)
E
Eric Sandeen 已提交
1310 1311
		return error;
	return retval;
L
Linus Torvalds 已提交
1312 1313
}

1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
/*
 * Shrink an attribute from leaf to shortform
 */
STATIC int
xfs_attr_node_shrink(
	struct xfs_da_args	*args,
	struct xfs_da_state     *state)
{
	struct xfs_inode	*dp = args->dp;
	int			error, forkoff;
	struct xfs_buf		*bp;

	/*
	 * Have to get rid of the copy of this dabuf in the state.
	 */
	ASSERT(state->path.active == 1);
	ASSERT(state->path.blk[0].bp);
	state->path.blk[0].bp = NULL;

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

1344
	return error;
1345 1346
}

1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372
/*
 * 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);
}

1373 1374 1375 1376 1377 1378 1379
/*
 * 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(
1380
	struct xfs_attr_item		*attr)
1381
{
1382 1383
	struct xfs_da_args		*args = attr->xattri_da_args;
	struct xfs_da_state		**state = &attr->xattri_da_state;
1384
	int				error;
1385 1386 1387

	error = xfs_attr_node_hasname(args, state);
	if (error != -EEXIST)
1388
		goto out;
1389
	error = 0;
1390 1391 1392 1393 1394 1395 1396 1397

	ASSERT((*state)->path.blk[(*state)->path.active - 1].bp != NULL);
	ASSERT((*state)->path.blk[(*state)->path.active - 1].magic ==
		XFS_ATTR_LEAF_MAGIC);

	if (args->rmtblkno > 0) {
		error = xfs_attr_leaf_mark_incomplete(args, *state);
		if (error)
1398
			goto out;
1399

1400
		error = xfs_attr_rmtval_invalidate(args);
1401
	}
1402 1403 1404
out:
	if (error)
		xfs_da_state_free(*state);
1405

1406
	return error;
1407 1408
}

1409
STATIC int
1410
xfs_attr_node_removename(
1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
	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;
}

L
Linus Torvalds 已提交
1428
/*
1429
 * Remove the attribute specified in @args.
L
Linus Torvalds 已提交
1430 1431 1432 1433
 *
 * This will involve walking down the Btree, and may involve joining
 * leaf nodes and even joining intermediate nodes up to and including
 * the root node (a special case of an intermediate node).
1434 1435 1436 1437 1438
 *
 * This routine is meant to function as either an in-line or delayed operation,
 * and may return -EAGAIN when the transaction needs to be rolled.  Calling
 * functions will need to handle this, and call the function until a
 * successful error code is returned.
L
Linus Torvalds 已提交
1439
 */
1440 1441
int
xfs_attr_remove_iter(
1442
	struct xfs_attr_item		*attr)
L
Linus Torvalds 已提交
1443
{
1444 1445
	struct xfs_da_args		*args = attr->xattri_da_args;
	struct xfs_da_state		*state = attr->xattri_da_state;
1446
	int				retval, error = 0;
1447
	struct xfs_inode		*dp = args->dp;
L
Linus Torvalds 已提交
1448

1449 1450
	trace_xfs_attr_node_removename(args);

1451
	switch (attr->xattri_dela_state) {
1452 1453 1454
	case XFS_DAS_UNINIT:
		if (!xfs_inode_hasattr(dp))
			return -ENOATTR;
L
Linus Torvalds 已提交
1455

1456 1457 1458 1459 1460
		/*
		 * Shortform or leaf formats don't require transaction rolls and
		 * thus state transitions. Call the right helper and return.
		 */
		if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
1461
			return xfs_attr_sf_removename(args);
1462 1463 1464

		if (xfs_attr_is_leaf(dp))
			return xfs_attr_leaf_removename(args);
1465 1466

		/*
1467 1468
		 * Node format may require transaction rolls. Set up the
		 * state context and fall into the state machine.
1469
		 */
1470 1471
		if (!attr->xattri_da_state) {
			error = xfs_attr_node_removename_setup(attr);
1472 1473
			if (error)
				return error;
1474
			state = attr->xattri_da_state;
1475 1476
		}

1477
		fallthrough;
1478
	case XFS_DAS_RMTBLK:
1479
		attr->xattri_dela_state = XFS_DAS_RMTBLK;
L
Linus Torvalds 已提交
1480 1481

		/*
1482 1483 1484 1485
		 * If there is an out-of-line value, de-allocate the blocks.
		 * This is done before we remove the attribute so that we don't
		 * overflow the maximum size of a transaction and/or hit a
		 * deadlock.
L
Linus Torvalds 已提交
1486
		 */
1487 1488 1489 1490 1491
		if (args->rmtblkno > 0) {
			/*
			 * May return -EAGAIN. Roll and repeat until all remote
			 * blocks are removed.
			 */
1492
			error = xfs_attr_rmtval_remove(attr);
1493 1494
			if (error == -EAGAIN) {
				trace_xfs_attr_remove_iter_return(
1495
					attr->xattri_dela_state, args->dp);
1496
				return error;
1497
			} else if (error) {
1498
				goto out;
1499
			}
L
Linus Torvalds 已提交
1500

1501 1502 1503 1504 1505 1506 1507 1508 1509
			/*
			 * Refill the state structure with buffers (the prior
			 * calls released our buffers) and close out this
			 * transaction before proceeding.
			 */
			ASSERT(args->rmtblkno == 0);
			error = xfs_attr_refillstate(state);
			if (error)
				goto out;
1510 1511 1512 1513

			attr->xattri_dela_state = XFS_DAS_RM_NAME;
			trace_xfs_attr_remove_iter_return(
					attr->xattri_dela_state, args->dp);
1514 1515 1516
			return -EAGAIN;
		}

1517
		fallthrough;
1518 1519 1520 1521 1522
	case XFS_DAS_RM_NAME:
		/*
		 * If we came here fresh from a transaction roll, reattach all
		 * the buffers to the current transaction.
		 */
1523
		if (attr->xattri_dela_state == XFS_DAS_RM_NAME) {
1524 1525 1526 1527
			error = xfs_attr_refillstate(state);
			if (error)
				goto out;
		}
L
Linus Torvalds 已提交
1528

1529
		retval = xfs_attr_node_removename(args, state);
1530 1531 1532 1533 1534 1535 1536 1537 1538 1539

		/*
		 * Check to see if the tree needs to be collapsed. If so, roll
		 * the transacton and fall into the shrink state.
		 */
		if (retval && (state->path.active > 1)) {
			error = xfs_da3_join(state);
			if (error)
				goto out;

1540
			attr->xattri_dela_state = XFS_DAS_RM_SHRINK;
1541
			trace_xfs_attr_remove_iter_return(
1542
					attr->xattri_dela_state, args->dp);
1543 1544 1545
			return -EAGAIN;
		}

1546
		fallthrough;
1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561
	case XFS_DAS_RM_SHRINK:
		/*
		 * If the result is small enough, push it all into the inode.
		 * This is our final state so it's safe to return a dirty
		 * transaction.
		 */
		if (xfs_attr_is_leaf(dp))
			error = xfs_attr_node_shrink(args, state);
		ASSERT(error != -EAGAIN);
		break;
	default:
		ASSERT(0);
		error = -EINVAL;
		goto out;
	}
L
Linus Torvalds 已提交
1562
out:
1563 1564
	if (state)
		xfs_da_state_free(state);
E
Eric Sandeen 已提交
1565
	return error;
L
Linus Torvalds 已提交
1566 1567 1568 1569 1570 1571
}

/*
 * 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
1572
 * after some set of transaction commits have released these buffers.
L
Linus Torvalds 已提交
1573 1574 1575 1576 1577 1578 1579 1580
 */
STATIC int
xfs_attr_fillstate(xfs_da_state_t *state)
{
	xfs_da_state_path_t *path;
	xfs_da_state_blk_t *blk;
	int level;

1581 1582
	trace_xfs_attr_fillstate(state->args);

L
Linus Torvalds 已提交
1583 1584 1585 1586 1587 1588 1589 1590
	/*
	 * 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) {
D
Dave Chinner 已提交
1591
			blk->disk_blkno = xfs_buf_daddr(blk->bp);
L
Linus Torvalds 已提交
1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605
			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) {
D
Dave Chinner 已提交
1606
			blk->disk_blkno = xfs_buf_daddr(blk->bp);
L
Linus Torvalds 已提交
1607 1608 1609 1610 1611 1612
			blk->bp = NULL;
		} else {
			blk->disk_blkno = 0;
		}
	}

E
Eric Sandeen 已提交
1613
	return 0;
L
Linus Torvalds 已提交
1614 1615 1616 1617 1618
}

/*
 * Reattach the buffers to the state structure based on the disk block
 * numbers stored in the state structure.
1619
 * This is done after some set of transaction commits have released those
L
Linus Torvalds 已提交
1620 1621 1622 1623 1624 1625 1626 1627 1628
 * 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;

1629 1630
	trace_xfs_attr_refillstate(state->args);

L
Linus Torvalds 已提交
1631 1632 1633 1634 1635 1636 1637 1638
	/*
	 * 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) {
C
Christoph Hellwig 已提交
1639 1640 1641
			error = xfs_da3_node_read_mapped(state->args->trans,
					state->args->dp, blk->disk_blkno,
					&blk->bp, XFS_ATTR_FORK);
L
Linus Torvalds 已提交
1642
			if (error)
E
Eric Sandeen 已提交
1643
				return error;
L
Linus Torvalds 已提交
1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656
		} 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) {
C
Christoph Hellwig 已提交
1657 1658 1659
			error = xfs_da3_node_read_mapped(state->args->trans,
					state->args->dp, blk->disk_blkno,
					&blk->bp, XFS_ATTR_FORK);
L
Linus Torvalds 已提交
1660
			if (error)
E
Eric Sandeen 已提交
1661
				return error;
L
Linus Torvalds 已提交
1662 1663 1664 1665 1666
		} else {
			blk->bp = NULL;
		}
	}

E
Eric Sandeen 已提交
1667
	return 0;
L
Linus Torvalds 已提交
1668 1669 1670
}

/*
1671
 * Retrieve the attribute data from a node attribute list.
L
Linus Torvalds 已提交
1672 1673 1674 1675
 *
 * 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.
1676 1677
 *
 * Returns 0 on successful retrieval, otherwise an error.
L
Linus Torvalds 已提交
1678
 */
1679
STATIC int
1680 1681
xfs_attr_node_get(
	struct xfs_da_args	*args)
L
Linus Torvalds 已提交
1682
{
1683 1684 1685 1686
	struct xfs_da_state	*state;
	struct xfs_da_state_blk	*blk;
	int			i;
	int			error;
L
Linus Torvalds 已提交
1687

1688 1689
	trace_xfs_attr_node_get(args);

L
Linus Torvalds 已提交
1690 1691 1692
	/*
	 * Search to see if name exists, and get back a pointer to it.
	 */
1693 1694
	error = xfs_attr_node_hasname(args, &state);
	if (error != -EEXIST)
1695 1696 1697 1698 1699 1700
		goto out_release;

	/*
	 * Get the value, local or "remote"
	 */
	blk = &state->path.blk[state->path.active - 1];
1701
	error = xfs_attr3_leaf_getvalue(blk->bp, args);
L
Linus Torvalds 已提交
1702 1703 1704 1705

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

1712 1713 1714
	if (state)
		xfs_da_state_free(state);
	return error;
L
Linus Torvalds 已提交
1715
}
1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732

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