1 /*
2  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 
19 #include "xfs.h"
20 #include "xfs_fs.h"
21 #include "xfs_types.h"
22 #include "xfs_bit.h"
23 #include "xfs_log.h"
24 #include "xfs_inum.h"
25 #include "xfs_trans.h"
26 #include "xfs_sb.h"
27 #include "xfs_ag.h"
28 #include "xfs_mount.h"
29 #include "xfs_da_btree.h"
30 #include "xfs_bmap_btree.h"
31 #include "xfs_attr_sf.h"
32 #include "xfs_dinode.h"
33 #include "xfs_inode.h"
34 #include "xfs_alloc.h"
35 #include "xfs_inode_item.h"
36 #include "xfs_bmap.h"
37 #include "xfs_attr.h"
38 #include "xfs_attr_leaf.h"
39 #include "xfs_error.h"
40 #include "xfs_quota.h"
41 #include "xfs_trans_space.h"
42 #include "xfs_rw.h"
43 #include "xfs_vnodeops.h"
44 #include "xfs_trace.h"
45 
46 /*
47  * xfs_attr.c
48  *
49  * Provide the external interfaces to manage attribute lists.
50  */
51 
52 /*========================================================================
53  * Function prototypes for the kernel.
54  *========================================================================*/
55 
56 /*
57  * Internal routines when attribute list fits inside the inode.
58  */
59 STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
60 
61 /*
62  * Internal routines when attribute list is one block.
63  */
64 STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
65 STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
66 STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
67 STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context);
68 
69 /*
70  * Internal routines when attribute list is more than one block.
71  */
72 STATIC int xfs_attr_node_get(xfs_da_args_t *args);
73 STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
74 STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
75 STATIC int xfs_attr_node_list(xfs_attr_list_context_t *context);
76 STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
77 STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
78 
79 /*
80  * Routines to manipulate out-of-line attribute values.
81  */
82 STATIC int xfs_attr_rmtval_set(xfs_da_args_t *args);
83 STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args);
84 
85 #define ATTR_RMTVALUE_MAPSIZE	1	/* # of map entries at once */
86 
87 STATIC int
xfs_attr_name_to_xname(struct xfs_name * xname,const unsigned char * aname)88 xfs_attr_name_to_xname(
89 	struct xfs_name	*xname,
90 	const unsigned char *aname)
91 {
92 	if (!aname)
93 		return EINVAL;
94 	xname->name = aname;
95 	xname->len = strlen((char *)aname);
96 	if (xname->len >= MAXNAMELEN)
97 		return EFAULT;		/* match IRIX behaviour */
98 
99 	return 0;
100 }
101 
102 STATIC int
xfs_inode_hasattr(struct xfs_inode * ip)103 xfs_inode_hasattr(
104 	struct xfs_inode	*ip)
105 {
106 	if (!XFS_IFORK_Q(ip) ||
107 	    (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
108 	     ip->i_d.di_anextents == 0))
109 		return 0;
110 	return 1;
111 }
112 
113 /*========================================================================
114  * Overall external interface routines.
115  *========================================================================*/
116 
117 STATIC int
xfs_attr_get_int(struct xfs_inode * ip,struct xfs_name * name,unsigned char * value,int * valuelenp,int flags)118 xfs_attr_get_int(
119 	struct xfs_inode	*ip,
120 	struct xfs_name		*name,
121 	unsigned char		*value,
122 	int			*valuelenp,
123 	int			flags)
124 {
125 	xfs_da_args_t   args;
126 	int             error;
127 
128 	if (!xfs_inode_hasattr(ip))
129 		return ENOATTR;
130 
131 	/*
132 	 * Fill in the arg structure for this request.
133 	 */
134 	memset((char *)&args, 0, sizeof(args));
135 	args.name = name->name;
136 	args.namelen = name->len;
137 	args.value = value;
138 	args.valuelen = *valuelenp;
139 	args.flags = flags;
140 	args.hashval = xfs_da_hashname(args.name, args.namelen);
141 	args.dp = ip;
142 	args.whichfork = XFS_ATTR_FORK;
143 
144 	/*
145 	 * Decide on what work routines to call based on the inode size.
146 	 */
147 	if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
148 		error = xfs_attr_shortform_getvalue(&args);
149 	} else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) {
150 		error = xfs_attr_leaf_get(&args);
151 	} else {
152 		error = xfs_attr_node_get(&args);
153 	}
154 
155 	/*
156 	 * Return the number of bytes in the value to the caller.
157 	 */
158 	*valuelenp = args.valuelen;
159 
160 	if (error == EEXIST)
161 		error = 0;
162 	return(error);
163 }
164 
165 int
xfs_attr_get(xfs_inode_t * ip,const unsigned char * name,unsigned char * value,int * valuelenp,int flags)166 xfs_attr_get(
167 	xfs_inode_t	*ip,
168 	const unsigned char *name,
169 	unsigned char	*value,
170 	int		*valuelenp,
171 	int		flags)
172 {
173 	int		error;
174 	struct xfs_name	xname;
175 
176 	XFS_STATS_INC(xs_attr_get);
177 
178 	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
179 		return(EIO);
180 
181 	error = xfs_attr_name_to_xname(&xname, name);
182 	if (error)
183 		return error;
184 
185 	xfs_ilock(ip, XFS_ILOCK_SHARED);
186 	error = xfs_attr_get_int(ip, &xname, value, valuelenp, flags);
187 	xfs_iunlock(ip, XFS_ILOCK_SHARED);
188 	return(error);
189 }
190 
191 /*
192  * Calculate how many blocks we need for the new attribute,
193  */
194 STATIC int
xfs_attr_calc_size(struct xfs_inode * ip,int namelen,int valuelen,int * local)195 xfs_attr_calc_size(
196 	struct xfs_inode 	*ip,
197 	int			namelen,
198 	int			valuelen,
199 	int			*local)
200 {
201 	struct xfs_mount 	*mp = ip->i_mount;
202 	int			size;
203 	int			nblks;
204 
205 	/*
206 	 * Determine space new attribute will use, and if it would be
207 	 * "local" or "remote" (note: local != inline).
208 	 */
209 	size = xfs_attr_leaf_newentsize(namelen, valuelen,
210 					mp->m_sb.sb_blocksize, local);
211 
212 	nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
213 	if (*local) {
214 		if (size > (mp->m_sb.sb_blocksize >> 1)) {
215 			/* Double split possible */
216 			nblks *= 2;
217 		}
218 	} else {
219 		/*
220 		 * Out of line attribute, cannot double split, but
221 		 * make room for the attribute value itself.
222 		 */
223 		uint	dblocks = XFS_B_TO_FSB(mp, valuelen);
224 		nblks += dblocks;
225 		nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
226 	}
227 
228 	return nblks;
229 }
230 
231 STATIC int
xfs_attr_set_int(struct xfs_inode * dp,struct xfs_name * name,unsigned char * value,int valuelen,int flags)232 xfs_attr_set_int(
233 	struct xfs_inode *dp,
234 	struct xfs_name	*name,
235 	unsigned char	*value,
236 	int		valuelen,
237 	int		flags)
238 {
239 	xfs_da_args_t	args;
240 	xfs_fsblock_t	firstblock;
241 	xfs_bmap_free_t flist;
242 	int		error, err2, committed;
243 	xfs_mount_t	*mp = dp->i_mount;
244 	int             rsvd = (flags & ATTR_ROOT) != 0;
245 	int		local;
246 
247 	/*
248 	 * Attach the dquots to the inode.
249 	 */
250 	error = xfs_qm_dqattach(dp, 0);
251 	if (error)
252 		return error;
253 
254 	/*
255 	 * If the inode doesn't have an attribute fork, add one.
256 	 * (inode must not be locked when we call this routine)
257 	 */
258 	if (XFS_IFORK_Q(dp) == 0) {
259 		int sf_size = sizeof(xfs_attr_sf_hdr_t) +
260 			      XFS_ATTR_SF_ENTSIZE_BYNAME(name->len, valuelen);
261 
262 		if ((error = xfs_bmap_add_attrfork(dp, sf_size, rsvd)))
263 			return(error);
264 	}
265 
266 	/*
267 	 * Fill in the arg structure for this request.
268 	 */
269 	memset((char *)&args, 0, sizeof(args));
270 	args.name = name->name;
271 	args.namelen = name->len;
272 	args.value = value;
273 	args.valuelen = valuelen;
274 	args.flags = flags;
275 	args.hashval = xfs_da_hashname(args.name, args.namelen);
276 	args.dp = dp;
277 	args.firstblock = &firstblock;
278 	args.flist = &flist;
279 	args.whichfork = XFS_ATTR_FORK;
280 	args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
281 
282 	/* Size is now blocks for attribute data */
283 	args.total = xfs_attr_calc_size(dp, name->len, valuelen, &local);
284 
285 	/*
286 	 * Start our first transaction of the day.
287 	 *
288 	 * All future transactions during this code must be "chained" off
289 	 * this one via the trans_dup() call.  All transactions will contain
290 	 * the inode, and the inode will always be marked with trans_ihold().
291 	 * Since the inode will be locked in all transactions, we must log
292 	 * the inode in every transaction to let it float upward through
293 	 * the log.
294 	 */
295 	args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_SET);
296 
297 	/*
298 	 * Root fork attributes can use reserved data blocks for this
299 	 * operation if necessary
300 	 */
301 
302 	if (rsvd)
303 		args.trans->t_flags |= XFS_TRANS_RESERVE;
304 
305 	if ((error = xfs_trans_reserve(args.trans, args.total,
306 			XFS_ATTRSET_LOG_RES(mp, args.total), 0,
307 			XFS_TRANS_PERM_LOG_RES, XFS_ATTRSET_LOG_COUNT))) {
308 		xfs_trans_cancel(args.trans, 0);
309 		return(error);
310 	}
311 	xfs_ilock(dp, XFS_ILOCK_EXCL);
312 
313 	error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0,
314 				rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
315 				       XFS_QMOPT_RES_REGBLKS);
316 	if (error) {
317 		xfs_iunlock(dp, XFS_ILOCK_EXCL);
318 		xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES);
319 		return (error);
320 	}
321 
322 	xfs_trans_ijoin(args.trans, dp, 0);
323 
324 	/*
325 	 * If the attribute list is non-existent or a shortform list,
326 	 * upgrade it to a single-leaf-block attribute list.
327 	 */
328 	if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) ||
329 	    ((dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) &&
330 	     (dp->i_d.di_anextents == 0))) {
331 
332 		/*
333 		 * Build initial attribute list (if required).
334 		 */
335 		if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
336 			xfs_attr_shortform_create(&args);
337 
338 		/*
339 		 * Try to add the attr to the attribute list in
340 		 * the inode.
341 		 */
342 		error = xfs_attr_shortform_addname(&args);
343 		if (error != ENOSPC) {
344 			/*
345 			 * Commit the shortform mods, and we're done.
346 			 * NOTE: this is also the error path (EEXIST, etc).
347 			 */
348 			ASSERT(args.trans != NULL);
349 
350 			/*
351 			 * If this is a synchronous mount, make sure that
352 			 * the transaction goes to disk before returning
353 			 * to the user.
354 			 */
355 			if (mp->m_flags & XFS_MOUNT_WSYNC) {
356 				xfs_trans_set_sync(args.trans);
357 			}
358 
359 			if (!error && (flags & ATTR_KERNOTIME) == 0) {
360 				xfs_trans_ichgtime(args.trans, dp,
361 							XFS_ICHGTIME_CHG);
362 			}
363 			err2 = xfs_trans_commit(args.trans,
364 						 XFS_TRANS_RELEASE_LOG_RES);
365 			xfs_iunlock(dp, XFS_ILOCK_EXCL);
366 
367 			return(error == 0 ? err2 : error);
368 		}
369 
370 		/*
371 		 * It won't fit in the shortform, transform to a leaf block.
372 		 * GROT: another possible req'mt for a double-split btree op.
373 		 */
374 		xfs_bmap_init(args.flist, args.firstblock);
375 		error = xfs_attr_shortform_to_leaf(&args);
376 		if (!error) {
377 			error = xfs_bmap_finish(&args.trans, args.flist,
378 						&committed);
379 		}
380 		if (error) {
381 			ASSERT(committed);
382 			args.trans = NULL;
383 			xfs_bmap_cancel(&flist);
384 			goto out;
385 		}
386 
387 		/*
388 		 * bmap_finish() may have committed the last trans and started
389 		 * a new one.  We need the inode to be in all transactions.
390 		 */
391 		if (committed)
392 			xfs_trans_ijoin(args.trans, dp, 0);
393 
394 		/*
395 		 * Commit the leaf transformation.  We'll need another (linked)
396 		 * transaction to add the new attribute to the leaf.
397 		 */
398 
399 		error = xfs_trans_roll(&args.trans, dp);
400 		if (error)
401 			goto out;
402 
403 	}
404 
405 	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
406 		error = xfs_attr_leaf_addname(&args);
407 	} else {
408 		error = xfs_attr_node_addname(&args);
409 	}
410 	if (error) {
411 		goto out;
412 	}
413 
414 	/*
415 	 * If this is a synchronous mount, make sure that the
416 	 * transaction goes to disk before returning to the user.
417 	 */
418 	if (mp->m_flags & XFS_MOUNT_WSYNC) {
419 		xfs_trans_set_sync(args.trans);
420 	}
421 
422 	if ((flags & ATTR_KERNOTIME) == 0)
423 		xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
424 
425 	/*
426 	 * Commit the last in the sequence of transactions.
427 	 */
428 	xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
429 	error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
430 	xfs_iunlock(dp, XFS_ILOCK_EXCL);
431 
432 	return(error);
433 
434 out:
435 	if (args.trans)
436 		xfs_trans_cancel(args.trans,
437 			XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
438 	xfs_iunlock(dp, XFS_ILOCK_EXCL);
439 	return(error);
440 }
441 
442 int
xfs_attr_set(xfs_inode_t * dp,const unsigned char * name,unsigned char * value,int valuelen,int flags)443 xfs_attr_set(
444 	xfs_inode_t	*dp,
445 	const unsigned char *name,
446 	unsigned char	*value,
447 	int		valuelen,
448 	int		flags)
449 {
450 	int             error;
451 	struct xfs_name	xname;
452 
453 	XFS_STATS_INC(xs_attr_set);
454 
455 	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
456 		return (EIO);
457 
458 	error = xfs_attr_name_to_xname(&xname, name);
459 	if (error)
460 		return error;
461 
462 	return xfs_attr_set_int(dp, &xname, value, valuelen, flags);
463 }
464 
465 /*
466  * Generic handler routine to remove a name from an attribute list.
467  * Transitions attribute list from Btree to shortform as necessary.
468  */
469 STATIC int
xfs_attr_remove_int(xfs_inode_t * dp,struct xfs_name * name,int flags)470 xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
471 {
472 	xfs_da_args_t	args;
473 	xfs_fsblock_t	firstblock;
474 	xfs_bmap_free_t	flist;
475 	int		error;
476 	xfs_mount_t	*mp = dp->i_mount;
477 
478 	/*
479 	 * Fill in the arg structure for this request.
480 	 */
481 	memset((char *)&args, 0, sizeof(args));
482 	args.name = name->name;
483 	args.namelen = name->len;
484 	args.flags = flags;
485 	args.hashval = xfs_da_hashname(args.name, args.namelen);
486 	args.dp = dp;
487 	args.firstblock = &firstblock;
488 	args.flist = &flist;
489 	args.total = 0;
490 	args.whichfork = XFS_ATTR_FORK;
491 
492 	/*
493 	 * we have no control over the attribute names that userspace passes us
494 	 * to remove, so we have to allow the name lookup prior to attribute
495 	 * removal to fail.
496 	 */
497 	args.op_flags = XFS_DA_OP_OKNOENT;
498 
499 	/*
500 	 * Attach the dquots to the inode.
501 	 */
502 	error = xfs_qm_dqattach(dp, 0);
503 	if (error)
504 		return error;
505 
506 	/*
507 	 * Start our first transaction of the day.
508 	 *
509 	 * All future transactions during this code must be "chained" off
510 	 * this one via the trans_dup() call.  All transactions will contain
511 	 * the inode, and the inode will always be marked with trans_ihold().
512 	 * Since the inode will be locked in all transactions, we must log
513 	 * the inode in every transaction to let it float upward through
514 	 * the log.
515 	 */
516 	args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_RM);
517 
518 	/*
519 	 * Root fork attributes can use reserved data blocks for this
520 	 * operation if necessary
521 	 */
522 
523 	if (flags & ATTR_ROOT)
524 		args.trans->t_flags |= XFS_TRANS_RESERVE;
525 
526 	if ((error = xfs_trans_reserve(args.trans,
527 				      XFS_ATTRRM_SPACE_RES(mp),
528 				      XFS_ATTRRM_LOG_RES(mp),
529 				      0, XFS_TRANS_PERM_LOG_RES,
530 				      XFS_ATTRRM_LOG_COUNT))) {
531 		xfs_trans_cancel(args.trans, 0);
532 		return(error);
533 	}
534 
535 	xfs_ilock(dp, XFS_ILOCK_EXCL);
536 	/*
537 	 * No need to make quota reservations here. We expect to release some
538 	 * blocks not allocate in the common case.
539 	 */
540 	xfs_trans_ijoin(args.trans, dp, 0);
541 
542 	/*
543 	 * Decide on what work routines to call based on the inode size.
544 	 */
545 	if (!xfs_inode_hasattr(dp)) {
546 		error = XFS_ERROR(ENOATTR);
547 		goto out;
548 	}
549 	if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
550 		ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
551 		error = xfs_attr_shortform_remove(&args);
552 		if (error) {
553 			goto out;
554 		}
555 	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
556 		error = xfs_attr_leaf_removename(&args);
557 	} else {
558 		error = xfs_attr_node_removename(&args);
559 	}
560 	if (error) {
561 		goto out;
562 	}
563 
564 	/*
565 	 * If this is a synchronous mount, make sure that the
566 	 * transaction goes to disk before returning to the user.
567 	 */
568 	if (mp->m_flags & XFS_MOUNT_WSYNC) {
569 		xfs_trans_set_sync(args.trans);
570 	}
571 
572 	if ((flags & ATTR_KERNOTIME) == 0)
573 		xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
574 
575 	/*
576 	 * Commit the last in the sequence of transactions.
577 	 */
578 	xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
579 	error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
580 	xfs_iunlock(dp, XFS_ILOCK_EXCL);
581 
582 	return(error);
583 
584 out:
585 	if (args.trans)
586 		xfs_trans_cancel(args.trans,
587 			XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
588 	xfs_iunlock(dp, XFS_ILOCK_EXCL);
589 	return(error);
590 }
591 
592 int
xfs_attr_remove(xfs_inode_t * dp,const unsigned char * name,int flags)593 xfs_attr_remove(
594 	xfs_inode_t	*dp,
595 	const unsigned char *name,
596 	int		flags)
597 {
598 	int		error;
599 	struct xfs_name	xname;
600 
601 	XFS_STATS_INC(xs_attr_remove);
602 
603 	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
604 		return (EIO);
605 
606 	error = xfs_attr_name_to_xname(&xname, name);
607 	if (error)
608 		return error;
609 
610 	xfs_ilock(dp, XFS_ILOCK_SHARED);
611 	if (!xfs_inode_hasattr(dp)) {
612 		xfs_iunlock(dp, XFS_ILOCK_SHARED);
613 		return XFS_ERROR(ENOATTR);
614 	}
615 	xfs_iunlock(dp, XFS_ILOCK_SHARED);
616 
617 	return xfs_attr_remove_int(dp, &xname, flags);
618 }
619 
620 int
xfs_attr_list_int(xfs_attr_list_context_t * context)621 xfs_attr_list_int(xfs_attr_list_context_t *context)
622 {
623 	int error;
624 	xfs_inode_t *dp = context->dp;
625 
626 	XFS_STATS_INC(xs_attr_list);
627 
628 	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
629 		return EIO;
630 
631 	xfs_ilock(dp, XFS_ILOCK_SHARED);
632 
633 	/*
634 	 * Decide on what work routines to call based on the inode size.
635 	 */
636 	if (!xfs_inode_hasattr(dp)) {
637 		error = 0;
638 	} else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
639 		error = xfs_attr_shortform_list(context);
640 	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
641 		error = xfs_attr_leaf_list(context);
642 	} else {
643 		error = xfs_attr_node_list(context);
644 	}
645 
646 	xfs_iunlock(dp, XFS_ILOCK_SHARED);
647 
648 	return error;
649 }
650 
651 #define	ATTR_ENTBASESIZE		/* minimum bytes used by an attr */ \
652 	(((struct attrlist_ent *) 0)->a_name - (char *) 0)
653 #define	ATTR_ENTSIZE(namelen)		/* actual bytes used by an attr */ \
654 	((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(u_int32_t)-1) \
655 	 & ~(sizeof(u_int32_t)-1))
656 
657 /*
658  * Format an attribute and copy it out to the user's buffer.
659  * Take care to check values and protect against them changing later,
660  * we may be reading them directly out of a user buffer.
661  */
662 /*ARGSUSED*/
663 STATIC int
xfs_attr_put_listent(xfs_attr_list_context_t * context,int flags,unsigned char * name,int namelen,int valuelen,unsigned char * value)664 xfs_attr_put_listent(
665 	xfs_attr_list_context_t *context,
666 	int		flags,
667 	unsigned char	*name,
668 	int		namelen,
669 	int		valuelen,
670 	unsigned char	*value)
671 {
672 	struct attrlist *alist = (struct attrlist *)context->alist;
673 	attrlist_ent_t *aep;
674 	int arraytop;
675 
676 	ASSERT(!(context->flags & ATTR_KERNOVAL));
677 	ASSERT(context->count >= 0);
678 	ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
679 	ASSERT(context->firstu >= sizeof(*alist));
680 	ASSERT(context->firstu <= context->bufsize);
681 
682 	/*
683 	 * Only list entries in the right namespace.
684 	 */
685 	if (((context->flags & ATTR_SECURE) == 0) !=
686 	    ((flags & XFS_ATTR_SECURE) == 0))
687 		return 0;
688 	if (((context->flags & ATTR_ROOT) == 0) !=
689 	    ((flags & XFS_ATTR_ROOT) == 0))
690 		return 0;
691 
692 	arraytop = sizeof(*alist) +
693 			context->count * sizeof(alist->al_offset[0]);
694 	context->firstu -= ATTR_ENTSIZE(namelen);
695 	if (context->firstu < arraytop) {
696 		trace_xfs_attr_list_full(context);
697 		alist->al_more = 1;
698 		context->seen_enough = 1;
699 		return 1;
700 	}
701 
702 	aep = (attrlist_ent_t *)&context->alist[context->firstu];
703 	aep->a_valuelen = valuelen;
704 	memcpy(aep->a_name, name, namelen);
705 	aep->a_name[namelen] = 0;
706 	alist->al_offset[context->count++] = context->firstu;
707 	alist->al_count = context->count;
708 	trace_xfs_attr_list_add(context);
709 	return 0;
710 }
711 
712 /*
713  * Generate a list of extended attribute names and optionally
714  * also value lengths.  Positive return value follows the XFS
715  * convention of being an error, zero or negative return code
716  * is the length of the buffer returned (negated), indicating
717  * success.
718  */
719 int
xfs_attr_list(xfs_inode_t * dp,char * buffer,int bufsize,int flags,attrlist_cursor_kern_t * cursor)720 xfs_attr_list(
721 	xfs_inode_t	*dp,
722 	char		*buffer,
723 	int		bufsize,
724 	int		flags,
725 	attrlist_cursor_kern_t *cursor)
726 {
727 	xfs_attr_list_context_t context;
728 	struct attrlist *alist;
729 	int error;
730 
731 	/*
732 	 * Validate the cursor.
733 	 */
734 	if (cursor->pad1 || cursor->pad2)
735 		return(XFS_ERROR(EINVAL));
736 	if ((cursor->initted == 0) &&
737 	    (cursor->hashval || cursor->blkno || cursor->offset))
738 		return XFS_ERROR(EINVAL);
739 
740 	/*
741 	 * Check for a properly aligned buffer.
742 	 */
743 	if (((long)buffer) & (sizeof(int)-1))
744 		return XFS_ERROR(EFAULT);
745 	if (flags & ATTR_KERNOVAL)
746 		bufsize = 0;
747 
748 	/*
749 	 * Initialize the output buffer.
750 	 */
751 	memset(&context, 0, sizeof(context));
752 	context.dp = dp;
753 	context.cursor = cursor;
754 	context.resynch = 1;
755 	context.flags = flags;
756 	context.alist = buffer;
757 	context.bufsize = (bufsize & ~(sizeof(int)-1));  /* align */
758 	context.firstu = context.bufsize;
759 	context.put_listent = xfs_attr_put_listent;
760 
761 	alist = (struct attrlist *)context.alist;
762 	alist->al_count = 0;
763 	alist->al_more = 0;
764 	alist->al_offset[0] = context.bufsize;
765 
766 	error = xfs_attr_list_int(&context);
767 	ASSERT(error >= 0);
768 	return error;
769 }
770 
771 int								/* error */
xfs_attr_inactive(xfs_inode_t * dp)772 xfs_attr_inactive(xfs_inode_t *dp)
773 {
774 	xfs_trans_t *trans;
775 	xfs_mount_t *mp;
776 	int error;
777 
778 	mp = dp->i_mount;
779 	ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
780 
781 	xfs_ilock(dp, XFS_ILOCK_SHARED);
782 	if (!xfs_inode_hasattr(dp) ||
783 	    dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
784 		xfs_iunlock(dp, XFS_ILOCK_SHARED);
785 		return 0;
786 	}
787 	xfs_iunlock(dp, XFS_ILOCK_SHARED);
788 
789 	/*
790 	 * Start our first transaction of the day.
791 	 *
792 	 * All future transactions during this code must be "chained" off
793 	 * this one via the trans_dup() call.  All transactions will contain
794 	 * the inode, and the inode will always be marked with trans_ihold().
795 	 * Since the inode will be locked in all transactions, we must log
796 	 * the inode in every transaction to let it float upward through
797 	 * the log.
798 	 */
799 	trans = xfs_trans_alloc(mp, XFS_TRANS_ATTRINVAL);
800 	if ((error = xfs_trans_reserve(trans, 0, XFS_ATTRINVAL_LOG_RES(mp), 0,
801 				      XFS_TRANS_PERM_LOG_RES,
802 				      XFS_ATTRINVAL_LOG_COUNT))) {
803 		xfs_trans_cancel(trans, 0);
804 		return(error);
805 	}
806 	xfs_ilock(dp, XFS_ILOCK_EXCL);
807 
808 	/*
809 	 * No need to make quota reservations here. We expect to release some
810 	 * blocks, not allocate, in the common case.
811 	 */
812 	xfs_trans_ijoin(trans, dp, 0);
813 
814 	/*
815 	 * Decide on what work routines to call based on the inode size.
816 	 */
817 	if (!xfs_inode_hasattr(dp) ||
818 	    dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
819 		error = 0;
820 		goto out;
821 	}
822 	error = xfs_attr_root_inactive(&trans, dp);
823 	if (error)
824 		goto out;
825 
826 	error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK, 0);
827 	if (error)
828 		goto out;
829 
830 	error = xfs_trans_commit(trans, XFS_TRANS_RELEASE_LOG_RES);
831 	xfs_iunlock(dp, XFS_ILOCK_EXCL);
832 
833 	return(error);
834 
835 out:
836 	xfs_trans_cancel(trans, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
837 	xfs_iunlock(dp, XFS_ILOCK_EXCL);
838 	return(error);
839 }
840 
841 
842 
843 /*========================================================================
844  * External routines when attribute list is inside the inode
845  *========================================================================*/
846 
847 /*
848  * Add a name to the shortform attribute list structure
849  * This is the external routine.
850  */
851 STATIC int
xfs_attr_shortform_addname(xfs_da_args_t * args)852 xfs_attr_shortform_addname(xfs_da_args_t *args)
853 {
854 	int newsize, forkoff, retval;
855 
856 	retval = xfs_attr_shortform_lookup(args);
857 	if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
858 		return(retval);
859 	} else if (retval == EEXIST) {
860 		if (args->flags & ATTR_CREATE)
861 			return(retval);
862 		retval = xfs_attr_shortform_remove(args);
863 		ASSERT(retval == 0);
864 	}
865 
866 	if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
867 	    args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
868 		return(XFS_ERROR(ENOSPC));
869 
870 	newsize = XFS_ATTR_SF_TOTSIZE(args->dp);
871 	newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen);
872 
873 	forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
874 	if (!forkoff)
875 		return(XFS_ERROR(ENOSPC));
876 
877 	xfs_attr_shortform_add(args, forkoff);
878 	return(0);
879 }
880 
881 
882 /*========================================================================
883  * External routines when attribute list is one block
884  *========================================================================*/
885 
886 /*
887  * Add a name to the leaf attribute list structure
888  *
889  * This leaf block cannot have a "remote" value, we only call this routine
890  * if bmap_one_block() says there is only one block (ie: no remote blks).
891  */
892 STATIC int
xfs_attr_leaf_addname(xfs_da_args_t * args)893 xfs_attr_leaf_addname(xfs_da_args_t *args)
894 {
895 	xfs_inode_t *dp;
896 	xfs_dabuf_t *bp;
897 	int retval, error, committed, forkoff;
898 
899 	/*
900 	 * Read the (only) block in the attribute list in.
901 	 */
902 	dp = args->dp;
903 	args->blkno = 0;
904 	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
905 					     XFS_ATTR_FORK);
906 	if (error)
907 		return(error);
908 	ASSERT(bp != NULL);
909 
910 	/*
911 	 * Look up the given attribute in the leaf block.  Figure out if
912 	 * the given flags produce an error or call for an atomic rename.
913 	 */
914 	retval = xfs_attr_leaf_lookup_int(bp, args);
915 	if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
916 		xfs_da_brelse(args->trans, bp);
917 		return(retval);
918 	} else if (retval == EEXIST) {
919 		if (args->flags & ATTR_CREATE) {	/* pure create op */
920 			xfs_da_brelse(args->trans, bp);
921 			return(retval);
922 		}
923 		args->op_flags |= XFS_DA_OP_RENAME;	/* an atomic rename */
924 		args->blkno2 = args->blkno;		/* set 2nd entry info*/
925 		args->index2 = args->index;
926 		args->rmtblkno2 = args->rmtblkno;
927 		args->rmtblkcnt2 = args->rmtblkcnt;
928 	}
929 
930 	/*
931 	 * Add the attribute to the leaf block, transitioning to a Btree
932 	 * if required.
933 	 */
934 	retval = xfs_attr_leaf_add(bp, args);
935 	xfs_da_buf_done(bp);
936 	if (retval == ENOSPC) {
937 		/*
938 		 * Promote the attribute list to the Btree format, then
939 		 * Commit that transaction so that the node_addname() call
940 		 * can manage its own transactions.
941 		 */
942 		xfs_bmap_init(args->flist, args->firstblock);
943 		error = xfs_attr_leaf_to_node(args);
944 		if (!error) {
945 			error = xfs_bmap_finish(&args->trans, args->flist,
946 						&committed);
947 		}
948 		if (error) {
949 			ASSERT(committed);
950 			args->trans = NULL;
951 			xfs_bmap_cancel(args->flist);
952 			return(error);
953 		}
954 
955 		/*
956 		 * bmap_finish() may have committed the last trans and started
957 		 * a new one.  We need the inode to be in all transactions.
958 		 */
959 		if (committed)
960 			xfs_trans_ijoin(args->trans, dp, 0);
961 
962 		/*
963 		 * Commit the current trans (including the inode) and start
964 		 * a new one.
965 		 */
966 		error = xfs_trans_roll(&args->trans, dp);
967 		if (error)
968 			return (error);
969 
970 		/*
971 		 * Fob the whole rest of the problem off on the Btree code.
972 		 */
973 		error = xfs_attr_node_addname(args);
974 		return(error);
975 	}
976 
977 	/*
978 	 * Commit the transaction that added the attr name so that
979 	 * later routines can manage their own transactions.
980 	 */
981 	error = xfs_trans_roll(&args->trans, dp);
982 	if (error)
983 		return (error);
984 
985 	/*
986 	 * If there was an out-of-line value, allocate the blocks we
987 	 * identified for its storage and copy the value.  This is done
988 	 * after we create the attribute so that we don't overflow the
989 	 * maximum size of a transaction and/or hit a deadlock.
990 	 */
991 	if (args->rmtblkno > 0) {
992 		error = xfs_attr_rmtval_set(args);
993 		if (error)
994 			return(error);
995 	}
996 
997 	/*
998 	 * If this is an atomic rename operation, we must "flip" the
999 	 * incomplete flags on the "new" and "old" attribute/value pairs
1000 	 * so that one disappears and one appears atomically.  Then we
1001 	 * must remove the "old" attribute/value pair.
1002 	 */
1003 	if (args->op_flags & XFS_DA_OP_RENAME) {
1004 		/*
1005 		 * In a separate transaction, set the incomplete flag on the
1006 		 * "old" attr and clear the incomplete flag on the "new" attr.
1007 		 */
1008 		error = xfs_attr_leaf_flipflags(args);
1009 		if (error)
1010 			return(error);
1011 
1012 		/*
1013 		 * Dismantle the "old" attribute/value pair by removing
1014 		 * a "remote" value (if it exists).
1015 		 */
1016 		args->index = args->index2;
1017 		args->blkno = args->blkno2;
1018 		args->rmtblkno = args->rmtblkno2;
1019 		args->rmtblkcnt = args->rmtblkcnt2;
1020 		if (args->rmtblkno) {
1021 			error = xfs_attr_rmtval_remove(args);
1022 			if (error)
1023 				return(error);
1024 		}
1025 
1026 		/*
1027 		 * Read in the block containing the "old" attr, then
1028 		 * remove the "old" attr from that block (neat, huh!)
1029 		 */
1030 		error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1,
1031 						     &bp, XFS_ATTR_FORK);
1032 		if (error)
1033 			return(error);
1034 		ASSERT(bp != NULL);
1035 		(void)xfs_attr_leaf_remove(bp, args);
1036 
1037 		/*
1038 		 * If the result is small enough, shrink it all into the inode.
1039 		 */
1040 		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1041 			xfs_bmap_init(args->flist, args->firstblock);
1042 			error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1043 			/* bp is gone due to xfs_da_shrink_inode */
1044 			if (!error) {
1045 				error = xfs_bmap_finish(&args->trans,
1046 							args->flist,
1047 							&committed);
1048 			}
1049 			if (error) {
1050 				ASSERT(committed);
1051 				args->trans = NULL;
1052 				xfs_bmap_cancel(args->flist);
1053 				return(error);
1054 			}
1055 
1056 			/*
1057 			 * bmap_finish() may have committed the last trans
1058 			 * and started a new one.  We need the inode to be
1059 			 * in all transactions.
1060 			 */
1061 			if (committed)
1062 				xfs_trans_ijoin(args->trans, dp, 0);
1063 		} else
1064 			xfs_da_buf_done(bp);
1065 
1066 		/*
1067 		 * Commit the remove and start the next trans in series.
1068 		 */
1069 		error = xfs_trans_roll(&args->trans, dp);
1070 
1071 	} else if (args->rmtblkno > 0) {
1072 		/*
1073 		 * Added a "remote" value, just clear the incomplete flag.
1074 		 */
1075 		error = xfs_attr_leaf_clearflag(args);
1076 	}
1077 	return(error);
1078 }
1079 
1080 /*
1081  * Remove a name from the leaf attribute list structure
1082  *
1083  * This leaf block cannot have a "remote" value, we only call this routine
1084  * if bmap_one_block() says there is only one block (ie: no remote blks).
1085  */
1086 STATIC int
xfs_attr_leaf_removename(xfs_da_args_t * args)1087 xfs_attr_leaf_removename(xfs_da_args_t *args)
1088 {
1089 	xfs_inode_t *dp;
1090 	xfs_dabuf_t *bp;
1091 	int error, committed, forkoff;
1092 
1093 	/*
1094 	 * Remove the attribute.
1095 	 */
1096 	dp = args->dp;
1097 	args->blkno = 0;
1098 	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
1099 					     XFS_ATTR_FORK);
1100 	if (error) {
1101 		return(error);
1102 	}
1103 
1104 	ASSERT(bp != NULL);
1105 	error = xfs_attr_leaf_lookup_int(bp, args);
1106 	if (error == ENOATTR) {
1107 		xfs_da_brelse(args->trans, bp);
1108 		return(error);
1109 	}
1110 
1111 	(void)xfs_attr_leaf_remove(bp, args);
1112 
1113 	/*
1114 	 * If the result is small enough, shrink it all into the inode.
1115 	 */
1116 	if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1117 		xfs_bmap_init(args->flist, args->firstblock);
1118 		error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1119 		/* bp is gone due to xfs_da_shrink_inode */
1120 		if (!error) {
1121 			error = xfs_bmap_finish(&args->trans, args->flist,
1122 						&committed);
1123 		}
1124 		if (error) {
1125 			ASSERT(committed);
1126 			args->trans = NULL;
1127 			xfs_bmap_cancel(args->flist);
1128 			return(error);
1129 		}
1130 
1131 		/*
1132 		 * bmap_finish() may have committed the last trans and started
1133 		 * a new one.  We need the inode to be in all transactions.
1134 		 */
1135 		if (committed)
1136 			xfs_trans_ijoin(args->trans, dp, 0);
1137 	} else
1138 		xfs_da_buf_done(bp);
1139 	return(0);
1140 }
1141 
1142 /*
1143  * Look up a name in a leaf attribute list structure.
1144  *
1145  * This leaf block cannot have a "remote" value, we only call this routine
1146  * if bmap_one_block() says there is only one block (ie: no remote blks).
1147  */
1148 STATIC int
xfs_attr_leaf_get(xfs_da_args_t * args)1149 xfs_attr_leaf_get(xfs_da_args_t *args)
1150 {
1151 	xfs_dabuf_t *bp;
1152 	int error;
1153 
1154 	args->blkno = 0;
1155 	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
1156 					     XFS_ATTR_FORK);
1157 	if (error)
1158 		return(error);
1159 	ASSERT(bp != NULL);
1160 
1161 	error = xfs_attr_leaf_lookup_int(bp, args);
1162 	if (error != EEXIST)  {
1163 		xfs_da_brelse(args->trans, bp);
1164 		return(error);
1165 	}
1166 	error = xfs_attr_leaf_getvalue(bp, args);
1167 	xfs_da_brelse(args->trans, bp);
1168 	if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) {
1169 		error = xfs_attr_rmtval_get(args);
1170 	}
1171 	return(error);
1172 }
1173 
1174 /*
1175  * Copy out attribute entries for attr_list(), for leaf attribute lists.
1176  */
1177 STATIC int
xfs_attr_leaf_list(xfs_attr_list_context_t * context)1178 xfs_attr_leaf_list(xfs_attr_list_context_t *context)
1179 {
1180 	xfs_attr_leafblock_t *leaf;
1181 	int error;
1182 	xfs_dabuf_t *bp;
1183 
1184 	context->cursor->blkno = 0;
1185 	error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK);
1186 	if (error)
1187 		return XFS_ERROR(error);
1188 	ASSERT(bp != NULL);
1189 	leaf = bp->data;
1190 	if (unlikely(leaf->hdr.info.magic != cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) {
1191 		XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW,
1192 				     context->dp->i_mount, leaf);
1193 		xfs_da_brelse(NULL, bp);
1194 		return XFS_ERROR(EFSCORRUPTED);
1195 	}
1196 
1197 	error = xfs_attr_leaf_list_int(bp, context);
1198 	xfs_da_brelse(NULL, bp);
1199 	return XFS_ERROR(error);
1200 }
1201 
1202 
1203 /*========================================================================
1204  * External routines when attribute list size > XFS_LBSIZE(mp).
1205  *========================================================================*/
1206 
1207 /*
1208  * Add a name to a Btree-format attribute list.
1209  *
1210  * This will involve walking down the Btree, and may involve splitting
1211  * leaf nodes and even splitting intermediate nodes up to and including
1212  * the root node (a special case of an intermediate node).
1213  *
1214  * "Remote" attribute values confuse the issue and atomic rename operations
1215  * add a whole extra layer of confusion on top of that.
1216  */
1217 STATIC int
xfs_attr_node_addname(xfs_da_args_t * args)1218 xfs_attr_node_addname(xfs_da_args_t *args)
1219 {
1220 	xfs_da_state_t *state;
1221 	xfs_da_state_blk_t *blk;
1222 	xfs_inode_t *dp;
1223 	xfs_mount_t *mp;
1224 	int committed, retval, error;
1225 
1226 	/*
1227 	 * Fill in bucket of arguments/results/context to carry around.
1228 	 */
1229 	dp = args->dp;
1230 	mp = dp->i_mount;
1231 restart:
1232 	state = xfs_da_state_alloc();
1233 	state->args = args;
1234 	state->mp = mp;
1235 	state->blocksize = state->mp->m_sb.sb_blocksize;
1236 	state->node_ents = state->mp->m_attr_node_ents;
1237 
1238 	/*
1239 	 * Search to see if name already exists, and get back a pointer
1240 	 * to where it should go.
1241 	 */
1242 	error = xfs_da_node_lookup_int(state, &retval);
1243 	if (error)
1244 		goto out;
1245 	blk = &state->path.blk[ state->path.active-1 ];
1246 	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1247 	if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
1248 		goto out;
1249 	} else if (retval == EEXIST) {
1250 		if (args->flags & ATTR_CREATE)
1251 			goto out;
1252 		args->op_flags |= XFS_DA_OP_RENAME;	/* atomic rename op */
1253 		args->blkno2 = args->blkno;		/* set 2nd entry info*/
1254 		args->index2 = args->index;
1255 		args->rmtblkno2 = args->rmtblkno;
1256 		args->rmtblkcnt2 = args->rmtblkcnt;
1257 		args->rmtblkno = 0;
1258 		args->rmtblkcnt = 0;
1259 	}
1260 
1261 	retval = xfs_attr_leaf_add(blk->bp, state->args);
1262 	if (retval == ENOSPC) {
1263 		if (state->path.active == 1) {
1264 			/*
1265 			 * Its really a single leaf node, but it had
1266 			 * out-of-line values so it looked like it *might*
1267 			 * have been a b-tree.
1268 			 */
1269 			xfs_da_state_free(state);
1270 			xfs_bmap_init(args->flist, args->firstblock);
1271 			error = xfs_attr_leaf_to_node(args);
1272 			if (!error) {
1273 				error = xfs_bmap_finish(&args->trans,
1274 							args->flist,
1275 							&committed);
1276 			}
1277 			if (error) {
1278 				ASSERT(committed);
1279 				args->trans = NULL;
1280 				xfs_bmap_cancel(args->flist);
1281 				goto out;
1282 			}
1283 
1284 			/*
1285 			 * bmap_finish() may have committed the last trans
1286 			 * and started a new one.  We need the inode to be
1287 			 * in all transactions.
1288 			 */
1289 			if (committed)
1290 				xfs_trans_ijoin(args->trans, dp, 0);
1291 
1292 			/*
1293 			 * Commit the node conversion and start the next
1294 			 * trans in the chain.
1295 			 */
1296 			error = xfs_trans_roll(&args->trans, dp);
1297 			if (error)
1298 				goto out;
1299 
1300 			goto restart;
1301 		}
1302 
1303 		/*
1304 		 * Split as many Btree elements as required.
1305 		 * This code tracks the new and old attr's location
1306 		 * in the index/blkno/rmtblkno/rmtblkcnt fields and
1307 		 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
1308 		 */
1309 		xfs_bmap_init(args->flist, args->firstblock);
1310 		error = xfs_da_split(state);
1311 		if (!error) {
1312 			error = xfs_bmap_finish(&args->trans, args->flist,
1313 						&committed);
1314 		}
1315 		if (error) {
1316 			ASSERT(committed);
1317 			args->trans = NULL;
1318 			xfs_bmap_cancel(args->flist);
1319 			goto out;
1320 		}
1321 
1322 		/*
1323 		 * bmap_finish() may have committed the last trans and started
1324 		 * a new one.  We need the inode to be in all transactions.
1325 		 */
1326 		if (committed)
1327 			xfs_trans_ijoin(args->trans, dp, 0);
1328 	} else {
1329 		/*
1330 		 * Addition succeeded, update Btree hashvals.
1331 		 */
1332 		xfs_da_fixhashpath(state, &state->path);
1333 	}
1334 
1335 	/*
1336 	 * Kill the state structure, we're done with it and need to
1337 	 * allow the buffers to come back later.
1338 	 */
1339 	xfs_da_state_free(state);
1340 	state = NULL;
1341 
1342 	/*
1343 	 * Commit the leaf addition or btree split and start the next
1344 	 * trans in the chain.
1345 	 */
1346 	error = xfs_trans_roll(&args->trans, dp);
1347 	if (error)
1348 		goto out;
1349 
1350 	/*
1351 	 * If there was an out-of-line value, allocate the blocks we
1352 	 * identified for its storage and copy the value.  This is done
1353 	 * after we create the attribute so that we don't overflow the
1354 	 * maximum size of a transaction and/or hit a deadlock.
1355 	 */
1356 	if (args->rmtblkno > 0) {
1357 		error = xfs_attr_rmtval_set(args);
1358 		if (error)
1359 			return(error);
1360 	}
1361 
1362 	/*
1363 	 * If this is an atomic rename operation, we must "flip" the
1364 	 * incomplete flags on the "new" and "old" attribute/value pairs
1365 	 * so that one disappears and one appears atomically.  Then we
1366 	 * must remove the "old" attribute/value pair.
1367 	 */
1368 	if (args->op_flags & XFS_DA_OP_RENAME) {
1369 		/*
1370 		 * In a separate transaction, set the incomplete flag on the
1371 		 * "old" attr and clear the incomplete flag on the "new" attr.
1372 		 */
1373 		error = xfs_attr_leaf_flipflags(args);
1374 		if (error)
1375 			goto out;
1376 
1377 		/*
1378 		 * Dismantle the "old" attribute/value pair by removing
1379 		 * a "remote" value (if it exists).
1380 		 */
1381 		args->index = args->index2;
1382 		args->blkno = args->blkno2;
1383 		args->rmtblkno = args->rmtblkno2;
1384 		args->rmtblkcnt = args->rmtblkcnt2;
1385 		if (args->rmtblkno) {
1386 			error = xfs_attr_rmtval_remove(args);
1387 			if (error)
1388 				return(error);
1389 		}
1390 
1391 		/*
1392 		 * Re-find the "old" attribute entry after any split ops.
1393 		 * The INCOMPLETE flag means that we will find the "old"
1394 		 * attr, not the "new" one.
1395 		 */
1396 		args->flags |= XFS_ATTR_INCOMPLETE;
1397 		state = xfs_da_state_alloc();
1398 		state->args = args;
1399 		state->mp = mp;
1400 		state->blocksize = state->mp->m_sb.sb_blocksize;
1401 		state->node_ents = state->mp->m_attr_node_ents;
1402 		state->inleaf = 0;
1403 		error = xfs_da_node_lookup_int(state, &retval);
1404 		if (error)
1405 			goto out;
1406 
1407 		/*
1408 		 * Remove the name and update the hashvals in the tree.
1409 		 */
1410 		blk = &state->path.blk[ state->path.active-1 ];
1411 		ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1412 		error = xfs_attr_leaf_remove(blk->bp, args);
1413 		xfs_da_fixhashpath(state, &state->path);
1414 
1415 		/*
1416 		 * Check to see if the tree needs to be collapsed.
1417 		 */
1418 		if (retval && (state->path.active > 1)) {
1419 			xfs_bmap_init(args->flist, args->firstblock);
1420 			error = xfs_da_join(state);
1421 			if (!error) {
1422 				error = xfs_bmap_finish(&args->trans,
1423 							args->flist,
1424 							&committed);
1425 			}
1426 			if (error) {
1427 				ASSERT(committed);
1428 				args->trans = NULL;
1429 				xfs_bmap_cancel(args->flist);
1430 				goto out;
1431 			}
1432 
1433 			/*
1434 			 * bmap_finish() may have committed the last trans
1435 			 * and started a new one.  We need the inode to be
1436 			 * in all transactions.
1437 			 */
1438 			if (committed)
1439 				xfs_trans_ijoin(args->trans, dp, 0);
1440 		}
1441 
1442 		/*
1443 		 * Commit and start the next trans in the chain.
1444 		 */
1445 		error = xfs_trans_roll(&args->trans, dp);
1446 		if (error)
1447 			goto out;
1448 
1449 	} else if (args->rmtblkno > 0) {
1450 		/*
1451 		 * Added a "remote" value, just clear the incomplete flag.
1452 		 */
1453 		error = xfs_attr_leaf_clearflag(args);
1454 		if (error)
1455 			goto out;
1456 	}
1457 	retval = error = 0;
1458 
1459 out:
1460 	if (state)
1461 		xfs_da_state_free(state);
1462 	if (error)
1463 		return(error);
1464 	return(retval);
1465 }
1466 
1467 /*
1468  * Remove a name from a B-tree attribute list.
1469  *
1470  * This will involve walking down the Btree, and may involve joining
1471  * leaf nodes and even joining intermediate nodes up to and including
1472  * the root node (a special case of an intermediate node).
1473  */
1474 STATIC int
xfs_attr_node_removename(xfs_da_args_t * args)1475 xfs_attr_node_removename(xfs_da_args_t *args)
1476 {
1477 	xfs_da_state_t *state;
1478 	xfs_da_state_blk_t *blk;
1479 	xfs_inode_t *dp;
1480 	xfs_dabuf_t *bp;
1481 	int retval, error, committed, forkoff;
1482 
1483 	/*
1484 	 * Tie a string around our finger to remind us where we are.
1485 	 */
1486 	dp = args->dp;
1487 	state = xfs_da_state_alloc();
1488 	state->args = args;
1489 	state->mp = dp->i_mount;
1490 	state->blocksize = state->mp->m_sb.sb_blocksize;
1491 	state->node_ents = state->mp->m_attr_node_ents;
1492 
1493 	/*
1494 	 * Search to see if name exists, and get back a pointer to it.
1495 	 */
1496 	error = xfs_da_node_lookup_int(state, &retval);
1497 	if (error || (retval != EEXIST)) {
1498 		if (error == 0)
1499 			error = retval;
1500 		goto out;
1501 	}
1502 
1503 	/*
1504 	 * If there is an out-of-line value, de-allocate the blocks.
1505 	 * This is done before we remove the attribute so that we don't
1506 	 * overflow the maximum size of a transaction and/or hit a deadlock.
1507 	 */
1508 	blk = &state->path.blk[ state->path.active-1 ];
1509 	ASSERT(blk->bp != NULL);
1510 	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1511 	if (args->rmtblkno > 0) {
1512 		/*
1513 		 * Fill in disk block numbers in the state structure
1514 		 * so that we can get the buffers back after we commit
1515 		 * several transactions in the following calls.
1516 		 */
1517 		error = xfs_attr_fillstate(state);
1518 		if (error)
1519 			goto out;
1520 
1521 		/*
1522 		 * Mark the attribute as INCOMPLETE, then bunmapi() the
1523 		 * remote value.
1524 		 */
1525 		error = xfs_attr_leaf_setflag(args);
1526 		if (error)
1527 			goto out;
1528 		error = xfs_attr_rmtval_remove(args);
1529 		if (error)
1530 			goto out;
1531 
1532 		/*
1533 		 * Refill the state structure with buffers, the prior calls
1534 		 * released our buffers.
1535 		 */
1536 		error = xfs_attr_refillstate(state);
1537 		if (error)
1538 			goto out;
1539 	}
1540 
1541 	/*
1542 	 * Remove the name and update the hashvals in the tree.
1543 	 */
1544 	blk = &state->path.blk[ state->path.active-1 ];
1545 	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1546 	retval = xfs_attr_leaf_remove(blk->bp, args);
1547 	xfs_da_fixhashpath(state, &state->path);
1548 
1549 	/*
1550 	 * Check to see if the tree needs to be collapsed.
1551 	 */
1552 	if (retval && (state->path.active > 1)) {
1553 		xfs_bmap_init(args->flist, args->firstblock);
1554 		error = xfs_da_join(state);
1555 		if (!error) {
1556 			error = xfs_bmap_finish(&args->trans, args->flist,
1557 						&committed);
1558 		}
1559 		if (error) {
1560 			ASSERT(committed);
1561 			args->trans = NULL;
1562 			xfs_bmap_cancel(args->flist);
1563 			goto out;
1564 		}
1565 
1566 		/*
1567 		 * bmap_finish() may have committed the last trans and started
1568 		 * a new one.  We need the inode to be in all transactions.
1569 		 */
1570 		if (committed)
1571 			xfs_trans_ijoin(args->trans, dp, 0);
1572 
1573 		/*
1574 		 * Commit the Btree join operation and start a new trans.
1575 		 */
1576 		error = xfs_trans_roll(&args->trans, dp);
1577 		if (error)
1578 			goto out;
1579 	}
1580 
1581 	/*
1582 	 * If the result is small enough, push it all into the inode.
1583 	 */
1584 	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
1585 		/*
1586 		 * Have to get rid of the copy of this dabuf in the state.
1587 		 */
1588 		ASSERT(state->path.active == 1);
1589 		ASSERT(state->path.blk[0].bp);
1590 		xfs_da_buf_done(state->path.blk[0].bp);
1591 		state->path.blk[0].bp = NULL;
1592 
1593 		error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
1594 						     XFS_ATTR_FORK);
1595 		if (error)
1596 			goto out;
1597 		ASSERT((((xfs_attr_leafblock_t *)bp->data)->hdr.info.magic) ==
1598 		       cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
1599 
1600 		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1601 			xfs_bmap_init(args->flist, args->firstblock);
1602 			error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1603 			/* bp is gone due to xfs_da_shrink_inode */
1604 			if (!error) {
1605 				error = xfs_bmap_finish(&args->trans,
1606 							args->flist,
1607 							&committed);
1608 			}
1609 			if (error) {
1610 				ASSERT(committed);
1611 				args->trans = NULL;
1612 				xfs_bmap_cancel(args->flist);
1613 				goto out;
1614 			}
1615 
1616 			/*
1617 			 * bmap_finish() may have committed the last trans
1618 			 * and started a new one.  We need the inode to be
1619 			 * in all transactions.
1620 			 */
1621 			if (committed)
1622 				xfs_trans_ijoin(args->trans, dp, 0);
1623 		} else
1624 			xfs_da_brelse(args->trans, bp);
1625 	}
1626 	error = 0;
1627 
1628 out:
1629 	xfs_da_state_free(state);
1630 	return(error);
1631 }
1632 
1633 /*
1634  * Fill in the disk block numbers in the state structure for the buffers
1635  * that are attached to the state structure.
1636  * This is done so that we can quickly reattach ourselves to those buffers
1637  * after some set of transaction commits have released these buffers.
1638  */
1639 STATIC int
xfs_attr_fillstate(xfs_da_state_t * state)1640 xfs_attr_fillstate(xfs_da_state_t *state)
1641 {
1642 	xfs_da_state_path_t *path;
1643 	xfs_da_state_blk_t *blk;
1644 	int level;
1645 
1646 	/*
1647 	 * Roll down the "path" in the state structure, storing the on-disk
1648 	 * block number for those buffers in the "path".
1649 	 */
1650 	path = &state->path;
1651 	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1652 	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1653 		if (blk->bp) {
1654 			blk->disk_blkno = xfs_da_blkno(blk->bp);
1655 			xfs_da_buf_done(blk->bp);
1656 			blk->bp = NULL;
1657 		} else {
1658 			blk->disk_blkno = 0;
1659 		}
1660 	}
1661 
1662 	/*
1663 	 * Roll down the "altpath" in the state structure, storing the on-disk
1664 	 * block number for those buffers in the "altpath".
1665 	 */
1666 	path = &state->altpath;
1667 	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1668 	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1669 		if (blk->bp) {
1670 			blk->disk_blkno = xfs_da_blkno(blk->bp);
1671 			xfs_da_buf_done(blk->bp);
1672 			blk->bp = NULL;
1673 		} else {
1674 			blk->disk_blkno = 0;
1675 		}
1676 	}
1677 
1678 	return(0);
1679 }
1680 
1681 /*
1682  * Reattach the buffers to the state structure based on the disk block
1683  * numbers stored in the state structure.
1684  * This is done after some set of transaction commits have released those
1685  * buffers from our grip.
1686  */
1687 STATIC int
xfs_attr_refillstate(xfs_da_state_t * state)1688 xfs_attr_refillstate(xfs_da_state_t *state)
1689 {
1690 	xfs_da_state_path_t *path;
1691 	xfs_da_state_blk_t *blk;
1692 	int level, error;
1693 
1694 	/*
1695 	 * Roll down the "path" in the state structure, storing the on-disk
1696 	 * block number for those buffers in the "path".
1697 	 */
1698 	path = &state->path;
1699 	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1700 	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1701 		if (blk->disk_blkno) {
1702 			error = xfs_da_read_buf(state->args->trans,
1703 						state->args->dp,
1704 						blk->blkno, blk->disk_blkno,
1705 						&blk->bp, XFS_ATTR_FORK);
1706 			if (error)
1707 				return(error);
1708 		} else {
1709 			blk->bp = NULL;
1710 		}
1711 	}
1712 
1713 	/*
1714 	 * Roll down the "altpath" in the state structure, storing the on-disk
1715 	 * block number for those buffers in the "altpath".
1716 	 */
1717 	path = &state->altpath;
1718 	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1719 	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1720 		if (blk->disk_blkno) {
1721 			error = xfs_da_read_buf(state->args->trans,
1722 						state->args->dp,
1723 						blk->blkno, blk->disk_blkno,
1724 						&blk->bp, XFS_ATTR_FORK);
1725 			if (error)
1726 				return(error);
1727 		} else {
1728 			blk->bp = NULL;
1729 		}
1730 	}
1731 
1732 	return(0);
1733 }
1734 
1735 /*
1736  * Look up a filename in a node attribute list.
1737  *
1738  * This routine gets called for any attribute fork that has more than one
1739  * block, ie: both true Btree attr lists and for single-leaf-blocks with
1740  * "remote" values taking up more blocks.
1741  */
1742 STATIC int
xfs_attr_node_get(xfs_da_args_t * args)1743 xfs_attr_node_get(xfs_da_args_t *args)
1744 {
1745 	xfs_da_state_t *state;
1746 	xfs_da_state_blk_t *blk;
1747 	int error, retval;
1748 	int i;
1749 
1750 	state = xfs_da_state_alloc();
1751 	state->args = args;
1752 	state->mp = args->dp->i_mount;
1753 	state->blocksize = state->mp->m_sb.sb_blocksize;
1754 	state->node_ents = state->mp->m_attr_node_ents;
1755 
1756 	/*
1757 	 * Search to see if name exists, and get back a pointer to it.
1758 	 */
1759 	error = xfs_da_node_lookup_int(state, &retval);
1760 	if (error) {
1761 		retval = error;
1762 	} else if (retval == EEXIST) {
1763 		blk = &state->path.blk[ state->path.active-1 ];
1764 		ASSERT(blk->bp != NULL);
1765 		ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1766 
1767 		/*
1768 		 * Get the value, local or "remote"
1769 		 */
1770 		retval = xfs_attr_leaf_getvalue(blk->bp, args);
1771 		if (!retval && (args->rmtblkno > 0)
1772 		    && !(args->flags & ATTR_KERNOVAL)) {
1773 			retval = xfs_attr_rmtval_get(args);
1774 		}
1775 	}
1776 
1777 	/*
1778 	 * If not in a transaction, we have to release all the buffers.
1779 	 */
1780 	for (i = 0; i < state->path.active; i++) {
1781 		xfs_da_brelse(args->trans, state->path.blk[i].bp);
1782 		state->path.blk[i].bp = NULL;
1783 	}
1784 
1785 	xfs_da_state_free(state);
1786 	return(retval);
1787 }
1788 
1789 STATIC int							/* error */
xfs_attr_node_list(xfs_attr_list_context_t * context)1790 xfs_attr_node_list(xfs_attr_list_context_t *context)
1791 {
1792 	attrlist_cursor_kern_t *cursor;
1793 	xfs_attr_leafblock_t *leaf;
1794 	xfs_da_intnode_t *node;
1795 	xfs_da_node_entry_t *btree;
1796 	int error, i;
1797 	xfs_dabuf_t *bp;
1798 
1799 	cursor = context->cursor;
1800 	cursor->initted = 1;
1801 
1802 	/*
1803 	 * Do all sorts of validation on the passed-in cursor structure.
1804 	 * If anything is amiss, ignore the cursor and look up the hashval
1805 	 * starting from the btree root.
1806 	 */
1807 	bp = NULL;
1808 	if (cursor->blkno > 0) {
1809 		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
1810 					      &bp, XFS_ATTR_FORK);
1811 		if ((error != 0) && (error != EFSCORRUPTED))
1812 			return(error);
1813 		if (bp) {
1814 			node = bp->data;
1815 			switch (be16_to_cpu(node->hdr.info.magic)) {
1816 			case XFS_DA_NODE_MAGIC:
1817 				trace_xfs_attr_list_wrong_blk(context);
1818 				xfs_da_brelse(NULL, bp);
1819 				bp = NULL;
1820 				break;
1821 			case XFS_ATTR_LEAF_MAGIC:
1822 				leaf = bp->data;
1823 				if (cursor->hashval > be32_to_cpu(leaf->entries[
1824 				    be16_to_cpu(leaf->hdr.count)-1].hashval)) {
1825 					trace_xfs_attr_list_wrong_blk(context);
1826 					xfs_da_brelse(NULL, bp);
1827 					bp = NULL;
1828 				} else if (cursor->hashval <=
1829 					     be32_to_cpu(leaf->entries[0].hashval)) {
1830 					trace_xfs_attr_list_wrong_blk(context);
1831 					xfs_da_brelse(NULL, bp);
1832 					bp = NULL;
1833 				}
1834 				break;
1835 			default:
1836 				trace_xfs_attr_list_wrong_blk(context);
1837 				xfs_da_brelse(NULL, bp);
1838 				bp = NULL;
1839 			}
1840 		}
1841 	}
1842 
1843 	/*
1844 	 * We did not find what we expected given the cursor's contents,
1845 	 * so we start from the top and work down based on the hash value.
1846 	 * Note that start of node block is same as start of leaf block.
1847 	 */
1848 	if (bp == NULL) {
1849 		cursor->blkno = 0;
1850 		for (;;) {
1851 			error = xfs_da_read_buf(NULL, context->dp,
1852 						      cursor->blkno, -1, &bp,
1853 						      XFS_ATTR_FORK);
1854 			if (error)
1855 				return(error);
1856 			if (unlikely(bp == NULL)) {
1857 				XFS_ERROR_REPORT("xfs_attr_node_list(2)",
1858 						 XFS_ERRLEVEL_LOW,
1859 						 context->dp->i_mount);
1860 				return(XFS_ERROR(EFSCORRUPTED));
1861 			}
1862 			node = bp->data;
1863 			if (node->hdr.info.magic ==
1864 			    cpu_to_be16(XFS_ATTR_LEAF_MAGIC))
1865 				break;
1866 			if (unlikely(node->hdr.info.magic !=
1867 				     cpu_to_be16(XFS_DA_NODE_MAGIC))) {
1868 				XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)",
1869 						     XFS_ERRLEVEL_LOW,
1870 						     context->dp->i_mount,
1871 						     node);
1872 				xfs_da_brelse(NULL, bp);
1873 				return(XFS_ERROR(EFSCORRUPTED));
1874 			}
1875 			btree = node->btree;
1876 			for (i = 0; i < be16_to_cpu(node->hdr.count);
1877 								btree++, i++) {
1878 				if (cursor->hashval
1879 						<= be32_to_cpu(btree->hashval)) {
1880 					cursor->blkno = be32_to_cpu(btree->before);
1881 					trace_xfs_attr_list_node_descend(context,
1882 									 btree);
1883 					break;
1884 				}
1885 			}
1886 			if (i == be16_to_cpu(node->hdr.count)) {
1887 				xfs_da_brelse(NULL, bp);
1888 				return(0);
1889 			}
1890 			xfs_da_brelse(NULL, bp);
1891 		}
1892 	}
1893 	ASSERT(bp != NULL);
1894 
1895 	/*
1896 	 * Roll upward through the blocks, processing each leaf block in
1897 	 * order.  As long as there is space in the result buffer, keep
1898 	 * adding the information.
1899 	 */
1900 	for (;;) {
1901 		leaf = bp->data;
1902 		if (unlikely(leaf->hdr.info.magic !=
1903 			     cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) {
1904 			XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)",
1905 					     XFS_ERRLEVEL_LOW,
1906 					     context->dp->i_mount, leaf);
1907 			xfs_da_brelse(NULL, bp);
1908 			return(XFS_ERROR(EFSCORRUPTED));
1909 		}
1910 		error = xfs_attr_leaf_list_int(bp, context);
1911 		if (error) {
1912 			xfs_da_brelse(NULL, bp);
1913 			return error;
1914 		}
1915 		if (context->seen_enough || leaf->hdr.info.forw == 0)
1916 			break;
1917 		cursor->blkno = be32_to_cpu(leaf->hdr.info.forw);
1918 		xfs_da_brelse(NULL, bp);
1919 		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
1920 					      &bp, XFS_ATTR_FORK);
1921 		if (error)
1922 			return(error);
1923 		if (unlikely((bp == NULL))) {
1924 			XFS_ERROR_REPORT("xfs_attr_node_list(5)",
1925 					 XFS_ERRLEVEL_LOW,
1926 					 context->dp->i_mount);
1927 			return(XFS_ERROR(EFSCORRUPTED));
1928 		}
1929 	}
1930 	xfs_da_brelse(NULL, bp);
1931 	return(0);
1932 }
1933 
1934 
1935 /*========================================================================
1936  * External routines for manipulating out-of-line attribute values.
1937  *========================================================================*/
1938 
1939 /*
1940  * Read the value associated with an attribute from the out-of-line buffer
1941  * that we stored it in.
1942  */
1943 int
xfs_attr_rmtval_get(xfs_da_args_t * args)1944 xfs_attr_rmtval_get(xfs_da_args_t *args)
1945 {
1946 	xfs_bmbt_irec_t map[ATTR_RMTVALUE_MAPSIZE];
1947 	xfs_mount_t *mp;
1948 	xfs_daddr_t dblkno;
1949 	void *dst;
1950 	xfs_buf_t *bp;
1951 	int nmap, error, tmp, valuelen, blkcnt, i;
1952 	xfs_dablk_t lblkno;
1953 
1954 	ASSERT(!(args->flags & ATTR_KERNOVAL));
1955 
1956 	mp = args->dp->i_mount;
1957 	dst = args->value;
1958 	valuelen = args->valuelen;
1959 	lblkno = args->rmtblkno;
1960 	while (valuelen > 0) {
1961 		nmap = ATTR_RMTVALUE_MAPSIZE;
1962 		error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
1963 				       args->rmtblkcnt, map, &nmap,
1964 				       XFS_BMAPI_ATTRFORK);
1965 		if (error)
1966 			return(error);
1967 		ASSERT(nmap >= 1);
1968 
1969 		for (i = 0; (i < nmap) && (valuelen > 0); i++) {
1970 			ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) &&
1971 			       (map[i].br_startblock != HOLESTARTBLOCK));
1972 			dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
1973 			blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
1974 			error = xfs_read_buf(mp, mp->m_ddev_targp, dblkno,
1975 					     blkcnt, XBF_LOCK | XBF_DONT_BLOCK,
1976 					     &bp);
1977 			if (error)
1978 				return(error);
1979 
1980 			tmp = (valuelen < XFS_BUF_SIZE(bp))
1981 				? valuelen : XFS_BUF_SIZE(bp);
1982 			xfs_buf_iomove(bp, 0, tmp, dst, XBRW_READ);
1983 			xfs_buf_relse(bp);
1984 			dst += tmp;
1985 			valuelen -= tmp;
1986 
1987 			lblkno += map[i].br_blockcount;
1988 		}
1989 	}
1990 	ASSERT(valuelen == 0);
1991 	return(0);
1992 }
1993 
1994 /*
1995  * Write the value associated with an attribute into the out-of-line buffer
1996  * that we have defined for it.
1997  */
1998 STATIC int
xfs_attr_rmtval_set(xfs_da_args_t * args)1999 xfs_attr_rmtval_set(xfs_da_args_t *args)
2000 {
2001 	xfs_mount_t *mp;
2002 	xfs_fileoff_t lfileoff;
2003 	xfs_inode_t *dp;
2004 	xfs_bmbt_irec_t map;
2005 	xfs_daddr_t dblkno;
2006 	void *src;
2007 	xfs_buf_t *bp;
2008 	xfs_dablk_t lblkno;
2009 	int blkcnt, valuelen, nmap, error, tmp, committed;
2010 
2011 	dp = args->dp;
2012 	mp = dp->i_mount;
2013 	src = args->value;
2014 
2015 	/*
2016 	 * Find a "hole" in the attribute address space large enough for
2017 	 * us to drop the new attribute's value into.
2018 	 */
2019 	blkcnt = XFS_B_TO_FSB(mp, args->valuelen);
2020 	lfileoff = 0;
2021 	error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff,
2022 						   XFS_ATTR_FORK);
2023 	if (error) {
2024 		return(error);
2025 	}
2026 	args->rmtblkno = lblkno = (xfs_dablk_t)lfileoff;
2027 	args->rmtblkcnt = blkcnt;
2028 
2029 	/*
2030 	 * Roll through the "value", allocating blocks on disk as required.
2031 	 */
2032 	while (blkcnt > 0) {
2033 		/*
2034 		 * Allocate a single extent, up to the size of the value.
2035 		 */
2036 		xfs_bmap_init(args->flist, args->firstblock);
2037 		nmap = 1;
2038 		error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno,
2039 				  blkcnt,
2040 				  XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
2041 				  args->firstblock, args->total, &map, &nmap,
2042 				  args->flist);
2043 		if (!error) {
2044 			error = xfs_bmap_finish(&args->trans, args->flist,
2045 						&committed);
2046 		}
2047 		if (error) {
2048 			ASSERT(committed);
2049 			args->trans = NULL;
2050 			xfs_bmap_cancel(args->flist);
2051 			return(error);
2052 		}
2053 
2054 		/*
2055 		 * bmap_finish() may have committed the last trans and started
2056 		 * a new one.  We need the inode to be in all transactions.
2057 		 */
2058 		if (committed)
2059 			xfs_trans_ijoin(args->trans, dp, 0);
2060 
2061 		ASSERT(nmap == 1);
2062 		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
2063 		       (map.br_startblock != HOLESTARTBLOCK));
2064 		lblkno += map.br_blockcount;
2065 		blkcnt -= map.br_blockcount;
2066 
2067 		/*
2068 		 * Start the next trans in the chain.
2069 		 */
2070 		error = xfs_trans_roll(&args->trans, dp);
2071 		if (error)
2072 			return (error);
2073 	}
2074 
2075 	/*
2076 	 * Roll through the "value", copying the attribute value to the
2077 	 * already-allocated blocks.  Blocks are written synchronously
2078 	 * so that we can know they are all on disk before we turn off
2079 	 * the INCOMPLETE flag.
2080 	 */
2081 	lblkno = args->rmtblkno;
2082 	valuelen = args->valuelen;
2083 	while (valuelen > 0) {
2084 		/*
2085 		 * Try to remember where we decided to put the value.
2086 		 */
2087 		xfs_bmap_init(args->flist, args->firstblock);
2088 		nmap = 1;
2089 		error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno,
2090 				       args->rmtblkcnt, &map, &nmap,
2091 				       XFS_BMAPI_ATTRFORK);
2092 		if (error)
2093 			return(error);
2094 		ASSERT(nmap == 1);
2095 		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
2096 		       (map.br_startblock != HOLESTARTBLOCK));
2097 
2098 		dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
2099 		blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
2100 
2101 		bp = xfs_buf_get(mp->m_ddev_targp, dblkno, blkcnt,
2102 				 XBF_LOCK | XBF_DONT_BLOCK);
2103 		if (!bp)
2104 			return ENOMEM;
2105 		tmp = (valuelen < XFS_BUF_SIZE(bp)) ? valuelen :
2106 							XFS_BUF_SIZE(bp);
2107 		xfs_buf_iomove(bp, 0, tmp, src, XBRW_WRITE);
2108 		if (tmp < XFS_BUF_SIZE(bp))
2109 			xfs_buf_zero(bp, tmp, XFS_BUF_SIZE(bp) - tmp);
2110 		error = xfs_bwrite(bp);	/* GROT: NOTE: synchronous write */
2111 		xfs_buf_relse(bp);
2112 		if (error)
2113 			return error;
2114 		src += tmp;
2115 		valuelen -= tmp;
2116 
2117 		lblkno += map.br_blockcount;
2118 	}
2119 	ASSERT(valuelen == 0);
2120 	return(0);
2121 }
2122 
2123 /*
2124  * Remove the value associated with an attribute by deleting the
2125  * out-of-line buffer that it is stored on.
2126  */
2127 STATIC int
xfs_attr_rmtval_remove(xfs_da_args_t * args)2128 xfs_attr_rmtval_remove(xfs_da_args_t *args)
2129 {
2130 	xfs_mount_t *mp;
2131 	xfs_bmbt_irec_t map;
2132 	xfs_buf_t *bp;
2133 	xfs_daddr_t dblkno;
2134 	xfs_dablk_t lblkno;
2135 	int valuelen, blkcnt, nmap, error, done, committed;
2136 
2137 	mp = args->dp->i_mount;
2138 
2139 	/*
2140 	 * Roll through the "value", invalidating the attribute value's
2141 	 * blocks.
2142 	 */
2143 	lblkno = args->rmtblkno;
2144 	valuelen = args->rmtblkcnt;
2145 	while (valuelen > 0) {
2146 		/*
2147 		 * Try to remember where we decided to put the value.
2148 		 */
2149 		nmap = 1;
2150 		error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
2151 				       args->rmtblkcnt, &map, &nmap,
2152 				       XFS_BMAPI_ATTRFORK);
2153 		if (error)
2154 			return(error);
2155 		ASSERT(nmap == 1);
2156 		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
2157 		       (map.br_startblock != HOLESTARTBLOCK));
2158 
2159 		dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
2160 		blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
2161 
2162 		/*
2163 		 * If the "remote" value is in the cache, remove it.
2164 		 */
2165 		bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt, XBF_TRYLOCK);
2166 		if (bp) {
2167 			xfs_buf_stale(bp);
2168 			xfs_buf_relse(bp);
2169 			bp = NULL;
2170 		}
2171 
2172 		valuelen -= map.br_blockcount;
2173 
2174 		lblkno += map.br_blockcount;
2175 	}
2176 
2177 	/*
2178 	 * Keep de-allocating extents until the remote-value region is gone.
2179 	 */
2180 	lblkno = args->rmtblkno;
2181 	blkcnt = args->rmtblkcnt;
2182 	done = 0;
2183 	while (!done) {
2184 		xfs_bmap_init(args->flist, args->firstblock);
2185 		error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt,
2186 				    XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
2187 				    1, args->firstblock, args->flist,
2188 				    &done);
2189 		if (!error) {
2190 			error = xfs_bmap_finish(&args->trans, args->flist,
2191 						&committed);
2192 		}
2193 		if (error) {
2194 			ASSERT(committed);
2195 			args->trans = NULL;
2196 			xfs_bmap_cancel(args->flist);
2197 			return(error);
2198 		}
2199 
2200 		/*
2201 		 * bmap_finish() may have committed the last trans and started
2202 		 * a new one.  We need the inode to be in all transactions.
2203 		 */
2204 		if (committed)
2205 			xfs_trans_ijoin(args->trans, args->dp, 0);
2206 
2207 		/*
2208 		 * Close out trans and start the next one in the chain.
2209 		 */
2210 		error = xfs_trans_roll(&args->trans, args->dp);
2211 		if (error)
2212 			return (error);
2213 	}
2214 	return(0);
2215 }
2216