linux/fs/xfs/libxfs/xfs_attr.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc.
   4 * All Rights Reserved.
   5 */
   6#ifndef __XFS_ATTR_H__
   7#define __XFS_ATTR_H__
   8
   9struct xfs_inode;
  10struct xfs_da_args;
  11struct xfs_attr_list_context;
  12
  13/*
  14 * Large attribute lists are structured around Btrees where all the data
  15 * elements are in the leaf nodes.  Attribute names are hashed into an int,
  16 * then that int is used as the index into the Btree.  Since the hashval
  17 * of an attribute name may not be unique, we may have duplicate keys.
  18 * The internal links in the Btree are logical block offsets into the file.
  19 *
  20 * Small attribute lists use a different format and are packed as tightly
  21 * as possible so as to fit into the literal area of the inode.
  22 */
  23
  24/*
  25 * The maximum size (into the kernel or returned from the kernel) of an
  26 * attribute value or the buffer used for an attr_list() call.  Larger
  27 * sizes will result in an ERANGE return code.
  28 */
  29#define ATTR_MAX_VALUELEN       (64*1024)       /* max length of a value */
  30
  31/*
  32 * Kernel-internal version of the attrlist cursor.
  33 */
  34struct xfs_attrlist_cursor_kern {
  35        __u32   hashval;        /* hash value of next entry to add */
  36        __u32   blkno;          /* block containing entry (suggestion) */
  37        __u32   offset;         /* offset in list of equal-hashvals */
  38        __u16   pad1;           /* padding to match user-level */
  39        __u8    pad2;           /* padding to match user-level */
  40        __u8    initted;        /* T/F: cursor has been initialized */
  41};
  42
  43
  44/*========================================================================
  45 * Structure used to pass context around among the routines.
  46 *========================================================================*/
  47
  48
  49/* void; state communicated via *context */
  50typedef void (*put_listent_func_t)(struct xfs_attr_list_context *, int,
  51                              unsigned char *, int, int);
  52
  53struct xfs_attr_list_context {
  54        struct xfs_trans        *tp;
  55        struct xfs_inode        *dp;            /* inode */
  56        struct xfs_attrlist_cursor_kern cursor; /* position in list */
  57        void                    *buffer;        /* output buffer */
  58
  59        /*
  60         * Abort attribute list iteration if non-zero.  Can be used to pass
  61         * error values to the xfs_attr_list caller.
  62         */
  63        int                     seen_enough;
  64        bool                    allow_incomplete;
  65
  66        ssize_t                 count;          /* num used entries */
  67        int                     dupcnt;         /* count dup hashvals seen */
  68        int                     bufsize;        /* total buffer size */
  69        int                     firstu;         /* first used byte in buffer */
  70        unsigned int            attr_filter;    /* XFS_ATTR_{ROOT,SECURE} */
  71        int                     resynch;        /* T/F: resynch with cursor */
  72        put_listent_func_t      put_listent;    /* list output fmt function */
  73        int                     index;          /* index into output buffer */
  74};
  75
  76
  77/*
  78 * ========================================================================
  79 * Structure used to pass context around among the delayed routines.
  80 * ========================================================================
  81 */
  82
  83/*
  84 * Below is a state machine diagram for attr remove operations. The  XFS_DAS_*
  85 * states indicate places where the function would return -EAGAIN, and then
  86 * immediately resume from after being called by the calling function. States
  87 * marked as a "subroutine state" indicate that they belong to a subroutine, and
  88 * so the calling function needs to pass them back to that subroutine to allow
  89 * it to finish where it left off. But they otherwise do not have a role in the
  90 * calling function other than just passing through.
  91 *
  92 * xfs_attr_remove_iter()
  93 *              │
  94 *              v
  95 *        have attr to remove? ──n──> done
  96 *              │
  97 *              y
  98 *              │
  99 *              v
 100 *        are we short form? ──y──> xfs_attr_shortform_remove ──> done
 101 *              │
 102 *              n
 103 *              │
 104 *              V
 105 *        are we leaf form? ──y──> xfs_attr_leaf_removename ──> done
 106 *              │
 107 *              n
 108 *              │
 109 *              V
 110 *   ┌── need to setup state?
 111 *   │          │
 112 *   n          y
 113 *   │          │
 114 *   │          v
 115 *   │ find attr and get state
 116 *   │ attr has remote blks? ──n─┐
 117 *   │          │                v
 118 *   │          │         find and invalidate
 119 *   │          y         the remote blocks.
 120 *   │          │         mark attr incomplete
 121 *   │          ├────────────────┘
 122 *   └──────────┤
 123 *              │
 124 *              v
 125 *   Have remote blks to remove? ───y─────┐
 126 *              │        ^          remove the blks
 127 *              │        │                │
 128 *              │        │                v
 129 *              │  XFS_DAS_RMTBLK <─n── done?
 130 *              │  re-enter with          │
 131 *              │  one less blk to        y
 132 *              │      remove             │
 133 *              │                         V
 134 *              │                  refill the state
 135 *              n                         │
 136 *              │                         v
 137 *              │                   XFS_DAS_RM_NAME
 138 *              │                         │
 139 *              ├─────────────────────────┘
 140 *              │
 141 *              v
 142 *       remove leaf and
 143 *       update hash with
 144 *   xfs_attr_node_remove_cleanup
 145 *              │
 146 *              v
 147 *           need to
 148 *        shrink tree? ─n─┐
 149 *              │         │
 150 *              y         │
 151 *              │         │
 152 *              v         │
 153 *          join leaf     │
 154 *              │         │
 155 *              v         │
 156 *      XFS_DAS_RM_SHRINK │
 157 *              │         │
 158 *              v         │
 159 *       do the shrink    │
 160 *              │         │
 161 *              v         │
 162 *          free state <──┘
 163 *              │
 164 *              v
 165 *            done
 166 *
 167 *
 168 * Below is a state machine diagram for attr set operations.
 169 *
 170 * It seems the challenge with understanding this system comes from trying to
 171 * absorb the state machine all at once, when really one should only be looking
 172 * at it with in the context of a single function. Once a state sensitive
 173 * function is called, the idea is that it "takes ownership" of the
 174 * state machine. It isn't concerned with the states that may have belonged to
 175 * it's calling parent. Only the states relevant to itself or any other
 176 * subroutines there in. Once a calling function hands off the state machine to
 177 * a subroutine, it needs to respect the simple rule that it doesn't "own" the
 178 * state machine anymore, and it's the responsibility of that calling function
 179 * to propagate the -EAGAIN back up the call stack. Upon reentry, it is
 180 * committed to re-calling that subroutine until it returns something other than
 181 * -EAGAIN. Once that subroutine signals completion (by returning anything other
 182 * than -EAGAIN), the calling function can resume using the state machine.
 183 *
 184 *  xfs_attr_set_iter()
 185 *              │
 186 *              v
 187 *   ┌─y─ has an attr fork?
 188 *   │          |
 189 *   │          n
 190 *   │          |
 191 *   │          V
 192 *   │       add a fork
 193 *   │          │
 194 *   └──────────┤
 195 *              │
 196 *              V
 197 *   ┌─── is shortform?
 198 *   │          │
 199 *   │          y
 200 *   │          │
 201 *   │          V
 202 *   │   xfs_attr_set_fmt
 203 *   │          |
 204 *   │          V
 205 *   │ xfs_attr_try_sf_addname
 206 *   │          │
 207 *   │          V
 208 *   │      had enough ──y──> done
 209 *   │        space?
 210 *   n          │
 211 *   │          n
 212 *   │          │
 213 *   │          V
 214 *   │   transform to leaf
 215 *   │          │
 216 *   │          V
 217 *   │   hold the leaf buffer
 218 *   │          │
 219 *   │          V
 220 *   │     return -EAGAIN
 221 *   │      Re-enter in
 222 *   │       leaf form
 223 *   │
 224 *   └─> release leaf buffer
 225 *          if needed
 226 *              │
 227 *              V
 228 *   ┌───n── fork has
 229 *   │      only 1 blk?
 230 *   │          │
 231 *   │          y
 232 *   │          │
 233 *   │          v
 234 *   │ xfs_attr_leaf_try_add()
 235 *   │          │
 236 *   │          v
 237 *   │      had enough ──────────────y─────────────┐
 238 *   │        space?                               │
 239 *   │          │                                  │
 240 *   │          n                                  │
 241 *   │          │                                  │
 242 *   │          v                                  │
 243 *   │    return -EAGAIN                           │
 244 *   │      re-enter in                            │
 245 *   │        node form                            │
 246 *   │          │                                  │
 247 *   └──────────┤                                  │
 248 *              │                                  │
 249 *              V                                  │
 250 * xfs_attr_node_addname_find_attr                 │
 251 *        determines if this                       │
 252 *       is create or rename                       │
 253 *     find space to store attr                    │
 254 *              │                                  │
 255 *              v                                  │
 256 *     xfs_attr_node_addname                       │
 257 *              │                                  │
 258 *              v                                  │
 259 *   fits in a node leaf? ────n─────┐              │
 260 *              │     ^             v              │
 261 *              │     │       single leaf node?    │
 262 *              │     │         │            │     │
 263 *              y     │         y            n     │
 264 *              │     │         │            │     │
 265 *              v     │         v            v     │
 266 *            update  │    grow the leaf  split if │
 267 *           hashvals └── return -EAGAIN   needed  │
 268 *              │         retry leaf add     │     │
 269 *              │           on reentry       │     │
 270 *              ├────────────────────────────┘     │
 271 *              │                                  │
 272 *              v                                  │
 273 *         need to alloc                           │
 274 *   ┌─y── or flip flag?                           │
 275 *   │          │                                  │
 276 *   │          n                                  │
 277 *   │          │                                  │
 278 *   │          v                                  │
 279 *   │         done                                │
 280 *   │                                             │
 281 *   │                                             │
 282 *   │         XFS_DAS_FOUND_LBLK <────────────────┘
 283 *   │                  │
 284 *   │                  V
 285 *   │        xfs_attr_leaf_addname()
 286 *   │                  │
 287 *   │                  v
 288 *   │      ┌──first time through?
 289 *   │      │          │
 290 *   │      │          y
 291 *   │      │          │
 292 *   │      n          v
 293 *   │      │    if we have rmt blks
 294 *   │      │    find space for them
 295 *   │      │          │
 296 *   │      └──────────┤
 297 *   │                 │
 298 *   │                 v
 299 *   │            still have
 300 *   │      ┌─n─ blks to alloc? <──┐
 301 *   │      │          │           │
 302 *   │      │          y           │
 303 *   │      │          │           │
 304 *   │      │          v           │
 305 *   │      │     alloc one blk    │
 306 *   │      │     return -EAGAIN ──┘
 307 *   │      │    re-enter with one
 308 *   │      │    less blk to alloc
 309 *   │      │
 310 *   │      │
 311 *   │      └───> set the rmt
 312 *   │               value
 313 *   │                 │
 314 *   │                 v
 315 *   │               was this
 316 *   │              a rename? ──n─┐
 317 *   │                 │          │
 318 *   │                 y          │
 319 *   │                 │          │
 320 *   │                 v          │
 321 *   │           flip incomplete  │
 322 *   │               flag         │
 323 *   │                 │          │
 324 *   │                 v          │
 325 *   │         XFS_DAS_FLIP_LFLAG │
 326 *   │                 │          │
 327 *   │                 v          │
 328 *   │          need to remove    │
 329 *   │              old bks? ──n──┤
 330 *   │                 │          │
 331 *   │                 y          │
 332 *   │                 │          │
 333 *   │                 V          │
 334 *   │               remove       │
 335 *   │        ┌───> old blks      │
 336 *   │        │        │          │
 337 *   │ XFS_DAS_RM_LBLK │          │
 338 *   │        ^        │          │
 339 *   │        │        v          │
 340 *   │        └──y── more to      │
 341 *   │              remove?       │
 342 *   │                 │          │
 343 *   │                 n          │
 344 *   │                 │          │
 345 *   │                 v          │
 346 *   │          XFS_DAS_RD_LEAF   │
 347 *   │                 │          │
 348 *   │                 v          │
 349 *   │            remove leaf     │
 350 *   │                 │          │
 351 *   │                 v          │
 352 *   │            shrink to sf    │
 353 *   │             if needed      │
 354 *   │                 │          │
 355 *   │                 v          │
 356 *   │                done <──────┘
 357 *   │
 358 *   └──────> XFS_DAS_FOUND_NBLK
 359 *                     │
 360 *                     v
 361 *       ┌─────n──  need to
 362 *       │        alloc blks?
 363 *       │             │
 364 *       │             y
 365 *       │             │
 366 *       │             v
 367 *       │        find space
 368 *       │             │
 369 *       │             v
 370 *       │  ┌─>XFS_DAS_ALLOC_NODE
 371 *       │  │          │
 372 *       │  │          v
 373 *       │  │      alloc blk
 374 *       │  │          │
 375 *       │  │          v
 376 *       │  └──y── need to alloc
 377 *       │         more blocks?
 378 *       │             │
 379 *       │             n
 380 *       │             │
 381 *       │             v
 382 *       │      set the rmt value
 383 *       │             │
 384 *       │             v
 385 *       │          was this
 386 *       └────────> a rename? ──n─┐
 387 *                     │          │
 388 *                     y          │
 389 *                     │          │
 390 *                     v          │
 391 *               flip incomplete  │
 392 *                   flag         │
 393 *                     │          │
 394 *                     v          │
 395 *             XFS_DAS_FLIP_NFLAG │
 396 *                     │          │
 397 *                     v          │
 398 *                 need to        │
 399 *               remove blks? ─n──┤
 400 *                     │          │
 401 *                     y          │
 402 *                     │          │
 403 *                     v          │
 404 *                   remove       │
 405 *        ┌────────> old blks     │
 406 *        │            │          │
 407 *  XFS_DAS_RM_NBLK    │          │
 408 *        ^            │          │
 409 *        │            v          │
 410 *        └──────y── more to      │
 411 *                   remove       │
 412 *                     │          │
 413 *                     n          │
 414 *                     │          │
 415 *                     v          │
 416 *              XFS_DAS_CLR_FLAG  │
 417 *                     │          │
 418 *                     v          │
 419 *                clear flags     │
 420 *                     │          │
 421 *                     ├──────────┘
 422 *                     │
 423 *                     v
 424 *                   done
 425 */
 426
 427/*
 428 * Enum values for xfs_delattr_context.da_state
 429 *
 430 * These values are used by delayed attribute operations to keep track  of where
 431 * they were before they returned -EAGAIN.  A return code of -EAGAIN signals the
 432 * calling function to roll the transaction, and then call the subroutine to
 433 * finish the operation.  The enum is then used by the subroutine to jump back
 434 * to where it was and resume executing where it left off.
 435 */
 436enum xfs_delattr_state {
 437        XFS_DAS_UNINIT          = 0,  /* No state has been set yet */
 438        XFS_DAS_RMTBLK,               /* Removing remote blks */
 439        XFS_DAS_RM_NAME,              /* Remove attr name */
 440        XFS_DAS_RM_SHRINK,            /* We are shrinking the tree */
 441        XFS_DAS_FOUND_LBLK,           /* We found leaf blk for attr */
 442        XFS_DAS_FOUND_NBLK,           /* We found node blk for attr */
 443        XFS_DAS_FLIP_LFLAG,           /* Flipped leaf INCOMPLETE attr flag */
 444        XFS_DAS_RM_LBLK,              /* A rename is removing leaf blocks */
 445        XFS_DAS_RD_LEAF,              /* Read in the new leaf */
 446        XFS_DAS_ALLOC_NODE,           /* We are allocating node blocks */
 447        XFS_DAS_FLIP_NFLAG,           /* Flipped node INCOMPLETE attr flag */
 448        XFS_DAS_RM_NBLK,              /* A rename is removing node blocks */
 449        XFS_DAS_CLR_FLAG,             /* Clear incomplete flag */
 450};
 451
 452/*
 453 * Defines for xfs_delattr_context.flags
 454 */
 455#define XFS_DAC_DEFER_FINISH            0x01 /* finish the transaction */
 456#define XFS_DAC_LEAF_ADDNAME_INIT       0x02 /* xfs_attr_leaf_addname init*/
 457
 458/*
 459 * Context used for keeping track of delayed attribute operations
 460 */
 461struct xfs_delattr_context {
 462        struct xfs_da_args      *da_args;
 463
 464        /* Used in xfs_attr_rmtval_set_blk to roll through allocating blocks */
 465        struct xfs_bmbt_irec    map;
 466        xfs_dablk_t             lblkno;
 467        int                     blkcnt;
 468
 469        /* Used in xfs_attr_node_removename to roll through removing blocks */
 470        struct xfs_da_state     *da_state;
 471
 472        /* Used to keep track of current state of delayed operation */
 473        unsigned int            flags;
 474        enum xfs_delattr_state  dela_state;
 475};
 476
 477/*========================================================================
 478 * Function prototypes for the kernel.
 479 *========================================================================*/
 480
 481/*
 482 * Overall external interface routines.
 483 */
 484int xfs_attr_inactive(struct xfs_inode *dp);
 485int xfs_attr_list_ilocked(struct xfs_attr_list_context *);
 486int xfs_attr_list(struct xfs_attr_list_context *);
 487int xfs_inode_hasattr(struct xfs_inode *ip);
 488bool xfs_attr_is_leaf(struct xfs_inode *ip);
 489int xfs_attr_get_ilocked(struct xfs_da_args *args);
 490int xfs_attr_get(struct xfs_da_args *args);
 491int xfs_attr_set(struct xfs_da_args *args);
 492int xfs_attr_set_args(struct xfs_da_args *args);
 493int xfs_attr_remove_args(struct xfs_da_args *args);
 494int xfs_attr_remove_iter(struct xfs_delattr_context *dac);
 495bool xfs_attr_namecheck(const void *name, size_t length);
 496void xfs_delattr_context_init(struct xfs_delattr_context *dac,
 497                              struct xfs_da_args *args);
 498
 499#endif  /* __XFS_ATTR_H__ */
 500