/*
- * Copyright (c) 2000-2015 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
/* Internal Data structures*/
+#define NEW_XATTR TARGET_CPU_ARM64
+
+#if NEW_XATTR
+
+// number of concurrent xattr IOs permitted
+#define XATTR_NUM_FEXTS 64u
+// bitmap size, in 64bit words, used to track concurrent xattr IOs
+#define XATTR_BM_SIZE ((XATTR_NUM_FEXTS) / (NBBY * sizeof(uint64_t)))
+
+/*
+ * State for all stream based xattr IO on a volume.
+ *
+ * Fixed size thread local storage for use across the IO stack.
+ *
+ * Fields:
+ * - lock
+ * A spin lock used to access both the free file extent bitmap, `free_bm',
+ * and the xattr file extents themselves, `xattr_fexts'.
+ * - free_bm
+ * This bitmap represents the unused indices of `xattr_fexts'. The name is
+ * somewhat backwards: set bits (with a value of one) denote *used* indices.
+ * - xattr_fexts
+ * These are references to xattr file extents used as thread local storage to
+ * communicate from top level xattr IO functions, through the cluster layer,
+ * down into lower level IO functions (hfs_vnop_blockmap()).
+ * Each index which contains a non-NULL fext should have its corresponding
+ * bit within `free_bm' set. Though the reverse is not strictly true: a bit
+ * within the bitmap may be set before the corresponding fext is. This is
+ * the case when memory for a file extent reference is preallocated before
+ * the value of the file extent is available.
+ * This is an array of pointers rather than an array of file extents because:
+ * - it avoids both copying a full fext into and out from the array
+ * - it prints more nicely in lldb
+ */
+typedef struct {
+ lck_spin_t lock;
+ uint64_t free_bm[XATTR_BM_SIZE];
+ const HFSPlusExtentDescriptor *xattr_fexts[XATTR_NUM_FEXTS];
+} xattr_io_info_t;
+
+#endif
+
/* This structure describes the HFS specific mount structure data. */
typedef struct hfsmount {
u_int32_t hfs_flags; /* see below */
struct vnode * hfs_attribute_vp;
struct vnode * hfs_startup_vp;
struct vnode * hfs_attrdata_vp; /* pseudo file */
+#if NEW_XATTR
+ xattr_io_info_t hfs_xattr_io; /* Note, this is a big structure ~(64 * 8 bytes) */
+#endif
struct cnode * hfs_extents_cp;
struct cnode * hfs_catalog_cp;
struct cnode * hfs_allocation_cp;
extern errno_t hfs_get_fsinfo(struct hfsmount *hfsmp, void *a_data);
extern void hfs_fsinfo_data_add(struct hfs_fsinfo_data *fsinfo, uint64_t entry);
+#if NEW_XATTR
+bool hfs_xattr_fext_find(xattr_io_info_t *info, uint32_t fs_bsize,
+ uint64_t off, HFSPlusExtentDescriptor *out, uint64_t *off_out);
+#endif
+
struct hfs_sysctl_chain {
struct sysctl_oid *oid;
struct hfs_sysctl_chain *next;