summaryrefslogtreecommitdiffstats
path: root/sys/fs/nfs/nfs_commonsubs.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/nfs/nfs_commonsubs.c')
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c110
1 files changed, 84 insertions, 26 deletions
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index 5c50dfd..b94091c 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -1733,6 +1733,23 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
}
attrsum += NFSX_HYPER;
break;
+ case NFSATTRBIT_SUPPATTREXCLCREAT:
+ retnotsup = 0;
+ error = nfsrv_getattrbits(nd, &retattrbits,
+ &cnt, &retnotsup);
+ if (error)
+ goto nfsmout;
+ if (compare && !(*retcmpp)) {
+ NFSSETSUPP_ATTRBIT(&checkattrbits);
+ NFSCLRNOTSETABLE_ATTRBIT(&checkattrbits);
+ NFSCLRBIT_ATTRBIT(&checkattrbits,
+ NFSATTRBIT_TIMEACCESSSET);
+ if (!NFSEQUAL_ATTRBIT(&retattrbits, &checkattrbits)
+ || retnotsup)
+ *retcmpp = NFSERR_NOTSAME;
+ }
+ attrsum += cnt;
+ break;
default:
printf("EEK! nfsv4_loadattr unknown attr=%d\n",
bitpos);
@@ -2469,6 +2486,12 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
txdr_hyper(uquad, tl);
retnum += NFSX_HYPER;
break;
+ case NFSATTRBIT_SUPPATTREXCLCREAT:
+ NFSSETSUPP_ATTRBIT(&attrbits);
+ NFSCLRNOTSETABLE_ATTRBIT(&attrbits);
+ NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET);
+ retnum += nfsrv_putattrbit(nd, &attrbits);
+ break;
default:
printf("EEK! Bad V4 attribute bitpos=%d\n", bitpos);
};
@@ -3663,6 +3686,9 @@ nfsmout:
/*
* Handle an NFSv4.1 Sequence request for the session.
+ * If reply != NULL, use it to return the cached reply, as required.
+ * The client gets a cached reply via this call for callbacks, however the
+ * server gets a cached reply via the nfsv4_seqsess_cachereply() call.
*/
int
nfsv4_seqsession(uint32_t seqid, uint32_t slotid, uint32_t highslot,
@@ -3671,7 +3697,8 @@ nfsv4_seqsession(uint32_t seqid, uint32_t slotid, uint32_t highslot,
int error;
error = 0;
- *reply = NULL;
+ if (reply != NULL)
+ *reply = NULL;
if (slotid > maxslot)
return (NFSERR_BADSLOT);
if (seqid == slots[slotid].nfssl_seq) {
@@ -3679,13 +3706,18 @@ nfsv4_seqsession(uint32_t seqid, uint32_t slotid, uint32_t highslot,
if (slots[slotid].nfssl_inprog != 0)
error = NFSERR_DELAY;
else if (slots[slotid].nfssl_reply != NULL) {
- *reply = slots[slotid].nfssl_reply;
- slots[slotid].nfssl_reply = NULL;
+ if (reply != NULL) {
+ *reply = slots[slotid].nfssl_reply;
+ slots[slotid].nfssl_reply = NULL;
+ }
slots[slotid].nfssl_inprog = 1;
+ error = NFSERR_REPLYFROMCACHE;
} else
- error = NFSERR_SEQMISORDERED;
+ /* No reply cached, so just do it. */
+ slots[slotid].nfssl_inprog = 1;
} else if ((slots[slotid].nfssl_seq + 1) == seqid) {
- m_freem(slots[slotid].nfssl_reply);
+ if (slots[slotid].nfssl_reply != NULL)
+ m_freem(slots[slotid].nfssl_reply);
slots[slotid].nfssl_reply = NULL;
slots[slotid].nfssl_inprog = 1;
slots[slotid].nfssl_seq++;
@@ -3696,12 +3728,22 @@ nfsv4_seqsession(uint32_t seqid, uint32_t slotid, uint32_t highslot,
/*
* Cache this reply for the slot.
+ * Use the "rep" argument to return the cached reply if repstat is set to
+ * NFSERR_REPLYFROMCACHE. The client never sets repstat to this value.
*/
void
-nfsv4_seqsess_cacherep(uint32_t slotid, struct nfsslot *slots, struct mbuf *rep)
+nfsv4_seqsess_cacherep(uint32_t slotid, struct nfsslot *slots, int repstat,
+ struct mbuf **rep)
{
- slots[slotid].nfssl_reply = rep;
+ if (repstat == NFSERR_REPLYFROMCACHE) {
+ *rep = slots[slotid].nfssl_reply;
+ slots[slotid].nfssl_reply = NULL;
+ } else {
+ if (slots[slotid].nfssl_reply != NULL)
+ m_freem(slots[slotid].nfssl_reply);
+ slots[slotid].nfssl_reply = *rep;
+ }
slots[slotid].nfssl_inprog = 0;
}
@@ -3713,9 +3755,36 @@ nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_descript *nd,
struct nfsclsession *sep, int dont_replycache)
{
uint32_t *tl, slotseq = 0;
+ int error, maxslot, slotpos;
+ uint8_t sessionid[NFSX_V4SESSIONID];
+
+ error = nfsv4_sequencelookup(nmp, sep, &slotpos, &maxslot, &slotseq,
+ sessionid);
+ if (error != 0)
+ return;
+ KASSERT(maxslot >= 0, ("nfscl_setsequence neg maxslot"));
+
+ /* Build the Sequence arguments. */
+ NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 4 * NFSX_UNSIGNED);
+ bcopy(sessionid, tl, NFSX_V4SESSIONID);
+ tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
+ nd->nd_slotseq = tl;
+ *tl++ = txdr_unsigned(slotseq);
+ *tl++ = txdr_unsigned(slotpos);
+ *tl++ = txdr_unsigned(maxslot);
+ if (dont_replycache == 0)
+ *tl = newnfs_true;
+ else
+ *tl = newnfs_false;
+ nd->nd_flag |= ND_HASSEQUENCE;
+}
+
+int
+nfsv4_sequencelookup(struct nfsmount *nmp, struct nfsclsession *sep,
+ int *slotposp, int *maxslotp, uint32_t *slotseqp, uint8_t *sessionid)
+{
int i, maxslot, slotpos;
uint64_t bitval;
- uint8_t sessionid[NFSX_V4SESSIONID];
/* Find an unused slot. */
slotpos = -1;
@@ -3728,7 +3797,7 @@ nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_descript *nd,
slotpos = i;
sep->nfsess_slots |= bitval;
sep->nfsess_slotseq[i]++;
- slotseq = sep->nfsess_slotseq[i];
+ *slotseqp = sep->nfsess_slotseq[i];
break;
}
bitval <<= 1;
@@ -3739,10 +3808,11 @@ nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_descript *nd,
* This RPC attempt will fail when it calls
* newnfs_request().
*/
- if ((nmp->nm_mountp->mnt_kern_flag & MNTK_UNMOUNTF)
+ if (nmp != NULL &&
+ (nmp->nm_mountp->mnt_kern_flag & MNTK_UNMOUNTF)
!= 0) {
mtx_unlock(&sep->nfsess_mtx);
- return;
+ return (ESTALE);
}
/* Wake up once/sec, to check for a forced dismount. */
(void)mtx_sleep(&sep->nfsess_slots, &sep->nfsess_mtx,
@@ -3758,21 +3828,9 @@ nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_descript *nd,
}
bcopy(sep->nfsess_sessionid, sessionid, NFSX_V4SESSIONID);
mtx_unlock(&sep->nfsess_mtx);
- KASSERT(maxslot >= 0, ("nfscl_setsequence neg maxslot"));
-
- /* Build the Sequence arguments. */
- NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 4 * NFSX_UNSIGNED);
- bcopy(sessionid, tl, NFSX_V4SESSIONID);
- tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
- nd->nd_slotseq = tl;
- *tl++ = txdr_unsigned(slotseq);
- *tl++ = txdr_unsigned(slotpos);
- *tl++ = txdr_unsigned(maxslot);
- if (dont_replycache == 0)
- *tl = newnfs_true;
- else
- *tl = newnfs_false;
- nd->nd_flag |= ND_HASSEQUENCE;
+ *slotposp = slotpos;
+ *maxslotp = maxslot;
+ return (0);
}
/*
OpenPOWER on IntegriCloud