Skip to content

Commit

Permalink
Merge branch 'nfsd-next' of git://linux-nfs.org/~bfields/linux
Browse files Browse the repository at this point in the history
Pull nfsd updates from Bruce Fields:
 "This was a very quiet cycle! Just a few bugfixes and some cleanup"

* 'nfsd-next' of git://linux-nfs.org/~bfields/linux:
  rpc: let xdr layer allocate gssproxy receieve pages
  rpc: fix huge kmalloc's in gss-proxy
  rpc: comment on linux_cred encoding, treat all as unsigned
  rpc: clean up decoding of gssproxy linux creds
  svcrpc: remove unused rq_resused
  nfsd4: nfsd4_create_clid_dir prints uninitialized data
  nfsd4: fix leak of inode reference on delegation failure
  Revert "nfsd: nfs4_file_get_access: need to be more careful with O_RDWR"
  sunrpc: prepare NFS for 2038
  nfsd4: fix setlease error return
  nfsd: nfs4_file_get_access: need to be more careful with O_RDWR
  • Loading branch information
Linus Torvalds committed Sep 11, 2013
2 parents 516f7b3 + d4a5165 commit cf59676
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 39 deletions.
2 changes: 0 additions & 2 deletions fs/nfsd/nfs4recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,6 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
int status;
struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);

dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);

if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
return;
if (!nn->rec_file)
Expand Down
33 changes: 21 additions & 12 deletions fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,11 +368,8 @@ static struct nfs4_delegation *
alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh)
{
struct nfs4_delegation *dp;
struct nfs4_file *fp = stp->st_file;

dprintk("NFSD alloc_init_deleg\n");
if (fp->fi_had_conflict)
return NULL;
if (num_delegations > max_delegations)
return NULL;
dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab));
Expand All @@ -389,8 +386,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv
INIT_LIST_HEAD(&dp->dl_perfile);
INIT_LIST_HEAD(&dp->dl_perclnt);
INIT_LIST_HEAD(&dp->dl_recall_lru);
get_nfs4_file(fp);
dp->dl_file = fp;
dp->dl_file = NULL;
dp->dl_type = NFS4_OPEN_DELEGATE_READ;
fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle);
dp->dl_time = 0;
Expand Down Expand Up @@ -3035,7 +3031,7 @@ static int nfs4_setlease(struct nfs4_delegation *dp)
if (status) {
list_del_init(&dp->dl_perclnt);
locks_free_lock(fl);
return -ENOMEM;
return status;
}
fp->fi_lease = fl;
fp->fi_deleg_file = get_file(fl->fl_file);
Expand All @@ -3044,22 +3040,35 @@ static int nfs4_setlease(struct nfs4_delegation *dp)
return 0;
}

static int nfs4_set_delegation(struct nfs4_delegation *dp)
static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp)
{
struct nfs4_file *fp = dp->dl_file;
int status;

if (!fp->fi_lease)
return nfs4_setlease(dp);
if (fp->fi_had_conflict)
return -EAGAIN;
get_nfs4_file(fp);
dp->dl_file = fp;
if (!fp->fi_lease) {
status = nfs4_setlease(dp);
if (status)
goto out_free;
return 0;
}
spin_lock(&recall_lock);
if (fp->fi_had_conflict) {
spin_unlock(&recall_lock);
return -EAGAIN;
status = -EAGAIN;
goto out_free;
}
atomic_inc(&fp->fi_delegees);
list_add(&dp->dl_perfile, &fp->fi_delegations);
spin_unlock(&recall_lock);
list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations);
return 0;
out_free:
put_nfs4_file(fp);
dp->dl_file = fp;
return status;
}

static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
Expand Down Expand Up @@ -3134,7 +3143,7 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh);
if (dp == NULL)
goto out_no_deleg;
status = nfs4_set_delegation(dp);
status = nfs4_set_delegation(dp, stp->st_file);
if (status)
goto out_free;

Expand Down
22 changes: 20 additions & 2 deletions include/linux/sunrpc/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,12 +264,30 @@ static inline int get_uint(char **bpp, unsigned int *anint)
return 0;
}

static inline int get_time(char **bpp, time_t *time)
{
char buf[50];
long long ll;
int len = qword_get(bpp, buf, sizeof(buf));

if (len < 0)
return -EINVAL;
if (len == 0)
return -ENOENT;

if (kstrtoll(buf, 0, &ll))
return -EINVAL;

*time = (time_t)ll;
return 0;
}

static inline time_t get_expiry(char **bpp)
{
int rv;
time_t rv;
struct timespec boot;

if (get_int(bpp, &rv))
if (get_time(bpp, &rv))
return 0;
if (rv < 0)
return 0;
Expand Down
1 change: 0 additions & 1 deletion include/linux/sunrpc/svc.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@ struct svc_rqst {
struct xdr_buf rq_res;
struct page * rq_pages[RPCSVC_MAXPAGES];
struct page * *rq_respages; /* points into rq_pages */
int rq_resused; /* number of pages used for result */
struct page * *rq_next_page; /* next reply page to use */

struct kvec rq_vec[RPCSVC_MAXPAGES]; /* generally useful.. */
Expand Down
26 changes: 26 additions & 0 deletions net/sunrpc/auth_gss/gss_rpc_upcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,26 @@ static int gssp_call(struct net *net, struct rpc_message *msg)
return status;
}

static void gssp_free_receive_pages(struct gssx_arg_accept_sec_context *arg)
{
int i;

for (i = 0; i < arg->npages && arg->pages[i]; i++)
__free_page(arg->pages[i]);
}

static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg)
{
arg->npages = DIV_ROUND_UP(NGROUPS_MAX * 4, PAGE_SIZE);
arg->pages = kzalloc(arg->npages * sizeof(struct page *), GFP_KERNEL);
/*
* XXX: actual pages are allocated by xdr layer in
* xdr_partial_copy_from_skb.
*/
if (!arg->pages)
return -ENOMEM;
return 0;
}

/*
* Public functions
Expand Down Expand Up @@ -261,10 +281,16 @@ int gssp_accept_sec_context_upcall(struct net *net,
arg.context_handle = &ctxh;
res.output_token->len = GSSX_max_output_token_sz;

ret = gssp_alloc_receive_pages(&arg);
if (ret)
return ret;

/* use nfs/ for targ_name ? */

ret = gssp_call(net, &msg);

gssp_free_receive_pages(&arg);

/* we need to fetch all data even in case of error so
* that we can free special strctures is they have been allocated */
data->major_status = res.status.major_status;
Expand Down
41 changes: 20 additions & 21 deletions net/sunrpc/auth_gss/gss_rpc_xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,15 @@ static int dummy_dec_opt_array(struct xdr_stream *xdr,
return 0;
}

static int get_s32(void **p, void *max, s32 *res)
static int get_host_u32(struct xdr_stream *xdr, u32 *res)
{
void *base = *p;
void *next = (void *)((char *)base + sizeof(s32));
if (unlikely(next > max || next < base))
__be32 *p;

p = xdr_inline_decode(xdr, 4);
if (!p)
return -EINVAL;
memcpy(res, base, sizeof(s32));
*p = next;
/* Contents of linux creds are all host-endian: */
memcpy(res, p, sizeof(u32));
return 0;
}

Expand All @@ -182,51 +183,46 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr,
{
u32 length;
__be32 *p;
void *q, *end;
s32 tmp;
int N, i, err;
u32 tmp;
u32 N;
int i, err;

p = xdr_inline_decode(xdr, 4);
if (unlikely(p == NULL))
return -ENOSPC;

length = be32_to_cpup(p);

/* FIXME: we do not want to use the scratch buffer for this one
* may need to use functions that allows us to access an io vector
* directly */
p = xdr_inline_decode(xdr, length);
if (unlikely(p == NULL))
if (length > (3 + NGROUPS_MAX) * sizeof(u32))
return -ENOSPC;

q = p;
end = q + length;

/* uid */
err = get_s32(&q, end, &tmp);
err = get_host_u32(xdr, &tmp);
if (err)
return err;
creds->cr_uid = make_kuid(&init_user_ns, tmp);

/* gid */
err = get_s32(&q, end, &tmp);
err = get_host_u32(xdr, &tmp);
if (err)
return err;
creds->cr_gid = make_kgid(&init_user_ns, tmp);

/* number of additional gid's */
err = get_s32(&q, end, &tmp);
err = get_host_u32(xdr, &tmp);
if (err)
return err;
N = tmp;
if ((3 + N) * sizeof(u32) != length)
return -EINVAL;
creds->cr_group_info = groups_alloc(N);
if (creds->cr_group_info == NULL)
return -ENOMEM;

/* gid's */
for (i = 0; i < N; i++) {
kgid_t kgid;
err = get_s32(&q, end, &tmp);
err = get_host_u32(xdr, &tmp);
if (err)
goto out_free_groups;
err = -EINVAL;
Expand Down Expand Up @@ -784,6 +780,9 @@ void gssx_enc_accept_sec_context(struct rpc_rqst *req,
/* arg->options */
err = dummy_enc_opt_array(xdr, &arg->options);

xdr_inline_pages(&req->rq_rcv_buf,
PAGE_SIZE/2 /* pretty arbitrary */,
arg->pages, 0 /* page base */, arg->npages * PAGE_SIZE);
done:
if (err)
dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err);
Expand Down
5 changes: 4 additions & 1 deletion net/sunrpc/auth_gss/gss_rpc_xdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ struct gssx_arg_accept_sec_context {
struct gssx_cb *input_cb;
u32 ret_deleg_cred;
struct gssx_option_array options;
struct page **pages;
unsigned int npages;
};

struct gssx_res_accept_sec_context {
Expand Down Expand Up @@ -240,7 +242,8 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
2 * GSSX_max_princ_sz + \
8 + 8 + 4 + 4 + 4)
#define GSSX_max_output_token_sz 1024
#define GSSX_max_creds_sz (4 + 4 + 4 + NGROUPS_MAX * 4)
/* grouplist not included; we allocate separate pages for that: */
#define GSSX_max_creds_sz (4 + 4 + 4 /* + NGROUPS_MAX*4 */)
#define GSSX_RES_accept_sec_context_sz (GSSX_default_status_sz + \
GSSX_default_ctx_sz + \
GSSX_max_output_token_sz + \
Expand Down

0 comments on commit cf59676

Please sign in to comment.