blob: 6f6136165efe0b9da18434888c1abba86c0af814 [file] [log] [blame]
// 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__ */