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);
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);
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 	 * Attach the dquots to the inode.
494 	 */
495 	error = xfs_qm_dqattach(dp, 0);
496 	if (error)
497 		return error;
498 
499 	/*
500 	 * Start our first transaction of the day.
501 	 *
502 	 * All future transactions during this code must be "chained" off
503 	 * this one via the trans_dup() call.  All transactions will contain
504 	 * the inode, and the inode will always be marked with trans_ihold().
505 	 * Since the inode will be locked in all transactions, we must log
506 	 * the inode in every transaction to let it float upward through
507 	 * the log.
508 	 */
509 	args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_RM);
510 
511 	/*
512 	 * Root fork attributes can use reserved data blocks for this
513 	 * operation if necessary
514 	 */
515 
516 	if (flags & ATTR_ROOT)
517 		args.trans->t_flags |= XFS_TRANS_RESERVE;
518 
519 	if ((error = xfs_trans_reserve(args.trans,
520 				      XFS_ATTRRM_SPACE_RES(mp),
521 				      XFS_ATTRRM_LOG_RES(mp),
522 				      0, XFS_TRANS_PERM_LOG_RES,
523 				      XFS_ATTRRM_LOG_COUNT))) {
524 		xfs_trans_cancel(args.trans, 0);
525 		return(error);
526 	}
527 
528 	xfs_ilock(dp, XFS_ILOCK_EXCL);
529 	/*
530 	 * No need to make quota reservations here. We expect to release some
531 	 * blocks not allocate in the common case.
532 	 */
533 	xfs_trans_ijoin(args.trans, dp);
534 
535 	/*
536 	 * Decide on what work routines to call based on the inode size.
537 	 */
538 	if (!xfs_inode_hasattr(dp)) {
539 		error = XFS_ERROR(ENOATTR);
540 		goto out;
541 	}
542 	if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
543 		ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
544 		error = xfs_attr_shortform_remove(&args);
545 		if (error) {
546 			goto out;
547 		}
548 	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
549 		error = xfs_attr_leaf_removename(&args);
550 	} else {
551 		error = xfs_attr_node_removename(&args);
552 	}
553 	if (error) {
554 		goto out;
555 	}
556 
557 	/*
558 	 * If this is a synchronous mount, make sure that the
559 	 * transaction goes to disk before returning to the user.
560 	 */
561 	if (mp->m_flags & XFS_MOUNT_WSYNC) {
562 		xfs_trans_set_sync(args.trans);
563 	}
564 
565 	if ((flags & ATTR_KERNOTIME) == 0)
566 		xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
567 
568 	/*
569 	 * Commit the last in the sequence of transactions.
570 	 */
571 	xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
572 	error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
573 	xfs_iunlock(dp, XFS_ILOCK_EXCL);
574 
575 	return(error);
576 
577 out:
578 	if (args.trans)
579 		xfs_trans_cancel(args.trans,
580 			XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
581 	xfs_iunlock(dp, XFS_ILOCK_EXCL);
582 	return(error);
583 }
584 
585 int
xfs_attr_remove(xfs_inode_t * dp,const unsigned char * name,int flags)586 xfs_attr_remove(
587 	xfs_inode_t	*dp,
588 	const unsigned char *name,
589 	int		flags)
590 {
591 	int		error;
592 	struct xfs_name	xname;
593 
594 	XFS_STATS_INC(xs_attr_remove);
595 
596 	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
597 		return (EIO);
598 
599 	error = xfs_attr_name_to_xname(&xname, name);
600 	if (error)
601 		return error;
602 
603 	xfs_ilock(dp, XFS_ILOCK_SHARED);
604 	if (!xfs_inode_hasattr(dp)) {
605 		xfs_iunlock(dp, XFS_ILOCK_SHARED);
606 		return XFS_ERROR(ENOATTR);
607 	}
608 	xfs_iunlock(dp, XFS_ILOCK_SHARED);
609 
610 	return xfs_attr_remove_int(dp, &xname, flags);
611 }
612 
613 int
xfs_attr_list_int(xfs_attr_list_context_t * context)614 xfs_attr_list_int(xfs_attr_list_context_t *context)
615 {
616 	int error;
617 	xfs_inode_t *dp = context->dp;
618 
619 	XFS_STATS_INC(xs_attr_list);
620 
621 	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
622 		return EIO;
623 
624 	xfs_ilock(dp, XFS_ILOCK_SHARED);
625 
626 	/*
627 	 * Decide on what work routines to call based on the inode size.
628 	 */
629 	if (!xfs_inode_hasattr(dp)) {
630 		error = 0;
631 	} else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
632 		error = xfs_attr_shortform_list(context);
633 	} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
634 		error = xfs_attr_leaf_list(context);
635 	} else {
636 		error = xfs_attr_node_list(context);
637 	}
638 
639 	xfs_iunlock(dp, XFS_ILOCK_SHARED);
640 
641 	return error;
642 }
643 
644 #define	ATTR_ENTBASESIZE		/* minimum bytes used by an attr */ \
645 	(((struct attrlist_ent *) 0)->a_name - (char *) 0)
646 #define	ATTR_ENTSIZE(namelen)		/* actual bytes used by an attr */ \
647 	((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(u_int32_t)-1) \
648 	 & ~(sizeof(u_int32_t)-1))
649 
650 /*
651  * Format an attribute and copy it out to the user's buffer.
652  * Take care to check values and protect against them changing later,
653  * we may be reading them directly out of a user buffer.
654  */
655 /*ARGSUSED*/
656 STATIC int
xfs_attr_put_listent(xfs_attr_list_context_t * context,int flags,unsigned char * name,int namelen,int valuelen,unsigned char * value)657 xfs_attr_put_listent(
658 	xfs_attr_list_context_t *context,
659 	int		flags,
660 	unsigned char	*name,
661 	int		namelen,
662 	int		valuelen,
663 	unsigned char	*value)
664 {
665 	struct attrlist *alist = (struct attrlist *)context->alist;
666 	attrlist_ent_t *aep;
667 	int arraytop;
668 
669 	ASSERT(!(context->flags & ATTR_KERNOVAL));
670 	ASSERT(context->count >= 0);
671 	ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
672 	ASSERT(context->firstu >= sizeof(*alist));
673 	ASSERT(context->firstu <= context->bufsize);
674 
675 	/*
676 	 * Only list entries in the right namespace.
677 	 */
678 	if (((context->flags & ATTR_SECURE) == 0) !=
679 	    ((flags & XFS_ATTR_SECURE) == 0))
680 		return 0;
681 	if (((context->flags & ATTR_ROOT) == 0) !=
682 	    ((flags & XFS_ATTR_ROOT) == 0))
683 		return 0;
684 
685 	arraytop = sizeof(*alist) +
686 			context->count * sizeof(alist->al_offset[0]);
687 	context->firstu -= ATTR_ENTSIZE(namelen);
688 	if (context->firstu < arraytop) {
689 		trace_xfs_attr_list_full(context);
690 		alist->al_more = 1;
691 		context->seen_enough = 1;
692 		return 1;
693 	}
694 
695 	aep = (attrlist_ent_t *)&context->alist[context->firstu];
696 	aep->a_valuelen = valuelen;
697 	memcpy(aep->a_name, name, namelen);
698 	aep->a_name[namelen] = 0;
699 	alist->al_offset[context->count++] = context->firstu;
700 	alist->al_count = context->count;
701 	trace_xfs_attr_list_add(context);
702 	return 0;
703 }
704 
705 /*
706  * Generate a list of extended attribute names and optionally
707  * also value lengths.  Positive return value follows the XFS
708  * convention of being an error, zero or negative return code
709  * is the length of the buffer returned (negated), indicating
710  * success.
711  */
712 int
xfs_attr_list(xfs_inode_t * dp,char * buffer,int bufsize,int flags,attrlist_cursor_kern_t * cursor)713 xfs_attr_list(
714 	xfs_inode_t	*dp,
715 	char		*buffer,
716 	int		bufsize,
717 	int		flags,
718 	attrlist_cursor_kern_t *cursor)
719 {
720 	xfs_attr_list_context_t context;
721 	struct attrlist *alist;
722 	int error;
723 
724 	/*
725 	 * Validate the cursor.
726 	 */
727 	if (cursor->pad1 || cursor->pad2)
728 		return(XFS_ERROR(EINVAL));
729 	if ((cursor->initted == 0) &&
730 	    (cursor->hashval || cursor->blkno || cursor->offset))
731 		return XFS_ERROR(EINVAL);
732 
733 	/*
734 	 * Check for a properly aligned buffer.
735 	 */
736 	if (((long)buffer) & (sizeof(int)-1))
737 		return XFS_ERROR(EFAULT);
738 	if (flags & ATTR_KERNOVAL)
739 		bufsize = 0;
740 
741 	/*
742 	 * Initialize the output buffer.
743 	 */
744 	memset(&context, 0, sizeof(context));
745 	context.dp = dp;
746 	context.cursor = cursor;
747 	context.resynch = 1;
748 	context.flags = flags;
749 	context.alist = buffer;
750 	context.bufsize = (bufsize & ~(sizeof(int)-1));  /* align */
751 	context.firstu = context.bufsize;
752 	context.put_listent = xfs_attr_put_listent;
753 
754 	alist = (struct attrlist *)context.alist;
755 	alist->al_count = 0;
756 	alist->al_more = 0;
757 	alist->al_offset[0] = context.bufsize;
758 
759 	error = xfs_attr_list_int(&context);
760 	ASSERT(error >= 0);
761 	return error;
762 }
763 
764 int								/* error */
xfs_attr_inactive(xfs_inode_t * dp)765 xfs_attr_inactive(xfs_inode_t *dp)
766 {
767 	xfs_trans_t *trans;
768 	xfs_mount_t *mp;
769 	int error;
770 
771 	mp = dp->i_mount;
772 	ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
773 
774 	xfs_ilock(dp, XFS_ILOCK_SHARED);
775 	if (!xfs_inode_hasattr(dp) ||
776 	    dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
777 		xfs_iunlock(dp, XFS_ILOCK_SHARED);
778 		return 0;
779 	}
780 	xfs_iunlock(dp, XFS_ILOCK_SHARED);
781 
782 	/*
783 	 * Start our first transaction of the day.
784 	 *
785 	 * All future transactions during this code must be "chained" off
786 	 * this one via the trans_dup() call.  All transactions will contain
787 	 * the inode, and the inode will always be marked with trans_ihold().
788 	 * Since the inode will be locked in all transactions, we must log
789 	 * the inode in every transaction to let it float upward through
790 	 * the log.
791 	 */
792 	trans = xfs_trans_alloc(mp, XFS_TRANS_ATTRINVAL);
793 	if ((error = xfs_trans_reserve(trans, 0, XFS_ATTRINVAL_LOG_RES(mp), 0,
794 				      XFS_TRANS_PERM_LOG_RES,
795 				      XFS_ATTRINVAL_LOG_COUNT))) {
796 		xfs_trans_cancel(trans, 0);
797 		return(error);
798 	}
799 	xfs_ilock(dp, XFS_ILOCK_EXCL);
800 
801 	/*
802 	 * No need to make quota reservations here. We expect to release some
803 	 * blocks, not allocate, in the common case.
804 	 */
805 	xfs_trans_ijoin(trans, dp);
806 
807 	/*
808 	 * Decide on what work routines to call based on the inode size.
809 	 */
810 	if (!xfs_inode_hasattr(dp) ||
811 	    dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
812 		error = 0;
813 		goto out;
814 	}
815 	error = xfs_attr_root_inactive(&trans, dp);
816 	if (error)
817 		goto out;
818 	/*
819 	 * signal synchronous inactive transactions unless this
820 	 * is a synchronous mount filesystem in which case we
821 	 * know that we're here because we've been called out of
822 	 * xfs_inactive which means that the last reference is gone
823 	 * and the unlink transaction has already hit the disk so
824 	 * async inactive transactions are safe.
825 	 */
826 	if ((error = xfs_itruncate_finish(&trans, dp, 0LL, XFS_ATTR_FORK,
827 				(!(mp->m_flags & XFS_MOUNT_WSYNC)
828 				 ? 1 : 0))))
829 		goto out;
830 
831 	/*
832 	 * Commit the last in the sequence of transactions.
833 	 */
834 	xfs_trans_log_inode(trans, dp, XFS_ILOG_CORE);
835 	error = xfs_trans_commit(trans, XFS_TRANS_RELEASE_LOG_RES);
836 	xfs_iunlock(dp, XFS_ILOCK_EXCL);
837 
838 	return(error);
839 
840 out:
841 	xfs_trans_cancel(trans, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
842 	xfs_iunlock(dp, XFS_ILOCK_EXCL);
843 	return(error);
844 }
845 
846 
847 
848 /*========================================================================
849  * External routines when attribute list is inside the inode
850  *========================================================================*/
851 
852 /*
853  * Add a name to the shortform attribute list structure
854  * This is the external routine.
855  */
856 STATIC int
xfs_attr_shortform_addname(xfs_da_args_t * args)857 xfs_attr_shortform_addname(xfs_da_args_t *args)
858 {
859 	int newsize, forkoff, retval;
860 
861 	retval = xfs_attr_shortform_lookup(args);
862 	if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
863 		return(retval);
864 	} else if (retval == EEXIST) {
865 		if (args->flags & ATTR_CREATE)
866 			return(retval);
867 		retval = xfs_attr_shortform_remove(args);
868 		ASSERT(retval == 0);
869 	}
870 
871 	if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
872 	    args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
873 		return(XFS_ERROR(ENOSPC));
874 
875 	newsize = XFS_ATTR_SF_TOTSIZE(args->dp);
876 	newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen);
877 
878 	forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
879 	if (!forkoff)
880 		return(XFS_ERROR(ENOSPC));
881 
882 	xfs_attr_shortform_add(args, forkoff);
883 	return(0);
884 }
885 
886 
887 /*========================================================================
888  * External routines when attribute list is one block
889  *========================================================================*/
890 
891 /*
892  * Add a name to the leaf attribute list structure
893  *
894  * This leaf block cannot have a "remote" value, we only call this routine
895  * if bmap_one_block() says there is only one block (ie: no remote blks).
896  */
897 STATIC int
xfs_attr_leaf_addname(xfs_da_args_t * args)898 xfs_attr_leaf_addname(xfs_da_args_t *args)
899 {
900 	xfs_inode_t *dp;
901 	xfs_dabuf_t *bp;
902 	int retval, error, committed, forkoff;
903 
904 	/*
905 	 * Read the (only) block in the attribute list in.
906 	 */
907 	dp = args->dp;
908 	args->blkno = 0;
909 	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
910 					     XFS_ATTR_FORK);
911 	if (error)
912 		return(error);
913 	ASSERT(bp != NULL);
914 
915 	/*
916 	 * Look up the given attribute in the leaf block.  Figure out if
917 	 * the given flags produce an error or call for an atomic rename.
918 	 */
919 	retval = xfs_attr_leaf_lookup_int(bp, args);
920 	if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
921 		xfs_da_brelse(args->trans, bp);
922 		return(retval);
923 	} else if (retval == EEXIST) {
924 		if (args->flags & ATTR_CREATE) {	/* pure create op */
925 			xfs_da_brelse(args->trans, bp);
926 			return(retval);
927 		}
928 		args->op_flags |= XFS_DA_OP_RENAME;	/* an atomic rename */
929 		args->blkno2 = args->blkno;		/* set 2nd entry info*/
930 		args->index2 = args->index;
931 		args->rmtblkno2 = args->rmtblkno;
932 		args->rmtblkcnt2 = args->rmtblkcnt;
933 	}
934 
935 	/*
936 	 * Add the attribute to the leaf block, transitioning to a Btree
937 	 * if required.
938 	 */
939 	retval = xfs_attr_leaf_add(bp, args);
940 	xfs_da_buf_done(bp);
941 	if (retval == ENOSPC) {
942 		/*
943 		 * Promote the attribute list to the Btree format, then
944 		 * Commit that transaction so that the node_addname() call
945 		 * can manage its own transactions.
946 		 */
947 		xfs_bmap_init(args->flist, args->firstblock);
948 		error = xfs_attr_leaf_to_node(args);
949 		if (!error) {
950 			error = xfs_bmap_finish(&args->trans, args->flist,
951 						&committed);
952 		}
953 		if (error) {
954 			ASSERT(committed);
955 			args->trans = NULL;
956 			xfs_bmap_cancel(args->flist);
957 			return(error);
958 		}
959 
960 		/*
961 		 * bmap_finish() may have committed the last trans and started
962 		 * a new one.  We need the inode to be in all transactions.
963 		 */
964 		if (committed)
965 			xfs_trans_ijoin(args->trans, dp);
966 
967 		/*
968 		 * Commit the current trans (including the inode) and start
969 		 * a new one.
970 		 */
971 		error = xfs_trans_roll(&args->trans, dp);
972 		if (error)
973 			return (error);
974 
975 		/*
976 		 * Fob the whole rest of the problem off on the Btree code.
977 		 */
978 		error = xfs_attr_node_addname(args);
979 		return(error);
980 	}
981 
982 	/*
983 	 * Commit the transaction that added the attr name so that
984 	 * later routines can manage their own transactions.
985 	 */
986 	error = xfs_trans_roll(&args->trans, dp);
987 	if (error)
988 		return (error);
989 
990 	/*
991 	 * If there was an out-of-line value, allocate the blocks we
992 	 * identified for its storage and copy the value.  This is done
993 	 * after we create the attribute so that we don't overflow the
994 	 * maximum size of a transaction and/or hit a deadlock.
995 	 */
996 	if (args->rmtblkno > 0) {
997 		error = xfs_attr_rmtval_set(args);
998 		if (error)
999 			return(error);
1000 	}
1001 
1002 	/*
1003 	 * If this is an atomic rename operation, we must "flip" the
1004 	 * incomplete flags on the "new" and "old" attribute/value pairs
1005 	 * so that one disappears and one appears atomically.  Then we
1006 	 * must remove the "old" attribute/value pair.
1007 	 */
1008 	if (args->op_flags & XFS_DA_OP_RENAME) {
1009 		/*
1010 		 * In a separate transaction, set the incomplete flag on the
1011 		 * "old" attr and clear the incomplete flag on the "new" attr.
1012 		 */
1013 		error = xfs_attr_leaf_flipflags(args);
1014 		if (error)
1015 			return(error);
1016 
1017 		/*
1018 		 * Dismantle the "old" attribute/value pair by removing
1019 		 * a "remote" value (if it exists).
1020 		 */
1021 		args->index = args->index2;
1022 		args->blkno = args->blkno2;
1023 		args->rmtblkno = args->rmtblkno2;
1024 		args->rmtblkcnt = args->rmtblkcnt2;
1025 		if (args->rmtblkno) {
1026 			error = xfs_attr_rmtval_remove(args);
1027 			if (error)
1028 				return(error);
1029 		}
1030 
1031 		/*
1032 		 * Read in the block containing the "old" attr, then
1033 		 * remove the "old" attr from that block (neat, huh!)
1034 		 */
1035 		error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1,
1036 						     &bp, XFS_ATTR_FORK);
1037 		if (error)
1038 			return(error);
1039 		ASSERT(bp != NULL);
1040 		(void)xfs_attr_leaf_remove(bp, args);
1041 
1042 		/*
1043 		 * If the result is small enough, shrink it all into the inode.
1044 		 */
1045 		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1046 			xfs_bmap_init(args->flist, args->firstblock);
1047 			error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1048 			/* bp is gone due to xfs_da_shrink_inode */
1049 			if (!error) {
1050 				error = xfs_bmap_finish(&args->trans,
1051 							args->flist,
1052 							&committed);
1053 			}
1054 			if (error) {
1055 				ASSERT(committed);
1056 				args->trans = NULL;
1057 				xfs_bmap_cancel(args->flist);
1058 				return(error);
1059 			}
1060 
1061 			/*
1062 			 * bmap_finish() may have committed the last trans
1063 			 * and started a new one.  We need the inode to be
1064 			 * in all transactions.
1065 			 */
1066 			if (committed)
1067 				xfs_trans_ijoin(args->trans, dp);
1068 		} else
1069 			xfs_da_buf_done(bp);
1070 
1071 		/*
1072 		 * Commit the remove and start the next trans in series.
1073 		 */
1074 		error = xfs_trans_roll(&args->trans, dp);
1075 
1076 	} else if (args->rmtblkno > 0) {
1077 		/*
1078 		 * Added a "remote" value, just clear the incomplete flag.
1079 		 */
1080 		error = xfs_attr_leaf_clearflag(args);
1081 	}
1082 	return(error);
1083 }
1084 
1085 /*
1086  * Remove a name from the leaf attribute list structure
1087  *
1088  * This leaf block cannot have a "remote" value, we only call this routine
1089  * if bmap_one_block() says there is only one block (ie: no remote blks).
1090  */
1091 STATIC int
xfs_attr_leaf_removename(xfs_da_args_t * args)1092 xfs_attr_leaf_removename(xfs_da_args_t *args)
1093 {
1094 	xfs_inode_t *dp;
1095 	xfs_dabuf_t *bp;
1096 	int error, committed, forkoff;
1097 
1098 	/*
1099 	 * Remove the attribute.
1100 	 */
1101 	dp = args->dp;
1102 	args->blkno = 0;
1103 	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
1104 					     XFS_ATTR_FORK);
1105 	if (error) {
1106 		return(error);
1107 	}
1108 
1109 	ASSERT(bp != NULL);
1110 	error = xfs_attr_leaf_lookup_int(bp, args);
1111 	if (error == ENOATTR) {
1112 		xfs_da_brelse(args->trans, bp);
1113 		return(error);
1114 	}
1115 
1116 	(void)xfs_attr_leaf_remove(bp, args);
1117 
1118 	/*
1119 	 * If the result is small enough, shrink it all into the inode.
1120 	 */
1121 	if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1122 		xfs_bmap_init(args->flist, args->firstblock);
1123 		error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1124 		/* bp is gone due to xfs_da_shrink_inode */
1125 		if (!error) {
1126 			error = xfs_bmap_finish(&args->trans, args->flist,
1127 						&committed);
1128 		}
1129 		if (error) {
1130 			ASSERT(committed);
1131 			args->trans = NULL;
1132 			xfs_bmap_cancel(args->flist);
1133 			return(error);
1134 		}
1135 
1136 		/*
1137 		 * bmap_finish() may have committed the last trans and started
1138 		 * a new one.  We need the inode to be in all transactions.
1139 		 */
1140 		if (committed)
1141 			xfs_trans_ijoin(args->trans, dp);
1142 	} else
1143 		xfs_da_buf_done(bp);
1144 	return(0);
1145 }
1146 
1147 /*
1148  * Look up a name in a leaf attribute list structure.
1149  *
1150  * This leaf block cannot have a "remote" value, we only call this routine
1151  * if bmap_one_block() says there is only one block (ie: no remote blks).
1152  */
1153 STATIC int
xfs_attr_leaf_get(xfs_da_args_t * args)1154 xfs_attr_leaf_get(xfs_da_args_t *args)
1155 {
1156 	xfs_dabuf_t *bp;
1157 	int error;
1158 
1159 	args->blkno = 0;
1160 	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
1161 					     XFS_ATTR_FORK);
1162 	if (error)
1163 		return(error);
1164 	ASSERT(bp != NULL);
1165 
1166 	error = xfs_attr_leaf_lookup_int(bp, args);
1167 	if (error != EEXIST)  {
1168 		xfs_da_brelse(args->trans, bp);
1169 		return(error);
1170 	}
1171 	error = xfs_attr_leaf_getvalue(bp, args);
1172 	xfs_da_brelse(args->trans, bp);
1173 	if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) {
1174 		error = xfs_attr_rmtval_get(args);
1175 	}
1176 	return(error);
1177 }
1178 
1179 /*
1180  * Copy out attribute entries for attr_list(), for leaf attribute lists.
1181  */
1182 STATIC int
xfs_attr_leaf_list(xfs_attr_list_context_t * context)1183 xfs_attr_leaf_list(xfs_attr_list_context_t *context)
1184 {
1185 	xfs_attr_leafblock_t *leaf;
1186 	int error;
1187 	xfs_dabuf_t *bp;
1188 
1189 	context->cursor->blkno = 0;
1190 	error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK);
1191 	if (error)
1192 		return XFS_ERROR(error);
1193 	ASSERT(bp != NULL);
1194 	leaf = bp->data;
1195 	if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC)) {
1196 		XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW,
1197 				     context->dp->i_mount, leaf);
1198 		xfs_da_brelse(NULL, bp);
1199 		return XFS_ERROR(EFSCORRUPTED);
1200 	}
1201 
1202 	error = xfs_attr_leaf_list_int(bp, context);
1203 	xfs_da_brelse(NULL, bp);
1204 	return XFS_ERROR(error);
1205 }
1206 
1207 
1208 /*========================================================================
1209  * External routines when attribute list size > XFS_LBSIZE(mp).
1210  *========================================================================*/
1211 
1212 /*
1213  * Add a name to a Btree-format attribute list.
1214  *
1215  * This will involve walking down the Btree, and may involve splitting
1216  * leaf nodes and even splitting intermediate nodes up to and including
1217  * the root node (a special case of an intermediate node).
1218  *
1219  * "Remote" attribute values confuse the issue and atomic rename operations
1220  * add a whole extra layer of confusion on top of that.
1221  */
1222 STATIC int
xfs_attr_node_addname(xfs_da_args_t * args)1223 xfs_attr_node_addname(xfs_da_args_t *args)
1224 {
1225 	xfs_da_state_t *state;
1226 	xfs_da_state_blk_t *blk;
1227 	xfs_inode_t *dp;
1228 	xfs_mount_t *mp;
1229 	int committed, retval, error;
1230 
1231 	/*
1232 	 * Fill in bucket of arguments/results/context to carry around.
1233 	 */
1234 	dp = args->dp;
1235 	mp = dp->i_mount;
1236 restart:
1237 	state = xfs_da_state_alloc();
1238 	state->args = args;
1239 	state->mp = mp;
1240 	state->blocksize = state->mp->m_sb.sb_blocksize;
1241 	state->node_ents = state->mp->m_attr_node_ents;
1242 
1243 	/*
1244 	 * Search to see if name already exists, and get back a pointer
1245 	 * to where it should go.
1246 	 */
1247 	error = xfs_da_node_lookup_int(state, &retval);
1248 	if (error)
1249 		goto out;
1250 	blk = &state->path.blk[ state->path.active-1 ];
1251 	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1252 	if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
1253 		goto out;
1254 	} else if (retval == EEXIST) {
1255 		if (args->flags & ATTR_CREATE)
1256 			goto out;
1257 		args->op_flags |= XFS_DA_OP_RENAME;	/* atomic rename op */
1258 		args->blkno2 = args->blkno;		/* set 2nd entry info*/
1259 		args->index2 = args->index;
1260 		args->rmtblkno2 = args->rmtblkno;
1261 		args->rmtblkcnt2 = args->rmtblkcnt;
1262 		args->rmtblkno = 0;
1263 		args->rmtblkcnt = 0;
1264 	}
1265 
1266 	retval = xfs_attr_leaf_add(blk->bp, state->args);
1267 	if (retval == ENOSPC) {
1268 		if (state->path.active == 1) {
1269 			/*
1270 			 * Its really a single leaf node, but it had
1271 			 * out-of-line values so it looked like it *might*
1272 			 * have been a b-tree.
1273 			 */
1274 			xfs_da_state_free(state);
1275 			xfs_bmap_init(args->flist, args->firstblock);
1276 			error = xfs_attr_leaf_to_node(args);
1277 			if (!error) {
1278 				error = xfs_bmap_finish(&args->trans,
1279 							args->flist,
1280 							&committed);
1281 			}
1282 			if (error) {
1283 				ASSERT(committed);
1284 				args->trans = NULL;
1285 				xfs_bmap_cancel(args->flist);
1286 				goto out;
1287 			}
1288 
1289 			/*
1290 			 * bmap_finish() may have committed the last trans
1291 			 * and started a new one.  We need the inode to be
1292 			 * in all transactions.
1293 			 */
1294 			if (committed)
1295 				xfs_trans_ijoin(args->trans, dp);
1296 
1297 			/*
1298 			 * Commit the node conversion and start the next
1299 			 * trans in the chain.
1300 			 */
1301 			error = xfs_trans_roll(&args->trans, dp);
1302 			if (error)
1303 				goto out;
1304 
1305 			goto restart;
1306 		}
1307 
1308 		/*
1309 		 * Split as many Btree elements as required.
1310 		 * This code tracks the new and old attr's location
1311 		 * in the index/blkno/rmtblkno/rmtblkcnt fields and
1312 		 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
1313 		 */
1314 		xfs_bmap_init(args->flist, args->firstblock);
1315 		error = xfs_da_split(state);
1316 		if (!error) {
1317 			error = xfs_bmap_finish(&args->trans, args->flist,
1318 						&committed);
1319 		}
1320 		if (error) {
1321 			ASSERT(committed);
1322 			args->trans = NULL;
1323 			xfs_bmap_cancel(args->flist);
1324 			goto out;
1325 		}
1326 
1327 		/*
1328 		 * bmap_finish() may have committed the last trans and started
1329 		 * a new one.  We need the inode to be in all transactions.
1330 		 */
1331 		if (committed)
1332 			xfs_trans_ijoin(args->trans, dp);
1333 	} else {
1334 		/*
1335 		 * Addition succeeded, update Btree hashvals.
1336 		 */
1337 		xfs_da_fixhashpath(state, &state->path);
1338 	}
1339 
1340 	/*
1341 	 * Kill the state structure, we're done with it and need to
1342 	 * allow the buffers to come back later.
1343 	 */
1344 	xfs_da_state_free(state);
1345 	state = NULL;
1346 
1347 	/*
1348 	 * Commit the leaf addition or btree split and start the next
1349 	 * trans in the chain.
1350 	 */
1351 	error = xfs_trans_roll(&args->trans, dp);
1352 	if (error)
1353 		goto out;
1354 
1355 	/*
1356 	 * If there was an out-of-line value, allocate the blocks we
1357 	 * identified for its storage and copy the value.  This is done
1358 	 * after we create the attribute so that we don't overflow the
1359 	 * maximum size of a transaction and/or hit a deadlock.
1360 	 */
1361 	if (args->rmtblkno > 0) {
1362 		error = xfs_attr_rmtval_set(args);
1363 		if (error)
1364 			return(error);
1365 	}
1366 
1367 	/*
1368 	 * If this is an atomic rename operation, we must "flip" the
1369 	 * incomplete flags on the "new" and "old" attribute/value pairs
1370 	 * so that one disappears and one appears atomically.  Then we
1371 	 * must remove the "old" attribute/value pair.
1372 	 */
1373 	if (args->op_flags & XFS_DA_OP_RENAME) {
1374 		/*
1375 		 * In a separate transaction, set the incomplete flag on the
1376 		 * "old" attr and clear the incomplete flag on the "new" attr.
1377 		 */
1378 		error = xfs_attr_leaf_flipflags(args);
1379 		if (error)
1380 			goto out;
1381 
1382 		/*
1383 		 * Dismantle the "old" attribute/value pair by removing
1384 		 * a "remote" value (if it exists).
1385 		 */
1386 		args->index = args->index2;
1387 		args->blkno = args->blkno2;
1388 		args->rmtblkno = args->rmtblkno2;
1389 		args->rmtblkcnt = args->rmtblkcnt2;
1390 		if (args->rmtblkno) {
1391 			error = xfs_attr_rmtval_remove(args);
1392 			if (error)
1393 				return(error);
1394 		}
1395 
1396 		/*
1397 		 * Re-find the "old" attribute entry after any split ops.
1398 		 * The INCOMPLETE flag means that we will find the "old"
1399 		 * attr, not the "new" one.
1400 		 */
1401 		args->flags |= XFS_ATTR_INCOMPLETE;
1402 		state = xfs_da_state_alloc();
1403 		state->args = args;
1404 		state->mp = mp;
1405 		state->blocksize = state->mp->m_sb.sb_blocksize;
1406 		state->node_ents = state->mp->m_attr_node_ents;
1407 		state->inleaf = 0;
1408 		error = xfs_da_node_lookup_int(state, &retval);
1409 		if (error)
1410 			goto out;
1411 
1412 		/*
1413 		 * Remove the name and update the hashvals in the tree.
1414 		 */
1415 		blk = &state->path.blk[ state->path.active-1 ];
1416 		ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1417 		error = xfs_attr_leaf_remove(blk->bp, args);
1418 		xfs_da_fixhashpath(state, &state->path);
1419 
1420 		/*
1421 		 * Check to see if the tree needs to be collapsed.
1422 		 */
1423 		if (retval && (state->path.active > 1)) {
1424 			xfs_bmap_init(args->flist, args->firstblock);
1425 			error = xfs_da_join(state);
1426 			if (!error) {
1427 				error = xfs_bmap_finish(&args->trans,
1428 							args->flist,
1429 							&committed);
1430 			}
1431 			if (error) {
1432 				ASSERT(committed);
1433 				args->trans = NULL;
1434 				xfs_bmap_cancel(args->flist);
1435 				goto out;
1436 			}
1437 
1438 			/*
1439 			 * bmap_finish() may have committed the last trans
1440 			 * and started a new one.  We need the inode to be
1441 			 * in all transactions.
1442 			 */
1443 			if (committed)
1444 				xfs_trans_ijoin(args->trans, dp);
1445 		}
1446 
1447 		/*
1448 		 * Commit and start the next trans in the chain.
1449 		 */
1450 		error = xfs_trans_roll(&args->trans, dp);
1451 		if (error)
1452 			goto out;
1453 
1454 	} else if (args->rmtblkno > 0) {
1455 		/*
1456 		 * Added a "remote" value, just clear the incomplete flag.
1457 		 */
1458 		error = xfs_attr_leaf_clearflag(args);
1459 		if (error)
1460 			goto out;
1461 	}
1462 	retval = error = 0;
1463 
1464 out:
1465 	if (state)
1466 		xfs_da_state_free(state);
1467 	if (error)
1468 		return(error);
1469 	return(retval);
1470 }
1471 
1472 /*
1473  * Remove a name from a B-tree attribute list.
1474  *
1475  * This will involve walking down the Btree, and may involve joining
1476  * leaf nodes and even joining intermediate nodes up to and including
1477  * the root node (a special case of an intermediate node).
1478  */
1479 STATIC int
xfs_attr_node_removename(xfs_da_args_t * args)1480 xfs_attr_node_removename(xfs_da_args_t *args)
1481 {
1482 	xfs_da_state_t *state;
1483 	xfs_da_state_blk_t *blk;
1484 	xfs_inode_t *dp;
1485 	xfs_dabuf_t *bp;
1486 	int retval, error, committed, forkoff;
1487 
1488 	/*
1489 	 * Tie a string around our finger to remind us where we are.
1490 	 */
1491 	dp = args->dp;
1492 	state = xfs_da_state_alloc();
1493 	state->args = args;
1494 	state->mp = dp->i_mount;
1495 	state->blocksize = state->mp->m_sb.sb_blocksize;
1496 	state->node_ents = state->mp->m_attr_node_ents;
1497 
1498 	/*
1499 	 * Search to see if name exists, and get back a pointer to it.
1500 	 */
1501 	error = xfs_da_node_lookup_int(state, &retval);
1502 	if (error || (retval != EEXIST)) {
1503 		if (error == 0)
1504 			error = retval;
1505 		goto out;
1506 	}
1507 
1508 	/*
1509 	 * If there is an out-of-line value, de-allocate the blocks.
1510 	 * This is done before we remove the attribute so that we don't
1511 	 * overflow the maximum size of a transaction and/or hit a deadlock.
1512 	 */
1513 	blk = &state->path.blk[ state->path.active-1 ];
1514 	ASSERT(blk->bp != NULL);
1515 	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1516 	if (args->rmtblkno > 0) {
1517 		/*
1518 		 * Fill in disk block numbers in the state structure
1519 		 * so that we can get the buffers back after we commit
1520 		 * several transactions in the following calls.
1521 		 */
1522 		error = xfs_attr_fillstate(state);
1523 		if (error)
1524 			goto out;
1525 
1526 		/*
1527 		 * Mark the attribute as INCOMPLETE, then bunmapi() the
1528 		 * remote value.
1529 		 */
1530 		error = xfs_attr_leaf_setflag(args);
1531 		if (error)
1532 			goto out;
1533 		error = xfs_attr_rmtval_remove(args);
1534 		if (error)
1535 			goto out;
1536 
1537 		/*
1538 		 * Refill the state structure with buffers, the prior calls
1539 		 * released our buffers.
1540 		 */
1541 		error = xfs_attr_refillstate(state);
1542 		if (error)
1543 			goto out;
1544 	}
1545 
1546 	/*
1547 	 * Remove the name and update the hashvals in the tree.
1548 	 */
1549 	blk = &state->path.blk[ state->path.active-1 ];
1550 	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1551 	retval = xfs_attr_leaf_remove(blk->bp, args);
1552 	xfs_da_fixhashpath(state, &state->path);
1553 
1554 	/*
1555 	 * Check to see if the tree needs to be collapsed.
1556 	 */
1557 	if (retval && (state->path.active > 1)) {
1558 		xfs_bmap_init(args->flist, args->firstblock);
1559 		error = xfs_da_join(state);
1560 		if (!error) {
1561 			error = xfs_bmap_finish(&args->trans, args->flist,
1562 						&committed);
1563 		}
1564 		if (error) {
1565 			ASSERT(committed);
1566 			args->trans = NULL;
1567 			xfs_bmap_cancel(args->flist);
1568 			goto out;
1569 		}
1570 
1571 		/*
1572 		 * bmap_finish() may have committed the last trans and started
1573 		 * a new one.  We need the inode to be in all transactions.
1574 		 */
1575 		if (committed)
1576 			xfs_trans_ijoin(args->trans, dp);
1577 
1578 		/*
1579 		 * Commit the Btree join operation and start a new trans.
1580 		 */
1581 		error = xfs_trans_roll(&args->trans, dp);
1582 		if (error)
1583 			goto out;
1584 	}
1585 
1586 	/*
1587 	 * If the result is small enough, push it all into the inode.
1588 	 */
1589 	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
1590 		/*
1591 		 * Have to get rid of the copy of this dabuf in the state.
1592 		 */
1593 		ASSERT(state->path.active == 1);
1594 		ASSERT(state->path.blk[0].bp);
1595 		xfs_da_buf_done(state->path.blk[0].bp);
1596 		state->path.blk[0].bp = NULL;
1597 
1598 		error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
1599 						     XFS_ATTR_FORK);
1600 		if (error)
1601 			goto out;
1602 		ASSERT(be16_to_cpu(((xfs_attr_leafblock_t *)
1603 				      bp->data)->hdr.info.magic)
1604 						       == XFS_ATTR_LEAF_MAGIC);
1605 
1606 		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1607 			xfs_bmap_init(args->flist, args->firstblock);
1608 			error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1609 			/* bp is gone due to xfs_da_shrink_inode */
1610 			if (!error) {
1611 				error = xfs_bmap_finish(&args->trans,
1612 							args->flist,
1613 							&committed);
1614 			}
1615 			if (error) {
1616 				ASSERT(committed);
1617 				args->trans = NULL;
1618 				xfs_bmap_cancel(args->flist);
1619 				goto out;
1620 			}
1621 
1622 			/*
1623 			 * bmap_finish() may have committed the last trans
1624 			 * and started a new one.  We need the inode to be
1625 			 * in all transactions.
1626 			 */
1627 			if (committed)
1628 				xfs_trans_ijoin(args->trans, dp);
1629 		} else
1630 			xfs_da_brelse(args->trans, bp);
1631 	}
1632 	error = 0;
1633 
1634 out:
1635 	xfs_da_state_free(state);
1636 	return(error);
1637 }
1638 
1639 /*
1640  * Fill in the disk block numbers in the state structure for the buffers
1641  * that are attached to the state structure.
1642  * This is done so that we can quickly reattach ourselves to those buffers
1643  * after some set of transaction commits have released these buffers.
1644  */
1645 STATIC int
xfs_attr_fillstate(xfs_da_state_t * state)1646 xfs_attr_fillstate(xfs_da_state_t *state)
1647 {
1648 	xfs_da_state_path_t *path;
1649 	xfs_da_state_blk_t *blk;
1650 	int level;
1651 
1652 	/*
1653 	 * Roll down the "path" in the state structure, storing the on-disk
1654 	 * block number for those buffers in the "path".
1655 	 */
1656 	path = &state->path;
1657 	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1658 	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1659 		if (blk->bp) {
1660 			blk->disk_blkno = xfs_da_blkno(blk->bp);
1661 			xfs_da_buf_done(blk->bp);
1662 			blk->bp = NULL;
1663 		} else {
1664 			blk->disk_blkno = 0;
1665 		}
1666 	}
1667 
1668 	/*
1669 	 * Roll down the "altpath" in the state structure, storing the on-disk
1670 	 * block number for those buffers in the "altpath".
1671 	 */
1672 	path = &state->altpath;
1673 	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1674 	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1675 		if (blk->bp) {
1676 			blk->disk_blkno = xfs_da_blkno(blk->bp);
1677 			xfs_da_buf_done(blk->bp);
1678 			blk->bp = NULL;
1679 		} else {
1680 			blk->disk_blkno = 0;
1681 		}
1682 	}
1683 
1684 	return(0);
1685 }
1686 
1687 /*
1688  * Reattach the buffers to the state structure based on the disk block
1689  * numbers stored in the state structure.
1690  * This is done after some set of transaction commits have released those
1691  * buffers from our grip.
1692  */
1693 STATIC int
xfs_attr_refillstate(xfs_da_state_t * state)1694 xfs_attr_refillstate(xfs_da_state_t *state)
1695 {
1696 	xfs_da_state_path_t *path;
1697 	xfs_da_state_blk_t *blk;
1698 	int level, error;
1699 
1700 	/*
1701 	 * Roll down the "path" in the state structure, storing the on-disk
1702 	 * block number for those buffers in the "path".
1703 	 */
1704 	path = &state->path;
1705 	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1706 	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1707 		if (blk->disk_blkno) {
1708 			error = xfs_da_read_buf(state->args->trans,
1709 						state->args->dp,
1710 						blk->blkno, blk->disk_blkno,
1711 						&blk->bp, XFS_ATTR_FORK);
1712 			if (error)
1713 				return(error);
1714 		} else {
1715 			blk->bp = NULL;
1716 		}
1717 	}
1718 
1719 	/*
1720 	 * Roll down the "altpath" in the state structure, storing the on-disk
1721 	 * block number for those buffers in the "altpath".
1722 	 */
1723 	path = &state->altpath;
1724 	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1725 	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1726 		if (blk->disk_blkno) {
1727 			error = xfs_da_read_buf(state->args->trans,
1728 						state->args->dp,
1729 						blk->blkno, blk->disk_blkno,
1730 						&blk->bp, XFS_ATTR_FORK);
1731 			if (error)
1732 				return(error);
1733 		} else {
1734 			blk->bp = NULL;
1735 		}
1736 	}
1737 
1738 	return(0);
1739 }
1740 
1741 /*
1742  * Look up a filename in a node attribute list.
1743  *
1744  * This routine gets called for any attribute fork that has more than one
1745  * block, ie: both true Btree attr lists and for single-leaf-blocks with
1746  * "remote" values taking up more blocks.
1747  */
1748 STATIC int
xfs_attr_node_get(xfs_da_args_t * args)1749 xfs_attr_node_get(xfs_da_args_t *args)
1750 {
1751 	xfs_da_state_t *state;
1752 	xfs_da_state_blk_t *blk;
1753 	int error, retval;
1754 	int i;
1755 
1756 	state = xfs_da_state_alloc();
1757 	state->args = args;
1758 	state->mp = args->dp->i_mount;
1759 	state->blocksize = state->mp->m_sb.sb_blocksize;
1760 	state->node_ents = state->mp->m_attr_node_ents;
1761 
1762 	/*
1763 	 * Search to see if name exists, and get back a pointer to it.
1764 	 */
1765 	error = xfs_da_node_lookup_int(state, &retval);
1766 	if (error) {
1767 		retval = error;
1768 	} else if (retval == EEXIST) {
1769 		blk = &state->path.blk[ state->path.active-1 ];
1770 		ASSERT(blk->bp != NULL);
1771 		ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1772 
1773 		/*
1774 		 * Get the value, local or "remote"
1775 		 */
1776 		retval = xfs_attr_leaf_getvalue(blk->bp, args);
1777 		if (!retval && (args->rmtblkno > 0)
1778 		    && !(args->flags & ATTR_KERNOVAL)) {
1779 			retval = xfs_attr_rmtval_get(args);
1780 		}
1781 	}
1782 
1783 	/*
1784 	 * If not in a transaction, we have to release all the buffers.
1785 	 */
1786 	for (i = 0; i < state->path.active; i++) {
1787 		xfs_da_brelse(args->trans, state->path.blk[i].bp);
1788 		state->path.blk[i].bp = NULL;
1789 	}
1790 
1791 	xfs_da_state_free(state);
1792 	return(retval);
1793 }
1794 
1795 STATIC int							/* error */
xfs_attr_node_list(xfs_attr_list_context_t * context)1796 xfs_attr_node_list(xfs_attr_list_context_t *context)
1797 {
1798 	attrlist_cursor_kern_t *cursor;
1799 	xfs_attr_leafblock_t *leaf;
1800 	xfs_da_intnode_t *node;
1801 	xfs_da_node_entry_t *btree;
1802 	int error, i;
1803 	xfs_dabuf_t *bp;
1804 
1805 	cursor = context->cursor;
1806 	cursor->initted = 1;
1807 
1808 	/*
1809 	 * Do all sorts of validation on the passed-in cursor structure.
1810 	 * If anything is amiss, ignore the cursor and look up the hashval
1811 	 * starting from the btree root.
1812 	 */
1813 	bp = NULL;
1814 	if (cursor->blkno > 0) {
1815 		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
1816 					      &bp, XFS_ATTR_FORK);
1817 		if ((error != 0) && (error != EFSCORRUPTED))
1818 			return(error);
1819 		if (bp) {
1820 			node = bp->data;
1821 			switch (be16_to_cpu(node->hdr.info.magic)) {
1822 			case XFS_DA_NODE_MAGIC:
1823 				trace_xfs_attr_list_wrong_blk(context);
1824 				xfs_da_brelse(NULL, bp);
1825 				bp = NULL;
1826 				break;
1827 			case XFS_ATTR_LEAF_MAGIC:
1828 				leaf = bp->data;
1829 				if (cursor->hashval > be32_to_cpu(leaf->entries[
1830 				    be16_to_cpu(leaf->hdr.count)-1].hashval)) {
1831 					trace_xfs_attr_list_wrong_blk(context);
1832 					xfs_da_brelse(NULL, bp);
1833 					bp = NULL;
1834 				} else if (cursor->hashval <=
1835 					     be32_to_cpu(leaf->entries[0].hashval)) {
1836 					trace_xfs_attr_list_wrong_blk(context);
1837 					xfs_da_brelse(NULL, bp);
1838 					bp = NULL;
1839 				}
1840 				break;
1841 			default:
1842 				trace_xfs_attr_list_wrong_blk(context);
1843 				xfs_da_brelse(NULL, bp);
1844 				bp = NULL;
1845 			}
1846 		}
1847 	}
1848 
1849 	/*
1850 	 * We did not find what we expected given the cursor's contents,
1851 	 * so we start from the top and work down based on the hash value.
1852 	 * Note that start of node block is same as start of leaf block.
1853 	 */
1854 	if (bp == NULL) {
1855 		cursor->blkno = 0;
1856 		for (;;) {
1857 			error = xfs_da_read_buf(NULL, context->dp,
1858 						      cursor->blkno, -1, &bp,
1859 						      XFS_ATTR_FORK);
1860 			if (error)
1861 				return(error);
1862 			if (unlikely(bp == NULL)) {
1863 				XFS_ERROR_REPORT("xfs_attr_node_list(2)",
1864 						 XFS_ERRLEVEL_LOW,
1865 						 context->dp->i_mount);
1866 				return(XFS_ERROR(EFSCORRUPTED));
1867 			}
1868 			node = bp->data;
1869 			if (be16_to_cpu(node->hdr.info.magic)
1870 							== XFS_ATTR_LEAF_MAGIC)
1871 				break;
1872 			if (unlikely(be16_to_cpu(node->hdr.info.magic)
1873 							!= XFS_DA_NODE_MAGIC)) {
1874 				XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)",
1875 						     XFS_ERRLEVEL_LOW,
1876 						     context->dp->i_mount,
1877 						     node);
1878 				xfs_da_brelse(NULL, bp);
1879 				return(XFS_ERROR(EFSCORRUPTED));
1880 			}
1881 			btree = node->btree;
1882 			for (i = 0; i < be16_to_cpu(node->hdr.count);
1883 								btree++, i++) {
1884 				if (cursor->hashval
1885 						<= be32_to_cpu(btree->hashval)) {
1886 					cursor->blkno = be32_to_cpu(btree->before);
1887 					trace_xfs_attr_list_node_descend(context,
1888 									 btree);
1889 					break;
1890 				}
1891 			}
1892 			if (i == be16_to_cpu(node->hdr.count)) {
1893 				xfs_da_brelse(NULL, bp);
1894 				return(0);
1895 			}
1896 			xfs_da_brelse(NULL, bp);
1897 		}
1898 	}
1899 	ASSERT(bp != NULL);
1900 
1901 	/*
1902 	 * Roll upward through the blocks, processing each leaf block in
1903 	 * order.  As long as there is space in the result buffer, keep
1904 	 * adding the information.
1905 	 */
1906 	for (;;) {
1907 		leaf = bp->data;
1908 		if (unlikely(be16_to_cpu(leaf->hdr.info.magic)
1909 						!= XFS_ATTR_LEAF_MAGIC)) {
1910 			XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)",
1911 					     XFS_ERRLEVEL_LOW,
1912 					     context->dp->i_mount, leaf);
1913 			xfs_da_brelse(NULL, bp);
1914 			return(XFS_ERROR(EFSCORRUPTED));
1915 		}
1916 		error = xfs_attr_leaf_list_int(bp, context);
1917 		if (error) {
1918 			xfs_da_brelse(NULL, bp);
1919 			return error;
1920 		}
1921 		if (context->seen_enough || leaf->hdr.info.forw == 0)
1922 			break;
1923 		cursor->blkno = be32_to_cpu(leaf->hdr.info.forw);
1924 		xfs_da_brelse(NULL, bp);
1925 		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
1926 					      &bp, XFS_ATTR_FORK);
1927 		if (error)
1928 			return(error);
1929 		if (unlikely((bp == NULL))) {
1930 			XFS_ERROR_REPORT("xfs_attr_node_list(5)",
1931 					 XFS_ERRLEVEL_LOW,
1932 					 context->dp->i_mount);
1933 			return(XFS_ERROR(EFSCORRUPTED));
1934 		}
1935 	}
1936 	xfs_da_brelse(NULL, bp);
1937 	return(0);
1938 }
1939 
1940 
1941 /*========================================================================
1942  * External routines for manipulating out-of-line attribute values.
1943  *========================================================================*/
1944 
1945 /*
1946  * Read the value associated with an attribute from the out-of-line buffer
1947  * that we stored it in.
1948  */
1949 int
xfs_attr_rmtval_get(xfs_da_args_t * args)1950 xfs_attr_rmtval_get(xfs_da_args_t *args)
1951 {
1952 	xfs_bmbt_irec_t map[ATTR_RMTVALUE_MAPSIZE];
1953 	xfs_mount_t *mp;
1954 	xfs_daddr_t dblkno;
1955 	void *dst;
1956 	xfs_buf_t *bp;
1957 	int nmap, error, tmp, valuelen, blkcnt, i;
1958 	xfs_dablk_t lblkno;
1959 
1960 	ASSERT(!(args->flags & ATTR_KERNOVAL));
1961 
1962 	mp = args->dp->i_mount;
1963 	dst = args->value;
1964 	valuelen = args->valuelen;
1965 	lblkno = args->rmtblkno;
1966 	while (valuelen > 0) {
1967 		nmap = ATTR_RMTVALUE_MAPSIZE;
1968 		error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno,
1969 				  args->rmtblkcnt,
1970 				  XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
1971 				  NULL, 0, map, &nmap, NULL);
1972 		if (error)
1973 			return(error);
1974 		ASSERT(nmap >= 1);
1975 
1976 		for (i = 0; (i < nmap) && (valuelen > 0); i++) {
1977 			ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) &&
1978 			       (map[i].br_startblock != HOLESTARTBLOCK));
1979 			dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
1980 			blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
1981 			error = xfs_read_buf(mp, mp->m_ddev_targp, dblkno,
1982 					     blkcnt, XBF_LOCK | XBF_DONT_BLOCK,
1983 					     &bp);
1984 			if (error)
1985 				return(error);
1986 
1987 			tmp = (valuelen < XFS_BUF_SIZE(bp))
1988 				? valuelen : XFS_BUF_SIZE(bp);
1989 			xfs_buf_iomove(bp, 0, tmp, dst, XBRW_READ);
1990 			xfs_buf_relse(bp);
1991 			dst += tmp;
1992 			valuelen -= tmp;
1993 
1994 			lblkno += map[i].br_blockcount;
1995 		}
1996 	}
1997 	ASSERT(valuelen == 0);
1998 	return(0);
1999 }
2000 
2001 /*
2002  * Write the value associated with an attribute into the out-of-line buffer
2003  * that we have defined for it.
2004  */
2005 STATIC int
xfs_attr_rmtval_set(xfs_da_args_t * args)2006 xfs_attr_rmtval_set(xfs_da_args_t *args)
2007 {
2008 	xfs_mount_t *mp;
2009 	xfs_fileoff_t lfileoff;
2010 	xfs_inode_t *dp;
2011 	xfs_bmbt_irec_t map;
2012 	xfs_daddr_t dblkno;
2013 	void *src;
2014 	xfs_buf_t *bp;
2015 	xfs_dablk_t lblkno;
2016 	int blkcnt, valuelen, nmap, error, tmp, committed;
2017 
2018 	dp = args->dp;
2019 	mp = dp->i_mount;
2020 	src = args->value;
2021 
2022 	/*
2023 	 * Find a "hole" in the attribute address space large enough for
2024 	 * us to drop the new attribute's value into.
2025 	 */
2026 	blkcnt = XFS_B_TO_FSB(mp, args->valuelen);
2027 	lfileoff = 0;
2028 	error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff,
2029 						   XFS_ATTR_FORK);
2030 	if (error) {
2031 		return(error);
2032 	}
2033 	args->rmtblkno = lblkno = (xfs_dablk_t)lfileoff;
2034 	args->rmtblkcnt = blkcnt;
2035 
2036 	/*
2037 	 * Roll through the "value", allocating blocks on disk as required.
2038 	 */
2039 	while (blkcnt > 0) {
2040 		/*
2041 		 * Allocate a single extent, up to the size of the value.
2042 		 */
2043 		xfs_bmap_init(args->flist, args->firstblock);
2044 		nmap = 1;
2045 		error = xfs_bmapi(args->trans, dp, (xfs_fileoff_t)lblkno,
2046 				  blkcnt,
2047 				  XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA |
2048 							XFS_BMAPI_WRITE,
2049 				  args->firstblock, args->total, &map, &nmap,
2050 				  args->flist);
2051 		if (!error) {
2052 			error = xfs_bmap_finish(&args->trans, args->flist,
2053 						&committed);
2054 		}
2055 		if (error) {
2056 			ASSERT(committed);
2057 			args->trans = NULL;
2058 			xfs_bmap_cancel(args->flist);
2059 			return(error);
2060 		}
2061 
2062 		/*
2063 		 * bmap_finish() may have committed the last trans and started
2064 		 * a new one.  We need the inode to be in all transactions.
2065 		 */
2066 		if (committed)
2067 			xfs_trans_ijoin(args->trans, dp);
2068 
2069 		ASSERT(nmap == 1);
2070 		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
2071 		       (map.br_startblock != HOLESTARTBLOCK));
2072 		lblkno += map.br_blockcount;
2073 		blkcnt -= map.br_blockcount;
2074 
2075 		/*
2076 		 * Start the next trans in the chain.
2077 		 */
2078 		error = xfs_trans_roll(&args->trans, dp);
2079 		if (error)
2080 			return (error);
2081 	}
2082 
2083 	/*
2084 	 * Roll through the "value", copying the attribute value to the
2085 	 * already-allocated blocks.  Blocks are written synchronously
2086 	 * so that we can know they are all on disk before we turn off
2087 	 * the INCOMPLETE flag.
2088 	 */
2089 	lblkno = args->rmtblkno;
2090 	valuelen = args->valuelen;
2091 	while (valuelen > 0) {
2092 		/*
2093 		 * Try to remember where we decided to put the value.
2094 		 */
2095 		xfs_bmap_init(args->flist, args->firstblock);
2096 		nmap = 1;
2097 		error = xfs_bmapi(NULL, dp, (xfs_fileoff_t)lblkno,
2098 				  args->rmtblkcnt,
2099 				  XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
2100 				  args->firstblock, 0, &map, &nmap,
2101 				  NULL);
2102 		if (error) {
2103 			return(error);
2104 		}
2105 		ASSERT(nmap == 1);
2106 		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
2107 		       (map.br_startblock != HOLESTARTBLOCK));
2108 
2109 		dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
2110 		blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
2111 
2112 		bp = xfs_buf_get(mp->m_ddev_targp, dblkno, blkcnt,
2113 				 XBF_LOCK | XBF_DONT_BLOCK);
2114 		ASSERT(bp);
2115 		ASSERT(!XFS_BUF_GETERROR(bp));
2116 
2117 		tmp = (valuelen < XFS_BUF_SIZE(bp)) ? valuelen :
2118 							XFS_BUF_SIZE(bp);
2119 		xfs_buf_iomove(bp, 0, tmp, src, XBRW_WRITE);
2120 		if (tmp < XFS_BUF_SIZE(bp))
2121 			xfs_buf_zero(bp, tmp, XFS_BUF_SIZE(bp) - tmp);
2122 		if ((error = xfs_bwrite(mp, bp))) {/* GROT: NOTE: synchronous write */
2123 			return (error);
2124 		}
2125 		src += tmp;
2126 		valuelen -= tmp;
2127 
2128 		lblkno += map.br_blockcount;
2129 	}
2130 	ASSERT(valuelen == 0);
2131 	return(0);
2132 }
2133 
2134 /*
2135  * Remove the value associated with an attribute by deleting the
2136  * out-of-line buffer that it is stored on.
2137  */
2138 STATIC int
xfs_attr_rmtval_remove(xfs_da_args_t * args)2139 xfs_attr_rmtval_remove(xfs_da_args_t *args)
2140 {
2141 	xfs_mount_t *mp;
2142 	xfs_bmbt_irec_t map;
2143 	xfs_buf_t *bp;
2144 	xfs_daddr_t dblkno;
2145 	xfs_dablk_t lblkno;
2146 	int valuelen, blkcnt, nmap, error, done, committed;
2147 
2148 	mp = args->dp->i_mount;
2149 
2150 	/*
2151 	 * Roll through the "value", invalidating the attribute value's
2152 	 * blocks.
2153 	 */
2154 	lblkno = args->rmtblkno;
2155 	valuelen = args->rmtblkcnt;
2156 	while (valuelen > 0) {
2157 		/*
2158 		 * Try to remember where we decided to put the value.
2159 		 */
2160 		xfs_bmap_init(args->flist, args->firstblock);
2161 		nmap = 1;
2162 		error = xfs_bmapi(NULL, args->dp, (xfs_fileoff_t)lblkno,
2163 					args->rmtblkcnt,
2164 					XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
2165 					args->firstblock, 0, &map, &nmap,
2166 					args->flist);
2167 		if (error) {
2168 			return(error);
2169 		}
2170 		ASSERT(nmap == 1);
2171 		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
2172 		       (map.br_startblock != HOLESTARTBLOCK));
2173 
2174 		dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
2175 		blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
2176 
2177 		/*
2178 		 * If the "remote" value is in the cache, remove it.
2179 		 */
2180 		bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt, XBF_TRYLOCK);
2181 		if (bp) {
2182 			XFS_BUF_STALE(bp);
2183 			XFS_BUF_UNDELAYWRITE(bp);
2184 			xfs_buf_relse(bp);
2185 			bp = NULL;
2186 		}
2187 
2188 		valuelen -= map.br_blockcount;
2189 
2190 		lblkno += map.br_blockcount;
2191 	}
2192 
2193 	/*
2194 	 * Keep de-allocating extents until the remote-value region is gone.
2195 	 */
2196 	lblkno = args->rmtblkno;
2197 	blkcnt = args->rmtblkcnt;
2198 	done = 0;
2199 	while (!done) {
2200 		xfs_bmap_init(args->flist, args->firstblock);
2201 		error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt,
2202 				    XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
2203 				    1, args->firstblock, args->flist,
2204 				    &done);
2205 		if (!error) {
2206 			error = xfs_bmap_finish(&args->trans, args->flist,
2207 						&committed);
2208 		}
2209 		if (error) {
2210 			ASSERT(committed);
2211 			args->trans = NULL;
2212 			xfs_bmap_cancel(args->flist);
2213 			return(error);
2214 		}
2215 
2216 		/*
2217 		 * bmap_finish() may have committed the last trans and started
2218 		 * a new one.  We need the inode to be in all transactions.
2219 		 */
2220 		if (committed)
2221 			xfs_trans_ijoin(args->trans, args->dp);
2222 
2223 		/*
2224 		 * Close out trans and start the next one in the chain.
2225 		 */
2226 		error = xfs_trans_roll(&args->trans, args->dp);
2227 		if (error)
2228 			return (error);
2229 	}
2230 	return(0);
2231 }
2232