| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Copyright (c) 2022 Oracle, Inc. |
| * All Rights Reserved. |
| */ |
| #ifndef __XFS_PARENT_H__ |
| #define __XFS_PARENT_H__ |
| |
| extern struct kmem_cache *xfs_parent_intent_cache; |
| |
| /* Metadata validators */ |
| bool xfs_parent_namecheck(struct xfs_mount *mp, |
| const struct xfs_parent_name_rec *rec, size_t reclen, |
| unsigned int attr_flags); |
| bool xfs_parent_valuecheck(struct xfs_mount *mp, size_t namelen, |
| const void *value, size_t valuelen); |
| |
| /* |
| * Incore version of a parent pointer, also contains dirent name so callers |
| * can pass/obtain all the parent pointer information in a single structure |
| */ |
| struct xfs_parent_name_irec { |
| /* Key fields for looking up a particular parent pointer. */ |
| xfs_ino_t p_ino; |
| uint32_t p_gen; |
| uint8_t hashlen; |
| uint8_t p_namehash[XFS_PARENT_NAME_MAX_HASH_SIZE]; |
| |
| /* Attributes of a parent pointer. */ |
| uint8_t p_namelen; |
| unsigned char p_name[MAXNAMELEN]; |
| }; |
| |
| void xfs_parent_irec_from_disk(struct xfs_parent_name_irec *irec, |
| const struct xfs_parent_name_rec *rec, int reclen, |
| const void *value, int valuelen); |
| void xfs_parent_irec_to_disk(struct xfs_parent_name_rec *rec, int *reclen, |
| void *value, int *valuelen, |
| const struct xfs_parent_name_irec *irec); |
| |
| /* |
| * Dynamically allocd structure used to wrap the needed data to pass around |
| * the defer ops machinery |
| */ |
| struct xfs_parent_defer { |
| union { |
| struct xfs_parent_name_rec rec; |
| __u8 dummy1[XFS_PARENT_NAME_MAX_SIZE]; |
| }; |
| union { |
| struct xfs_parent_name_rec old_rec; |
| __u8 dummy2[XFS_PARENT_NAME_MAX_SIZE]; |
| }; |
| struct xfs_da_args args; |
| bool have_log; |
| }; |
| |
| /* |
| * Parent pointer attribute prototypes |
| */ |
| int __xfs_parent_init(struct xfs_mount *mp, bool grab_log, |
| struct xfs_parent_defer **parentp); |
| |
| static inline int |
| xfs_parent_start( |
| struct xfs_mount *mp, |
| struct xfs_parent_defer **pp) |
| { |
| *pp = NULL; |
| |
| if (xfs_has_parent(mp)) |
| return __xfs_parent_init(mp, true, pp); |
| return 0; |
| } |
| |
| static inline int |
| xfs_parent_start_locked( |
| struct xfs_mount *mp, |
| struct xfs_parent_defer **pp) |
| { |
| *pp = NULL; |
| |
| if (xfs_has_parent(mp)) |
| return __xfs_parent_init(mp, false, pp); |
| return 0; |
| } |
| |
| int xfs_parent_add(struct xfs_trans *tp, struct xfs_parent_defer *parent, |
| struct xfs_inode *dp, const struct xfs_name *parent_name, |
| struct xfs_inode *child); |
| int xfs_parent_replace(struct xfs_trans *tp, |
| struct xfs_parent_defer *new_parent, struct xfs_inode *old_dp, |
| const struct xfs_name *old_name, struct xfs_inode *new_ip, |
| const struct xfs_name *new_name, struct xfs_inode *child); |
| int xfs_parent_remove(struct xfs_trans *tp, |
| struct xfs_parent_defer *parent, struct xfs_inode *dp, |
| const struct xfs_name *name, struct xfs_inode *child); |
| |
| void __xfs_parent_cancel(struct xfs_mount *mp, struct xfs_parent_defer *parent); |
| |
| static inline void |
| xfs_parent_finish( |
| struct xfs_mount *mp, |
| struct xfs_parent_defer *p) |
| { |
| if (p) |
| __xfs_parent_cancel(mp, p); |
| } |
| |
| int xfs_parent_namehash(struct xfs_inode *ip, const struct xfs_name *name, |
| void *namehash, unsigned int namehash_len); |
| |
| int xfs_parent_irec_hash(struct xfs_inode *ip, |
| struct xfs_parent_name_irec *pptr); |
| |
| unsigned int xfs_pptr_calc_space_res(struct xfs_mount *mp, |
| unsigned int namelen); |
| |
| /* Scratchpad memory so that raw parent operations don't burn stack space. */ |
| struct xfs_parent_scratch { |
| union { |
| struct xfs_parent_name_rec rec; |
| __u8 dummy1[XFS_PARENT_NAME_MAX_SIZE]; |
| }; |
| struct xfs_da_args args; |
| }; |
| |
| int xfs_parent_lookup(struct xfs_trans *tp, struct xfs_inode *ip, |
| const struct xfs_parent_name_irec *pptr, unsigned char *name, |
| unsigned int namelen, struct xfs_parent_scratch *scratch); |
| |
| int xfs_parent_set(struct xfs_inode *ip, |
| const struct xfs_parent_name_irec *pptr, |
| struct xfs_parent_scratch *scratch); |
| |
| int xfs_parent_unset(struct xfs_inode *ip, |
| const struct xfs_parent_name_irec *rec, |
| struct xfs_parent_scratch *scratch); |
| |
| #endif /* __XFS_PARENT_H__ */ |