~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/xfs/libxfs/xfs_attr.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
  4  * All Rights Reserved.
  5  */
  6 #include "xfs.h"
  7 #include "xfs_fs.h"
  8 #include "xfs_shared.h"
  9 #include "xfs_format.h"
 10 #include "xfs_log_format.h"
 11 #include "xfs_trans_resv.h"
 12 #include "xfs_mount.h"
 13 #include "xfs_defer.h"
 14 #include "xfs_da_format.h"
 15 #include "xfs_da_btree.h"
 16 #include "xfs_attr_sf.h"
 17 #include "xfs_inode.h"
 18 #include "xfs_trans.h"
 19 #include "xfs_bmap.h"
 20 #include "xfs_bmap_btree.h"
 21 #include "xfs_attr.h"
 22 #include "xfs_attr_leaf.h"
 23 #include "xfs_attr_remote.h"
 24 #include "xfs_quota.h"
 25 #include "xfs_trans_space.h"
 26 #include "xfs_trace.h"
 27 #include "xfs_attr_item.h"
 28 #include "xfs_xattr.h"
 29 #include "xfs_parent.h"
 30 
 31 struct kmem_cache               *xfs_attr_intent_cache;
 32 
 33 /*
 34  * xfs_attr.c
 35  *
 36  * Provide the external interfaces to manage attribute lists.
 37  */
 38 
 39 /*========================================================================
 40  * Function prototypes for the kernel.
 41  *========================================================================*/
 42 
 43 /*
 44  * Internal routines when attribute list fits inside the inode.
 45  */
 46 STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
 47 
 48 /*
 49  * Internal routines when attribute list is one block.
 50  */
 51 STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
 52 STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
 53 STATIC int xfs_attr_leaf_hasname(struct xfs_da_args *args, struct xfs_buf **bp);
 54 STATIC int xfs_attr_leaf_try_add(struct xfs_da_args *args);
 55 
 56 /*
 57  * Internal routines when attribute list is more than one block.
 58  */
 59 STATIC int xfs_attr_node_get(xfs_da_args_t *args);
 60 STATIC void xfs_attr_restore_rmt_blk(struct xfs_da_args *args);
 61 static int xfs_attr_node_try_addname(struct xfs_attr_intent *attr);
 62 STATIC int xfs_attr_node_addname_find_attr(struct xfs_attr_intent *attr);
 63 STATIC int xfs_attr_node_remove_attr(struct xfs_attr_intent *attr);
 64 STATIC int xfs_attr_node_lookup(struct xfs_da_args *args,
 65                 struct xfs_da_state *state);
 66 
 67 int
 68 xfs_inode_hasattr(
 69         struct xfs_inode        *ip)
 70 {
 71         if (!xfs_inode_has_attr_fork(ip))
 72                 return 0;
 73         if (ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS &&
 74             ip->i_af.if_nextents == 0)
 75                 return 0;
 76         return 1;
 77 }
 78 
 79 /*
 80  * Returns true if the there is exactly only block in the attr fork, in which
 81  * case the attribute fork consists of a single leaf block entry.
 82  */
 83 bool
 84 xfs_attr_is_leaf(
 85         struct xfs_inode        *ip)
 86 {
 87         struct xfs_ifork        *ifp = &ip->i_af;
 88         struct xfs_iext_cursor  icur;
 89         struct xfs_bmbt_irec    imap;
 90 
 91         ASSERT(!xfs_need_iread_extents(ifp));
 92 
 93         if (ifp->if_nextents != 1 || ifp->if_format != XFS_DINODE_FMT_EXTENTS)
 94                 return false;
 95 
 96         xfs_iext_first(ifp, &icur);
 97         xfs_iext_get_extent(ifp, &icur, &imap);
 98         return imap.br_startoff == 0 && imap.br_blockcount == 1;
 99 }
100 
101 /*
102  * XXX (dchinner): name path state saving and refilling is an optimisation to
103  * avoid needing to look up name entries after rolling transactions removing
104  * remote xattr blocks between the name entry lookup and name entry removal.
105  * This optimisation got sidelined when combining the set and remove state
106  * machines, but the code has been left in place because it is worthwhile to
107  * restore the optimisation once the combined state machine paths have settled.
108  *
109  * This comment is a public service announcement to remind Future Dave that he
110  * still needs to restore this code to working order.
111  */
112 #if 0
113 /*
114  * Fill in the disk block numbers in the state structure for the buffers
115  * that are attached to the state structure.
116  * This is done so that we can quickly reattach ourselves to those buffers
117  * after some set of transaction commits have released these buffers.
118  */
119 static int
120 xfs_attr_fillstate(xfs_da_state_t *state)
121 {
122         xfs_da_state_path_t *path;
123         xfs_da_state_blk_t *blk;
124         int level;
125 
126         trace_xfs_attr_fillstate(state->args);
127 
128         /*
129          * Roll down the "path" in the state structure, storing the on-disk
130          * block number for those buffers in the "path".
131          */
132         path = &state->path;
133         ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
134         for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
135                 if (blk->bp) {
136                         blk->disk_blkno = xfs_buf_daddr(blk->bp);
137                         blk->bp = NULL;
138                 } else {
139                         blk->disk_blkno = 0;
140                 }
141         }
142 
143         /*
144          * Roll down the "altpath" in the state structure, storing the on-disk
145          * block number for those buffers in the "altpath".
146          */
147         path = &state->altpath;
148         ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
149         for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
150                 if (blk->bp) {
151                         blk->disk_blkno = xfs_buf_daddr(blk->bp);
152                         blk->bp = NULL;
153                 } else {
154                         blk->disk_blkno = 0;
155                 }
156         }
157 
158         return 0;
159 }
160 
161 /*
162  * Reattach the buffers to the state structure based on the disk block
163  * numbers stored in the state structure.
164  * This is done after some set of transaction commits have released those
165  * buffers from our grip.
166  */
167 static int
168 xfs_attr_refillstate(xfs_da_state_t *state)
169 {
170         xfs_da_state_path_t *path;
171         xfs_da_state_blk_t *blk;
172         int level, error;
173 
174         trace_xfs_attr_refillstate(state->args);
175 
176         /*
177          * Roll down the "path" in the state structure, storing the on-disk
178          * block number for those buffers in the "path".
179          */
180         path = &state->path;
181         ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
182         for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
183                 if (blk->disk_blkno) {
184                         error = xfs_da3_node_read_mapped(state->args->trans,
185                                         state->args->dp, blk->disk_blkno,
186                                         &blk->bp, XFS_ATTR_FORK);
187                         if (error)
188                                 return error;
189                 } else {
190                         blk->bp = NULL;
191                 }
192         }
193 
194         /*
195          * Roll down the "altpath" in the state structure, storing the on-disk
196          * block number for those buffers in the "altpath".
197          */
198         path = &state->altpath;
199         ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
200         for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
201                 if (blk->disk_blkno) {
202                         error = xfs_da3_node_read_mapped(state->args->trans,
203                                         state->args->dp, blk->disk_blkno,
204                                         &blk->bp, XFS_ATTR_FORK);
205                         if (error)
206                                 return error;
207                 } else {
208                         blk->bp = NULL;
209                 }
210         }
211 
212         return 0;
213 }
214 #else
215 static int xfs_attr_fillstate(xfs_da_state_t *state) { return 0; }
216 #endif
217 
218 /*========================================================================
219  * Overall external interface routines.
220  *========================================================================*/
221 
222 /*
223  * Retrieve an extended attribute and its value.  Must have ilock.
224  * Returns 0 on successful retrieval, otherwise an error.
225  */
226 int
227 xfs_attr_get_ilocked(
228         struct xfs_da_args      *args)
229 {
230         int                     error;
231 
232         xfs_assert_ilocked(args->dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL);
233 
234         if (!xfs_inode_hasattr(args->dp))
235                 return -ENOATTR;
236 
237         /*
238          * The incore attr fork iext tree must be loaded for xfs_attr_is_leaf
239          * to work correctly.
240          */
241         error = xfs_iread_extents(args->trans, args->dp, XFS_ATTR_FORK);
242         if (error)
243                 return error;
244 
245         if (args->dp->i_af.if_format == XFS_DINODE_FMT_LOCAL)
246                 return xfs_attr_shortform_getvalue(args);
247         if (xfs_attr_is_leaf(args->dp))
248                 return xfs_attr_leaf_get(args);
249         return xfs_attr_node_get(args);
250 }
251 
252 /*
253  * Retrieve an extended attribute by name, and its value if requested.
254  *
255  * If args->valuelen is zero, then the caller does not want the value, just an
256  * indication whether the attribute exists and the size of the value if it
257  * exists. The size is returned in args.valuelen.
258  *
259  * If args->value is NULL but args->valuelen is non-zero, allocate the buffer
260  * for the value after existence of the attribute has been determined. The
261  * caller always has to free args->value if it is set, no matter if this
262  * function was successful or not.
263  *
264  * If the attribute is found, but exceeds the size limit set by the caller in
265  * args->valuelen, return -ERANGE with the size of the attribute that was found
266  * in args->valuelen.
267  */
268 int
269 xfs_attr_get(
270         struct xfs_da_args      *args)
271 {
272         uint                    lock_mode;
273         int                     error;
274 
275         XFS_STATS_INC(args->dp->i_mount, xs_attr_get);
276 
277         if (xfs_is_shutdown(args->dp->i_mount))
278                 return -EIO;
279 
280         if (!args->owner)
281                 args->owner = args->dp->i_ino;
282         args->geo = args->dp->i_mount->m_attr_geo;
283         args->whichfork = XFS_ATTR_FORK;
284         xfs_attr_sethash(args);
285 
286         /* Entirely possible to look up a name which doesn't exist */
287         args->op_flags = XFS_DA_OP_OKNOENT;
288 
289         lock_mode = xfs_ilock_attr_map_shared(args->dp);
290         error = xfs_attr_get_ilocked(args);
291         xfs_iunlock(args->dp, lock_mode);
292 
293         return error;
294 }
295 
296 /*
297  * Calculate how many blocks we need for the new attribute,
298  */
299 int
300 xfs_attr_calc_size(
301         struct xfs_da_args      *args,
302         int                     *local)
303 {
304         struct xfs_mount        *mp = args->dp->i_mount;
305         int                     size;
306         int                     nblks;
307 
308         /*
309          * Determine space new attribute will use, and if it would be
310          * "local" or "remote" (note: local != inline).
311          */
312         size = xfs_attr_leaf_newentsize(args, local);
313         nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
314         if (*local) {
315                 if (size > (args->geo->blksize / 2)) {
316                         /* Double split possible */
317                         nblks *= 2;
318                 }
319         } else {
320                 /*
321                  * Out of line attribute, cannot double split, but
322                  * make room for the attribute value itself.
323                  */
324                 uint    dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen);
325                 nblks += dblocks;
326                 nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
327         }
328 
329         return nblks;
330 }
331 
332 /* Initialize transaction reservation for an xattr set/replace/upsert */
333 inline struct xfs_trans_res
334 xfs_attr_set_resv(
335         const struct xfs_da_args        *args)
336 {
337         struct xfs_mount                *mp = args->dp->i_mount;
338         struct xfs_trans_res            ret = {
339                 .tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
340                             M_RES(mp)->tr_attrsetrt.tr_logres * args->total,
341                 .tr_logcount            = XFS_ATTRSET_LOG_COUNT,
342                 .tr_logflags            = XFS_TRANS_PERM_LOG_RES,
343         };
344 
345         return ret;
346 }
347 
348 /*
349  * Add an attr to a shortform fork. If there is no space,
350  * xfs_attr_shortform_addname() will convert to leaf format and return -ENOSPC.
351  * to use.
352  */
353 STATIC int
354 xfs_attr_try_sf_addname(
355         struct xfs_inode        *dp,
356         struct xfs_da_args      *args)
357 {
358 
359         int                     error;
360 
361         /*
362          * Build initial attribute list (if required).
363          */
364         if (dp->i_af.if_format == XFS_DINODE_FMT_EXTENTS)
365                 xfs_attr_shortform_create(args);
366 
367         error = xfs_attr_shortform_addname(args);
368         if (error == -ENOSPC)
369                 return error;
370 
371         /*
372          * Commit the shortform mods, and we're done.
373          * NOTE: this is also the error path (EEXIST, etc).
374          */
375         if (!error)
376                 xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG);
377 
378         if (xfs_has_wsync(dp->i_mount))
379                 xfs_trans_set_sync(args->trans);
380 
381         return error;
382 }
383 
384 static int
385 xfs_attr_sf_addname(
386         struct xfs_attr_intent          *attr)
387 {
388         struct xfs_da_args              *args = attr->xattri_da_args;
389         struct xfs_inode                *dp = args->dp;
390         int                             error = 0;
391 
392         error = xfs_attr_try_sf_addname(dp, args);
393         if (error != -ENOSPC) {
394                 ASSERT(!error || error == -EEXIST);
395                 attr->xattri_dela_state = XFS_DAS_DONE;
396                 goto out;
397         }
398 
399         /*
400          * It won't fit in the shortform, transform to a leaf block.  GROT:
401          * another possible req'mt for a double-split btree op.
402          */
403         error = xfs_attr_shortform_to_leaf(args);
404         if (error)
405                 return error;
406 
407         attr->xattri_dela_state = XFS_DAS_LEAF_ADD;
408 out:
409         trace_xfs_attr_sf_addname_return(attr->xattri_dela_state, args->dp);
410         return error;
411 }
412 
413 /* Compute the hash value for a user/root/secure extended attribute */
414 xfs_dahash_t
415 xfs_attr_hashname(
416         const uint8_t           *name,
417         int                     namelen)
418 {
419         return xfs_da_hashname(name, namelen);
420 }
421 
422 /* Compute the hash value for any extended attribute from any namespace. */
423 xfs_dahash_t
424 xfs_attr_hashval(
425         struct xfs_mount        *mp,
426         unsigned int            attr_flags,
427         const uint8_t           *name,
428         int                     namelen,
429         const void              *value,
430         int                     valuelen)
431 {
432         ASSERT(xfs_attr_check_namespace(attr_flags));
433 
434         if (attr_flags & XFS_ATTR_PARENT)
435                 return xfs_parent_hashattr(mp, name, namelen, value, valuelen);
436 
437         return xfs_attr_hashname(name, namelen);
438 }
439 
440 /*
441  * PPTR_REPLACE operations require the caller to set the old and new names and
442  * values explicitly.  Update the canonical fields to the new name and value
443  * here now that the removal phase has finished.
444  */
445 static void
446 xfs_attr_update_pptr_replace_args(
447         struct xfs_da_args      *args)
448 {
449         ASSERT(args->new_namelen > 0);
450         args->name = args->new_name;
451         args->namelen = args->new_namelen;
452         args->value = args->new_value;
453         args->valuelen = args->new_valuelen;
454         xfs_attr_sethash(args);
455 }
456 
457 /*
458  * Handle the state change on completion of a multi-state attr operation.
459  *
460  * If the XFS_DA_OP_REPLACE flag is set, this means the operation was the first
461  * modification in a attr replace operation and we still have to do the second
462  * state, indicated by @replace_state.
463  *
464  * We consume the XFS_DA_OP_REPLACE flag so that when we are called again on
465  * completion of the second half of the attr replace operation we correctly
466  * signal that it is done.
467  */
468 static enum xfs_delattr_state
469 xfs_attr_complete_op(
470         struct xfs_attr_intent  *attr,
471         enum xfs_delattr_state  replace_state)
472 {
473         struct xfs_da_args      *args = attr->xattri_da_args;
474 
475         if (!(args->op_flags & XFS_DA_OP_REPLACE))
476                 replace_state = XFS_DAS_DONE;
477         else if (xfs_attr_intent_op(attr) == XFS_ATTRI_OP_FLAGS_PPTR_REPLACE)
478                 xfs_attr_update_pptr_replace_args(args);
479 
480         args->op_flags &= ~XFS_DA_OP_REPLACE;
481         args->attr_filter &= ~XFS_ATTR_INCOMPLETE;
482         return replace_state;
483 }
484 
485 static int
486 xfs_attr_leaf_addname(
487         struct xfs_attr_intent  *attr)
488 {
489         struct xfs_da_args      *args = attr->xattri_da_args;
490         int                     error;
491 
492         ASSERT(xfs_attr_is_leaf(args->dp));
493 
494         /*
495          * Use the leaf buffer we may already hold locked as a result of
496          * a sf-to-leaf conversion.
497          */
498         error = xfs_attr_leaf_try_add(args);
499 
500         if (error == -ENOSPC) {
501                 error = xfs_attr3_leaf_to_node(args);
502                 if (error)
503                         return error;
504 
505                 /*
506                  * We're not in leaf format anymore, so roll the transaction and
507                  * retry the add to the newly allocated node block.
508                  */
509                 attr->xattri_dela_state = XFS_DAS_NODE_ADD;
510                 goto out;
511         }
512         if (error)
513                 return error;
514 
515         /*
516          * We need to commit and roll if we need to allocate remote xattr blocks
517          * or perform more xattr manipulations. Otherwise there is nothing more
518          * to do and we can return success.
519          */
520         if (args->rmtblkno)
521                 attr->xattri_dela_state = XFS_DAS_LEAF_SET_RMT;
522         else
523                 attr->xattri_dela_state = xfs_attr_complete_op(attr,
524                                                         XFS_DAS_LEAF_REPLACE);
525 out:
526         trace_xfs_attr_leaf_addname_return(attr->xattri_dela_state, args->dp);
527         return error;
528 }
529 
530 /*
531  * Add an entry to a node format attr tree.
532  *
533  * Note that we might still have a leaf here - xfs_attr_is_leaf() cannot tell
534  * the difference between leaf + remote attr blocks and a node format tree,
535  * so we may still end up having to convert from leaf to node format here.
536  */
537 static int
538 xfs_attr_node_addname(
539         struct xfs_attr_intent  *attr)
540 {
541         struct xfs_da_args      *args = attr->xattri_da_args;
542         int                     error;
543 
544         error = xfs_attr_node_addname_find_attr(attr);
545         if (error)
546                 return error;
547 
548         error = xfs_attr_node_try_addname(attr);
549         if (error == -ENOSPC) {
550                 error = xfs_attr3_leaf_to_node(args);
551                 if (error)
552                         return error;
553                 /*
554                  * No state change, we really are in node form now
555                  * but we need the transaction rolled to continue.
556                  */
557                 goto out;
558         }
559         if (error)
560                 return error;
561 
562         if (args->rmtblkno)
563                 attr->xattri_dela_state = XFS_DAS_NODE_SET_RMT;
564         else
565                 attr->xattri_dela_state = xfs_attr_complete_op(attr,
566                                                         XFS_DAS_NODE_REPLACE);
567 out:
568         trace_xfs_attr_node_addname_return(attr->xattri_dela_state, args->dp);
569         return error;
570 }
571 
572 static int
573 xfs_attr_rmtval_alloc(
574         struct xfs_attr_intent          *attr)
575 {
576         struct xfs_da_args              *args = attr->xattri_da_args;
577         int                             error = 0;
578 
579         /*
580          * If there was an out-of-line value, allocate the blocks we
581          * identified for its storage and copy the value.  This is done
582          * after we create the attribute so that we don't overflow the
583          * maximum size of a transaction and/or hit a deadlock.
584          */
585         if (attr->xattri_blkcnt > 0) {
586                 error = xfs_attr_rmtval_set_blk(attr);
587                 if (error)
588                         return error;
589                 /* Roll the transaction only if there is more to allocate. */
590                 if (attr->xattri_blkcnt > 0)
591                         goto out;
592         }
593 
594         error = xfs_attr_rmtval_set_value(args);
595         if (error)
596                 return error;
597 
598         attr->xattri_dela_state = xfs_attr_complete_op(attr,
599                                                 ++attr->xattri_dela_state);
600         /*
601          * If we are not doing a rename, we've finished the operation but still
602          * have to clear the incomplete flag protecting the new attr from
603          * exposing partially initialised state if we crash during creation.
604          */
605         if (attr->xattri_dela_state == XFS_DAS_DONE)
606                 error = xfs_attr3_leaf_clearflag(args);
607 out:
608         trace_xfs_attr_rmtval_alloc(attr->xattri_dela_state, args->dp);
609         return error;
610 }
611 
612 /*
613  * Mark an attribute entry INCOMPLETE and save pointers to the relevant buffers
614  * for later deletion of the entry.
615  */
616 static int
617 xfs_attr_leaf_mark_incomplete(
618         struct xfs_da_args      *args,
619         struct xfs_da_state     *state)
620 {
621         int                     error;
622 
623         /*
624          * Fill in disk block numbers in the state structure
625          * so that we can get the buffers back after we commit
626          * several transactions in the following calls.
627          */
628         error = xfs_attr_fillstate(state);
629         if (error)
630                 return error;
631 
632         /*
633          * Mark the attribute as INCOMPLETE
634          */
635         return xfs_attr3_leaf_setflag(args);
636 }
637 
638 /* Ensure the da state of an xattr deferred work item is ready to go. */
639 static inline void
640 xfs_attr_item_init_da_state(
641         struct xfs_attr_intent  *attr)
642 {
643         struct xfs_da_args      *args = attr->xattri_da_args;
644 
645         if (!attr->xattri_da_state)
646                 attr->xattri_da_state = xfs_da_state_alloc(args);
647         else
648                 xfs_da_state_reset(attr->xattri_da_state, args);
649 }
650 
651 /*
652  * Initial setup for xfs_attr_node_removename.  Make sure the attr is there and
653  * the blocks are valid.  Attr keys with remote blocks will be marked
654  * incomplete.
655  */
656 static
657 int xfs_attr_node_removename_setup(
658         struct xfs_attr_intent          *attr)
659 {
660         struct xfs_da_args              *args = attr->xattri_da_args;
661         struct xfs_da_state             *state;
662         int                             error;
663 
664         xfs_attr_item_init_da_state(attr);
665         error = xfs_attr_node_lookup(args, attr->xattri_da_state);
666         if (error != -EEXIST)
667                 goto out;
668         error = 0;
669 
670         state = attr->xattri_da_state;
671         ASSERT(state->path.blk[state->path.active - 1].bp != NULL);
672         ASSERT(state->path.blk[state->path.active - 1].magic ==
673                 XFS_ATTR_LEAF_MAGIC);
674 
675         error = xfs_attr_leaf_mark_incomplete(args, state);
676         if (error)
677                 goto out;
678         if (args->rmtblkno > 0)
679                 error = xfs_attr_rmtval_invalidate(args);
680 out:
681         if (error) {
682                 xfs_da_state_free(attr->xattri_da_state);
683                 attr->xattri_da_state = NULL;
684         }
685 
686         return error;
687 }
688 
689 /*
690  * Remove the original attr we have just replaced. This is dependent on the
691  * original lookup and insert placing the old attr in args->blkno/args->index
692  * and the new attr in args->blkno2/args->index2.
693  */
694 static int
695 xfs_attr_leaf_remove_attr(
696         struct xfs_attr_intent          *attr)
697 {
698         struct xfs_da_args              *args = attr->xattri_da_args;
699         struct xfs_inode                *dp = args->dp;
700         struct xfs_buf                  *bp = NULL;
701         int                             forkoff;
702         int                             error;
703 
704         error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner,
705                         args->blkno, &bp);
706         if (error)
707                 return error;
708 
709         xfs_attr3_leaf_remove(bp, args);
710 
711         forkoff = xfs_attr_shortform_allfit(bp, dp);
712         if (forkoff)
713                 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
714                 /* bp is gone due to xfs_da_shrink_inode */
715 
716         return error;
717 }
718 
719 /*
720  * Shrink an attribute from leaf to shortform. Used by the node format remove
721  * path when the node format collapses to a single block and so we have to check
722  * if it can be collapsed further.
723  */
724 static int
725 xfs_attr_leaf_shrink(
726         struct xfs_da_args      *args)
727 {
728         struct xfs_inode        *dp = args->dp;
729         struct xfs_buf          *bp;
730         int                     forkoff;
731         int                     error;
732 
733         if (!xfs_attr_is_leaf(dp))
734                 return 0;
735 
736         error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, &bp);
737         if (error)
738                 return error;
739 
740         forkoff = xfs_attr_shortform_allfit(bp, dp);
741         if (forkoff) {
742                 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
743                 /* bp is gone due to xfs_da_shrink_inode */
744         } else {
745                 xfs_trans_brelse(args->trans, bp);
746         }
747 
748         return error;
749 }
750 
751 /*
752  * Run the attribute operation specified in @attr.
753  *
754  * This routine is meant to function as a delayed operation and will set the
755  * state to XFS_DAS_DONE when the operation is complete.  Calling functions will
756  * need to handle this, and recall the function until either an error or
757  * XFS_DAS_DONE is detected.
758  */
759 int
760 xfs_attr_set_iter(
761         struct xfs_attr_intent          *attr)
762 {
763         struct xfs_da_args              *args = attr->xattri_da_args;
764         int                             error = 0;
765 
766         /* State machine switch */
767 next_state:
768         switch (attr->xattri_dela_state) {
769         case XFS_DAS_UNINIT:
770                 ASSERT(0);
771                 return -EFSCORRUPTED;
772         case XFS_DAS_SF_ADD:
773                 return xfs_attr_sf_addname(attr);
774         case XFS_DAS_LEAF_ADD:
775                 return xfs_attr_leaf_addname(attr);
776         case XFS_DAS_NODE_ADD:
777                 return xfs_attr_node_addname(attr);
778 
779         case XFS_DAS_SF_REMOVE:
780                 error = xfs_attr_sf_removename(args);
781                 attr->xattri_dela_state = xfs_attr_complete_op(attr,
782                                                 xfs_attr_init_add_state(args));
783                 break;
784         case XFS_DAS_LEAF_REMOVE:
785                 error = xfs_attr_leaf_removename(args);
786                 attr->xattri_dela_state = xfs_attr_complete_op(attr,
787                                                 xfs_attr_init_add_state(args));
788                 break;
789         case XFS_DAS_NODE_REMOVE:
790                 error = xfs_attr_node_removename_setup(attr);
791                 if (error == -ENOATTR &&
792                     (args->op_flags & XFS_DA_OP_RECOVERY)) {
793                         attr->xattri_dela_state = xfs_attr_complete_op(attr,
794                                                 xfs_attr_init_add_state(args));
795                         error = 0;
796                         break;
797                 }
798                 if (error)
799                         return error;
800                 attr->xattri_dela_state = XFS_DAS_NODE_REMOVE_RMT;
801                 if (args->rmtblkno == 0)
802                         attr->xattri_dela_state++;
803                 break;
804 
805         case XFS_DAS_LEAF_SET_RMT:
806         case XFS_DAS_NODE_SET_RMT:
807                 error = xfs_attr_rmtval_find_space(attr);
808                 if (error)
809                         return error;
810                 attr->xattri_dela_state++;
811                 fallthrough;
812 
813         case XFS_DAS_LEAF_ALLOC_RMT:
814         case XFS_DAS_NODE_ALLOC_RMT:
815                 error = xfs_attr_rmtval_alloc(attr);
816                 if (error)
817                         return error;
818                 if (attr->xattri_dela_state == XFS_DAS_DONE)
819                         break;
820                 goto next_state;
821 
822         case XFS_DAS_LEAF_REPLACE:
823         case XFS_DAS_NODE_REPLACE:
824                 /*
825                  * We must "flip" the incomplete flags on the "new" and "old"
826                  * attribute/value pairs so that one disappears and one appears
827                  * atomically.
828                  */
829                 error = xfs_attr3_leaf_flipflags(args);
830                 if (error)
831                         return error;
832                 /*
833                  * We must commit the flag value change now to make it atomic
834                  * and then we can start the next trans in series at REMOVE_OLD.
835                  */
836                 attr->xattri_dela_state++;
837                 break;
838 
839         case XFS_DAS_LEAF_REMOVE_OLD:
840         case XFS_DAS_NODE_REMOVE_OLD:
841                 /*
842                  * If we have a remote attr, start the process of removing it
843                  * by invalidating any cached buffers.
844                  *
845                  * If we don't have a remote attr, we skip the remote block
846                  * removal state altogether with a second state increment.
847                  */
848                 xfs_attr_restore_rmt_blk(args);
849                 if (args->rmtblkno) {
850                         error = xfs_attr_rmtval_invalidate(args);
851                         if (error)
852                                 return error;
853                 } else {
854                         attr->xattri_dela_state++;
855                 }
856 
857                 attr->xattri_dela_state++;
858                 goto next_state;
859 
860         case XFS_DAS_LEAF_REMOVE_RMT:
861         case XFS_DAS_NODE_REMOVE_RMT:
862                 error = xfs_attr_rmtval_remove(attr);
863                 if (error == -EAGAIN) {
864                         error = 0;
865                         break;
866                 }
867                 if (error)
868                         return error;
869 
870                 /*
871                  * We've finished removing the remote attr blocks, so commit the
872                  * transaction and move on to removing the attr name from the
873                  * leaf/node block. Removing the attr might require a full
874                  * transaction reservation for btree block freeing, so we
875                  * can't do that in the same transaction where we removed the
876                  * remote attr blocks.
877                  */
878                 attr->xattri_dela_state++;
879                 break;
880 
881         case XFS_DAS_LEAF_REMOVE_ATTR:
882                 error = xfs_attr_leaf_remove_attr(attr);
883                 attr->xattri_dela_state = xfs_attr_complete_op(attr,
884                                                 xfs_attr_init_add_state(args));
885                 break;
886 
887         case XFS_DAS_NODE_REMOVE_ATTR:
888                 error = xfs_attr_node_remove_attr(attr);
889                 if (!error)
890                         error = xfs_attr_leaf_shrink(args);
891                 attr->xattri_dela_state = xfs_attr_complete_op(attr,
892                                                 xfs_attr_init_add_state(args));
893                 break;
894         default:
895                 ASSERT(0);
896                 break;
897         }
898 
899         trace_xfs_attr_set_iter_return(attr->xattri_dela_state, args->dp);
900         return error;
901 }
902 
903 
904 /*
905  * Return EEXIST if attr is found, or ENOATTR if not
906  */
907 static int
908 xfs_attr_lookup(
909         struct xfs_da_args      *args)
910 {
911         struct xfs_inode        *dp = args->dp;
912         struct xfs_buf          *bp = NULL;
913         struct xfs_da_state     *state;
914         int                     error;
915 
916         if (!xfs_inode_hasattr(dp))
917                 return -ENOATTR;
918 
919         if (dp->i_af.if_format == XFS_DINODE_FMT_LOCAL) {
920                 if (xfs_attr_sf_findname(args))
921                         return -EEXIST;
922                 return -ENOATTR;
923         }
924 
925         /* Prerequisite for xfs_attr_is_leaf */
926         error = xfs_iread_extents(args->trans, args->dp, XFS_ATTR_FORK);
927         if (error)
928                 return error;
929 
930         if (xfs_attr_is_leaf(dp)) {
931                 error = xfs_attr_leaf_hasname(args, &bp);
932 
933                 if (bp)
934                         xfs_trans_brelse(args->trans, bp);
935 
936                 return error;
937         }
938 
939         state = xfs_da_state_alloc(args);
940         error = xfs_attr_node_lookup(args, state);
941         xfs_da_state_free(state);
942         return error;
943 }
944 
945 int
946 xfs_attr_add_fork(
947         struct xfs_inode        *ip,            /* incore inode pointer */
948         int                     size,           /* space new attribute needs */
949         int                     rsvd)           /* xact may use reserved blks */
950 {
951         struct xfs_mount        *mp = ip->i_mount;
952         struct xfs_trans        *tp;            /* transaction pointer */
953         unsigned int            blks;           /* space reservation */
954         int                     error;          /* error return value */
955 
956         ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
957 
958         blks = XFS_ADDAFORK_SPACE_RES(mp);
959 
960         error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_addafork, blks, 0,
961                         rsvd, &tp);
962         if (error)
963                 return error;
964 
965         if (xfs_inode_has_attr_fork(ip))
966                 goto trans_cancel;
967 
968         error = xfs_bmap_add_attrfork(tp, ip, size, rsvd);
969         if (error)
970                 goto trans_cancel;
971 
972         error = xfs_trans_commit(tp);
973         xfs_iunlock(ip, XFS_ILOCK_EXCL);
974         return error;
975 
976 trans_cancel:
977         xfs_trans_cancel(tp);
978         xfs_iunlock(ip, XFS_ILOCK_EXCL);
979         return error;
980 }
981 
982 /*
983  * Make a change to the xattr structure.
984  *
985  * The caller must have initialized @args, attached dquots, and must not hold
986  * any ILOCKs.  Reserved data blocks may be used if @rsvd is set.
987  *
988  * Returns -EEXIST for XFS_ATTRUPDATE_CREATE if the name already exists.
989  * Returns -ENOATTR for XFS_ATTRUPDATE_REMOVE if the name does not exist.
990  * Returns 0 on success, or a negative errno if something else went wrong.
991  */
992 int
993 xfs_attr_set(
994         struct xfs_da_args      *args,
995         enum xfs_attr_update    op,
996         bool                    rsvd)
997 {
998         struct xfs_inode        *dp = args->dp;
999         struct xfs_mount        *mp = dp->i_mount;
1000         struct xfs_trans_res    tres;
1001         int                     error, local;
1002         int                     rmt_blks = 0;
1003         unsigned int            total = 0;
1004 
1005         ASSERT(!args->trans);
1006 
1007         switch (op) {
1008         case XFS_ATTRUPDATE_UPSERT:
1009         case XFS_ATTRUPDATE_CREATE:
1010         case XFS_ATTRUPDATE_REPLACE:
1011                 XFS_STATS_INC(mp, xs_attr_set);
1012                 args->total = xfs_attr_calc_size(args, &local);
1013 
1014                 /*
1015                  * If the inode doesn't have an attribute fork, add one.
1016                  * (inode must not be locked when we call this routine)
1017                  */
1018                 if (xfs_inode_has_attr_fork(dp) == 0) {
1019                         int sf_size = sizeof(struct xfs_attr_sf_hdr) +
1020                                 xfs_attr_sf_entsize_byname(args->namelen,
1021                                                 args->valuelen);
1022 
1023                         error = xfs_attr_add_fork(dp, sf_size, rsvd);
1024                         if (error)
1025                                 return error;
1026                 }
1027 
1028                 if (!local)
1029                         rmt_blks = xfs_attr3_rmt_blocks(mp, args->valuelen);
1030 
1031                 tres = xfs_attr_set_resv(args);
1032                 total = args->total;
1033                 break;
1034         case XFS_ATTRUPDATE_REMOVE:
1035                 XFS_STATS_INC(mp, xs_attr_remove);
1036                 rmt_blks = xfs_attr3_max_rmt_blocks(mp);
1037                 tres = M_RES(mp)->tr_attrrm;
1038                 total = XFS_ATTRRM_SPACE_RES(mp);
1039                 break;
1040         }
1041 
1042         /*
1043          * Root fork attributes can use reserved data blocks for this
1044          * operation if necessary
1045          */
1046         error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans);
1047         if (error)
1048                 return error;
1049 
1050         if (op != XFS_ATTRUPDATE_REMOVE || xfs_inode_hasattr(dp)) {
1051                 error = xfs_iext_count_extend(args->trans, dp, XFS_ATTR_FORK,
1052                                 XFS_IEXT_ATTR_MANIP_CNT(rmt_blks));
1053                 if (error)
1054                         goto out_trans_cancel;
1055         }
1056 
1057         error = xfs_attr_lookup(args);
1058         switch (error) {
1059         case -EEXIST:
1060                 if (op == XFS_ATTRUPDATE_REMOVE) {
1061                         /* if no value, we are performing a remove operation */
1062                         xfs_attr_defer_add(args, XFS_ATTR_DEFER_REMOVE);
1063                         break;
1064                 }
1065 
1066                 /* Pure create fails if the attr already exists */
1067                 if (op == XFS_ATTRUPDATE_CREATE)
1068                         goto out_trans_cancel;
1069                 xfs_attr_defer_add(args, XFS_ATTR_DEFER_REPLACE);
1070                 break;
1071         case -ENOATTR:
1072                 /* Can't remove what isn't there. */
1073                 if (op == XFS_ATTRUPDATE_REMOVE)
1074                         goto out_trans_cancel;
1075 
1076                 /* Pure replace fails if no existing attr to replace. */
1077                 if (op == XFS_ATTRUPDATE_REPLACE)
1078                         goto out_trans_cancel;
1079                 xfs_attr_defer_add(args, XFS_ATTR_DEFER_SET);
1080                 break;
1081         default:
1082                 goto out_trans_cancel;
1083         }
1084 
1085         /*
1086          * If this is a synchronous mount, make sure that the
1087          * transaction goes to disk before returning to the user.
1088          */
1089         if (xfs_has_wsync(mp))
1090                 xfs_trans_set_sync(args->trans);
1091 
1092         xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG);
1093 
1094         /*
1095          * Commit the last in the sequence of transactions.
1096          */
1097         xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
1098         error = xfs_trans_commit(args->trans);
1099 out_unlock:
1100         xfs_iunlock(dp, XFS_ILOCK_EXCL);
1101         args->trans = NULL;
1102         return error;
1103 
1104 out_trans_cancel:
1105         if (args->trans)
1106                 xfs_trans_cancel(args->trans);
1107         goto out_unlock;
1108 }
1109 
1110 /*========================================================================
1111  * External routines when attribute list is inside the inode
1112  *========================================================================*/
1113 
1114 int xfs_attr_sf_totsize(struct xfs_inode *dp)
1115 {
1116         struct xfs_attr_sf_hdr *sf = dp->i_af.if_data;
1117 
1118         return be16_to_cpu(sf->totsize);
1119 }
1120 
1121 /*
1122  * Add a name to the shortform attribute list structure
1123  * This is the external routine.
1124  */
1125 static int
1126 xfs_attr_shortform_addname(
1127         struct xfs_da_args      *args)
1128 {
1129         int                     newsize, forkoff;
1130 
1131         trace_xfs_attr_sf_addname(args);
1132 
1133         if (xfs_attr_sf_findname(args)) {
1134                 int             error;
1135 
1136                 ASSERT(args->op_flags & XFS_DA_OP_REPLACE);
1137 
1138                 error = xfs_attr_sf_removename(args);
1139                 if (error)
1140                         return error;
1141 
1142                 /*
1143                  * Since we have removed the old attr, clear XFS_DA_OP_REPLACE
1144                  * so that the new attr doesn't fit in shortform format, the
1145                  * leaf format add routine won't trip over the attr not being
1146                  * around.
1147                  */
1148                 args->op_flags &= ~XFS_DA_OP_REPLACE;
1149         } else {
1150                 ASSERT(!(args->op_flags & XFS_DA_OP_REPLACE));
1151         }
1152 
1153         if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
1154             args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
1155                 return -ENOSPC;
1156 
1157         newsize = xfs_attr_sf_totsize(args->dp);
1158         newsize += xfs_attr_sf_entsize_byname(args->namelen, args->valuelen);
1159 
1160         forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
1161         if (!forkoff)
1162                 return -ENOSPC;
1163 
1164         xfs_attr_shortform_add(args, forkoff);
1165         return 0;
1166 }
1167 
1168 
1169 /*========================================================================
1170  * External routines when attribute list is one block
1171  *========================================================================*/
1172 
1173 /* Save the current remote block info and clear the current pointers. */
1174 static void
1175 xfs_attr_save_rmt_blk(
1176         struct xfs_da_args      *args)
1177 {
1178         args->blkno2 = args->blkno;
1179         args->index2 = args->index;
1180         args->rmtblkno2 = args->rmtblkno;
1181         args->rmtblkcnt2 = args->rmtblkcnt;
1182         args->rmtvaluelen2 = args->rmtvaluelen;
1183         args->rmtblkno = 0;
1184         args->rmtblkcnt = 0;
1185         args->rmtvaluelen = 0;
1186 }
1187 
1188 /* Set stored info about a remote block */
1189 static void
1190 xfs_attr_restore_rmt_blk(
1191         struct xfs_da_args      *args)
1192 {
1193         args->blkno = args->blkno2;
1194         args->index = args->index2;
1195         args->rmtblkno = args->rmtblkno2;
1196         args->rmtblkcnt = args->rmtblkcnt2;
1197         args->rmtvaluelen = args->rmtvaluelen2;
1198 }
1199 
1200 /*
1201  * Tries to add an attribute to an inode in leaf form
1202  *
1203  * This function is meant to execute as part of a delayed operation and leaves
1204  * the transaction handling to the caller.  On success the attribute is added
1205  * and the inode and transaction are left dirty.  If there is not enough space,
1206  * the attr data is converted to node format and -ENOSPC is returned. Caller is
1207  * responsible for handling the dirty inode and transaction or adding the attr
1208  * in node format.
1209  */
1210 STATIC int
1211 xfs_attr_leaf_try_add(
1212         struct xfs_da_args      *args)
1213 {
1214         struct xfs_buf          *bp;
1215         int                     error;
1216 
1217         error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, &bp);
1218         if (error)
1219                 return error;
1220 
1221         /*
1222          * Look up the xattr name to set the insertion point for the new xattr.
1223          */
1224         error = xfs_attr3_leaf_lookup_int(bp, args);
1225         switch (error) {
1226         case -ENOATTR:
1227                 if (args->op_flags & XFS_DA_OP_REPLACE)
1228                         goto out_brelse;
1229                 break;
1230         case -EEXIST:
1231                 if (!(args->op_flags & XFS_DA_OP_REPLACE))
1232                         goto out_brelse;
1233 
1234                 trace_xfs_attr_leaf_replace(args);
1235                 /*
1236                  * Save the existing remote attr state so that the current
1237                  * values reflect the state of the new attribute we are about to
1238                  * add, not the attribute we just found and will remove later.
1239                  */
1240                 xfs_attr_save_rmt_blk(args);
1241                 break;
1242         case 0:
1243                 break;
1244         default:
1245                 goto out_brelse;
1246         }
1247 
1248         return xfs_attr3_leaf_add(bp, args);
1249 
1250 out_brelse:
1251         xfs_trans_brelse(args->trans, bp);
1252         return error;
1253 }
1254 
1255 /*
1256  * Return EEXIST if attr is found, or ENOATTR if not
1257  */
1258 STATIC int
1259 xfs_attr_leaf_hasname(
1260         struct xfs_da_args      *args,
1261         struct xfs_buf          **bp)
1262 {
1263         int                     error = 0;
1264 
1265         error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, bp);
1266         if (error)
1267                 return error;
1268 
1269         error = xfs_attr3_leaf_lookup_int(*bp, args);
1270         if (error != -ENOATTR && error != -EEXIST)
1271                 xfs_trans_brelse(args->trans, *bp);
1272 
1273         return error;
1274 }
1275 
1276 /*
1277  * Remove a name from the leaf attribute list structure
1278  *
1279  * This leaf block cannot have a "remote" value, we only call this routine
1280  * if bmap_one_block() says there is only one block (ie: no remote blks).
1281  */
1282 STATIC int
1283 xfs_attr_leaf_removename(
1284         struct xfs_da_args      *args)
1285 {
1286         struct xfs_inode        *dp;
1287         struct xfs_buf          *bp;
1288         int                     error, forkoff;
1289 
1290         trace_xfs_attr_leaf_removename(args);
1291 
1292         /*
1293          * Remove the attribute.
1294          */
1295         dp = args->dp;
1296 
1297         error = xfs_attr_leaf_hasname(args, &bp);
1298         if (error == -ENOATTR) {
1299                 xfs_trans_brelse(args->trans, bp);
1300                 if (args->op_flags & XFS_DA_OP_RECOVERY)
1301                         return 0;
1302                 return error;
1303         } else if (error != -EEXIST)
1304                 return error;
1305 
1306         xfs_attr3_leaf_remove(bp, args);
1307 
1308         /*
1309          * If the result is small enough, shrink it all into the inode.
1310          */
1311         forkoff = xfs_attr_shortform_allfit(bp, dp);
1312         if (forkoff)
1313                 return xfs_attr3_leaf_to_shortform(bp, args, forkoff);
1314                 /* bp is gone due to xfs_da_shrink_inode */
1315 
1316         return 0;
1317 }
1318 
1319 /*
1320  * Look up a name in a leaf attribute list structure.
1321  *
1322  * This leaf block cannot have a "remote" value, we only call this routine
1323  * if bmap_one_block() says there is only one block (ie: no remote blks).
1324  *
1325  * Returns 0 on successful retrieval, otherwise an error.
1326  */
1327 STATIC int
1328 xfs_attr_leaf_get(xfs_da_args_t *args)
1329 {
1330         struct xfs_buf *bp;
1331         int error;
1332 
1333         trace_xfs_attr_leaf_get(args);
1334 
1335         error = xfs_attr_leaf_hasname(args, &bp);
1336 
1337         if (error == -ENOATTR)  {
1338                 xfs_trans_brelse(args->trans, bp);
1339                 return error;
1340         } else if (error != -EEXIST)
1341                 return error;
1342 
1343 
1344         error = xfs_attr3_leaf_getvalue(bp, args);
1345         xfs_trans_brelse(args->trans, bp);
1346         return error;
1347 }
1348 
1349 /* Return EEXIST if attr is found, or ENOATTR if not. */
1350 STATIC int
1351 xfs_attr_node_lookup(
1352         struct xfs_da_args      *args,
1353         struct xfs_da_state     *state)
1354 {
1355         int                     retval, error;
1356 
1357         /*
1358          * Search to see if name exists, and get back a pointer to it.
1359          */
1360         error = xfs_da3_node_lookup_int(state, &retval);
1361         if (error)
1362                 return error;
1363 
1364         return retval;
1365 }
1366 
1367 /*========================================================================
1368  * External routines when attribute list size > geo->blksize
1369  *========================================================================*/
1370 
1371 STATIC int
1372 xfs_attr_node_addname_find_attr(
1373          struct xfs_attr_intent *attr)
1374 {
1375         struct xfs_da_args      *args = attr->xattri_da_args;
1376         int                     error;
1377 
1378         /*
1379          * Search to see if name already exists, and get back a pointer
1380          * to where it should go.
1381          */
1382         xfs_attr_item_init_da_state(attr);
1383         error = xfs_attr_node_lookup(args, attr->xattri_da_state);
1384         switch (error) {
1385         case -ENOATTR:
1386                 if (args->op_flags & XFS_DA_OP_REPLACE)
1387                         goto error;
1388                 break;
1389         case -EEXIST:
1390                 if (!(args->op_flags & XFS_DA_OP_REPLACE))
1391                         goto error;
1392 
1393 
1394                 trace_xfs_attr_node_replace(args);
1395                 /*
1396                  * Save the existing remote attr state so that the current
1397                  * values reflect the state of the new attribute we are about to
1398                  * add, not the attribute we just found and will remove later.
1399                  */
1400                 xfs_attr_save_rmt_blk(args);
1401                 break;
1402         case 0:
1403                 break;
1404         default:
1405                 goto error;
1406         }
1407 
1408         return 0;
1409 error:
1410         if (attr->xattri_da_state) {
1411                 xfs_da_state_free(attr->xattri_da_state);
1412                 attr->xattri_da_state = NULL;
1413         }
1414         return error;
1415 }
1416 
1417 /*
1418  * Add a name to a Btree-format attribute list.
1419  *
1420  * This will involve walking down the Btree, and may involve splitting
1421  * leaf nodes and even splitting intermediate nodes up to and including
1422  * the root node (a special case of an intermediate node).
1423  */
1424 static int
1425 xfs_attr_node_try_addname(
1426         struct xfs_attr_intent          *attr)
1427 {
1428         struct xfs_da_state             *state = attr->xattri_da_state;
1429         struct xfs_da_state_blk         *blk;
1430         int                             error;
1431 
1432         trace_xfs_attr_node_addname(state->args);
1433 
1434         blk = &state->path.blk[state->path.active-1];
1435         ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1436 
1437         error = xfs_attr3_leaf_add(blk->bp, state->args);
1438         if (error == -ENOSPC) {
1439                 if (state->path.active == 1) {
1440                         /*
1441                          * Its really a single leaf node, but it had
1442                          * out-of-line values so it looked like it *might*
1443                          * have been a b-tree. Let the caller deal with this.
1444                          */
1445                         goto out;
1446                 }
1447 
1448                 /*
1449                  * Split as many Btree elements as required.
1450                  * This code tracks the new and old attr's location
1451                  * in the index/blkno/rmtblkno/rmtblkcnt fields and
1452                  * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
1453                  */
1454                 error = xfs_da3_split(state);
1455                 if (error)
1456                         goto out;
1457         } else {
1458                 /*
1459                  * Addition succeeded, update Btree hashvals.
1460                  */
1461                 xfs_da3_fixhashpath(state, &state->path);
1462         }
1463 
1464 out:
1465         xfs_da_state_free(state);
1466         attr->xattri_da_state = NULL;
1467         return error;
1468 }
1469 
1470 static int
1471 xfs_attr_node_removename(
1472         struct xfs_da_args      *args,
1473         struct xfs_da_state     *state)
1474 {
1475         struct xfs_da_state_blk *blk;
1476         int                     retval;
1477 
1478         /*
1479          * Remove the name and update the hashvals in the tree.
1480          */
1481         blk = &state->path.blk[state->path.active-1];
1482         ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
1483         retval = xfs_attr3_leaf_remove(blk->bp, args);
1484         xfs_da3_fixhashpath(state, &state->path);
1485 
1486         return retval;
1487 }
1488 
1489 static int
1490 xfs_attr_node_remove_attr(
1491         struct xfs_attr_intent          *attr)
1492 {
1493         struct xfs_da_args              *args = attr->xattri_da_args;
1494         struct xfs_da_state             *state = xfs_da_state_alloc(args);
1495         int                             retval = 0;
1496         int                             error = 0;
1497 
1498         /*
1499          * The attr we are removing has already been marked incomplete, so
1500          * we need to set the filter appropriately to re-find the "old"
1501          * attribute entry after any split ops.
1502          */
1503         args->attr_filter |= XFS_ATTR_INCOMPLETE;
1504         error = xfs_da3_node_lookup_int(state, &retval);
1505         if (error)
1506                 goto out;
1507 
1508         error = xfs_attr_node_removename(args, state);
1509 
1510         /*
1511          * Check to see if the tree needs to be collapsed.
1512          */
1513         if (retval && (state->path.active > 1)) {
1514                 error = xfs_da3_join(state);
1515                 if (error)
1516                         goto out;
1517         }
1518         retval = error = 0;
1519 
1520 out:
1521         xfs_da_state_free(state);
1522         if (error)
1523                 return error;
1524         return retval;
1525 }
1526 
1527 /*
1528  * Retrieve the attribute data from a node attribute list.
1529  *
1530  * This routine gets called for any attribute fork that has more than one
1531  * block, ie: both true Btree attr lists and for single-leaf-blocks with
1532  * "remote" values taking up more blocks.
1533  *
1534  * Returns 0 on successful retrieval, otherwise an error.
1535  */
1536 STATIC int
1537 xfs_attr_node_get(
1538         struct xfs_da_args      *args)
1539 {
1540         struct xfs_da_state     *state;
1541         struct xfs_da_state_blk *blk;
1542         int                     i;
1543         int                     error;
1544 
1545         trace_xfs_attr_node_get(args);
1546 
1547         /*
1548          * Search to see if name exists, and get back a pointer to it.
1549          */
1550         state = xfs_da_state_alloc(args);
1551         error = xfs_attr_node_lookup(args, state);
1552         if (error != -EEXIST)
1553                 goto out_release;
1554 
1555         /*
1556          * Get the value, local or "remote"
1557          */
1558         blk = &state->path.blk[state->path.active - 1];
1559         error = xfs_attr3_leaf_getvalue(blk->bp, args);
1560 
1561         /*
1562          * If not in a transaction, we have to release all the buffers.
1563          */
1564 out_release:
1565         for (i = 0; i < state->path.active; i++) {
1566                 xfs_trans_brelse(args->trans, state->path.blk[i].bp);
1567                 state->path.blk[i].bp = NULL;
1568         }
1569 
1570         xfs_da_state_free(state);
1571         return error;
1572 }
1573 
1574 /* Enforce that there is at most one namespace bit per attr. */
1575 inline bool xfs_attr_check_namespace(unsigned int attr_flags)
1576 {
1577         return hweight32(attr_flags & XFS_ATTR_NSP_ONDISK_MASK) < 2;
1578 }
1579 
1580 /* Returns true if the attribute entry name is valid. */
1581 bool
1582 xfs_attr_namecheck(
1583         unsigned int    attr_flags,
1584         const void      *name,
1585         size_t          length)
1586 {
1587         /* Only one namespace bit allowed. */
1588         if (!xfs_attr_check_namespace(attr_flags))
1589                 return false;
1590 
1591         /*
1592          * MAXNAMELEN includes the trailing null, but (name/length) leave it
1593          * out, so use >= for the length check.
1594          */
1595         if (length >= MAXNAMELEN)
1596                 return false;
1597 
1598         /* Parent pointers have their own validation. */
1599         if (attr_flags & XFS_ATTR_PARENT)
1600                 return xfs_parent_namecheck(attr_flags, name, length);
1601 
1602         /* There shouldn't be any nulls here */
1603         return !memchr(name, 0, length);
1604 }
1605 
1606 int __init
1607 xfs_attr_intent_init_cache(void)
1608 {
1609         xfs_attr_intent_cache = kmem_cache_create("xfs_attr_intent",
1610                         sizeof(struct xfs_attr_intent),
1611                         0, 0, NULL);
1612 
1613         return xfs_attr_intent_cache != NULL ? 0 : -ENOMEM;
1614 }
1615 
1616 void
1617 xfs_attr_intent_destroy_cache(void)
1618 {
1619         kmem_cache_destroy(xfs_attr_intent_cache);
1620         xfs_attr_intent_cache = NULL;
1621 }
1622 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php