Skip to content

Commit

Permalink
[XFS] Switches xfs_vn_listxattr to set it's put_listent callback dire…
Browse files Browse the repository at this point in the history
…ctly

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>
  • Loading branch information
Christoph Hellwig authored and Niv Sardi committed Jul 28, 2008
1 parent caf8aab commit ad9b463
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 203 deletions.
3 changes: 1 addition & 2 deletions fs/xfs/xfs_acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,7 @@ xfs_acl_iaccess(

/* If the file has no ACL return -1. */
rval = sizeof(xfs_acl_t);
if (xfs_attr_fetch(ip, &acl_name, (char *)acl, &rval,
ATTR_ROOT | ATTR_KERNACCESS)) {
if (xfs_attr_fetch(ip, &acl_name, (char *)acl, &rval, ATTR_ROOT)) {
_ACL_FREE(acl);
return -1;
}
Expand Down
139 changes: 45 additions & 94 deletions fs/xfs/xfs_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <linux/capability.h>

#include "xfs.h"
#include "xfs_fs.h"
#include "xfs_types.h"
Expand Down Expand Up @@ -607,12 +605,20 @@ xfs_attr_remove(
return xfs_attr_remove_int(dp, &xname, flags);
}

STATIC int
int
xfs_attr_list_int(xfs_attr_list_context_t *context)
{
int error;
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.
*/
Expand All @@ -625,6 +631,10 @@ xfs_attr_list_int(xfs_attr_list_context_t *context)
} else {
error = xfs_attr_node_list(context);
}

xfs_iunlock(dp, XFS_ILOCK_SHARED);
xfs_attr_trace_l_c("syscall end", context);

return error;
}

Expand All @@ -641,74 +651,50 @@ xfs_attr_list_int(xfs_attr_list_context_t *context)
*/
/*ARGSUSED*/
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,
int valuelen, char *value)
{
struct attrlist *alist = (struct attrlist *)context->alist;
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 >= sizeof(*alist));
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);
if (context->firstu < arraytop) {
xfs_attr_trace_l_c("buffer full", context);
context->alist->al_more = 1;
alist->al_more = 1;
context->seen_enough = 1;
return 1;
}

aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]);
aep = (attrlist_ent_t *)&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;
aep->a_name[namelen] = 0;
alist->al_offset[context->count++] = context->firstu;
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
Expand All @@ -725,10 +711,9 @@ xfs_attr_list(
attrlist_cursor_kern_t *cursor)
{
xfs_attr_list_context_t context;
struct attrlist *alist;
int error;

XFS_STATS_INC(xs_attr_list);

/*
* Validate the cursor.
*/
Expand All @@ -749,52 +734,23 @@ xfs_attr_list(
/*
* Initialize the output buffer.
*/
memset(&context, 0, sizeof(context));
context.dp = dp;
context.cursor = cursor;
context.count = 0;
context.dupcnt = 0;
context.resynch = 1;
context.flags = flags;
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->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;
context.alist = buffer;
context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */
context.firstu = context.bufsize;
context.put_listent = xfs_attr_put_listent;

xfs_ilock(dp, XFS_ILOCK_SHARED);
xfs_attr_trace_l_c("syscall start", &context);
alist = (struct attrlist *)context.alist;
alist->al_count = 0;
alist->al_more = 0;
alist->al_offset[0] = context.bufsize;

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)) {
/* must return negated buffer size or the error */
if (context.count < 0)
error = XFS_ERROR(ERANGE);
else
error = -context.count;
} else
ASSERT(error >= 0);

ASSERT(error >= 0);
return error;
}

Expand Down Expand Up @@ -2357,12 +2313,7 @@ xfs_attr_trace_enter(int type, char *where,
(void *)((__psunsigned_t)context->bufsize),
(void *)((__psunsigned_t)context->count),
(void *)((__psunsigned_t)context->firstu),
(void *)((__psunsigned_t)
(((context->count > 0) &&
!(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL)))
? (ATTR_ENTRY(context->alist,
context->count-1)->a_valuelen)
: 0)),
NULL,
(void *)((__psunsigned_t)context->dupcnt),
(void *)((__psunsigned_t)context->flags),
(void *)a13, (void *)a14, (void *)a15);
Expand Down
55 changes: 30 additions & 25 deletions fs/xfs/xfs_attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
#ifndef __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
* 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
Expand All @@ -35,17 +37,6 @@
* 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_ROOT 0x0002 /* use attrs in root (trusted) namespace */
Expand All @@ -54,14 +45,8 @@ extern struct attrnames attr_trusted;
#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_KERNACCESS 0x0400 /* [kernel] iaccess, inode held io-locked */
#define ATTR_KERNOTIME 0x1000 /* [kernel] don't update inode timestamps */
#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
Expand Down Expand Up @@ -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;
struct xfs_da_args;

typedef int (*put_listent_func_t)(struct xfs_attr_list_context *, int,
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.
*/
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_rmtval_get(struct xfs_da_args *args);
int xfs_attr_list_int(struct xfs_attr_list_context *);

#endif /* __XFS_ATTR_H__ */
Loading

0 comments on commit ad9b463

Please sign in to comment.