// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * Copyright (c) 2013 Red Hat, Inc. * All Rights Reserved. */ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_bmap.h" #include "xfs_attr.h" #include "xfs_attr_remote.h" #include "xfs_trace.h" #include "xfs_error.h" #include "xfs_health.h" #define ATTR_RMTVALUE_MAPSIZE … /* * Remote Attribute Values * ======================= * * Remote extended attribute values are conceptually simple -- they're written * to data blocks mapped by an inode's attribute fork, and they have an upper * size limit of 64k. Setting a value does not involve the XFS log. * * However, on a v5 filesystem, maximally sized remote attr values require one * block more than 64k worth of space to hold both the remote attribute value * header (64 bytes). On a 4k block filesystem this results in a 68k buffer; * on a 64k block filesystem, this would be a 128k buffer. Note that the log * format can only handle a dirty buffer of XFS_MAX_BLOCKSIZE length (64k). * Therefore, we /must/ ensure that remote attribute value buffers never touch * the logging system and therefore never have a log item. */ /* How many bytes can be stored in a remote value buffer? */ inline unsigned int xfs_attr3_rmt_buf_space( struct xfs_mount *mp) { … } /* Compute number of fsblocks needed to store a remote attr value */ unsigned int xfs_attr3_rmt_blocks( struct xfs_mount *mp, unsigned int attrlen) { … } /* * Checking of the remote attribute header is split into two parts. The verifier * does CRC, location and bounds checking, the unpacking function checks the * attribute parameters and owner. */ static xfs_failaddr_t xfs_attr3_rmt_hdr_ok( void *ptr, xfs_ino_t ino, uint32_t offset, uint32_t size, xfs_daddr_t bno) { … } static xfs_failaddr_t xfs_attr3_rmt_verify( struct xfs_mount *mp, struct xfs_buf *bp, void *ptr, xfs_daddr_t bno) { … } static int __xfs_attr3_rmt_read_verify( struct xfs_buf *bp, bool check_crc, xfs_failaddr_t *failaddr) { … } static void xfs_attr3_rmt_read_verify( struct xfs_buf *bp) { … } static xfs_failaddr_t xfs_attr3_rmt_verify_struct( struct xfs_buf *bp) { … } static void xfs_attr3_rmt_write_verify( struct xfs_buf *bp) { … } const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = …; STATIC int xfs_attr3_rmt_hdr_set( struct xfs_mount *mp, void *ptr, xfs_ino_t ino, uint32_t offset, uint32_t size, xfs_daddr_t bno) { … } /* * Helper functions to copy attribute data in and out of the one disk extents */ STATIC int xfs_attr_rmtval_copyout( struct xfs_mount *mp, struct xfs_buf *bp, struct xfs_inode *dp, xfs_ino_t owner, unsigned int *offset, unsigned int *valuelen, uint8_t **dst) { … } STATIC void xfs_attr_rmtval_copyin( struct xfs_mount *mp, struct xfs_buf *bp, xfs_ino_t ino, unsigned int *offset, unsigned int *valuelen, uint8_t **src) { … } /* * Read the value associated with an attribute from the out-of-line buffer * that we stored it in. * * Returns 0 on successful retrieval, otherwise an error. */ int xfs_attr_rmtval_get( struct xfs_da_args *args) { … } /* * Find a "hole" in the attribute address space large enough for us to drop the * new attributes value into */ int xfs_attr_rmt_find_hole( struct xfs_da_args *args) { … } int xfs_attr_rmtval_set_value( struct xfs_da_args *args) { … } /* Mark stale any incore buffers for the remote value. */ int xfs_attr_rmtval_stale( struct xfs_inode *ip, struct xfs_bmbt_irec *map, xfs_buf_flags_t incore_flags) { … } /* * Find a hole for the attr and store it in the delayed attr context. This * initializes the context to roll through allocating an attr extent for a * delayed attr operation */ int xfs_attr_rmtval_find_space( struct xfs_attr_intent *attr) { … } /* * Write one block of the value associated with an attribute into the * out-of-line buffer that we have defined for it. This is similar to a subset * of xfs_attr_rmtval_set, but records the current block to the delayed attr * context, and leaves transaction handling to the caller. */ int xfs_attr_rmtval_set_blk( struct xfs_attr_intent *attr) { … } /* * Remove the value associated with an attribute by deleting the * out-of-line buffer that it is stored on. */ int xfs_attr_rmtval_invalidate( struct xfs_da_args *args) { … } /* * Remove the value associated with an attribute by deleting the out-of-line * buffer that it is stored on. Returns -EAGAIN for the caller to refresh the * transaction and re-call the function. Callers should keep calling this * routine until it returns something other than -EAGAIN. */ int xfs_attr_rmtval_remove( struct xfs_attr_intent *attr) { … }