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 	trace_xfs_attr_sf_addname(args);
857 
858 	retval = xfs_attr_shortform_lookup(args);
859 	if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
860 		return(retval);
861 	} else if (retval == EEXIST) {
862 		if (args->flags & ATTR_CREATE)
863 			return(retval);
864 		retval = xfs_attr_shortform_remove(args);
865 		ASSERT(retval == 0);
866 	}
867 
868 	if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
869 	    args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
870 		return(XFS_ERROR(ENOSPC));
871 
872 	newsize = XFS_ATTR_SF_TOTSIZE(args->dp);
873 	newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen);
874 
875 	forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
876 	if (!forkoff)
877 		return(XFS_ERROR(ENOSPC));
878 
879 	xfs_attr_shortform_add(args, forkoff);
880 	return(0);
881 }
882 
883 
884 /*========================================================================
885  * External routines when attribute list is one block
886  *========================================================================*/
887 
888 /*
889  * Add a name to the leaf attribute list structure
890  *
891  * This leaf block cannot have a "remote" value, we only call this routine
892  * if bmap_one_block() says there is only one block (ie: no remote blks).
893  */
894 STATIC int
xfs_attr_leaf_addname(xfs_da_args_t * args)895 xfs_attr_leaf_addname(xfs_da_args_t *args)
896 {
897 	xfs_inode_t *dp;
898 	xfs_dabuf_t *bp;
899 	int retval, error, committed, forkoff;
900 
901 	trace_xfs_attr_leaf_addname(args);
902 
903 	/*
904 	 * Read the (only) block in the attribute list in.
905 	 */
906 	dp = args->dp;
907 	args->blkno = 0;
908 	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
909 					     XFS_ATTR_FORK);
910 	if (error)
911 		return(error);
912 	ASSERT(bp != NULL);
913 
914 	/*
915 	 * Look up the given attribute in the leaf block.  Figure out if
916 	 * the given flags produce an error or call for an atomic rename.
917 	 */
918 	retval = xfs_attr_leaf_lookup_int(bp, args);
919 	if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
920 		xfs_da_brelse(args->trans, bp);
921 		return(retval);
922 	} else if (retval == EEXIST) {
923 		if (args->flags & ATTR_CREATE) {	/* pure create op */
924 			xfs_da_brelse(args->trans, bp);
925 			return(retval);
926 		}
927 
928 		trace_xfs_attr_leaf_replace(args);
929 
930 		args->op_flags |= XFS_DA_OP_RENAME;	/* an atomic rename */
931 		args->blkno2 = args->blkno;		/* set 2nd entry info*/
932 		args->index2 = args->index;
933 		args->rmtblkno2 = args->rmtblkno;
934 		args->rmtblkcnt2 = args->rmtblkcnt;
935 	}
936 
937 	/*
938 	 * Add the attribute to the leaf block, transitioning to a Btree
939 	 * if required.
940 	 */
941 	retval = xfs_attr_leaf_add(bp, args);
942 	xfs_da_buf_done(bp);
943 	if (retval == ENOSPC) {
944 		/*
945 		 * Promote the attribute list to the Btree format, then
946 		 * Commit that transaction so that the node_addname() call
947 		 * can manage its own transactions.
948 		 */
949 		xfs_bmap_init(args->flist, args->firstblock);
950 		error = xfs_attr_leaf_to_node(args);
951 		if (!error) {
952 			error = xfs_bmap_finish(&args->trans, args->flist,
953 						&committed);
954 		}
955 		if (error) {
956 			ASSERT(committed);
957 			args->trans = NULL;
958 			xfs_bmap_cancel(args->flist);
959 			return(error);
960 		}
961 
962 		/*
963 		 * bmap_finish() may have committed the last trans and started
964 		 * a new one.  We need the inode to be in all transactions.
965 		 */
966 		if (committed)
967 			xfs_trans_ijoin(args->trans, dp, 0);
968 
969 		/*
970 		 * Commit the current trans (including the inode) and start
971 		 * a new one.
972 		 */
973 		error = xfs_trans_roll(&args->trans, dp);
974 		if (error)
975 			return (error);
976 
977 		/*
978 		 * Fob the whole rest of the problem off on the Btree code.
979 		 */
980 		error = xfs_attr_node_addname(args);
981 		return(error);
982 	}
983 
984 	/*
985 	 * Commit the transaction that added the attr name so that
986 	 * later routines can manage their own transactions.
987 	 */
988 	error = xfs_trans_roll(&args->trans, dp);
989 	if (error)
990 		return (error);
991 
992 	/*
993 	 * If there was an out-of-line value, allocate the blocks we
994 	 * identified for its storage and copy the value.  This is done
995 	 * after we create the attribute so that we don't overflow the
996 	 * maximum size of a transaction and/or hit a deadlock.
997 	 */
998 	if (args->rmtblkno > 0) {
999 		error = xfs_attr_rmtval_set(args);
1000 		if (error)
1001 			return(error);
1002 	}
1003 
1004 	/*
1005 	 * If this is an atomic rename operation, we must "flip" the
1006 	 * incomplete flags on the "new" and "old" attribute/value pairs
1007 	 * so that one disappears and one appears atomically.  Then we
1008 	 * must remove the "old" attribute/value pair.
1009 	 */
1010 	if (args->op_flags & XFS_DA_OP_RENAME) {
1011 		/*
1012 		 * In a separate transaction, set the incomplete flag on the
1013 		 * "old" attr and clear the incomplete flag on the "new" attr.
1014 		 */
1015 		error = xfs_attr_leaf_flipflags(args);
1016 		if (error)
1017 			return(error);
1018 
1019 		/*
1020 		 * Dismantle the "old" attribute/value pair by removing
1021 		 * a "remote" value (if it exists).
1022 		 */
1023 		args->index = args->index2;
1024 		args->blkno = args->blkno2;
1025 		args->rmtblkno = args->rmtblkno2;
1026 		args->rmtblkcnt = args->rmtblkcnt2;
1027 		if (args->rmtblkno) {
1028 			error = xfs_attr_rmtval_remove(args);
1029 			if (error)
1030 				return(error);
1031 		}
1032 
1033 		/*
1034 		 * Read in the block containing the "old" attr, then
1035 		 * remove the "old" attr from that block (neat, huh!)
1036 		 */
1037 		error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1,
1038 						     &bp, XFS_ATTR_FORK);
1039 		if (error)
1040 			return(error);
1041 		ASSERT(bp != NULL);
1042 		(void)xfs_attr_leaf_remove(bp, args);
1043 
1044 		/*
1045 		 * If the result is small enough, shrink it all into the inode.
1046 		 */
1047 		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1048 			xfs_bmap_init(args->flist, args->firstblock);
1049 			error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1050 			/* bp is gone due to xfs_da_shrink_inode */
1051 			if (!error) {
1052 				error = xfs_bmap_finish(&args->trans,
1053 							args->flist,
1054 							&committed);
1055 			}
1056 			if (error) {
1057 				ASSERT(committed);
1058 				args->trans = NULL;
1059 				xfs_bmap_cancel(args->flist);
1060 				return(error);
1061 			}
1062 
1063 			/*
1064 			 * bmap_finish() may have committed the last trans
1065 			 * and started a new one.  We need the inode to be
1066 			 * in all transactions.
1067 			 */
1068 			if (committed)
1069 				xfs_trans_ijoin(args->trans, dp, 0);
1070 		} else
1071 			xfs_da_buf_done(bp);
1072 
1073 		/*
1074 		 * Commit the remove and start the next trans in series.
1075 		 */
1076 		error = xfs_trans_roll(&args->trans, dp);
1077 
1078 	} else if (args->rmtblkno > 0) {
1079 		/*
1080 		 * Added a "remote" value, just clear the incomplete flag.
1081 		 */
1082 		error = xfs_attr_leaf_clearflag(args);
1083 	}
1084 	return(error);
1085 }
1086 
1087 /*
1088  * Remove a name from the leaf attribute list structure
1089  *
1090  * This leaf block cannot have a "remote" value, we only call this routine
1091  * if bmap_one_block() says there is only one block (ie: no remote blks).
1092  */
1093 STATIC int
xfs_attr_leaf_removename(xfs_da_args_t * args)1094 xfs_attr_leaf_removename(xfs_da_args_t *args)
1095 {
1096 	xfs_inode_t *dp;
1097 	xfs_dabuf_t *bp;
1098 	int error, committed, forkoff;
1099 
1100 	trace_xfs_attr_leaf_removename(args);
1101 
1102 	/*
1103 	 * Remove the attribute.
1104 	 */
1105 	dp = args->dp;
1106 	args->blkno = 0;
1107 	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
1108 					     XFS_ATTR_FORK);
1109 	if (error) {
1110 		return(error);
1111 	}
1112 
1113 	ASSERT(bp != NULL);
1114 	error = xfs_attr_leaf_lookup_int(bp, args);
1115 	if (error == ENOATTR) {
1116 		xfs_da_brelse(args->trans, bp);
1117 		return(error);
1118 	}
1119 
1120 	(void)xfs_attr_leaf_remove(bp, args);
1121 
1122 	/*
1123 	 * If the result is small enough, shrink it all into the inode.
1124 	 */
1125 	if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1126 		xfs_bmap_init(args->flist, args->firstblock);
1127 		error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1128 		/* bp is gone due to xfs_da_shrink_inode */
1129 		if (!error) {
1130 			error = xfs_bmap_finish(&args->trans, args->flist,
1131 						&committed);
1132 		}
1133 		if (error) {
1134 			ASSERT(committed);
1135 			args->trans = NULL;
1136 			xfs_bmap_cancel(args->flist);
1137 			return(error);
1138 		}
1139 
1140 		/*
1141 		 * bmap_finish() may have committed the last trans and started
1142 		 * a new one.  We need the inode to be in all transactions.
1143 		 */
1144 		if (committed)
1145 			xfs_trans_ijoin(args->trans, dp, 0);
1146 	} else
1147 		xfs_da_buf_done(bp);
1148 	return(0);
1149 }
1150 
1151 /*
1152  * Look up a name in a leaf attribute list structure.
1153  *
1154  * This leaf block cannot have a "remote" value, we only call this routine
1155  * if bmap_one_block() says there is only one block (ie: no remote blks).
1156  */
1157 STATIC int
xfs_attr_leaf_get(xfs_da_args_t * args)1158 xfs_attr_leaf_get(xfs_da_args_t *args)
1159 {
1160 	xfs_dabuf_t *bp;
1161 	int error;
1162 
1163 	args->blkno = 0;
1164 	error = xfs_da_read_buf(args->trans, args->dp, args->blkno, -1, &bp,
1165 					     XFS_ATTR_FORK);
1166 	if (error)
1167 		return(error);
1168 	ASSERT(bp != NULL);
1169 
1170 	error = xfs_attr_leaf_lookup_int(bp, args);
1171 	if (error != EEXIST)  {
1172 		xfs_da_brelse(args->trans, bp);
1173 		return(error);
1174 	}
1175 	error = xfs_attr_leaf_getvalue(bp, args);
1176 	xfs_da_brelse(args->trans, bp);
1177 	if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) {
1178 		error = xfs_attr_rmtval_get(args);
1179 	}
1180 	return(error);
1181 }
1182 
1183 /*
1184  * Copy out attribute entries for attr_list(), for leaf attribute lists.
1185  */
1186 STATIC int
xfs_attr_leaf_list(xfs_attr_list_context_t * context)1187 xfs_attr_leaf_list(xfs_attr_list_context_t *context)
1188 {
1189 	xfs_attr_leafblock_t *leaf;
1190 	int error;
1191 	xfs_dabuf_t *bp;
1192 
1193 	context->cursor->blkno = 0;
1194 	error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK);
1195 	if (error)
1196 		return XFS_ERROR(error);
1197 	ASSERT(bp != NULL);
1198 	leaf = bp->data;
1199 	if (unlikely(leaf->hdr.info.magic != cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) {
1200 		XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW,
1201 				     context->dp->i_mount, leaf);
1202 		xfs_da_brelse(NULL, bp);
1203 		return XFS_ERROR(EFSCORRUPTED);
1204 	}
1205 
1206 	error = xfs_attr_leaf_list_int(bp, context);
1207 	xfs_da_brelse(NULL, bp);
1208 	return XFS_ERROR(error);
1209 }
1210 
1211 
1212 /*========================================================================
1213  * External routines when attribute list size > XFS_LBSIZE(mp).
1214  *========================================================================*/
1215 
1216 /*
1217  * Add a name to a Btree-format attribute list.
1218  *
1219  * This will involve walking down the Btree, and may involve splitting
1220  * leaf nodes and even splitting intermediate nodes up to and including
1221  * the root node (a special case of an intermediate node).
1222  *
1223  * "Remote" attribute values confuse the issue and atomic rename operations
1224  * add a whole extra layer of confusion on top of that.
1225  */
1226 STATIC int
xfs_attr_node_addname(xfs_da_args_t * args)1227 xfs_attr_node_addname(xfs_da_args_t *args)
1228 {
1229 	xfs_da_state_t *state;
1230 	xfs_da_state_blk_t *blk;
1231 	xfs_inode_t *dp;
1232 	xfs_mount_t *mp;
1233 	int committed, retval, error;
1234 
1235 	trace_xfs_attr_node_addname(args);
1236 
1237 	/*
1238 	 * Fill in bucket of arguments/results/context to carry around.
1239 	 */
1240 	dp = args->dp;
1241 	mp = dp->i_mount;
1242 restart:
1243 	state = xfs_da_state_alloc();
1244 	state->args = args;
1245 	state->mp = mp;
1246 	state->blocksize = state->mp->m_sb.sb_blocksize;
1247 	state->node_ents = state->mp->m_attr_node_ents;
1248 
1249 	/*
1250 	 * Search to see if name already exists, and get back a pointer
1251 	 * to where it should go.
1252 	 */
1253 	error = xfs_da_node_lookup_int(state, &retval);
1254 	if (error)
1255 		goto out;
1256 	blk = &state->path.blk[ state->path.active-1 ];
1257 	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1258 	if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
1259 		goto out;
1260 	} else if (retval == EEXIST) {
1261 		if (args->flags & ATTR_CREATE)
1262 			goto out;
1263 
1264 		trace_xfs_attr_node_replace(args);
1265 
1266 		args->op_flags |= XFS_DA_OP_RENAME;	/* atomic rename op */
1267 		args->blkno2 = args->blkno;		/* set 2nd entry info*/
1268 		args->index2 = args->index;
1269 		args->rmtblkno2 = args->rmtblkno;
1270 		args->rmtblkcnt2 = args->rmtblkcnt;
1271 		args->rmtblkno = 0;
1272 		args->rmtblkcnt = 0;
1273 	}
1274 
1275 	retval = xfs_attr_leaf_add(blk->bp, state->args);
1276 	if (retval == ENOSPC) {
1277 		if (state->path.active == 1) {
1278 			/*
1279 			 * Its really a single leaf node, but it had
1280 			 * out-of-line values so it looked like it *might*
1281 			 * have been a b-tree.
1282 			 */
1283 			xfs_da_state_free(state);
1284 			xfs_bmap_init(args->flist, args->firstblock);
1285 			error = xfs_attr_leaf_to_node(args);
1286 			if (!error) {
1287 				error = xfs_bmap_finish(&args->trans,
1288 							args->flist,
1289 							&committed);
1290 			}
1291 			if (error) {
1292 				ASSERT(committed);
1293 				args->trans = NULL;
1294 				xfs_bmap_cancel(args->flist);
1295 				goto out;
1296 			}
1297 
1298 			/*
1299 			 * bmap_finish() may have committed the last trans
1300 			 * and started a new one.  We need the inode to be
1301 			 * in all transactions.
1302 			 */
1303 			if (committed)
1304 				xfs_trans_ijoin(args->trans, dp, 0);
1305 
1306 			/*
1307 			 * Commit the node conversion and start the next
1308 			 * trans in the chain.
1309 			 */
1310 			error = xfs_trans_roll(&args->trans, dp);
1311 			if (error)
1312 				goto out;
1313 
1314 			goto restart;
1315 		}
1316 
1317 		/*
1318 		 * Split as many Btree elements as required.
1319 		 * This code tracks the new and old attr's location
1320 		 * in the index/blkno/rmtblkno/rmtblkcnt fields and
1321 		 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
1322 		 */
1323 		xfs_bmap_init(args->flist, args->firstblock);
1324 		error = xfs_da_split(state);
1325 		if (!error) {
1326 			error = xfs_bmap_finish(&args->trans, args->flist,
1327 						&committed);
1328 		}
1329 		if (error) {
1330 			ASSERT(committed);
1331 			args->trans = NULL;
1332 			xfs_bmap_cancel(args->flist);
1333 			goto out;
1334 		}
1335 
1336 		/*
1337 		 * bmap_finish() may have committed the last trans and started
1338 		 * a new one.  We need the inode to be in all transactions.
1339 		 */
1340 		if (committed)
1341 			xfs_trans_ijoin(args->trans, dp, 0);
1342 	} else {
1343 		/*
1344 		 * Addition succeeded, update Btree hashvals.
1345 		 */
1346 		xfs_da_fixhashpath(state, &state->path);
1347 	}
1348 
1349 	/*
1350 	 * Kill the state structure, we're done with it and need to
1351 	 * allow the buffers to come back later.
1352 	 */
1353 	xfs_da_state_free(state);
1354 	state = NULL;
1355 
1356 	/*
1357 	 * Commit the leaf addition or btree split and start the next
1358 	 * trans in the chain.
1359 	 */
1360 	error = xfs_trans_roll(&args->trans, dp);
1361 	if (error)
1362 		goto out;
1363 
1364 	/*
1365 	 * If there was an out-of-line value, allocate the blocks we
1366 	 * identified for its storage and copy the value.  This is done
1367 	 * after we create the attribute so that we don't overflow the
1368 	 * maximum size of a transaction and/or hit a deadlock.
1369 	 */
1370 	if (args->rmtblkno > 0) {
1371 		error = xfs_attr_rmtval_set(args);
1372 		if (error)
1373 			return(error);
1374 	}
1375 
1376 	/*
1377 	 * If this is an atomic rename operation, we must "flip" the
1378 	 * incomplete flags on the "new" and "old" attribute/value pairs
1379 	 * so that one disappears and one appears atomically.  Then we
1380 	 * must remove the "old" attribute/value pair.
1381 	 */
1382 	if (args->op_flags & XFS_DA_OP_RENAME) {
1383 		/*
1384 		 * In a separate transaction, set the incomplete flag on the
1385 		 * "old" attr and clear the incomplete flag on the "new" attr.
1386 		 */
1387 		error = xfs_attr_leaf_flipflags(args);
1388 		if (error)
1389 			goto out;
1390 
1391 		/*
1392 		 * Dismantle the "old" attribute/value pair by removing
1393 		 * a "remote" value (if it exists).
1394 		 */
1395 		args->index = args->index2;
1396 		args->blkno = args->blkno2;
1397 		args->rmtblkno = args->rmtblkno2;
1398 		args->rmtblkcnt = args->rmtblkcnt2;
1399 		if (args->rmtblkno) {
1400 			error = xfs_attr_rmtval_remove(args);
1401 			if (error)
1402 				return(error);
1403 		}
1404 
1405 		/*
1406 		 * Re-find the "old" attribute entry after any split ops.
1407 		 * The INCOMPLETE flag means that we will find the "old"
1408 		 * attr, not the "new" one.
1409 		 */
1410 		args->flags |= XFS_ATTR_INCOMPLETE;
1411 		state = xfs_da_state_alloc();
1412 		state->args = args;
1413 		state->mp = mp;
1414 		state->blocksize = state->mp->m_sb.sb_blocksize;
1415 		state->node_ents = state->mp->m_attr_node_ents;
1416 		state->inleaf = 0;
1417 		error = xfs_da_node_lookup_int(state, &retval);
1418 		if (error)
1419 			goto out;
1420 
1421 		/*
1422 		 * Remove the name and update the hashvals in the tree.
1423 		 */
1424 		blk = &state->path.blk[ state->path.active-1 ];
1425 		ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1426 		error = xfs_attr_leaf_remove(blk->bp, args);
1427 		xfs_da_fixhashpath(state, &state->path);
1428 
1429 		/*
1430 		 * Check to see if the tree needs to be collapsed.
1431 		 */
1432 		if (retval && (state->path.active > 1)) {
1433 			xfs_bmap_init(args->flist, args->firstblock);
1434 			error = xfs_da_join(state);
1435 			if (!error) {
1436 				error = xfs_bmap_finish(&args->trans,
1437 							args->flist,
1438 							&committed);
1439 			}
1440 			if (error) {
1441 				ASSERT(committed);
1442 				args->trans = NULL;
1443 				xfs_bmap_cancel(args->flist);
1444 				goto out;
1445 			}
1446 
1447 			/*
1448 			 * bmap_finish() may have committed the last trans
1449 			 * and started a new one.  We need the inode to be
1450 			 * in all transactions.
1451 			 */
1452 			if (committed)
1453 				xfs_trans_ijoin(args->trans, dp, 0);
1454 		}
1455 
1456 		/*
1457 		 * Commit and start the next trans in the chain.
1458 		 */
1459 		error = xfs_trans_roll(&args->trans, dp);
1460 		if (error)
1461 			goto out;
1462 
1463 	} else if (args->rmtblkno > 0) {
1464 		/*
1465 		 * Added a "remote" value, just clear the incomplete flag.
1466 		 */
1467 		error = xfs_attr_leaf_clearflag(args);
1468 		if (error)
1469 			goto out;
1470 	}
1471 	retval = error = 0;
1472 
1473 out:
1474 	if (state)
1475 		xfs_da_state_free(state);
1476 	if (error)
1477 		return(error);
1478 	return(retval);
1479 }
1480 
1481 /*
1482  * Remove a name from a B-tree attribute list.
1483  *
1484  * This will involve walking down the Btree, and may involve joining
1485  * leaf nodes and even joining intermediate nodes up to and including
1486  * the root node (a special case of an intermediate node).
1487  */
1488 STATIC int
xfs_attr_node_removename(xfs_da_args_t * args)1489 xfs_attr_node_removename(xfs_da_args_t *args)
1490 {
1491 	xfs_da_state_t *state;
1492 	xfs_da_state_blk_t *blk;
1493 	xfs_inode_t *dp;
1494 	xfs_dabuf_t *bp;
1495 	int retval, error, committed, forkoff;
1496 
1497 	trace_xfs_attr_node_removename(args);
1498 
1499 	/*
1500 	 * Tie a string around our finger to remind us where we are.
1501 	 */
1502 	dp = args->dp;
1503 	state = xfs_da_state_alloc();
1504 	state->args = args;
1505 	state->mp = dp->i_mount;
1506 	state->blocksize = state->mp->m_sb.sb_blocksize;
1507 	state->node_ents = state->mp->m_attr_node_ents;
1508 
1509 	/*
1510 	 * Search to see if name exists, and get back a pointer to it.
1511 	 */
1512 	error = xfs_da_node_lookup_int(state, &retval);
1513 	if (error || (retval != EEXIST)) {
1514 		if (error == 0)
1515 			error = retval;
1516 		goto out;
1517 	}
1518 
1519 	/*
1520 	 * If there is an out-of-line value, de-allocate the blocks.
1521 	 * This is done before we remove the attribute so that we don't
1522 	 * overflow the maximum size of a transaction and/or hit a deadlock.
1523 	 */
1524 	blk = &state->path.blk[ state->path.active-1 ];
1525 	ASSERT(blk->bp != NULL);
1526 	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1527 	if (args->rmtblkno > 0) {
1528 		/*
1529 		 * Fill in disk block numbers in the state structure
1530 		 * so that we can get the buffers back after we commit
1531 		 * several transactions in the following calls.
1532 		 */
1533 		error = xfs_attr_fillstate(state);
1534 		if (error)
1535 			goto out;
1536 
1537 		/*
1538 		 * Mark the attribute as INCOMPLETE, then bunmapi() the
1539 		 * remote value.
1540 		 */
1541 		error = xfs_attr_leaf_setflag(args);
1542 		if (error)
1543 			goto out;
1544 		error = xfs_attr_rmtval_remove(args);
1545 		if (error)
1546 			goto out;
1547 
1548 		/*
1549 		 * Refill the state structure with buffers, the prior calls
1550 		 * released our buffers.
1551 		 */
1552 		error = xfs_attr_refillstate(state);
1553 		if (error)
1554 			goto out;
1555 	}
1556 
1557 	/*
1558 	 * Remove the name and update the hashvals in the tree.
1559 	 */
1560 	blk = &state->path.blk[ state->path.active-1 ];
1561 	ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1562 	retval = xfs_attr_leaf_remove(blk->bp, args);
1563 	xfs_da_fixhashpath(state, &state->path);
1564 
1565 	/*
1566 	 * Check to see if the tree needs to be collapsed.
1567 	 */
1568 	if (retval && (state->path.active > 1)) {
1569 		xfs_bmap_init(args->flist, args->firstblock);
1570 		error = xfs_da_join(state);
1571 		if (!error) {
1572 			error = xfs_bmap_finish(&args->trans, args->flist,
1573 						&committed);
1574 		}
1575 		if (error) {
1576 			ASSERT(committed);
1577 			args->trans = NULL;
1578 			xfs_bmap_cancel(args->flist);
1579 			goto out;
1580 		}
1581 
1582 		/*
1583 		 * bmap_finish() may have committed the last trans and started
1584 		 * a new one.  We need the inode to be in all transactions.
1585 		 */
1586 		if (committed)
1587 			xfs_trans_ijoin(args->trans, dp, 0);
1588 
1589 		/*
1590 		 * Commit the Btree join operation and start a new trans.
1591 		 */
1592 		error = xfs_trans_roll(&args->trans, dp);
1593 		if (error)
1594 			goto out;
1595 	}
1596 
1597 	/*
1598 	 * If the result is small enough, push it all into the inode.
1599 	 */
1600 	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
1601 		/*
1602 		 * Have to get rid of the copy of this dabuf in the state.
1603 		 */
1604 		ASSERT(state->path.active == 1);
1605 		ASSERT(state->path.blk[0].bp);
1606 		xfs_da_buf_done(state->path.blk[0].bp);
1607 		state->path.blk[0].bp = NULL;
1608 
1609 		error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
1610 						     XFS_ATTR_FORK);
1611 		if (error)
1612 			goto out;
1613 		ASSERT((((xfs_attr_leafblock_t *)bp->data)->hdr.info.magic) ==
1614 		       cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
1615 
1616 		if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1617 			xfs_bmap_init(args->flist, args->firstblock);
1618 			error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1619 			/* bp is gone due to xfs_da_shrink_inode */
1620 			if (!error) {
1621 				error = xfs_bmap_finish(&args->trans,
1622 							args->flist,
1623 							&committed);
1624 			}
1625 			if (error) {
1626 				ASSERT(committed);
1627 				args->trans = NULL;
1628 				xfs_bmap_cancel(args->flist);
1629 				goto out;
1630 			}
1631 
1632 			/*
1633 			 * bmap_finish() may have committed the last trans
1634 			 * and started a new one.  We need the inode to be
1635 			 * in all transactions.
1636 			 */
1637 			if (committed)
1638 				xfs_trans_ijoin(args->trans, dp, 0);
1639 		} else
1640 			xfs_da_brelse(args->trans, bp);
1641 	}
1642 	error = 0;
1643 
1644 out:
1645 	xfs_da_state_free(state);
1646 	return(error);
1647 }
1648 
1649 /*
1650  * Fill in the disk block numbers in the state structure for the buffers
1651  * that are attached to the state structure.
1652  * This is done so that we can quickly reattach ourselves to those buffers
1653  * after some set of transaction commits have released these buffers.
1654  */
1655 STATIC int
xfs_attr_fillstate(xfs_da_state_t * state)1656 xfs_attr_fillstate(xfs_da_state_t *state)
1657 {
1658 	xfs_da_state_path_t *path;
1659 	xfs_da_state_blk_t *blk;
1660 	int level;
1661 
1662 	/*
1663 	 * Roll down the "path" in the state structure, storing the on-disk
1664 	 * block number for those buffers in the "path".
1665 	 */
1666 	path = &state->path;
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 	/*
1679 	 * Roll down the "altpath" in the state structure, storing the on-disk
1680 	 * block number for those buffers in the "altpath".
1681 	 */
1682 	path = &state->altpath;
1683 	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1684 	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1685 		if (blk->bp) {
1686 			blk->disk_blkno = xfs_da_blkno(blk->bp);
1687 			xfs_da_buf_done(blk->bp);
1688 			blk->bp = NULL;
1689 		} else {
1690 			blk->disk_blkno = 0;
1691 		}
1692 	}
1693 
1694 	return(0);
1695 }
1696 
1697 /*
1698  * Reattach the buffers to the state structure based on the disk block
1699  * numbers stored in the state structure.
1700  * This is done after some set of transaction commits have released those
1701  * buffers from our grip.
1702  */
1703 STATIC int
xfs_attr_refillstate(xfs_da_state_t * state)1704 xfs_attr_refillstate(xfs_da_state_t *state)
1705 {
1706 	xfs_da_state_path_t *path;
1707 	xfs_da_state_blk_t *blk;
1708 	int level, error;
1709 
1710 	/*
1711 	 * Roll down the "path" in the state structure, storing the on-disk
1712 	 * block number for those buffers in the "path".
1713 	 */
1714 	path = &state->path;
1715 	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1716 	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1717 		if (blk->disk_blkno) {
1718 			error = xfs_da_read_buf(state->args->trans,
1719 						state->args->dp,
1720 						blk->blkno, blk->disk_blkno,
1721 						&blk->bp, XFS_ATTR_FORK);
1722 			if (error)
1723 				return(error);
1724 		} else {
1725 			blk->bp = NULL;
1726 		}
1727 	}
1728 
1729 	/*
1730 	 * Roll down the "altpath" in the state structure, storing the on-disk
1731 	 * block number for those buffers in the "altpath".
1732 	 */
1733 	path = &state->altpath;
1734 	ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
1735 	for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
1736 		if (blk->disk_blkno) {
1737 			error = xfs_da_read_buf(state->args->trans,
1738 						state->args->dp,
1739 						blk->blkno, blk->disk_blkno,
1740 						&blk->bp, XFS_ATTR_FORK);
1741 			if (error)
1742 				return(error);
1743 		} else {
1744 			blk->bp = NULL;
1745 		}
1746 	}
1747 
1748 	return(0);
1749 }
1750 
1751 /*
1752  * Look up a filename in a node attribute list.
1753  *
1754  * This routine gets called for any attribute fork that has more than one
1755  * block, ie: both true Btree attr lists and for single-leaf-blocks with
1756  * "remote" values taking up more blocks.
1757  */
1758 STATIC int
xfs_attr_node_get(xfs_da_args_t * args)1759 xfs_attr_node_get(xfs_da_args_t *args)
1760 {
1761 	xfs_da_state_t *state;
1762 	xfs_da_state_blk_t *blk;
1763 	int error, retval;
1764 	int i;
1765 
1766 	state = xfs_da_state_alloc();
1767 	state->args = args;
1768 	state->mp = args->dp->i_mount;
1769 	state->blocksize = state->mp->m_sb.sb_blocksize;
1770 	state->node_ents = state->mp->m_attr_node_ents;
1771 
1772 	/*
1773 	 * Search to see if name exists, and get back a pointer to it.
1774 	 */
1775 	error = xfs_da_node_lookup_int(state, &retval);
1776 	if (error) {
1777 		retval = error;
1778 	} else if (retval == EEXIST) {
1779 		blk = &state->path.blk[ state->path.active-1 ];
1780 		ASSERT(blk->bp != NULL);
1781 		ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1782 
1783 		/*
1784 		 * Get the value, local or "remote"
1785 		 */
1786 		retval = xfs_attr_leaf_getvalue(blk->bp, args);
1787 		if (!retval && (args->rmtblkno > 0)
1788 		    && !(args->flags & ATTR_KERNOVAL)) {
1789 			retval = xfs_attr_rmtval_get(args);
1790 		}
1791 	}
1792 
1793 	/*
1794 	 * If not in a transaction, we have to release all the buffers.
1795 	 */
1796 	for (i = 0; i < state->path.active; i++) {
1797 		xfs_da_brelse(args->trans, state->path.blk[i].bp);
1798 		state->path.blk[i].bp = NULL;
1799 	}
1800 
1801 	xfs_da_state_free(state);
1802 	return(retval);
1803 }
1804 
1805 STATIC int							/* error */
xfs_attr_node_list(xfs_attr_list_context_t * context)1806 xfs_attr_node_list(xfs_attr_list_context_t *context)
1807 {
1808 	attrlist_cursor_kern_t *cursor;
1809 	xfs_attr_leafblock_t *leaf;
1810 	xfs_da_intnode_t *node;
1811 	xfs_da_node_entry_t *btree;
1812 	int error, i;
1813 	xfs_dabuf_t *bp;
1814 
1815 	cursor = context->cursor;
1816 	cursor->initted = 1;
1817 
1818 	/*
1819 	 * Do all sorts of validation on the passed-in cursor structure.
1820 	 * If anything is amiss, ignore the cursor and look up the hashval
1821 	 * starting from the btree root.
1822 	 */
1823 	bp = NULL;
1824 	if (cursor->blkno > 0) {
1825 		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
1826 					      &bp, XFS_ATTR_FORK);
1827 		if ((error != 0) && (error != EFSCORRUPTED))
1828 			return(error);
1829 		if (bp) {
1830 			node = bp->data;
1831 			switch (be16_to_cpu(node->hdr.info.magic)) {
1832 			case XFS_DA_NODE_MAGIC:
1833 				trace_xfs_attr_list_wrong_blk(context);
1834 				xfs_da_brelse(NULL, bp);
1835 				bp = NULL;
1836 				break;
1837 			case XFS_ATTR_LEAF_MAGIC:
1838 				leaf = bp->data;
1839 				if (cursor->hashval > be32_to_cpu(leaf->entries[
1840 				    be16_to_cpu(leaf->hdr.count)-1].hashval)) {
1841 					trace_xfs_attr_list_wrong_blk(context);
1842 					xfs_da_brelse(NULL, bp);
1843 					bp = NULL;
1844 				} else if (cursor->hashval <=
1845 					     be32_to_cpu(leaf->entries[0].hashval)) {
1846 					trace_xfs_attr_list_wrong_blk(context);
1847 					xfs_da_brelse(NULL, bp);
1848 					bp = NULL;
1849 				}
1850 				break;
1851 			default:
1852 				trace_xfs_attr_list_wrong_blk(context);
1853 				xfs_da_brelse(NULL, bp);
1854 				bp = NULL;
1855 			}
1856 		}
1857 	}
1858 
1859 	/*
1860 	 * We did not find what we expected given the cursor's contents,
1861 	 * so we start from the top and work down based on the hash value.
1862 	 * Note that start of node block is same as start of leaf block.
1863 	 */
1864 	if (bp == NULL) {
1865 		cursor->blkno = 0;
1866 		for (;;) {
1867 			error = xfs_da_read_buf(NULL, context->dp,
1868 						      cursor->blkno, -1, &bp,
1869 						      XFS_ATTR_FORK);
1870 			if (error)
1871 				return(error);
1872 			if (unlikely(bp == NULL)) {
1873 				XFS_ERROR_REPORT("xfs_attr_node_list(2)",
1874 						 XFS_ERRLEVEL_LOW,
1875 						 context->dp->i_mount);
1876 				return(XFS_ERROR(EFSCORRUPTED));
1877 			}
1878 			node = bp->data;
1879 			if (node->hdr.info.magic ==
1880 			    cpu_to_be16(XFS_ATTR_LEAF_MAGIC))
1881 				break;
1882 			if (unlikely(node->hdr.info.magic !=
1883 				     cpu_to_be16(XFS_DA_NODE_MAGIC))) {
1884 				XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)",
1885 						     XFS_ERRLEVEL_LOW,
1886 						     context->dp->i_mount,
1887 						     node);
1888 				xfs_da_brelse(NULL, bp);
1889 				return(XFS_ERROR(EFSCORRUPTED));
1890 			}
1891 			btree = node->btree;
1892 			for (i = 0; i < be16_to_cpu(node->hdr.count);
1893 								btree++, i++) {
1894 				if (cursor->hashval
1895 						<= be32_to_cpu(btree->hashval)) {
1896 					cursor->blkno = be32_to_cpu(btree->before);
1897 					trace_xfs_attr_list_node_descend(context,
1898 									 btree);
1899 					break;
1900 				}
1901 			}
1902 			if (i == be16_to_cpu(node->hdr.count)) {
1903 				xfs_da_brelse(NULL, bp);
1904 				return(0);
1905 			}
1906 			xfs_da_brelse(NULL, bp);
1907 		}
1908 	}
1909 	ASSERT(bp != NULL);
1910 
1911 	/*
1912 	 * Roll upward through the blocks, processing each leaf block in
1913 	 * order.  As long as there is space in the result buffer, keep
1914 	 * adding the information.
1915 	 */
1916 	for (;;) {
1917 		leaf = bp->data;
1918 		if (unlikely(leaf->hdr.info.magic !=
1919 			     cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) {
1920 			XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)",
1921 					     XFS_ERRLEVEL_LOW,
1922 					     context->dp->i_mount, leaf);
1923 			xfs_da_brelse(NULL, bp);
1924 			return(XFS_ERROR(EFSCORRUPTED));
1925 		}
1926 		error = xfs_attr_leaf_list_int(bp, context);
1927 		if (error) {
1928 			xfs_da_brelse(NULL, bp);
1929 			return error;
1930 		}
1931 		if (context->seen_enough || leaf->hdr.info.forw == 0)
1932 			break;
1933 		cursor->blkno = be32_to_cpu(leaf->hdr.info.forw);
1934 		xfs_da_brelse(NULL, bp);
1935 		error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
1936 					      &bp, XFS_ATTR_FORK);
1937 		if (error)
1938 			return(error);
1939 		if (unlikely((bp == NULL))) {
1940 			XFS_ERROR_REPORT("xfs_attr_node_list(5)",
1941 					 XFS_ERRLEVEL_LOW,
1942 					 context->dp->i_mount);
1943 			return(XFS_ERROR(EFSCORRUPTED));
1944 		}
1945 	}
1946 	xfs_da_brelse(NULL, bp);
1947 	return(0);
1948 }
1949 
1950 
1951 /*========================================================================
1952  * External routines for manipulating out-of-line attribute values.
1953  *========================================================================*/
1954 
1955 /*
1956  * Read the value associated with an attribute from the out-of-line buffer
1957  * that we stored it in.
1958  */
1959 int
xfs_attr_rmtval_get(xfs_da_args_t * args)1960 xfs_attr_rmtval_get(xfs_da_args_t *args)
1961 {
1962 	xfs_bmbt_irec_t map[ATTR_RMTVALUE_MAPSIZE];
1963 	xfs_mount_t *mp;
1964 	xfs_daddr_t dblkno;
1965 	void *dst;
1966 	xfs_buf_t *bp;
1967 	int nmap, error, tmp, valuelen, blkcnt, i;
1968 	xfs_dablk_t lblkno;
1969 
1970 	ASSERT(!(args->flags & ATTR_KERNOVAL));
1971 
1972 	mp = args->dp->i_mount;
1973 	dst = args->value;
1974 	valuelen = args->valuelen;
1975 	lblkno = args->rmtblkno;
1976 	while (valuelen > 0) {
1977 		nmap = ATTR_RMTVALUE_MAPSIZE;
1978 		error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
1979 				       args->rmtblkcnt, map, &nmap,
1980 				       XFS_BMAPI_ATTRFORK);
1981 		if (error)
1982 			return(error);
1983 		ASSERT(nmap >= 1);
1984 
1985 		for (i = 0; (i < nmap) && (valuelen > 0); i++) {
1986 			ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) &&
1987 			       (map[i].br_startblock != HOLESTARTBLOCK));
1988 			dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
1989 			blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
1990 			error = xfs_read_buf(mp, mp->m_ddev_targp, dblkno,
1991 					     blkcnt, XBF_LOCK | XBF_DONT_BLOCK,
1992 					     &bp);
1993 			if (error)
1994 				return(error);
1995 
1996 			tmp = (valuelen < XFS_BUF_SIZE(bp))
1997 				? valuelen : XFS_BUF_SIZE(bp);
1998 			xfs_buf_iomove(bp, 0, tmp, dst, XBRW_READ);
1999 			xfs_buf_relse(bp);
2000 			dst += tmp;
2001 			valuelen -= tmp;
2002 
2003 			lblkno += map[i].br_blockcount;
2004 		}
2005 	}
2006 	ASSERT(valuelen == 0);
2007 	return(0);
2008 }
2009 
2010 /*
2011  * Write the value associated with an attribute into the out-of-line buffer
2012  * that we have defined for it.
2013  */
2014 STATIC int
xfs_attr_rmtval_set(xfs_da_args_t * args)2015 xfs_attr_rmtval_set(xfs_da_args_t *args)
2016 {
2017 	xfs_mount_t *mp;
2018 	xfs_fileoff_t lfileoff;
2019 	xfs_inode_t *dp;
2020 	xfs_bmbt_irec_t map;
2021 	xfs_daddr_t dblkno;
2022 	void *src;
2023 	xfs_buf_t *bp;
2024 	xfs_dablk_t lblkno;
2025 	int blkcnt, valuelen, nmap, error, tmp, committed;
2026 
2027 	dp = args->dp;
2028 	mp = dp->i_mount;
2029 	src = args->value;
2030 
2031 	/*
2032 	 * Find a "hole" in the attribute address space large enough for
2033 	 * us to drop the new attribute's value into.
2034 	 */
2035 	blkcnt = XFS_B_TO_FSB(mp, args->valuelen);
2036 	lfileoff = 0;
2037 	error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff,
2038 						   XFS_ATTR_FORK);
2039 	if (error) {
2040 		return(error);
2041 	}
2042 	args->rmtblkno = lblkno = (xfs_dablk_t)lfileoff;
2043 	args->rmtblkcnt = blkcnt;
2044 
2045 	/*
2046 	 * Roll through the "value", allocating blocks on disk as required.
2047 	 */
2048 	while (blkcnt > 0) {
2049 		/*
2050 		 * Allocate a single extent, up to the size of the value.
2051 		 */
2052 		xfs_bmap_init(args->flist, args->firstblock);
2053 		nmap = 1;
2054 		error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno,
2055 				  blkcnt,
2056 				  XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
2057 				  args->firstblock, args->total, &map, &nmap,
2058 				  args->flist);
2059 		if (!error) {
2060 			error = xfs_bmap_finish(&args->trans, args->flist,
2061 						&committed);
2062 		}
2063 		if (error) {
2064 			ASSERT(committed);
2065 			args->trans = NULL;
2066 			xfs_bmap_cancel(args->flist);
2067 			return(error);
2068 		}
2069 
2070 		/*
2071 		 * bmap_finish() may have committed the last trans and started
2072 		 * a new one.  We need the inode to be in all transactions.
2073 		 */
2074 		if (committed)
2075 			xfs_trans_ijoin(args->trans, dp, 0);
2076 
2077 		ASSERT(nmap == 1);
2078 		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
2079 		       (map.br_startblock != HOLESTARTBLOCK));
2080 		lblkno += map.br_blockcount;
2081 		blkcnt -= map.br_blockcount;
2082 
2083 		/*
2084 		 * Start the next trans in the chain.
2085 		 */
2086 		error = xfs_trans_roll(&args->trans, dp);
2087 		if (error)
2088 			return (error);
2089 	}
2090 
2091 	/*
2092 	 * Roll through the "value", copying the attribute value to the
2093 	 * already-allocated blocks.  Blocks are written synchronously
2094 	 * so that we can know they are all on disk before we turn off
2095 	 * the INCOMPLETE flag.
2096 	 */
2097 	lblkno = args->rmtblkno;
2098 	valuelen = args->valuelen;
2099 	while (valuelen > 0) {
2100 		/*
2101 		 * Try to remember where we decided to put the value.
2102 		 */
2103 		xfs_bmap_init(args->flist, args->firstblock);
2104 		nmap = 1;
2105 		error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno,
2106 				       args->rmtblkcnt, &map, &nmap,
2107 				       XFS_BMAPI_ATTRFORK);
2108 		if (error)
2109 			return(error);
2110 		ASSERT(nmap == 1);
2111 		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
2112 		       (map.br_startblock != HOLESTARTBLOCK));
2113 
2114 		dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
2115 		blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
2116 
2117 		bp = xfs_buf_get(mp->m_ddev_targp, dblkno, blkcnt,
2118 				 XBF_LOCK | XBF_DONT_BLOCK);
2119 		if (!bp)
2120 			return ENOMEM;
2121 		tmp = (valuelen < XFS_BUF_SIZE(bp)) ? valuelen :
2122 							XFS_BUF_SIZE(bp);
2123 		xfs_buf_iomove(bp, 0, tmp, src, XBRW_WRITE);
2124 		if (tmp < XFS_BUF_SIZE(bp))
2125 			xfs_buf_zero(bp, tmp, XFS_BUF_SIZE(bp) - tmp);
2126 		error = xfs_bwrite(bp);	/* GROT: NOTE: synchronous write */
2127 		xfs_buf_relse(bp);
2128 		if (error)
2129 			return error;
2130 		src += tmp;
2131 		valuelen -= tmp;
2132 
2133 		lblkno += map.br_blockcount;
2134 	}
2135 	ASSERT(valuelen == 0);
2136 	return(0);
2137 }
2138 
2139 /*
2140  * Remove the value associated with an attribute by deleting the
2141  * out-of-line buffer that it is stored on.
2142  */
2143 STATIC int
xfs_attr_rmtval_remove(xfs_da_args_t * args)2144 xfs_attr_rmtval_remove(xfs_da_args_t *args)
2145 {
2146 	xfs_mount_t *mp;
2147 	xfs_bmbt_irec_t map;
2148 	xfs_buf_t *bp;
2149 	xfs_daddr_t dblkno;
2150 	xfs_dablk_t lblkno;
2151 	int valuelen, blkcnt, nmap, error, done, committed;
2152 
2153 	mp = args->dp->i_mount;
2154 
2155 	/*
2156 	 * Roll through the "value", invalidating the attribute value's
2157 	 * blocks.
2158 	 */
2159 	lblkno = args->rmtblkno;
2160 	valuelen = args->rmtblkcnt;
2161 	while (valuelen > 0) {
2162 		/*
2163 		 * Try to remember where we decided to put the value.
2164 		 */
2165 		nmap = 1;
2166 		error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
2167 				       args->rmtblkcnt, &map, &nmap,
2168 				       XFS_BMAPI_ATTRFORK);
2169 		if (error)
2170 			return(error);
2171 		ASSERT(nmap == 1);
2172 		ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
2173 		       (map.br_startblock != HOLESTARTBLOCK));
2174 
2175 		dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
2176 		blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
2177 
2178 		/*
2179 		 * If the "remote" value is in the cache, remove it.
2180 		 */
2181 		bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt, XBF_TRYLOCK);
2182 		if (bp) {
2183 			xfs_buf_stale(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, 0);
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