forked from Minki/linux
nfsd4: replace defer_free by svcxdr_tmpalloc
Avoid an extra allocation for the tmpbuf struct itself, and stop ignoring some allocation failures. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
parent
bcaab953b1
commit
d5e2338324
@ -181,25 +181,24 @@ static int zero_clientid(clientid_t *clid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* defer_free - mark an allocation as deferred freed
|
* svcxdr_tmpalloc - allocate memory to be freed after compound processing
|
||||||
* @argp: NFSv4 compound argument structure
|
* @argp: NFSv4 compound argument structure
|
||||||
* @p: pointer to be freed (with kfree())
|
* @p: pointer to be freed (with kfree())
|
||||||
*
|
*
|
||||||
* Marks @p to be freed when processing the compound operation
|
* Marks @p to be freed when processing the compound operation
|
||||||
* described in @argp finishes.
|
* described in @argp finishes.
|
||||||
*/
|
*/
|
||||||
static int
|
static void *
|
||||||
defer_free(struct nfsd4_compoundargs *argp, void *p)
|
svcxdr_tmpalloc(struct nfsd4_compoundargs *argp, u32 len)
|
||||||
{
|
{
|
||||||
struct tmpbuf *tb;
|
struct svcxdr_tmpbuf *tb;
|
||||||
|
|
||||||
tb = kmalloc(sizeof(*tb), GFP_KERNEL);
|
tb = kmalloc(sizeof(*tb) + len, GFP_KERNEL);
|
||||||
if (!tb)
|
if (!tb)
|
||||||
return -ENOMEM;
|
return NULL;
|
||||||
tb->buf = p;
|
|
||||||
tb->next = argp->to_free;
|
tb->next = argp->to_free;
|
||||||
argp->to_free = tb;
|
argp->to_free = tb;
|
||||||
return 0;
|
return tb->buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -212,13 +211,12 @@ defer_free(struct nfsd4_compoundargs *argp, void *p)
|
|||||||
static char *
|
static char *
|
||||||
svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, u32 len)
|
svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, u32 len)
|
||||||
{
|
{
|
||||||
char *p = kmalloc(len + 1, GFP_KERNEL);
|
char *p = svcxdr_tmpalloc(argp, len + 1);
|
||||||
|
|
||||||
if (!p)
|
if (!p)
|
||||||
return NULL;
|
return NULL;
|
||||||
memcpy(p, buf, len);
|
memcpy(p, buf, len);
|
||||||
p[len] = '\0';
|
p[len] = '\0';
|
||||||
defer_free(argp, p);
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,19 +232,13 @@ svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, u32 len)
|
|||||||
*/
|
*/
|
||||||
static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
|
static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
|
||||||
{
|
{
|
||||||
if (p == argp->tmp) {
|
void *ret;
|
||||||
p = kmemdup(argp->tmp, nbytes, GFP_KERNEL);
|
|
||||||
if (!p)
|
ret = svcxdr_tmpalloc(argp, nbytes);
|
||||||
return NULL;
|
if (!ret)
|
||||||
} else {
|
|
||||||
BUG_ON(p != argp->tmpp);
|
|
||||||
argp->tmpp = NULL;
|
|
||||||
}
|
|
||||||
if (defer_free(argp, p)) {
|
|
||||||
kfree(p);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
} else
|
memcpy(ret, p, nbytes);
|
||||||
return (char *)p;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __be32
|
static __be32
|
||||||
@ -309,12 +301,10 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
|
|||||||
if (nace > NFS4_ACL_MAX)
|
if (nace > NFS4_ACL_MAX)
|
||||||
return nfserr_fbig;
|
return nfserr_fbig;
|
||||||
|
|
||||||
*acl = kmalloc(nfs4_acl_bytes(nace), GFP_KERNEL);
|
*acl = svcxdr_tmpalloc(argp, nfs4_acl_bytes(nace));
|
||||||
if (*acl == NULL)
|
if (*acl == NULL)
|
||||||
return nfserr_jukebox;
|
return nfserr_jukebox;
|
||||||
|
|
||||||
defer_free(argp, *acl);
|
|
||||||
|
|
||||||
(*acl)->naces = nace;
|
(*acl)->naces = nace;
|
||||||
for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) {
|
for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) {
|
||||||
READ_BUF(16); len += 16;
|
READ_BUF(16); len += 16;
|
||||||
@ -1487,13 +1477,12 @@ nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_sta
|
|||||||
INIT_LIST_HEAD(&test_stateid->ts_stateid_list);
|
INIT_LIST_HEAD(&test_stateid->ts_stateid_list);
|
||||||
|
|
||||||
for (i = 0; i < test_stateid->ts_num_ids; i++) {
|
for (i = 0; i < test_stateid->ts_num_ids; i++) {
|
||||||
stateid = kmalloc(sizeof(struct nfsd4_test_stateid_id), GFP_KERNEL);
|
stateid = svcxdr_tmpalloc(argp, sizeof(*stateid));
|
||||||
if (!stateid) {
|
if (!stateid) {
|
||||||
status = nfserrno(-ENOMEM);
|
status = nfserrno(-ENOMEM);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
defer_free(argp, stateid);
|
|
||||||
INIT_LIST_HEAD(&stateid->ts_id_list);
|
INIT_LIST_HEAD(&stateid->ts_id_list);
|
||||||
list_add_tail(&stateid->ts_id_list, &test_stateid->ts_stateid_list);
|
list_add_tail(&stateid->ts_id_list, &test_stateid->ts_stateid_list);
|
||||||
|
|
||||||
@ -3977,9 +3966,8 @@ int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp)
|
|||||||
kfree(args->tmpp);
|
kfree(args->tmpp);
|
||||||
args->tmpp = NULL;
|
args->tmpp = NULL;
|
||||||
while (args->to_free) {
|
while (args->to_free) {
|
||||||
struct tmpbuf *tb = args->to_free;
|
struct svcxdr_tmpbuf *tb = args->to_free;
|
||||||
args->to_free = tb->next;
|
args->to_free = tb->next;
|
||||||
kfree(tb->buf);
|
|
||||||
kfree(tb);
|
kfree(tb);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -478,6 +478,14 @@ struct nfsd4_op {
|
|||||||
|
|
||||||
bool nfsd4_cache_this_op(struct nfsd4_op *);
|
bool nfsd4_cache_this_op(struct nfsd4_op *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Memory needed just for the duration of processing one compound:
|
||||||
|
*/
|
||||||
|
struct svcxdr_tmpbuf {
|
||||||
|
struct svcxdr_tmpbuf *next;
|
||||||
|
char buf[];
|
||||||
|
};
|
||||||
|
|
||||||
struct nfsd4_compoundargs {
|
struct nfsd4_compoundargs {
|
||||||
/* scratch variables for XDR decode */
|
/* scratch variables for XDR decode */
|
||||||
__be32 * p;
|
__be32 * p;
|
||||||
@ -486,10 +494,7 @@ struct nfsd4_compoundargs {
|
|||||||
int pagelen;
|
int pagelen;
|
||||||
__be32 tmp[8];
|
__be32 tmp[8];
|
||||||
__be32 * tmpp;
|
__be32 * tmpp;
|
||||||
struct tmpbuf {
|
struct svcxdr_tmpbuf *to_free;
|
||||||
struct tmpbuf *next;
|
|
||||||
void *buf;
|
|
||||||
} *to_free;
|
|
||||||
|
|
||||||
struct svc_rqst *rqstp;
|
struct svc_rqst *rqstp;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user