Skip to content

Commit c178fae

Browse files
committed
Merge tag 'nfs-for-5.11-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client fixes from Trond Myklebust: - SUNRPC: Handle 0 length opaque XDR object data properly - Fix a layout segment leak in pnfs_layout_process() - pNFS/NFSv4: Update the layout barrier when we schedule a layoutreturn - pNFS/NFSv4: Improve rejection of out-of-order layouts - pNFS/NFSv4: Try to return invalid layout in pnfs_layout_process() * tag 'nfs-for-5.11-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: SUNRPC: Handle 0 length opaque XDR object data properly SUNRPC: Move simple_get_bytes and simple_get_netobj into private header pNFS/NFSv4: Improve rejection of out-of-order layouts pNFS/NFSv4: Update the layout barrier when we schedule a layoutreturn pNFS/NFSv4: Try to return invalid layout in pnfs_layout_process() pNFS/NFSv4: Fix a layout segment leak in pnfs_layout_process()
2 parents 6642d60 + e4a7d1f commit c178fae

5 files changed

Lines changed: 93 additions & 85 deletions

File tree

fs/nfs/pnfs.c

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,21 @@ pnfs_grab_inode_layout_hdr(struct pnfs_layout_hdr *lo)
324324
return NULL;
325325
}
326326

327+
/*
328+
* Compare 2 layout stateid sequence ids, to see which is newer,
329+
* taking into account wraparound issues.
330+
*/
331+
static bool pnfs_seqid_is_newer(u32 s1, u32 s2)
332+
{
333+
return (s32)(s1 - s2) > 0;
334+
}
335+
336+
static void pnfs_barrier_update(struct pnfs_layout_hdr *lo, u32 newseq)
337+
{
338+
if (pnfs_seqid_is_newer(newseq, lo->plh_barrier))
339+
lo->plh_barrier = newseq;
340+
}
341+
327342
static void
328343
pnfs_set_plh_return_info(struct pnfs_layout_hdr *lo, enum pnfs_iomode iomode,
329344
u32 seq)
@@ -335,6 +350,7 @@ pnfs_set_plh_return_info(struct pnfs_layout_hdr *lo, enum pnfs_iomode iomode,
335350
if (seq != 0) {
336351
WARN_ON_ONCE(lo->plh_return_seq != 0 && lo->plh_return_seq != seq);
337352
lo->plh_return_seq = seq;
353+
pnfs_barrier_update(lo, seq);
338354
}
339355
}
340356

@@ -639,15 +655,6 @@ static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
639655
return rv;
640656
}
641657

642-
/*
643-
* Compare 2 layout stateid sequence ids, to see which is newer,
644-
* taking into account wraparound issues.
645-
*/
646-
static bool pnfs_seqid_is_newer(u32 s1, u32 s2)
647-
{
648-
return (s32)(s1 - s2) > 0;
649-
}
650-
651658
static bool
652659
pnfs_should_free_range(const struct pnfs_layout_range *lseg_range,
653660
const struct pnfs_layout_range *recall_range)
@@ -984,8 +991,7 @@ pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new,
984991
new_barrier = be32_to_cpu(new->seqid);
985992
else if (new_barrier == 0)
986993
return;
987-
if (pnfs_seqid_is_newer(new_barrier, lo->plh_barrier))
988-
lo->plh_barrier = new_barrier;
994+
pnfs_barrier_update(lo, new_barrier);
989995
}
990996

991997
static bool
@@ -994,7 +1000,7 @@ pnfs_layout_stateid_blocked(const struct pnfs_layout_hdr *lo,
9941000
{
9951001
u32 seqid = be32_to_cpu(stateid->seqid);
9961002

997-
return !pnfs_seqid_is_newer(seqid, lo->plh_barrier);
1003+
return !pnfs_seqid_is_newer(seqid, lo->plh_barrier) && lo->plh_barrier;
9981004
}
9991005

10001006
/* lget is set to 1 if called from inside send_layoutget call chain */
@@ -1183,20 +1189,17 @@ pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo,
11831189
return false;
11841190
set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
11851191
pnfs_get_layout_hdr(lo);
1192+
nfs4_stateid_copy(stateid, &lo->plh_stateid);
1193+
*cred = get_cred(lo->plh_lc_cred);
11861194
if (test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags)) {
1187-
nfs4_stateid_copy(stateid, &lo->plh_stateid);
1188-
*cred = get_cred(lo->plh_lc_cred);
11891195
if (lo->plh_return_seq != 0)
11901196
stateid->seqid = cpu_to_be32(lo->plh_return_seq);
11911197
if (iomode != NULL)
11921198
*iomode = lo->plh_return_iomode;
11931199
pnfs_clear_layoutreturn_info(lo);
1194-
return true;
1195-
}
1196-
nfs4_stateid_copy(stateid, &lo->plh_stateid);
1197-
*cred = get_cred(lo->plh_lc_cred);
1198-
if (iomode != NULL)
1200+
} else if (iomode != NULL)
11991201
*iomode = IOMODE_ANY;
1202+
pnfs_barrier_update(lo, be32_to_cpu(stateid->seqid));
12001203
return true;
12011204
}
12021205

@@ -1909,6 +1912,11 @@ static void nfs_layoutget_end(struct pnfs_layout_hdr *lo)
19091912
wake_up_var(&lo->plh_outstanding);
19101913
}
19111914

1915+
static bool pnfs_is_first_layoutget(struct pnfs_layout_hdr *lo)
1916+
{
1917+
return test_bit(NFS_LAYOUT_FIRST_LAYOUTGET, &lo->plh_flags);
1918+
}
1919+
19121920
static void pnfs_clear_first_layoutget(struct pnfs_layout_hdr *lo)
19131921
{
19141922
unsigned long *bitlock = &lo->plh_flags;
@@ -2383,23 +2391,34 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
23832391
goto out_forget;
23842392
}
23852393

2386-
if (!pnfs_layout_is_valid(lo)) {
2387-
/* We have a completely new layout */
2388-
pnfs_set_layout_stateid(lo, &res->stateid, lgp->cred, true);
2389-
} else if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) {
2394+
if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) {
23902395
/* existing state ID, make sure the sequence number matches. */
23912396
if (pnfs_layout_stateid_blocked(lo, &res->stateid)) {
2397+
if (!pnfs_layout_is_valid(lo) &&
2398+
pnfs_is_first_layoutget(lo))
2399+
lo->plh_barrier = 0;
23922400
dprintk("%s forget reply due to sequence\n", __func__);
23932401
goto out_forget;
23942402
}
23952403
pnfs_set_layout_stateid(lo, &res->stateid, lgp->cred, false);
2396-
} else {
2404+
} else if (pnfs_layout_is_valid(lo)) {
23972405
/*
23982406
* We got an entirely new state ID. Mark all segments for the
23992407
* inode invalid, and retry the layoutget
24002408
*/
2401-
pnfs_mark_layout_stateid_invalid(lo, &free_me);
2409+
struct pnfs_layout_range range = {
2410+
.iomode = IOMODE_ANY,
2411+
.length = NFS4_MAX_UINT64,
2412+
};
2413+
pnfs_set_plh_return_info(lo, IOMODE_ANY, 0);
2414+
pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs,
2415+
&range, 0);
24022416
goto out_forget;
2417+
} else {
2418+
/* We have a completely new layout */
2419+
if (!pnfs_is_first_layoutget(lo))
2420+
goto out_forget;
2421+
pnfs_set_layout_stateid(lo, &res->stateid, lgp->cred, true);
24032422
}
24042423

24052424
pnfs_get_lseg(lseg);

include/linux/sunrpc/xdr.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ struct rpc_rqst;
2525
#define XDR_QUADLEN(l) (((l) + 3) >> 2)
2626

2727
/*
28-
* Generic opaque `network object.' At the kernel level, this type
29-
* is used only by lockd.
28+
* Generic opaque `network object.'
3029
*/
3130
#define XDR_MAX_NETOBJ 1024
3231
struct xdr_netobj {

net/sunrpc/auth_gss/auth_gss.c

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <linux/uaccess.h>
3030
#include <linux/hashtable.h>
3131

32+
#include "auth_gss_internal.h"
3233
#include "../netns.h"
3334

3435
#include <trace/events/rpcgss.h>
@@ -125,35 +126,6 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
125126
clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
126127
}
127128

128-
static const void *
129-
simple_get_bytes(const void *p, const void *end, void *res, size_t len)
130-
{
131-
const void *q = (const void *)((const char *)p + len);
132-
if (unlikely(q > end || q < p))
133-
return ERR_PTR(-EFAULT);
134-
memcpy(res, p, len);
135-
return q;
136-
}
137-
138-
static inline const void *
139-
simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest)
140-
{
141-
const void *q;
142-
unsigned int len;
143-
144-
p = simple_get_bytes(p, end, &len, sizeof(len));
145-
if (IS_ERR(p))
146-
return p;
147-
q = (const void *)((const char *)p + len);
148-
if (unlikely(q > end || q < p))
149-
return ERR_PTR(-EFAULT);
150-
dest->data = kmemdup(p, len, GFP_NOFS);
151-
if (unlikely(dest->data == NULL))
152-
return ERR_PTR(-ENOMEM);
153-
dest->len = len;
154-
return q;
155-
}
156-
157129
static struct gss_cl_ctx *
158130
gss_cred_get_ctx(struct rpc_cred *cred)
159131
{
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
/*
3+
* linux/net/sunrpc/auth_gss/auth_gss_internal.h
4+
*
5+
* Internal definitions for RPCSEC_GSS client authentication
6+
*
7+
* Copyright (c) 2000 The Regents of the University of Michigan.
8+
* All rights reserved.
9+
*
10+
*/
11+
#include <linux/err.h>
12+
#include <linux/string.h>
13+
#include <linux/sunrpc/xdr.h>
14+
15+
static inline const void *
16+
simple_get_bytes(const void *p, const void *end, void *res, size_t len)
17+
{
18+
const void *q = (const void *)((const char *)p + len);
19+
if (unlikely(q > end || q < p))
20+
return ERR_PTR(-EFAULT);
21+
memcpy(res, p, len);
22+
return q;
23+
}
24+
25+
static inline const void *
26+
simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest)
27+
{
28+
const void *q;
29+
unsigned int len;
30+
31+
p = simple_get_bytes(p, end, &len, sizeof(len));
32+
if (IS_ERR(p))
33+
return p;
34+
q = (const void *)((const char *)p + len);
35+
if (unlikely(q > end || q < p))
36+
return ERR_PTR(-EFAULT);
37+
if (len) {
38+
dest->data = kmemdup(p, len, GFP_NOFS);
39+
if (unlikely(dest->data == NULL))
40+
return ERR_PTR(-ENOMEM);
41+
} else
42+
dest->data = NULL;
43+
dest->len = len;
44+
return q;
45+
}

net/sunrpc/auth_gss/gss_krb5_mech.c

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include <linux/sunrpc/xdr.h>
2222
#include <linux/sunrpc/gss_krb5_enctypes.h>
2323

24+
#include "auth_gss_internal.h"
25+
2426
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
2527
# define RPCDBG_FACILITY RPCDBG_AUTH
2628
#endif
@@ -143,35 +145,6 @@ get_gss_krb5_enctype(int etype)
143145
return NULL;
144146
}
145147

146-
static const void *
147-
simple_get_bytes(const void *p, const void *end, void *res, int len)
148-
{
149-
const void *q = (const void *)((const char *)p + len);
150-
if (unlikely(q > end || q < p))
151-
return ERR_PTR(-EFAULT);
152-
memcpy(res, p, len);
153-
return q;
154-
}
155-
156-
static const void *
157-
simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
158-
{
159-
const void *q;
160-
unsigned int len;
161-
162-
p = simple_get_bytes(p, end, &len, sizeof(len));
163-
if (IS_ERR(p))
164-
return p;
165-
q = (const void *)((const char *)p + len);
166-
if (unlikely(q > end || q < p))
167-
return ERR_PTR(-EFAULT);
168-
res->data = kmemdup(p, len, GFP_NOFS);
169-
if (unlikely(res->data == NULL))
170-
return ERR_PTR(-ENOMEM);
171-
res->len = len;
172-
return q;
173-
}
174-
175148
static inline const void *
176149
get_key(const void *p, const void *end,
177150
struct krb5_ctx *ctx, struct crypto_sync_skcipher **res)

0 commit comments

Comments
 (0)