Commit 726801ba authored by Tim Shimmin's avatar Tim Shimmin

[XFS] Add EA list callbacks for xfs kernel use. Cleanup some namespace

code.

SGI-PV: 954372
SGI-Modid: xfs-linux-melb:xfs-kern:26583a
Signed-off-by: default avatarTim Shimmin <tes@sgi.com>
parent 69e23b9a
......@@ -91,7 +91,6 @@ STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
/*
* Routines to manipulate out-of-line attribute values.
*/
STATIC int xfs_attr_rmtval_get(xfs_da_args_t *args);
STATIC int xfs_attr_rmtval_set(xfs_da_args_t *args);
STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args);
......@@ -180,7 +179,7 @@ xfs_attr_get(bhv_desc_t *bdp, const char *name, char *value, int *valuelenp,
return(error);
}
STATIC int
int
xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
char *value, int valuelen, int flags)
{
......@@ -440,7 +439,7 @@ xfs_attr_set(bhv_desc_t *bdp, const char *name, char *value, int valuelen, int f
* Generic handler routine to remove a name from an attribute list.
* Transitions attribute list from Btree to shortform as necessary.
*/
STATIC int
int
xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags)
{
xfs_da_args_t args;
......@@ -591,6 +590,110 @@ xfs_attr_remove(bhv_desc_t *bdp, const char *name, int flags, struct cred *cred)
return xfs_attr_remove_int(dp, name, namelen, flags);
}
int /* error */
xfs_attr_list_int(xfs_attr_list_context_t *context)
{
int error;
xfs_inode_t *dp = context->dp;
/*
* Decide on what work routines to call based on the inode size.
*/
if (XFS_IFORK_Q(dp) == 0 ||
(dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
dp->i_d.di_anextents == 0)) {
error = 0;
} else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
error = xfs_attr_shortform_list(context);
} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
error = xfs_attr_leaf_list(context);
} else {
error = xfs_attr_node_list(context);
}
return error;
}
#define ATTR_ENTBASESIZE /* minimum bytes used by an attr */ \
(((struct attrlist_ent *) 0)->a_name - (char *) 0)
#define ATTR_ENTSIZE(namelen) /* actual bytes used by an attr */ \
((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(u_int32_t)-1) \
& ~(sizeof(u_int32_t)-1))
/*
* Format an attribute and copy it out to the user's buffer.
* Take care to check values and protect against them changing later,
* we may be reading them directly out of a user buffer.
*/
/*ARGSUSED*/
STATIC int
xfs_attr_put_listent(xfs_attr_list_context_t *context, attrnames_t *namesp,
char *name, int namelen,
int valuelen, char *value)
{
attrlist_ent_t *aep;
int arraytop;
ASSERT(!(context->flags & ATTR_KERNOVAL));
ASSERT(context->count >= 0);
ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
ASSERT(context->firstu >= sizeof(*context->alist));
ASSERT(context->firstu <= context->bufsize);
arraytop = sizeof(*context->alist) +
context->count * sizeof(context->alist->al_offset[0]);
context->firstu -= ATTR_ENTSIZE(namelen);
if (context->firstu < arraytop) {
xfs_attr_trace_l_c("buffer full", context);
context->alist->al_more = 1;
context->seen_enough = 1;
return 1;
}
aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]);
aep->a_valuelen = valuelen;
memcpy(aep->a_name, name, namelen);
aep->a_name[ namelen ] = 0;
context->alist->al_offset[ context->count++ ] = context->firstu;
context->alist->al_count = context->count;
xfs_attr_trace_l_c("add", context);
return 0;
}
STATIC int
xfs_attr_kern_list(xfs_attr_list_context_t *context, attrnames_t *namesp,
char *name, int namelen,
int valuelen, char *value)
{
char *offset;
int arraytop;
ASSERT(context->count >= 0);
arraytop = context->count + namesp->attr_namelen + namelen + 1;
if (arraytop > context->firstu) {
context->count = -1; /* insufficient space */
return 1;
}
offset = (char *)context->alist + context->count;
strncpy(offset, namesp->attr_name, namesp->attr_namelen);
offset += namesp->attr_namelen;
strncpy(offset, name, namelen); /* real name */
offset += namelen;
*offset = '\0';
context->count += namesp->attr_namelen + namelen + 1;
return 0;
}
/*ARGSUSED*/
STATIC int
xfs_attr_kern_list_sizes(xfs_attr_list_context_t *context, attrnames_t *namesp,
char *name, int namelen,
int valuelen, char *value)
{
context->count += namesp->attr_namelen + namelen + 1;
return 0;
}
/*
* Generate a list of extended attribute names and optionally
* also value lengths. Positive return value follows the XFS
......@@ -615,13 +718,13 @@ xfs_attr_list(bhv_desc_t *bdp, char *buffer, int bufsize, int flags,
return(XFS_ERROR(EINVAL));
if ((cursor->initted == 0) &&
(cursor->hashval || cursor->blkno || cursor->offset))
return(XFS_ERROR(EINVAL));
return XFS_ERROR(EINVAL);
/*
* Check for a properly aligned buffer.
*/
if (((long)buffer) & (sizeof(int)-1))
return(XFS_ERROR(EFAULT));
return XFS_ERROR(EFAULT);
if (flags & ATTR_KERNOVAL)
bufsize = 0;
......@@ -634,53 +737,47 @@ xfs_attr_list(bhv_desc_t *bdp, char *buffer, int bufsize, int flags,
context.dupcnt = 0;
context.resynch = 1;
context.flags = flags;
if (!(flags & ATTR_KERNAMELS)) {
context.seen_enough = 0;
context.alist = (attrlist_t *)buffer;
context.put_value = 0;
if (flags & ATTR_KERNAMELS) {
context.bufsize = bufsize;
context.firstu = context.bufsize;
if (flags & ATTR_KERNOVAL)
context.put_listent = xfs_attr_kern_list_sizes;
else
context.put_listent = xfs_attr_kern_list;
} else {
context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */
context.firstu = context.bufsize;
context.alist = (attrlist_t *)buffer;
context.alist->al_count = 0;
context.alist->al_more = 0;
context.alist->al_offset[0] = context.bufsize;
}
else {
context.bufsize = bufsize;
context.firstu = context.bufsize;
context.alist = (attrlist_t *)buffer;
context.put_listent = xfs_attr_put_listent;
}
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return (EIO);
return EIO;
xfs_ilock(dp, XFS_ILOCK_SHARED);
/*
* Decide on what work routines to call based on the inode size.
*/
xfs_attr_trace_l_c("syscall start", &context);
if (XFS_IFORK_Q(dp) == 0 ||
(dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
dp->i_d.di_anextents == 0)) {
error = 0;
} else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
error = xfs_attr_shortform_list(&context);
} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
error = xfs_attr_leaf_list(&context);
} else {
error = xfs_attr_node_list(&context);
}
error = xfs_attr_list_int(&context);
xfs_iunlock(dp, XFS_ILOCK_SHARED);
xfs_attr_trace_l_c("syscall end", &context);
if (!(context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS))) {
ASSERT(error >= 0);
}
else { /* must return negated buffer size or the error */
if (context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS)) {
/* must return negated buffer size or the error */
if (context.count < 0)
error = XFS_ERROR(ERANGE);
else
error = -context.count;
}
} else
ASSERT(error >= 0);
return(error);
return error;
}
int /* error */
......@@ -1122,19 +1219,19 @@ xfs_attr_leaf_list(xfs_attr_list_context_t *context)
context->cursor->blkno = 0;
error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK);
if (error)
return(error);
return XFS_ERROR(error);
ASSERT(bp != NULL);
leaf = bp->data;
if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_ATTR_LEAF_MAGIC)) {
XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW,
context->dp->i_mount, leaf);
xfs_da_brelse(NULL, bp);
return(XFS_ERROR(EFSCORRUPTED));
return XFS_ERROR(EFSCORRUPTED);
}
(void)xfs_attr_leaf_list_int(bp, context);
error = xfs_attr_leaf_list_int(bp, context);
xfs_da_brelse(NULL, bp);
return(0);
return XFS_ERROR(error);
}
......@@ -1858,8 +1955,12 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
return(XFS_ERROR(EFSCORRUPTED));
}
error = xfs_attr_leaf_list_int(bp, context);
if (error || !leaf->hdr.info.forw)
break; /* not really an error, buffer full or EOF */
if (error) {
xfs_da_brelse(NULL, bp);
return error;
}
if (context->seen_enough || leaf->hdr.info.forw == 0)
break;
cursor->blkno = be32_to_cpu(leaf->hdr.info.forw);
xfs_da_brelse(NULL, bp);
error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1,
......@@ -1886,7 +1987,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
* Read the value associated with an attribute from the out-of-line buffer
* that we stored it in.
*/
STATIC int
int
xfs_attr_rmtval_get(xfs_da_args_t *args)
{
xfs_bmbt_irec_t map[ATTR_RMTVALUE_MAPSIZE];
......
......@@ -37,6 +37,7 @@
struct cred;
struct bhv_vnode;
struct xfs_attr_list_context;
typedef int (*attrset_t)(struct bhv_vnode *, char *, void *, size_t, int);
typedef int (*attrget_t)(struct bhv_vnode *, char *, void *, size_t, int);
......@@ -160,13 +161,16 @@ struct xfs_da_args;
*/
int xfs_attr_get(bhv_desc_t *, const char *, char *, int *, int, struct cred *);
int xfs_attr_set(bhv_desc_t *, const char *, char *, int, int, struct cred *);
int xfs_attr_set_int(struct xfs_inode *, const char *, int, char *, int, int);
int xfs_attr_remove(bhv_desc_t *, const char *, int, struct cred *);
int xfs_attr_list(bhv_desc_t *, char *, int, int,
struct attrlist_cursor_kern *, struct cred *);
int xfs_attr_remove_int(struct xfs_inode *, const char *, int, int);
int xfs_attr_list(bhv_desc_t *, char *, int, int, struct attrlist_cursor_kern *, struct cred *);
int xfs_attr_list_int(struct xfs_attr_list_context *);
int xfs_attr_inactive(struct xfs_inode *dp);
int xfs_attr_shortform_getvalue(struct xfs_da_args *);
int xfs_attr_fetch(struct xfs_inode *, const char *, int,
char *, int *, int, struct cred *);
int xfs_attr_rmtval_get(struct xfs_da_args *args);
#endif /* __XFS_ATTR_H__ */
This diff is collapsed.
......@@ -129,6 +129,19 @@ typedef struct xfs_attr_leafblock {
#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT)
#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT)
/*
* Conversion macros for converting namespace bits from argument flags
* to ondisk flags.
*/
#define XFS_ATTR_NSP_ARGS_MASK (ATTR_ROOT | ATTR_SECURE)
#define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE)
#define XFS_ATTR_NSP_ONDISK(flags) ((flags) & XFS_ATTR_NSP_ONDISK_MASK)
#define XFS_ATTR_NSP_ARGS(flags) ((flags) & XFS_ATTR_NSP_ARGS_MASK)
#define XFS_ATTR_NSP_ARGS_TO_ONDISK(x) (((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\
((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0))
#define XFS_ATTR_NSP_ONDISK_TO_ARGS(x) (((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\
((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0))
/*
* Alignment for namelist and valuelist entries (since they are mixed
* there can be only one alignment value)
......@@ -196,16 +209,26 @@ static inline int xfs_attr_leaf_entsize_local_max(int bsize)
* Structure used to pass context around among the routines.
*========================================================================*/
struct xfs_attr_list_context;
typedef int (*put_listent_func_t)(struct xfs_attr_list_context *, struct attrnames *,
char *, int, int, char *);
typedef struct xfs_attr_list_context {
struct xfs_inode *dp; /* inode */
struct attrlist_cursor_kern *cursor;/* position in list */
struct attrlist *alist; /* output buffer */
int count; /* num used entries */
int dupcnt; /* count dup hashvals seen */
int bufsize;/* total buffer size */
int firstu; /* first used byte in buffer */
int flags; /* from VOP call */
int resynch;/* T/F: resynch with cursor */
struct xfs_inode *dp; /* inode */
struct attrlist_cursor_kern *cursor; /* position in list */
struct attrlist *alist; /* output buffer */
int seen_enough; /* T/F: seen enough of list? */
int count; /* num used entries */
int dupcnt; /* count dup hashvals seen */
int bufsize; /* total buffer size */
int firstu; /* first used byte in buffer */
int flags; /* from VOP call */
int resynch; /* T/F: resynch with cursor */
int put_value; /* T/F: need value for listent */
put_listent_func_t put_listent; /* list output fmt function */
int index; /* index into output buffer */
} xfs_attr_list_context_t;
/*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment