[XFS] Switches xfs_vn_listxattr to set it's put_listent callback directly
and not go through xfs_attr_list. SGI-PV: 983395 SGI-Modid: xfs-linux-melb:xfs-kern:31324a Signed-off-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: Tim Shimmin <tes@sgi.com> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
This commit is contained in:
Родитель
caf8aabdbc
Коммит
ad9b463aa2
|
@ -341,8 +341,7 @@ xfs_acl_iaccess(
|
||||||
|
|
||||||
/* If the file has no ACL return -1. */
|
/* If the file has no ACL return -1. */
|
||||||
rval = sizeof(xfs_acl_t);
|
rval = sizeof(xfs_acl_t);
|
||||||
if (xfs_attr_fetch(ip, &acl_name, (char *)acl, &rval,
|
if (xfs_attr_fetch(ip, &acl_name, (char *)acl, &rval, ATTR_ROOT)) {
|
||||||
ATTR_ROOT | ATTR_KERNACCESS)) {
|
|
||||||
_ACL_FREE(acl);
|
_ACL_FREE(acl);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/capability.h>
|
|
||||||
|
|
||||||
#include "xfs.h"
|
#include "xfs.h"
|
||||||
#include "xfs_fs.h"
|
#include "xfs_fs.h"
|
||||||
#include "xfs_types.h"
|
#include "xfs_types.h"
|
||||||
|
@ -607,12 +605,20 @@ xfs_attr_remove(
|
||||||
return xfs_attr_remove_int(dp, &xname, flags);
|
return xfs_attr_remove_int(dp, &xname, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC int
|
int
|
||||||
xfs_attr_list_int(xfs_attr_list_context_t *context)
|
xfs_attr_list_int(xfs_attr_list_context_t *context)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
xfs_inode_t *dp = context->dp;
|
xfs_inode_t *dp = context->dp;
|
||||||
|
|
||||||
|
XFS_STATS_INC(xs_attr_list);
|
||||||
|
|
||||||
|
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
|
||||||
|
return EIO;
|
||||||
|
|
||||||
|
xfs_ilock(dp, XFS_ILOCK_SHARED);
|
||||||
|
xfs_attr_trace_l_c("syscall start", context);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Decide on what work routines to call based on the inode size.
|
* Decide on what work routines to call based on the inode size.
|
||||||
*/
|
*/
|
||||||
|
@ -625,6 +631,10 @@ xfs_attr_list_int(xfs_attr_list_context_t *context)
|
||||||
} else {
|
} else {
|
||||||
error = xfs_attr_node_list(context);
|
error = xfs_attr_node_list(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xfs_iunlock(dp, XFS_ILOCK_SHARED);
|
||||||
|
xfs_attr_trace_l_c("syscall end", context);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,74 +651,50 @@ xfs_attr_list_int(xfs_attr_list_context_t *context)
|
||||||
*/
|
*/
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
STATIC int
|
STATIC int
|
||||||
xfs_attr_put_listent(xfs_attr_list_context_t *context, attrnames_t *namesp,
|
xfs_attr_put_listent(xfs_attr_list_context_t *context, int flags,
|
||||||
char *name, int namelen,
|
char *name, int namelen,
|
||||||
int valuelen, char *value)
|
int valuelen, char *value)
|
||||||
{
|
{
|
||||||
|
struct attrlist *alist = (struct attrlist *)context->alist;
|
||||||
attrlist_ent_t *aep;
|
attrlist_ent_t *aep;
|
||||||
int arraytop;
|
int arraytop;
|
||||||
|
|
||||||
ASSERT(!(context->flags & ATTR_KERNOVAL));
|
ASSERT(!(context->flags & ATTR_KERNOVAL));
|
||||||
ASSERT(context->count >= 0);
|
ASSERT(context->count >= 0);
|
||||||
ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
|
ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
|
||||||
ASSERT(context->firstu >= sizeof(*context->alist));
|
ASSERT(context->firstu >= sizeof(*alist));
|
||||||
ASSERT(context->firstu <= context->bufsize);
|
ASSERT(context->firstu <= context->bufsize);
|
||||||
|
|
||||||
arraytop = sizeof(*context->alist) +
|
/*
|
||||||
context->count * sizeof(context->alist->al_offset[0]);
|
* Only list entries in the right namespace.
|
||||||
|
*/
|
||||||
|
if (((context->flags & ATTR_SECURE) == 0) !=
|
||||||
|
((flags & XFS_ATTR_SECURE) == 0))
|
||||||
|
return 0;
|
||||||
|
if (((context->flags & ATTR_ROOT) == 0) !=
|
||||||
|
((flags & XFS_ATTR_ROOT) == 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
arraytop = sizeof(*alist) +
|
||||||
|
context->count * sizeof(alist->al_offset[0]);
|
||||||
context->firstu -= ATTR_ENTSIZE(namelen);
|
context->firstu -= ATTR_ENTSIZE(namelen);
|
||||||
if (context->firstu < arraytop) {
|
if (context->firstu < arraytop) {
|
||||||
xfs_attr_trace_l_c("buffer full", context);
|
xfs_attr_trace_l_c("buffer full", context);
|
||||||
context->alist->al_more = 1;
|
alist->al_more = 1;
|
||||||
context->seen_enough = 1;
|
context->seen_enough = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]);
|
aep = (attrlist_ent_t *)&context->alist[context->firstu];
|
||||||
aep->a_valuelen = valuelen;
|
aep->a_valuelen = valuelen;
|
||||||
memcpy(aep->a_name, name, namelen);
|
memcpy(aep->a_name, name, namelen);
|
||||||
aep->a_name[ namelen ] = 0;
|
aep->a_name[namelen] = 0;
|
||||||
context->alist->al_offset[ context->count++ ] = context->firstu;
|
alist->al_offset[context->count++] = context->firstu;
|
||||||
context->alist->al_count = context->count;
|
alist->al_count = context->count;
|
||||||
xfs_attr_trace_l_c("add", context);
|
xfs_attr_trace_l_c("add", context);
|
||||||
return 0;
|
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
|
* Generate a list of extended attribute names and optionally
|
||||||
* also value lengths. Positive return value follows the XFS
|
* also value lengths. Positive return value follows the XFS
|
||||||
|
@ -725,10 +711,9 @@ xfs_attr_list(
|
||||||
attrlist_cursor_kern_t *cursor)
|
attrlist_cursor_kern_t *cursor)
|
||||||
{
|
{
|
||||||
xfs_attr_list_context_t context;
|
xfs_attr_list_context_t context;
|
||||||
|
struct attrlist *alist;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
XFS_STATS_INC(xs_attr_list);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Validate the cursor.
|
* Validate the cursor.
|
||||||
*/
|
*/
|
||||||
|
@ -749,52 +734,23 @@ xfs_attr_list(
|
||||||
/*
|
/*
|
||||||
* Initialize the output buffer.
|
* Initialize the output buffer.
|
||||||
*/
|
*/
|
||||||
|
memset(&context, 0, sizeof(context));
|
||||||
context.dp = dp;
|
context.dp = dp;
|
||||||
context.cursor = cursor;
|
context.cursor = cursor;
|
||||||
context.count = 0;
|
|
||||||
context.dupcnt = 0;
|
|
||||||
context.resynch = 1;
|
context.resynch = 1;
|
||||||
context.flags = flags;
|
context.flags = flags;
|
||||||
context.seen_enough = 0;
|
context.alist = buffer;
|
||||||
context.alist = (attrlist_t *)buffer;
|
context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */
|
||||||
context.put_value = 0;
|
context.firstu = context.bufsize;
|
||||||
|
context.put_listent = xfs_attr_put_listent;
|
||||||
|
|
||||||
if (flags & ATTR_KERNAMELS) {
|
alist = (struct attrlist *)context.alist;
|
||||||
context.bufsize = bufsize;
|
alist->al_count = 0;
|
||||||
context.firstu = context.bufsize;
|
alist->al_more = 0;
|
||||||
if (flags & ATTR_KERNOVAL)
|
alist->al_offset[0] = context.bufsize;
|
||||||
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->al_count = 0;
|
|
||||||
context.alist->al_more = 0;
|
|
||||||
context.alist->al_offset[0] = context.bufsize;
|
|
||||||
context.put_listent = xfs_attr_put_listent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
|
|
||||||
return EIO;
|
|
||||||
|
|
||||||
xfs_ilock(dp, XFS_ILOCK_SHARED);
|
|
||||||
xfs_attr_trace_l_c("syscall start", &context);
|
|
||||||
|
|
||||||
error = xfs_attr_list_int(&context);
|
error = xfs_attr_list_int(&context);
|
||||||
|
ASSERT(error >= 0);
|
||||||
xfs_iunlock(dp, XFS_ILOCK_SHARED);
|
|
||||||
xfs_attr_trace_l_c("syscall end", &context);
|
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2357,12 +2313,7 @@ xfs_attr_trace_enter(int type, char *where,
|
||||||
(void *)((__psunsigned_t)context->bufsize),
|
(void *)((__psunsigned_t)context->bufsize),
|
||||||
(void *)((__psunsigned_t)context->count),
|
(void *)((__psunsigned_t)context->count),
|
||||||
(void *)((__psunsigned_t)context->firstu),
|
(void *)((__psunsigned_t)context->firstu),
|
||||||
(void *)((__psunsigned_t)
|
NULL,
|
||||||
(((context->count > 0) &&
|
|
||||||
!(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
|
|
||||||
? (ATTR_ENTRY(context->alist,
|
|
||||||
context->count-1)->a_valuelen)
|
|
||||||
: 0)),
|
|
||||||
(void *)((__psunsigned_t)context->dupcnt),
|
(void *)((__psunsigned_t)context->dupcnt),
|
||||||
(void *)((__psunsigned_t)context->flags),
|
(void *)((__psunsigned_t)context->flags),
|
||||||
(void *)a13, (void *)a14, (void *)a15);
|
(void *)a13, (void *)a14, (void *)a15);
|
||||||
|
|
|
@ -18,9 +18,11 @@
|
||||||
#ifndef __XFS_ATTR_H__
|
#ifndef __XFS_ATTR_H__
|
||||||
#define __XFS_ATTR_H__
|
#define __XFS_ATTR_H__
|
||||||
|
|
||||||
|
struct xfs_inode;
|
||||||
|
struct xfs_da_args;
|
||||||
|
struct xfs_attr_list_context;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* xfs_attr.h
|
|
||||||
*
|
|
||||||
* Large attribute lists are structured around Btrees where all the data
|
* Large attribute lists are structured around Btrees where all the data
|
||||||
* elements are in the leaf nodes. Attribute names are hashed into an int,
|
* elements are in the leaf nodes. Attribute names are hashed into an int,
|
||||||
* then that int is used as the index into the Btree. Since the hashval
|
* then that int is used as the index into the Btree. Since the hashval
|
||||||
|
@ -35,17 +37,6 @@
|
||||||
* External interfaces
|
* External interfaces
|
||||||
*========================================================================*/
|
*========================================================================*/
|
||||||
|
|
||||||
struct cred;
|
|
||||||
struct xfs_attr_list_context;
|
|
||||||
|
|
||||||
typedef struct attrnames {
|
|
||||||
char * attr_name;
|
|
||||||
unsigned int attr_namelen;
|
|
||||||
} attrnames_t;
|
|
||||||
|
|
||||||
extern struct attrnames attr_user;
|
|
||||||
extern struct attrnames attr_secure;
|
|
||||||
extern struct attrnames attr_trusted;
|
|
||||||
|
|
||||||
#define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */
|
#define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */
|
||||||
#define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */
|
#define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */
|
||||||
|
@ -54,14 +45,8 @@ extern struct attrnames attr_trusted;
|
||||||
#define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */
|
#define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */
|
||||||
#define ATTR_REPLACE 0x0020 /* pure set: fail if attr does not exist */
|
#define ATTR_REPLACE 0x0020 /* pure set: fail if attr does not exist */
|
||||||
|
|
||||||
#define ATTR_KERNACCESS 0x0400 /* [kernel] iaccess, inode held io-locked */
|
|
||||||
#define ATTR_KERNOTIME 0x1000 /* [kernel] don't update inode timestamps */
|
#define ATTR_KERNOTIME 0x1000 /* [kernel] don't update inode timestamps */
|
||||||
#define ATTR_KERNOVAL 0x2000 /* [kernel] get attr size only, not value */
|
#define ATTR_KERNOVAL 0x2000 /* [kernel] get attr size only, not value */
|
||||||
#define ATTR_KERNAMELS 0x4000 /* [kernel] list attr names (simple list) */
|
|
||||||
|
|
||||||
#define ATTR_KERNORMALS 0x0800 /* [kernel] normal attr list: user+secure */
|
|
||||||
#define ATTR_KERNROOTLS 0x8000 /* [kernel] include root in the attr list */
|
|
||||||
#define ATTR_KERNFULLS (ATTR_KERNORMALS|ATTR_KERNROOTLS)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The maximum size (into the kernel or returned from the kernel) of an
|
* The maximum size (into the kernel or returned from the kernel) of an
|
||||||
|
@ -129,20 +114,40 @@ typedef struct attrlist_cursor_kern {
|
||||||
|
|
||||||
|
|
||||||
/*========================================================================
|
/*========================================================================
|
||||||
* Function prototypes for the kernel.
|
* Structure used to pass context around among the routines.
|
||||||
*========================================================================*/
|
*========================================================================*/
|
||||||
|
|
||||||
struct xfs_inode;
|
|
||||||
struct attrlist_cursor_kern;
|
typedef int (*put_listent_func_t)(struct xfs_attr_list_context *, int,
|
||||||
struct xfs_da_args;
|
char *, int, int, char *);
|
||||||
|
|
||||||
|
typedef struct xfs_attr_list_context {
|
||||||
|
struct xfs_inode *dp; /* inode */
|
||||||
|
struct attrlist_cursor_kern *cursor; /* position in list */
|
||||||
|
char *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;
|
||||||
|
|
||||||
|
|
||||||
|
/*========================================================================
|
||||||
|
* Function prototypes for the kernel.
|
||||||
|
*========================================================================*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Overall external interface routines.
|
* Overall external interface routines.
|
||||||
*/
|
*/
|
||||||
int xfs_attr_inactive(struct xfs_inode *dp);
|
int xfs_attr_inactive(struct xfs_inode *dp);
|
||||||
|
|
||||||
int xfs_attr_shortform_getvalue(struct xfs_da_args *);
|
|
||||||
int xfs_attr_fetch(struct xfs_inode *, struct xfs_name *, char *, int *, int);
|
int xfs_attr_fetch(struct xfs_inode *, struct xfs_name *, char *, int *, int);
|
||||||
int xfs_attr_rmtval_get(struct xfs_da_args *args);
|
int xfs_attr_rmtval_get(struct xfs_da_args *args);
|
||||||
|
int xfs_attr_list_int(struct xfs_attr_list_context *);
|
||||||
|
|
||||||
#endif /* __XFS_ATTR_H__ */
|
#endif /* __XFS_ATTR_H__ */
|
||||||
|
|
|
@ -94,13 +94,6 @@ STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
|
||||||
* Namespace helper routines
|
* Namespace helper routines
|
||||||
*========================================================================*/
|
*========================================================================*/
|
||||||
|
|
||||||
STATIC_INLINE attrnames_t *
|
|
||||||
xfs_attr_flags_namesp(int flags)
|
|
||||||
{
|
|
||||||
return ((flags & XFS_ATTR_SECURE) ? &attr_secure:
|
|
||||||
((flags & XFS_ATTR_ROOT) ? &attr_trusted : &attr_user));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If namespace bits don't match return 0.
|
* If namespace bits don't match return 0.
|
||||||
* If all match then return 1.
|
* If all match then return 1.
|
||||||
|
@ -111,25 +104,6 @@ xfs_attr_namesp_match(int arg_flags, int ondisk_flags)
|
||||||
return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags);
|
return XFS_ATTR_NSP_ONDISK(ondisk_flags) == XFS_ATTR_NSP_ARGS_TO_ONDISK(arg_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If namespace bits don't match and we don't have an override for it
|
|
||||||
* then return 0.
|
|
||||||
* If all match or are overridable then return 1.
|
|
||||||
*/
|
|
||||||
STATIC_INLINE int
|
|
||||||
xfs_attr_namesp_match_overrides(int arg_flags, int ondisk_flags)
|
|
||||||
{
|
|
||||||
if (((arg_flags & ATTR_SECURE) == 0) !=
|
|
||||||
((ondisk_flags & XFS_ATTR_SECURE) == 0) &&
|
|
||||||
!(arg_flags & ATTR_KERNORMALS))
|
|
||||||
return 0;
|
|
||||||
if (((arg_flags & ATTR_ROOT) == 0) !=
|
|
||||||
((ondisk_flags & XFS_ATTR_ROOT) == 0) &&
|
|
||||||
!(arg_flags & ATTR_KERNROOTLS))
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*========================================================================
|
/*========================================================================
|
||||||
* External routines when attribute fork size < XFS_LITINO(mp).
|
* External routines when attribute fork size < XFS_LITINO(mp).
|
||||||
|
@ -626,15 +600,8 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
|
||||||
(XFS_ISRESET_CURSOR(cursor) &&
|
(XFS_ISRESET_CURSOR(cursor) &&
|
||||||
(dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) {
|
(dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) {
|
||||||
for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
|
for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
|
||||||
attrnames_t *namesp;
|
|
||||||
|
|
||||||
if (!xfs_attr_namesp_match_overrides(context->flags, sfe->flags)) {
|
|
||||||
sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
namesp = xfs_attr_flags_namesp(sfe->flags);
|
|
||||||
error = context->put_listent(context,
|
error = context->put_listent(context,
|
||||||
namesp,
|
sfe->flags,
|
||||||
(char *)sfe->nameval,
|
(char *)sfe->nameval,
|
||||||
(int)sfe->namelen,
|
(int)sfe->namelen,
|
||||||
(int)sfe->valuelen,
|
(int)sfe->valuelen,
|
||||||
|
@ -681,10 +648,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
|
||||||
kmem_free(sbuf);
|
kmem_free(sbuf);
|
||||||
return XFS_ERROR(EFSCORRUPTED);
|
return XFS_ERROR(EFSCORRUPTED);
|
||||||
}
|
}
|
||||||
if (!xfs_attr_namesp_match_overrides(context->flags, sfe->flags)) {
|
|
||||||
sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sbp->entno = i;
|
sbp->entno = i;
|
||||||
sbp->hash = xfs_da_hashname((char *)sfe->nameval, sfe->namelen);
|
sbp->hash = xfs_da_hashname((char *)sfe->nameval, sfe->namelen);
|
||||||
sbp->name = (char *)sfe->nameval;
|
sbp->name = (char *)sfe->nameval;
|
||||||
|
@ -728,16 +692,12 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
|
||||||
* Loop putting entries into the user buffer.
|
* Loop putting entries into the user buffer.
|
||||||
*/
|
*/
|
||||||
for ( ; i < nsbuf; i++, sbp++) {
|
for ( ; i < nsbuf; i++, sbp++) {
|
||||||
attrnames_t *namesp;
|
|
||||||
|
|
||||||
namesp = xfs_attr_flags_namesp(sbp->flags);
|
|
||||||
|
|
||||||
if (cursor->hashval != sbp->hash) {
|
if (cursor->hashval != sbp->hash) {
|
||||||
cursor->hashval = sbp->hash;
|
cursor->hashval = sbp->hash;
|
||||||
cursor->offset = 0;
|
cursor->offset = 0;
|
||||||
}
|
}
|
||||||
error = context->put_listent(context,
|
error = context->put_listent(context,
|
||||||
namesp,
|
sbp->flags,
|
||||||
sbp->name,
|
sbp->name,
|
||||||
sbp->namelen,
|
sbp->namelen,
|
||||||
sbp->valuelen,
|
sbp->valuelen,
|
||||||
|
@ -2402,8 +2362,6 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
|
||||||
*/
|
*/
|
||||||
retval = 0;
|
retval = 0;
|
||||||
for ( ; (i < be16_to_cpu(leaf->hdr.count)); entry++, i++) {
|
for ( ; (i < be16_to_cpu(leaf->hdr.count)); entry++, i++) {
|
||||||
attrnames_t *namesp;
|
|
||||||
|
|
||||||
if (be32_to_cpu(entry->hashval) != cursor->hashval) {
|
if (be32_to_cpu(entry->hashval) != cursor->hashval) {
|
||||||
cursor->hashval = be32_to_cpu(entry->hashval);
|
cursor->hashval = be32_to_cpu(entry->hashval);
|
||||||
cursor->offset = 0;
|
cursor->offset = 0;
|
||||||
|
@ -2411,17 +2369,13 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
|
||||||
|
|
||||||
if (entry->flags & XFS_ATTR_INCOMPLETE)
|
if (entry->flags & XFS_ATTR_INCOMPLETE)
|
||||||
continue; /* skip incomplete entries */
|
continue; /* skip incomplete entries */
|
||||||
if (!xfs_attr_namesp_match_overrides(context->flags, entry->flags))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
namesp = xfs_attr_flags_namesp(entry->flags);
|
|
||||||
|
|
||||||
if (entry->flags & XFS_ATTR_LOCAL) {
|
if (entry->flags & XFS_ATTR_LOCAL) {
|
||||||
xfs_attr_leaf_name_local_t *name_loc =
|
xfs_attr_leaf_name_local_t *name_loc =
|
||||||
XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
|
XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
|
||||||
|
|
||||||
retval = context->put_listent(context,
|
retval = context->put_listent(context,
|
||||||
namesp,
|
entry->flags,
|
||||||
(char *)name_loc->nameval,
|
(char *)name_loc->nameval,
|
||||||
(int)name_loc->namelen,
|
(int)name_loc->namelen,
|
||||||
be16_to_cpu(name_loc->valuelen),
|
be16_to_cpu(name_loc->valuelen),
|
||||||
|
@ -2448,16 +2402,15 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
retval = context->put_listent(context,
|
retval = context->put_listent(context,
|
||||||
namesp,
|
entry->flags,
|
||||||
(char *)name_rmt->name,
|
(char *)name_rmt->name,
|
||||||
(int)name_rmt->namelen,
|
(int)name_rmt->namelen,
|
||||||
valuelen,
|
valuelen,
|
||||||
(char*)args.value);
|
(char*)args.value);
|
||||||
kmem_free(args.value);
|
kmem_free(args.value);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
retval = context->put_listent(context,
|
retval = context->put_listent(context,
|
||||||
namesp,
|
entry->flags,
|
||||||
(char *)name_rmt->name,
|
(char *)name_rmt->name,
|
||||||
(int)name_rmt->namelen,
|
(int)name_rmt->namelen,
|
||||||
valuelen,
|
valuelen,
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
struct attrlist;
|
struct attrlist;
|
||||||
struct attrlist_cursor_kern;
|
struct attrlist_cursor_kern;
|
||||||
struct attrnames;
|
struct xfs_attr_list_context;
|
||||||
struct xfs_dabuf;
|
struct xfs_dabuf;
|
||||||
struct xfs_da_args;
|
struct xfs_da_args;
|
||||||
struct xfs_da_state;
|
struct xfs_da_state;
|
||||||
|
@ -204,33 +204,6 @@ static inline int xfs_attr_leaf_entsize_local_max(int bsize)
|
||||||
return (((bsize) >> 1) + ((bsize) >> 2));
|
return (((bsize) >> 1) + ((bsize) >> 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*========================================================================
|
|
||||||
* 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 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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used to keep a list of "remote value" extents when unlinking an inode.
|
* Used to keep a list of "remote value" extents when unlinking an inode.
|
||||||
*/
|
*/
|
||||||
|
|
Загрузка…
Ссылка в новой задаче