nfscl: Make nfscl_getlayout() acquire the correct pNFS layout
Without this patch, if a pNFS read layout has already been acquired for a file, writes would be redirected to the Metadata Server (MDS), because nfscl_getlayout() would not acquire a read/write layout for the file. This happened because there was no "mode" argument to nfscl_getlayout() to indicate whether reading or writing was being done. Since doing I/O through the Metadata Server is not encouraged for some pNFS servers, it is preferable to get a read/write layout for writes instead of redirecting the write to the MDS. This patch adds a access mode argument to nfscl_getlayout() and nfsrpc_getlayout(), so that nfscl_getlayout() knows to acquire a read/write layout for writing, even if a read layout has already been acquired. This patch only affects NFSv4.1/4.2 client behaviour when pNFS ("pnfs" mount option against a server that supports pNFS) is in use. This problem was detected during a recent NFSv4 interoperability testing event held by the IETF working group. MFC after: 2 week
This commit is contained in:
parent
d5fd5cdc06
commit
24af0fcdfc
@ -637,7 +637,7 @@ int nfscl_layout(struct nfsmount *, vnode_t, u_int8_t *, int, nfsv4stateid_t *,
|
||||
int, int, struct nfsclflayouthead *, struct nfscllayout **, struct ucred *,
|
||||
NFSPROC_T *);
|
||||
struct nfscllayout *nfscl_getlayout(struct nfsclclient *, uint8_t *, int,
|
||||
uint64_t, struct nfsclflayout **, int *);
|
||||
uint64_t, uint32_t, struct nfsclflayout **, int *);
|
||||
void nfscl_dserr(uint32_t, uint32_t, struct nfscldevinfo *,
|
||||
struct nfscllayout *, struct nfsclds *);
|
||||
void nfscl_cancelreqs(struct nfsclds *);
|
||||
|
@ -150,7 +150,7 @@ static int nfsrpc_locku(struct nfsrv_descript *, struct nfsmount *,
|
||||
static int nfsrpc_setaclrpc(vnode_t, struct ucred *, NFSPROC_T *,
|
||||
struct acl *, nfsv4stateid_t *, void *);
|
||||
static int nfsrpc_getlayout(struct nfsmount *, vnode_t, struct nfsfh *, int,
|
||||
uint32_t *, nfsv4stateid_t *, uint64_t, struct nfscllayout **,
|
||||
uint32_t, uint32_t *, nfsv4stateid_t *, uint64_t, struct nfscllayout **,
|
||||
struct ucred *, NFSPROC_T *);
|
||||
static int nfsrpc_fillsa(struct nfsmount *, struct sockaddr_in *,
|
||||
struct sockaddr_in6 *, sa_family_t, int, int, struct nfsclds **,
|
||||
@ -5684,8 +5684,8 @@ nfsrpc_layoutreturn(struct nfsmount *nmp, uint8_t *fh, int fhlen, int reclaim,
|
||||
*/
|
||||
static int
|
||||
nfsrpc_getlayout(struct nfsmount *nmp, vnode_t vp, struct nfsfh *nfhp,
|
||||
int iomode, uint32_t *notifybitsp, nfsv4stateid_t *stateidp, uint64_t off,
|
||||
struct nfscllayout **lypp, struct ucred *cred, NFSPROC_T *p)
|
||||
int iomode, uint32_t rw, uint32_t *notifybitsp, nfsv4stateid_t *stateidp,
|
||||
uint64_t off, struct nfscllayout **lypp, struct ucred *cred, NFSPROC_T *p)
|
||||
{
|
||||
struct nfscllayout *lyp;
|
||||
struct nfsclflayout *flp;
|
||||
@ -5705,7 +5705,7 @@ nfsrpc_getlayout(struct nfsmount *nmp, vnode_t vp, struct nfsfh *nfhp,
|
||||
* flp == NULL.
|
||||
*/
|
||||
lyp = nfscl_getlayout(nmp->nm_clp, nfhp->nfh_fh, nfhp->nfh_len,
|
||||
off, &flp, &recalled);
|
||||
off, rw, &flp, &recalled);
|
||||
islocked = 0;
|
||||
if (lyp == NULL || flp == NULL) {
|
||||
if (recalled != 0)
|
||||
@ -6036,7 +6036,7 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
|
||||
/* Search for a layout for this file. */
|
||||
off = uiop->uio_offset;
|
||||
layp = nfscl_getlayout(nmp->nm_clp, np->n_fhp->nfh_fh,
|
||||
np->n_fhp->nfh_len, off, &rflp, &recalled);
|
||||
np->n_fhp->nfh_len, off, rwaccess, &rflp, &recalled);
|
||||
if (layp == NULL || rflp == NULL) {
|
||||
if (recalled != 0) {
|
||||
NFSFREECRED(newcred);
|
||||
@ -6054,7 +6054,7 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
|
||||
else
|
||||
iolaymode = NFSLAYOUTIOMODE_READ;
|
||||
error = nfsrpc_getlayout(nmp, vp, np->n_fhp, iolaymode,
|
||||
NULL, &stateid, off, &layp, newcred, p);
|
||||
rwaccess, NULL, &stateid, off, &layp, newcred, p);
|
||||
if (error != 0) {
|
||||
NFSLOCKNODE(np);
|
||||
np->n_flag |= NNOLAYOUT;
|
||||
@ -7740,7 +7740,7 @@ nfsrpc_getopenlayout(struct nfsmount *nmp, vnode_t vp, u_int8_t *nfhp,
|
||||
* on it, iff flp != NULL or a lock (exclusive lock) on it iff
|
||||
* flp == NULL.
|
||||
*/
|
||||
lyp = nfscl_getlayout(nmp->nm_clp, newfhp, newfhlen, 0, &flp,
|
||||
lyp = nfscl_getlayout(nmp->nm_clp, newfhp, newfhlen, 0, mode, &flp,
|
||||
&recalled);
|
||||
NFSCL_DEBUG(4, "nfsrpc_getopenlayout nfscl_getlayout lyp=%p\n", lyp);
|
||||
if (lyp == NULL)
|
||||
|
@ -5141,7 +5141,8 @@ nfscl_layout(struct nfsmount *nmp, vnode_t vp, u_int8_t *fhp, int fhlen,
|
||||
*/
|
||||
struct nfscllayout *
|
||||
nfscl_getlayout(struct nfsclclient *clp, uint8_t *fhp, int fhlen,
|
||||
uint64_t off, struct nfsclflayout **retflpp, int *recalledp)
|
||||
uint64_t off, uint32_t rwaccess, struct nfsclflayout **retflpp,
|
||||
int *recalledp)
|
||||
{
|
||||
struct nfscllayout *lyp;
|
||||
mount_t mp;
|
||||
@ -5157,8 +5158,8 @@ nfscl_getlayout(struct nfsclclient *clp, uint8_t *fhp, int fhlen,
|
||||
TAILQ_REMOVE(&clp->nfsc_layout, lyp, nfsly_list);
|
||||
TAILQ_INSERT_HEAD(&clp->nfsc_layout, lyp, nfsly_list);
|
||||
lyp->nfsly_timestamp = NFSD_MONOSEC + 120;
|
||||
error = nfscl_findlayoutforio(lyp, off,
|
||||
NFSV4OPEN_ACCESSREAD, retflpp);
|
||||
error = nfscl_findlayoutforio(lyp, off, rwaccess,
|
||||
retflpp);
|
||||
if (error == 0)
|
||||
nfsv4_getref(&lyp->nfsly_lock, NULL,
|
||||
NFSCLSTATEMUTEXPTR, mp);
|
||||
|
Loading…
Reference in New Issue
Block a user