Deleted Added
full compact
nfs_clstate.c (222389) nfs_clstate.c (222719)
1/*-
2 * Copyright (c) 2009 Rick Macklem, University of Guelph
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 12 unchanged lines hidden (view full) ---

21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2009 Rick Macklem, University of Guelph
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 12 unchanged lines hidden (view full) ---

21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/fs/nfsclient/nfs_clstate.c 222389 2011-05-27 22:05:10Z rmacklem $");
29__FBSDID("$FreeBSD: head/sys/fs/nfsclient/nfs_clstate.c 222719 2011-06-05 18:17:37Z rmacklem $");
30
31/*
32 * These functions implement the client side state handling for NFSv4.
33 * NFSv4 state handling:
34 * - A lockowner is used to determine lock contention, so it
35 * corresponds directly to a Posix pid. (1 to 1 mapping)
36 * - The correct granularity of an OpenOwner is not nearly so
37 * obvious. An OpenOwner does the following:

--- 183 unchanged lines hidden (view full) ---

221 return (ret);
222 }
223
224 /*
225 * Get the Open iff it already exists.
226 * If none found, add the new one or return error, depending upon
227 * "create".
228 */
30
31/*
32 * These functions implement the client side state handling for NFSv4.
33 * NFSv4 state handling:
34 * - A lockowner is used to determine lock contention, so it
35 * corresponds directly to a Posix pid. (1 to 1 mapping)
36 * - The correct granularity of an OpenOwner is not nearly so
37 * obvious. An OpenOwner does the following:

--- 183 unchanged lines hidden (view full) ---

221 return (ret);
222 }
223
224 /*
225 * Get the Open iff it already exists.
226 * If none found, add the new one or return error, depending upon
227 * "create".
228 */
229 nfscl_filllockowner(p, own);
229 nfscl_filllockowner(p->td_proc, own, F_POSIX);
230 NFSLOCKCLSTATE();
231 dp = NULL;
232 /* First check the delegation list */
233 if (nfhp != NULL && usedeleg) {
234 LIST_FOREACH(dp, NFSCLDELEGHASH(clp, nfhp, fhlen), nfsdl_hash) {
235 if (dp->nfsdl_fhlen == fhlen &&
236 !NFSBCMP(nfhp, dp->nfsdl_fh, fhlen)) {
237 if (!(amode & NFSV4OPEN_ACCESSWRITE) ||

--- 278 unchanged lines hidden (view full) ---

516 }
517 }
518
519 if (p != NULL) {
520 /*
521 * If p != NULL, we want to search the parentage tree
522 * for a matching OpenOwner and use that.
523 */
230 NFSLOCKCLSTATE();
231 dp = NULL;
232 /* First check the delegation list */
233 if (nfhp != NULL && usedeleg) {
234 LIST_FOREACH(dp, NFSCLDELEGHASH(clp, nfhp, fhlen), nfsdl_hash) {
235 if (dp->nfsdl_fhlen == fhlen &&
236 !NFSBCMP(nfhp, dp->nfsdl_fh, fhlen)) {
237 if (!(amode & NFSV4OPEN_ACCESSWRITE) ||

--- 278 unchanged lines hidden (view full) ---

516 }
517 }
518
519 if (p != NULL) {
520 /*
521 * If p != NULL, we want to search the parentage tree
522 * for a matching OpenOwner and use that.
523 */
524 nfscl_filllockowner(p, own);
524 nfscl_filllockowner(p->td_proc, own, F_POSIX);
525 error = nfscl_getopen(&clp->nfsc_owner, nfhp, fhlen, NULL, p,
526 mode, NULL, &op);
527 if (error == 0) {
528 /* now look for a lockowner */
529 LIST_FOREACH(lp, &op->nfso_lock, nfsl_list) {
530 if (!NFSBCMP(lp->nfsl_owner, own,
531 NFSV4CL_LOCKNAMELEN)) {
532 stateidp->seqid =

--- 58 unchanged lines hidden (view full) ---

591 struct nfsclopen *op;
592 NFSPROC_T *nproc;
593 u_int8_t own[NFSV4CL_LOCKNAMELEN], *ownp;
594
595 nproc = p;
596 op = NULL;
597 while (op == NULL && (nproc != NULL || rown != NULL)) {
598 if (nproc != NULL) {
525 error = nfscl_getopen(&clp->nfsc_owner, nfhp, fhlen, NULL, p,
526 mode, NULL, &op);
527 if (error == 0) {
528 /* now look for a lockowner */
529 LIST_FOREACH(lp, &op->nfso_lock, nfsl_list) {
530 if (!NFSBCMP(lp->nfsl_owner, own,
531 NFSV4CL_LOCKNAMELEN)) {
532 stateidp->seqid =

--- 58 unchanged lines hidden (view full) ---

591 struct nfsclopen *op;
592 NFSPROC_T *nproc;
593 u_int8_t own[NFSV4CL_LOCKNAMELEN], *ownp;
594
595 nproc = p;
596 op = NULL;
597 while (op == NULL && (nproc != NULL || rown != NULL)) {
598 if (nproc != NULL) {
599 nfscl_filllockowner(nproc, own);
599 nfscl_filllockowner(nproc->td_proc, own, F_POSIX);
600 ownp = own;
601 } else {
602 ownp = rown;
603 }
604 /* Search the client list */
605 LIST_FOREACH(owp, ohp, nfsow_list) {
606 if (!NFSBCMP(owp->nfsow_owner, ownp,
607 NFSV4CL_LOCKNAMELEN))

--- 268 unchanged lines hidden (view full) ---

876}
877
878/*
879 * Called when wanting to lock a byte region.
880 */
881APPLESTATIC int
882nfscl_getbytelock(vnode_t vp, u_int64_t off, u_int64_t len,
883 short type, struct ucred *cred, NFSPROC_T *p, struct nfsclclient *rclp,
600 ownp = own;
601 } else {
602 ownp = rown;
603 }
604 /* Search the client list */
605 LIST_FOREACH(owp, ohp, nfsow_list) {
606 if (!NFSBCMP(owp->nfsow_owner, ownp,
607 NFSV4CL_LOCKNAMELEN))

--- 268 unchanged lines hidden (view full) ---

876}
877
878/*
879 * Called when wanting to lock a byte region.
880 */
881APPLESTATIC int
882nfscl_getbytelock(vnode_t vp, u_int64_t off, u_int64_t len,
883 short type, struct ucred *cred, NFSPROC_T *p, struct nfsclclient *rclp,
884 int recovery, u_int8_t *rownp, u_int8_t *ropenownp,
884 int recovery, void *id, int flags, u_int8_t *rownp, u_int8_t *ropenownp,
885 struct nfscllockowner **lpp, int *newonep, int *donelocallyp)
886{
887 struct nfscllockowner *lp;
888 struct nfsclopen *op;
889 struct nfsclclient *clp;
890 struct nfscllockowner *nlp;
891 struct nfscllock *nlop, *otherlop;
892 struct nfscldeleg *dp = NULL, *ldp = NULL;

--- 44 unchanged lines hidden (view full) ---

937 FREE((caddr_t)nlop, M_NFSCLLOCK);
938 return (error);
939 }
940
941 op = NULL;
942 if (recovery) {
943 ownp = rownp;
944 } else {
885 struct nfscllockowner **lpp, int *newonep, int *donelocallyp)
886{
887 struct nfscllockowner *lp;
888 struct nfsclopen *op;
889 struct nfsclclient *clp;
890 struct nfscllockowner *nlp;
891 struct nfscllock *nlop, *otherlop;
892 struct nfscldeleg *dp = NULL, *ldp = NULL;

--- 44 unchanged lines hidden (view full) ---

937 FREE((caddr_t)nlop, M_NFSCLLOCK);
938 return (error);
939 }
940
941 op = NULL;
942 if (recovery) {
943 ownp = rownp;
944 } else {
945 nfscl_filllockowner(p, own);
945 nfscl_filllockowner(id, own, flags);
946 ownp = own;
947 }
948 if (!recovery) {
949 NFSLOCKCLSTATE();
950 /*
951 * First, search for a delegation. If one exists for this file,
952 * the lock can be done locally against it, so long as there
953 * isn't a local lock conflict.

--- 120 unchanged lines hidden (view full) ---

1074}
1075
1076/*
1077 * Called to unlock a byte range, for LockU.
1078 */
1079APPLESTATIC int
1080nfscl_relbytelock(vnode_t vp, u_int64_t off, u_int64_t len,
1081 __unused struct ucred *cred, NFSPROC_T *p, int callcnt,
946 ownp = own;
947 }
948 if (!recovery) {
949 NFSLOCKCLSTATE();
950 /*
951 * First, search for a delegation. If one exists for this file,
952 * the lock can be done locally against it, so long as there
953 * isn't a local lock conflict.

--- 120 unchanged lines hidden (view full) ---

1074}
1075
1076/*
1077 * Called to unlock a byte range, for LockU.
1078 */
1079APPLESTATIC int
1080nfscl_relbytelock(vnode_t vp, u_int64_t off, u_int64_t len,
1081 __unused struct ucred *cred, NFSPROC_T *p, int callcnt,
1082 struct nfsclclient *clp, struct nfscllockowner **lpp, int *dorpcp)
1082 struct nfsclclient *clp, void *id, int flags,
1083 struct nfscllockowner **lpp, int *dorpcp)
1083{
1084 struct nfscllockowner *lp;
1085 struct nfsclowner *owp;
1086 struct nfsclopen *op;
1087 struct nfscllock *nlop, *other_lop = NULL;
1088 struct nfscldeleg *dp;
1089 struct nfsnode *np;
1090 u_int8_t own[NFSV4CL_LOCKNAMELEN];

--- 20 unchanged lines hidden (view full) ---

1111 return (NFSERR_INVAL);
1112 }
1113 }
1114 if (callcnt == 0) {
1115 MALLOC(other_lop, struct nfscllock *,
1116 sizeof (struct nfscllock), M_NFSCLLOCK, M_WAITOK);
1117 *other_lop = *nlop;
1118 }
1084{
1085 struct nfscllockowner *lp;
1086 struct nfsclowner *owp;
1087 struct nfsclopen *op;
1088 struct nfscllock *nlop, *other_lop = NULL;
1089 struct nfscldeleg *dp;
1090 struct nfsnode *np;
1091 u_int8_t own[NFSV4CL_LOCKNAMELEN];

--- 20 unchanged lines hidden (view full) ---

1112 return (NFSERR_INVAL);
1113 }
1114 }
1115 if (callcnt == 0) {
1116 MALLOC(other_lop, struct nfscllock *,
1117 sizeof (struct nfscllock), M_NFSCLLOCK, M_WAITOK);
1118 *other_lop = *nlop;
1119 }
1119 nfscl_filllockowner(p, own);
1120 nfscl_filllockowner(id, own, flags);
1120 dp = NULL;
1121 NFSLOCKCLSTATE();
1122 if (callcnt == 0)
1123 dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh,
1124 np->n_fhp->nfh_len);
1125
1126 /*
1127 * First, unlock any local regions on a delegation.

--- 55 unchanged lines hidden (view full) ---

1183 FREE((caddr_t)other_lop, M_NFSCLLOCK);
1184 return (0);
1185}
1186
1187/*
1188 * Release all lockowners marked in progess for this process and file.
1189 */
1190APPLESTATIC void
1121 dp = NULL;
1122 NFSLOCKCLSTATE();
1123 if (callcnt == 0)
1124 dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh,
1125 np->n_fhp->nfh_len);
1126
1127 /*
1128 * First, unlock any local regions on a delegation.

--- 55 unchanged lines hidden (view full) ---

1184 FREE((caddr_t)other_lop, M_NFSCLLOCK);
1185 return (0);
1186}
1187
1188/*
1189 * Release all lockowners marked in progess for this process and file.
1190 */
1191APPLESTATIC void
1191nfscl_releasealllocks(struct nfsclclient *clp, vnode_t vp, NFSPROC_T *p)
1192nfscl_releasealllocks(struct nfsclclient *clp, vnode_t vp, NFSPROC_T *p,
1193 void *id, int flags)
1192{
1193 struct nfsclowner *owp;
1194 struct nfsclopen *op;
1195 struct nfscllockowner *lp;
1196 struct nfsnode *np;
1197 u_int8_t own[NFSV4CL_LOCKNAMELEN];
1198
1199 np = VTONFS(vp);
1194{
1195 struct nfsclowner *owp;
1196 struct nfsclopen *op;
1197 struct nfscllockowner *lp;
1198 struct nfsnode *np;
1199 u_int8_t own[NFSV4CL_LOCKNAMELEN];
1200
1201 np = VTONFS(vp);
1200 nfscl_filllockowner(p, own);
1202 nfscl_filllockowner(id, own, flags);
1201 NFSLOCKCLSTATE();
1202 LIST_FOREACH(owp, &clp->nfsc_owner, nfsow_list) {
1203 LIST_FOREACH(op, &owp->nfsow_open, nfso_list) {
1204 if (op->nfso_fhlen == np->n_fhp->nfh_len &&
1205 !NFSBCMP(op->nfso_fh, np->n_fhp->nfh_fh, op->nfso_fhlen)) {
1206 LIST_FOREACH(lp, &op->nfso_lock, nfsl_list) {
1207 if (lp->nfsl_inprog == p &&
1208 !NFSBCMP(lp->nfsl_owner, own,

--- 12 unchanged lines hidden (view full) ---

1221/*
1222 * Called to find out if any bytes within the byte range specified are
1223 * write locked by the calling process. Used to determine if flushing
1224 * is required before a LockU.
1225 * If in doubt, return 1, so the flush will occur.
1226 */
1227APPLESTATIC int
1228nfscl_checkwritelocked(vnode_t vp, struct flock *fl,
1203 NFSLOCKCLSTATE();
1204 LIST_FOREACH(owp, &clp->nfsc_owner, nfsow_list) {
1205 LIST_FOREACH(op, &owp->nfsow_open, nfso_list) {
1206 if (op->nfso_fhlen == np->n_fhp->nfh_len &&
1207 !NFSBCMP(op->nfso_fh, np->n_fhp->nfh_fh, op->nfso_fhlen)) {
1208 LIST_FOREACH(lp, &op->nfso_lock, nfsl_list) {
1209 if (lp->nfsl_inprog == p &&
1210 !NFSBCMP(lp->nfsl_owner, own,

--- 12 unchanged lines hidden (view full) ---

1223/*
1224 * Called to find out if any bytes within the byte range specified are
1225 * write locked by the calling process. Used to determine if flushing
1226 * is required before a LockU.
1227 * If in doubt, return 1, so the flush will occur.
1228 */
1229APPLESTATIC int
1230nfscl_checkwritelocked(vnode_t vp, struct flock *fl,
1229 struct ucred *cred, NFSPROC_T *p)
1231 struct ucred *cred, NFSPROC_T *p, void *id, int flags)
1230{
1231 struct nfsclowner *owp;
1232 struct nfscllockowner *lp;
1233 struct nfsclopen *op;
1234 struct nfsclclient *clp;
1235 struct nfscllock *lop;
1236 struct nfscldeleg *dp;
1237 struct nfsnode *np;

--- 23 unchanged lines hidden (view full) ---

1261 return (1);
1262 } else {
1263 end = NFS64BITSSET;
1264 }
1265
1266 error = nfscl_getcl(vp, cred, p, &clp);
1267 if (error)
1268 return (1);
1232{
1233 struct nfsclowner *owp;
1234 struct nfscllockowner *lp;
1235 struct nfsclopen *op;
1236 struct nfsclclient *clp;
1237 struct nfscllock *lop;
1238 struct nfscldeleg *dp;
1239 struct nfsnode *np;

--- 23 unchanged lines hidden (view full) ---

1263 return (1);
1264 } else {
1265 end = NFS64BITSSET;
1266 }
1267
1268 error = nfscl_getcl(vp, cred, p, &clp);
1269 if (error)
1270 return (1);
1269 nfscl_filllockowner(p, own);
1271 nfscl_filllockowner(id, own, flags);
1270 NFSLOCKCLSTATE();
1271
1272 /*
1273 * First check the delegation locks.
1274 */
1275 dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len);
1276 if (dp != NULL) {
1277 LIST_FOREACH(lp, &dp->nfsdl_lock, nfsl_list) {

--- 358 unchanged lines hidden (view full) ---

1636APPLESTATIC void
1637nfscl_cleanup(NFSPROC_T *p)
1638{
1639 struct nfsclclient *clp;
1640 u_int8_t own[NFSV4CL_LOCKNAMELEN];
1641
1642 if (!nfscl_inited)
1643 return;
1272 NFSLOCKCLSTATE();
1273
1274 /*
1275 * First check the delegation locks.
1276 */
1277 dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len);
1278 if (dp != NULL) {
1279 LIST_FOREACH(lp, &dp->nfsdl_lock, nfsl_list) {

--- 358 unchanged lines hidden (view full) ---

1638APPLESTATIC void
1639nfscl_cleanup(NFSPROC_T *p)
1640{
1641 struct nfsclclient *clp;
1642 u_int8_t own[NFSV4CL_LOCKNAMELEN];
1643
1644 if (!nfscl_inited)
1645 return;
1644 nfscl_filllockowner(p, own);
1646 nfscl_filllockowner(p->td_proc, own, F_POSIX);
1645
1646 NFSLOCKCLSTATE();
1647 /*
1648 * Loop through all the clientids, looking for the OpenOwners.
1649 */
1650 LIST_FOREACH(clp, &nfsclhead, nfsc_list)
1651 nfscl_cleanup_common(clp, own);
1652 NFSUNLOCKCLSTATE();

--- 1664 unchanged lines hidden (view full) ---

3317 return (0);
3318}
3319
3320/*
3321 * Check for a local conflicting lock.
3322 */
3323APPLESTATIC int
3324nfscl_lockt(vnode_t vp, struct nfsclclient *clp, u_int64_t off,
1647
1648 NFSLOCKCLSTATE();
1649 /*
1650 * Loop through all the clientids, looking for the OpenOwners.
1651 */
1652 LIST_FOREACH(clp, &nfsclhead, nfsc_list)
1653 nfscl_cleanup_common(clp, own);
1654 NFSUNLOCKCLSTATE();

--- 1664 unchanged lines hidden (view full) ---

3319 return (0);
3320}
3321
3322/*
3323 * Check for a local conflicting lock.
3324 */
3325APPLESTATIC int
3326nfscl_lockt(vnode_t vp, struct nfsclclient *clp, u_int64_t off,
3325 u_int64_t len, struct flock *fl, NFSPROC_T *p)
3327 u_int64_t len, struct flock *fl, NFSPROC_T *p, void *id, int flags)
3326{
3327 struct nfscllock *lop, nlck;
3328 struct nfscldeleg *dp;
3329 struct nfsnode *np;
3330 u_int8_t own[NFSV4CL_LOCKNAMELEN];
3331 int error;
3332
3333 nlck.nfslo_type = fl->l_type;
3334 nlck.nfslo_first = off;
3335 if (len == NFS64BITSSET) {
3336 nlck.nfslo_end = NFS64BITSSET;
3337 } else {
3338 nlck.nfslo_end = off + len;
3339 if (nlck.nfslo_end <= nlck.nfslo_first)
3340 return (NFSERR_INVAL);
3341 }
3342 np = VTONFS(vp);
3328{
3329 struct nfscllock *lop, nlck;
3330 struct nfscldeleg *dp;
3331 struct nfsnode *np;
3332 u_int8_t own[NFSV4CL_LOCKNAMELEN];
3333 int error;
3334
3335 nlck.nfslo_type = fl->l_type;
3336 nlck.nfslo_first = off;
3337 if (len == NFS64BITSSET) {
3338 nlck.nfslo_end = NFS64BITSSET;
3339 } else {
3340 nlck.nfslo_end = off + len;
3341 if (nlck.nfslo_end <= nlck.nfslo_first)
3342 return (NFSERR_INVAL);
3343 }
3344 np = VTONFS(vp);
3343 nfscl_filllockowner(p, own);
3345 nfscl_filllockowner(id, own, flags);
3344 NFSLOCKCLSTATE();
3345 dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len);
3346 error = nfscl_localconflict(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len,
3347 &nlck, own, dp, &lop);
3348 if (error != 0) {
3349 fl->l_whence = SEEK_SET;
3350 fl->l_start = lop->nfslo_first;
3351 if (lop->nfslo_end == NFS64BITSSET)

--- 258 unchanged lines hidden (view full) ---

3610 struct nfsfh *nfhp;
3611 u_int64_t off, len;
3612 u_int32_t clidrev = 0;
3613 int error, newone, donelocally;
3614
3615 off = lop->nfslo_first;
3616 len = lop->nfslo_end - lop->nfslo_first;
3617 error = nfscl_getbytelock(vp, off, len, lop->nfslo_type, cred, p,
3346 NFSLOCKCLSTATE();
3347 dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len);
3348 error = nfscl_localconflict(clp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len,
3349 &nlck, own, dp, &lop);
3350 if (error != 0) {
3351 fl->l_whence = SEEK_SET;
3352 fl->l_start = lop->nfslo_first;
3353 if (lop->nfslo_end == NFS64BITSSET)

--- 258 unchanged lines hidden (view full) ---

3612 struct nfsfh *nfhp;
3613 u_int64_t off, len;
3614 u_int32_t clidrev = 0;
3615 int error, newone, donelocally;
3616
3617 off = lop->nfslo_first;
3618 len = lop->nfslo_end - lop->nfslo_first;
3619 error = nfscl_getbytelock(vp, off, len, lop->nfslo_type, cred, p,
3618 clp, 1, lp->nfsl_owner, lp->nfsl_openowner, &nlp, &newone,
3620 clp, 1, NULL, 0, lp->nfsl_owner, lp->nfsl_openowner, &nlp, &newone,
3619 &donelocally);
3620 if (error || donelocally)
3621 return (error);
3622 if (nmp->nm_clp != NULL)
3623 clidrev = nmp->nm_clp->nfsc_clientidrev;
3624 else
3625 clidrev = 0;
3626 nfhp = VTONFS(vp)->n_fhp;

--- 637 unchanged lines hidden ---
3621 &donelocally);
3622 if (error || donelocally)
3623 return (error);
3624 if (nmp->nm_clp != NULL)
3625 clidrev = nmp->nm_clp->nfsc_clientidrev;
3626 else
3627 clidrev = 0;
3628 nfhp = VTONFS(vp)->n_fhp;

--- 637 unchanged lines hidden ---