Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/nfsclient/nfs_clstate.c
Show First 20 Lines • Show All 203 Lines • ▼ Show 20 Lines | |||||
#define NETFAMILY(clp) \ | #define NETFAMILY(clp) \ | ||||
(((clp)->nfsc_flags & NFSCLFLAGS_AFINET6) ? AF_INET6 : AF_INET) | (((clp)->nfsc_flags & NFSCLFLAGS_AFINET6) ? AF_INET6 : AF_INET) | ||||
/* | /* | ||||
* Called for an open operation. | * Called for an open operation. | ||||
* If the nfhp argument is NULL, just get an openowner. | * If the nfhp argument is NULL, just get an openowner. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_open(vnode_t vp, u_int8_t *nfhp, int fhlen, u_int32_t amode, int usedeleg, | nfscl_open(vnode_t vp, u_int8_t *nfhp, int fhlen, u_int32_t amode, int usedeleg, | ||||
struct ucred *cred, NFSPROC_T *p, struct nfsclowner **owpp, | struct ucred *cred, NFSPROC_T *p, struct nfsclowner **owpp, | ||||
struct nfsclopen **opp, int *newonep, int *retp, int lockit) | struct nfsclopen **opp, int *newonep, int *retp, int lockit) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfsclowner *owp, *nowp; | struct nfsclowner *owp, *nowp; | ||||
struct nfsclopen *op = NULL, *nop = NULL; | struct nfsclopen *op = NULL, *nop = NULL; | ||||
struct nfscldeleg *dp; | struct nfscldeleg *dp; | ||||
▲ Show 20 Lines • Show All 199 Lines • ▼ Show 20 Lines | if (op == NULL && nop != NULL) { | ||||
*opp = op; | *opp = op; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Called to find/add a delegation to a client. | * Called to find/add a delegation to a client. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_deleg(mount_t mp, struct nfsclclient *clp, u_int8_t *nfhp, | nfscl_deleg(mount_t mp, struct nfsclclient *clp, u_int8_t *nfhp, | ||||
int fhlen, struct ucred *cred, NFSPROC_T *p, struct nfscldeleg **dpp) | int fhlen, struct ucred *cred, NFSPROC_T *p, struct nfscldeleg **dpp) | ||||
{ | { | ||||
struct nfscldeleg *dp = *dpp, *tdp; | struct nfscldeleg *dp = *dpp, *tdp; | ||||
/* | /* | ||||
* First, if we have received a Read delegation for a file on a | * First, if we have received a Read delegation for a file on a | ||||
* read/write file system, just return it, because they aren't | * read/write file system, just return it, because they aren't | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | nfscl_finddeleg(struct nfsclclient *clp, u_int8_t *fhp, int fhlen) | ||||
return (dp); | return (dp); | ||||
} | } | ||||
/* | /* | ||||
* Get a stateid for an I/O operation. First, look for an open and iff | * Get a stateid for an I/O operation. First, look for an open and iff | ||||
* found, return either a lockowner stateid or the open stateid. | * found, return either a lockowner stateid or the open stateid. | ||||
* If no Open is found, just return error and the special stateid of all zeros. | * If no Open is found, just return error and the special stateid of all zeros. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_getstateid(vnode_t vp, u_int8_t *nfhp, int fhlen, u_int32_t mode, | nfscl_getstateid(vnode_t vp, u_int8_t *nfhp, int fhlen, u_int32_t mode, | ||||
int fords, struct ucred *cred, NFSPROC_T *p, nfsv4stateid_t *stateidp, | int fords, struct ucred *cred, NFSPROC_T *p, nfsv4stateid_t *stateidp, | ||||
void **lckpp) | void **lckpp) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfsclowner *owp; | struct nfsclowner *owp; | ||||
struct nfsclopen *op = NULL, *top; | struct nfsclopen *op = NULL, *top; | ||||
struct nfscllockowner *lp; | struct nfscllockowner *lp; | ||||
▲ Show 20 Lines • Show All 207 Lines • ▼ Show 20 Lines | nfscl_getopen(struct nfsclownerhead *ohp, u_int8_t *nfhp, int fhlen, | ||||
*opp = rop; | *opp = rop; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Release use of an open owner. Called when open operations are done | * Release use of an open owner. Called when open operations are done | ||||
* with the open owner. | * with the open owner. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_ownerrelease(struct nfsmount *nmp, struct nfsclowner *owp, | nfscl_ownerrelease(struct nfsmount *nmp, struct nfsclowner *owp, | ||||
__unused int error, __unused int candelete, int unlocked) | __unused int error, __unused int candelete, int unlocked) | ||||
{ | { | ||||
if (owp == NULL) | if (owp == NULL) | ||||
return; | return; | ||||
NFSLOCKCLSTATE(); | NFSLOCKCLSTATE(); | ||||
if (unlocked == 0) { | if (unlocked == 0) { | ||||
if (NFSHASONEOPENOWN(nmp)) | if (NFSHASONEOPENOWN(nmp)) | ||||
nfsv4_relref(&owp->nfsow_rwlock); | nfsv4_relref(&owp->nfsow_rwlock); | ||||
else | else | ||||
nfscl_lockunlock(&owp->nfsow_rwlock); | nfscl_lockunlock(&owp->nfsow_rwlock); | ||||
} | } | ||||
nfscl_clrelease(owp->nfsow_clp); | nfscl_clrelease(owp->nfsow_clp); | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
} | } | ||||
/* | /* | ||||
* Release use of an open structure under an open owner. | * Release use of an open structure under an open owner. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_openrelease(struct nfsmount *nmp, struct nfsclopen *op, int error, | nfscl_openrelease(struct nfsmount *nmp, struct nfsclopen *op, int error, | ||||
int candelete) | int candelete) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfsclowner *owp; | struct nfsclowner *owp; | ||||
if (op == NULL) | if (op == NULL) | ||||
return; | return; | ||||
Show All 17 Lines | |||||
* count on it. | * count on it. | ||||
* If the "cred" argument is NULL, a new clientid should not be created. | * If the "cred" argument is NULL, a new clientid should not be created. | ||||
* If the "p" argument is NULL, a SetClientID/SetClientIDConfirm cannot | * If the "p" argument is NULL, a SetClientID/SetClientIDConfirm cannot | ||||
* be done. | * be done. | ||||
* The start_renewthread argument tells nfscl_getcl() to start a renew | * The start_renewthread argument tells nfscl_getcl() to start a renew | ||||
* thread if this creates a new clp. | * thread if this creates a new clp. | ||||
* It always clpp with a reference count on it, unless returning an error. | * It always clpp with a reference count on it, unless returning an error. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_getcl(struct mount *mp, struct ucred *cred, NFSPROC_T *p, | nfscl_getcl(struct mount *mp, struct ucred *cred, NFSPROC_T *p, | ||||
int start_renewthread, struct nfsclclient **clpp) | int start_renewthread, struct nfsclclient **clpp) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfsclclient *newclp = NULL; | struct nfsclclient *newclp = NULL; | ||||
struct nfsmount *nmp; | struct nfsmount *nmp; | ||||
char uuid[HOSTUUIDLEN]; | char uuid[HOSTUUIDLEN]; | ||||
int igotlock = 0, error, trystalecnt, clidinusedelay, i; | int igotlock = 0, error, trystalecnt, clidinusedelay, i; | ||||
▲ Show 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | nfscl_getcl(struct mount *mp, struct ucred *cred, NFSPROC_T *p, | ||||
*clpp = clp; | *clpp = clp; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Get a reference to a clientid and return it, if valid. | * Get a reference to a clientid and return it, if valid. | ||||
*/ | */ | ||||
APPLESTATIC struct nfsclclient * | struct nfsclclient * | ||||
nfscl_findcl(struct nfsmount *nmp) | nfscl_findcl(struct nfsmount *nmp) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
clp = nmp->nm_clp; | clp = nmp->nm_clp; | ||||
if (clp == NULL || !(clp->nfsc_flags & NFSCLFLAGS_HASCLIENTID)) | if (clp == NULL || !(clp->nfsc_flags & NFSCLFLAGS_HASCLIENTID)) | ||||
return (NULL); | return (NULL); | ||||
return (clp); | return (clp); | ||||
Show All 10 Lines | if (clp->nfsc_lock.nfslock_lock & NFSV4LOCK_LOCK) | ||||
nfsv4_unlock(&clp->nfsc_lock, 0); | nfsv4_unlock(&clp->nfsc_lock, 0); | ||||
else | else | ||||
nfsv4_relref(&clp->nfsc_lock); | nfsv4_relref(&clp->nfsc_lock); | ||||
} | } | ||||
/* | /* | ||||
* External call for nfscl_clrelease. | * External call for nfscl_clrelease. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_clientrelease(struct nfsclclient *clp) | nfscl_clientrelease(struct nfsclclient *clp) | ||||
{ | { | ||||
NFSLOCKCLSTATE(); | NFSLOCKCLSTATE(); | ||||
if (clp->nfsc_lock.nfslock_lock & NFSV4LOCK_LOCK) | if (clp->nfsc_lock.nfslock_lock & NFSV4LOCK_LOCK) | ||||
nfsv4_unlock(&clp->nfsc_lock, 0); | nfsv4_unlock(&clp->nfsc_lock, 0); | ||||
else | else | ||||
nfsv4_relref(&clp->nfsc_lock); | nfsv4_relref(&clp->nfsc_lock); | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
} | } | ||||
/* | /* | ||||
* Called when wanting to lock a byte region. | * Called when wanting to lock a byte region. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_getbytelock(vnode_t vp, u_int64_t off, u_int64_t len, | nfscl_getbytelock(vnode_t vp, u_int64_t off, u_int64_t len, | ||||
short type, struct ucred *cred, NFSPROC_T *p, struct nfsclclient *rclp, | short type, struct ucred *cred, NFSPROC_T *p, struct nfsclclient *rclp, | ||||
int recovery, void *id, int flags, u_int8_t *rownp, u_int8_t *ropenownp, | int recovery, void *id, int flags, u_int8_t *rownp, u_int8_t *ropenownp, | ||||
struct nfscllockowner **lpp, int *newonep, int *donelocallyp) | struct nfscllockowner **lpp, int *newonep, int *donelocallyp) | ||||
{ | { | ||||
struct nfscllockowner *lp; | struct nfscllockowner *lp; | ||||
struct nfsclopen *op; | struct nfsclopen *op; | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
▲ Show 20 Lines • Show All 183 Lines • ▼ Show 20 Lines | nfscl_getbytelock(vnode_t vp, u_int64_t off, u_int64_t len, | ||||
*lpp = lp; | *lpp = lp; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Called to unlock a byte range, for LockU. | * Called to unlock a byte range, for LockU. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_relbytelock(vnode_t vp, u_int64_t off, u_int64_t len, | nfscl_relbytelock(vnode_t vp, u_int64_t off, u_int64_t len, | ||||
__unused struct ucred *cred, NFSPROC_T *p, int callcnt, | __unused struct ucred *cred, NFSPROC_T *p, int callcnt, | ||||
struct nfsclclient *clp, void *id, int flags, | struct nfsclclient *clp, void *id, int flags, | ||||
struct nfscllockowner **lpp, int *dorpcp) | struct nfscllockowner **lpp, int *dorpcp) | ||||
{ | { | ||||
struct nfscllockowner *lp; | struct nfscllockowner *lp; | ||||
struct nfsclowner *owp; | struct nfsclowner *owp; | ||||
struct nfsclopen *op; | struct nfsclopen *op; | ||||
▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | nfscl_relbytelock(vnode_t vp, u_int64_t off, u_int64_t len, | ||||
if (other_lop) | if (other_lop) | ||||
free(other_lop, M_NFSCLLOCK); | free(other_lop, M_NFSCLLOCK); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Release all lockowners marked in progess for this process and file. | * Release all lockowners marked in progess for this process and file. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_releasealllocks(struct nfsclclient *clp, vnode_t vp, NFSPROC_T *p, | nfscl_releasealllocks(struct nfsclclient *clp, vnode_t vp, NFSPROC_T *p, | ||||
void *id, int flags) | void *id, int flags) | ||||
{ | { | ||||
struct nfsclowner *owp; | struct nfsclowner *owp; | ||||
struct nfsclopen *op; | struct nfsclopen *op; | ||||
struct nfscllockowner *lp; | struct nfscllockowner *lp; | ||||
struct nfsnode *np; | struct nfsnode *np; | ||||
u_int8_t own[NFSV4CL_LOCKNAMELEN]; | u_int8_t own[NFSV4CL_LOCKNAMELEN]; | ||||
Show All 21 Lines | |||||
} | } | ||||
/* | /* | ||||
* Called to find out if any bytes within the byte range specified are | * Called to find out if any bytes within the byte range specified are | ||||
* write locked by the calling process. Used to determine if flushing | * write locked by the calling process. Used to determine if flushing | ||||
* is required before a LockU. | * is required before a LockU. | ||||
* If in doubt, return 1, so the flush will occur. | * If in doubt, return 1, so the flush will occur. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_checkwritelocked(vnode_t vp, struct flock *fl, | nfscl_checkwritelocked(vnode_t vp, struct flock *fl, | ||||
struct ucred *cred, NFSPROC_T *p, void *id, int flags) | struct ucred *cred, NFSPROC_T *p, void *id, int flags) | ||||
{ | { | ||||
struct nfsclowner *owp; | struct nfsclowner *owp; | ||||
struct nfscllockowner *lp; | struct nfscllockowner *lp; | ||||
struct nfsclopen *op; | struct nfsclopen *op; | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfscllock *lop; | struct nfscllock *lop; | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | nfscl_checkwritelocked(vnode_t vp, struct flock *fl, | ||||
nfscl_clrelease(clp); | nfscl_clrelease(clp); | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Release a byte range lock owner structure. | * Release a byte range lock owner structure. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_lockrelease(struct nfscllockowner *lp, int error, int candelete) | nfscl_lockrelease(struct nfscllockowner *lp, int error, int candelete) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
if (lp == NULL) | if (lp == NULL) | ||||
return; | return; | ||||
NFSLOCKCLSTATE(); | NFSLOCKCLSTATE(); | ||||
clp = lp->nfsl_open->nfso_own->nfsow_clp; | clp = lp->nfsl_open->nfso_own->nfsow_clp; | ||||
if (error != 0 && candelete && | if (error != 0 && candelete && | ||||
(lp->nfsl_rwlock.nfslock_lock & NFSV4LOCK_WANTED) == 0) | (lp->nfsl_rwlock.nfslock_lock & NFSV4LOCK_WANTED) == 0) | ||||
nfscl_freelockowner(lp, 0); | nfscl_freelockowner(lp, 0); | ||||
else | else | ||||
nfscl_lockunlock(&lp->nfsl_rwlock); | nfscl_lockunlock(&lp->nfsl_rwlock); | ||||
nfscl_clrelease(clp); | nfscl_clrelease(clp); | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
} | } | ||||
/* | /* | ||||
* Free up an open structure and any associated byte range lock structures. | * Free up an open structure and any associated byte range lock structures. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_freeopen(struct nfsclopen *op, int local) | nfscl_freeopen(struct nfsclopen *op, int local) | ||||
{ | { | ||||
LIST_REMOVE(op, nfso_list); | LIST_REMOVE(op, nfso_list); | ||||
nfscl_freealllocks(&op->nfso_lock, local); | nfscl_freealllocks(&op->nfso_lock, local); | ||||
free(op, M_NFSCLOPEN); | free(op, M_NFSCLOPEN); | ||||
if (local) | if (local) | ||||
nfsstatsv1.cllocalopens--; | nfsstatsv1.cllocalopens--; | ||||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | if (local) | ||||
nfsstatsv1.cllocalopenowners--; | nfsstatsv1.cllocalopenowners--; | ||||
else | else | ||||
nfsstatsv1.clopenowners--; | nfsstatsv1.clopenowners--; | ||||
} | } | ||||
/* | /* | ||||
* Free up a byte range lock owner structure. | * Free up a byte range lock owner structure. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_freelockowner(struct nfscllockowner *lp, int local) | nfscl_freelockowner(struct nfscllockowner *lp, int local) | ||||
{ | { | ||||
struct nfscllock *lop, *nlop; | struct nfscllock *lop, *nlop; | ||||
LIST_REMOVE(lp, nfsl_list); | LIST_REMOVE(lp, nfsl_list); | ||||
LIST_FOREACH_SAFE(lop, &lp->nfsl_lock, nfslo_list, nlop) { | LIST_FOREACH_SAFE(lop, &lp->nfsl_lock, nfslo_list, nlop) { | ||||
nfscl_freelock(lop, local); | nfscl_freelock(lop, local); | ||||
} | } | ||||
free(lp, M_NFSCLLOCKOWNER); | free(lp, M_NFSCLLOCKOWNER); | ||||
if (local) | if (local) | ||||
nfsstatsv1.cllocallockowners--; | nfsstatsv1.cllocallockowners--; | ||||
else | else | ||||
nfsstatsv1.cllockowners--; | nfsstatsv1.cllockowners--; | ||||
} | } | ||||
/* | /* | ||||
* Free up a byte range lock structure. | * Free up a byte range lock structure. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_freelock(struct nfscllock *lop, int local) | nfscl_freelock(struct nfscllock *lop, int local) | ||||
{ | { | ||||
LIST_REMOVE(lop, nfslo_list); | LIST_REMOVE(lop, nfslo_list); | ||||
free(lop, M_NFSCLLOCK); | free(lop, M_NFSCLLOCK); | ||||
if (local) | if (local) | ||||
nfsstatsv1.cllocallocks--; | nfsstatsv1.cllocallocks--; | ||||
else | else | ||||
▲ Show 20 Lines • Show All 290 Lines • ▼ Show 20 Lines | nfscl_emptylockowner(struct nfscllockowner *lp, | ||||
LIST_REMOVE(lp, nfsl_list); | LIST_REMOVE(lp, nfsl_list); | ||||
LIST_INSERT_HEAD(&mylfhp->nfslfh_lock, lp, nfsl_list); | LIST_INSERT_HEAD(&mylfhp->nfslfh_lock, lp, nfsl_list); | ||||
} | } | ||||
static int fake_global; /* Used to force visibility of MNTK_UNMOUNTF */ | static int fake_global; /* Used to force visibility of MNTK_UNMOUNTF */ | ||||
/* | /* | ||||
* Called from nfs umount to free up the clientid. | * Called from nfs umount to free up the clientid. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_umount(struct nfsmount *nmp, NFSPROC_T *p) | nfscl_umount(struct nfsmount *nmp, NFSPROC_T *p) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct ucred *cred; | struct ucred *cred; | ||||
int igotlock; | int igotlock; | ||||
/* | /* | ||||
* For the case that matters, this is the thread that set | * For the case that matters, this is the thread that set | ||||
▲ Show 20 Lines • Show All 403 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* This function is called when a server replies with NFSERR_EXPIRED. | * This function is called when a server replies with NFSERR_EXPIRED. | ||||
* It deletes all state for the client and does a fresh SetClientId/confirm. | * It deletes all state for the client and does a fresh SetClientId/confirm. | ||||
* XXX Someday it should post a signal to the process(es) that hold the | * XXX Someday it should post a signal to the process(es) that hold the | ||||
* state, so they know that lock state has been lost. | * state, so they know that lock state has been lost. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_hasexpired(struct nfsclclient *clp, u_int32_t clidrev, NFSPROC_T *p) | nfscl_hasexpired(struct nfsclclient *clp, u_int32_t clidrev, NFSPROC_T *p) | ||||
{ | { | ||||
struct nfsmount *nmp; | struct nfsmount *nmp; | ||||
struct ucred *cred; | struct ucred *cred; | ||||
int igotlock = 0, error, trycnt; | int igotlock = 0, error, trycnt; | ||||
/* | /* | ||||
* If the clientid has gone away or a new SetClientid has already | * If the clientid has gone away or a new SetClientid has already | ||||
▲ Show 20 Lines • Show All 211 Lines • ▼ Show 20 Lines | nfscl_updatelock(struct nfscllockowner *lp, struct nfscllock **new_lopp, | ||||
} | } | ||||
return (modified); | return (modified); | ||||
} | } | ||||
/* | /* | ||||
* This function must be run as a kernel thread. | * This function must be run as a kernel thread. | ||||
* It does Renew Ops and recovery, when required. | * It does Renew Ops and recovery, when required. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_renewthread(struct nfsclclient *clp, NFSPROC_T *p) | nfscl_renewthread(struct nfsclclient *clp, NFSPROC_T *p) | ||||
{ | { | ||||
struct nfsclowner *owp, *nowp; | struct nfsclowner *owp, *nowp; | ||||
struct nfsclopen *op; | struct nfsclopen *op; | ||||
struct nfscllockowner *lp, *nlp; | struct nfscllockowner *lp, *nlp; | ||||
struct nfscldeleghead dh; | struct nfscldeleghead dh; | ||||
struct nfscldeleg *dp, *ndp; | struct nfscldeleg *dp, *ndp; | ||||
struct ucred *cred; | struct ucred *cred; | ||||
▲ Show 20 Lines • Show All 320 Lines • ▼ Show 20 Lines | tryagain2: | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Initiate state recovery. Called when NFSERR_STALECLIENTID, | * Initiate state recovery. Called when NFSERR_STALECLIENTID, | ||||
* NFSERR_STALESTATEID or NFSERR_BADSESSION is received. | * NFSERR_STALESTATEID or NFSERR_BADSESSION is received. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_initiate_recovery(struct nfsclclient *clp) | nfscl_initiate_recovery(struct nfsclclient *clp) | ||||
{ | { | ||||
if (clp == NULL) | if (clp == NULL) | ||||
return; | return; | ||||
NFSLOCKCLSTATE(); | NFSLOCKCLSTATE(); | ||||
clp->nfsc_flags |= NFSCLFLAGS_RECOVER; | clp->nfsc_flags |= NFSCLFLAGS_RECOVER; | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
wakeup((caddr_t)clp); | wakeup((caddr_t)clp); | ||||
} | } | ||||
/* | /* | ||||
* Dump out the state stuff for debugging. | * Dump out the state stuff for debugging. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_dumpstate(struct nfsmount *nmp, int openowner, int opens, | nfscl_dumpstate(struct nfsmount *nmp, int openowner, int opens, | ||||
int lockowner, int locks) | int lockowner, int locks) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfsclowner *owp; | struct nfsclowner *owp; | ||||
struct nfsclopen *op; | struct nfsclopen *op; | ||||
struct nfscllockowner *lp; | struct nfscllockowner *lp; | ||||
struct nfscllock *lop; | struct nfscllock *lop; | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
} | } | ||||
/* | /* | ||||
* Check for duplicate open owners and opens. | * Check for duplicate open owners and opens. | ||||
* (Only used as a diagnostic aid.) | * (Only used as a diagnostic aid.) | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_dupopen(vnode_t vp, int dupopens) | nfscl_dupopen(vnode_t vp, int dupopens) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfsclowner *owp, *owp2; | struct nfsclowner *owp, *owp2; | ||||
struct nfsclopen *op, *op2; | struct nfsclopen *op, *op2; | ||||
struct nfsfh *nfhp; | struct nfsfh *nfhp; | ||||
clp = VFSTONFS(vnode_mount(vp))->nm_clp; | clp = VFSTONFS(vnode_mount(vp))->nm_clp; | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | |||||
* Opens aren't actually Close'd until VOP_INACTIVE() is performed | * Opens aren't actually Close'd until VOP_INACTIVE() is performed | ||||
* on the file's vnode. | * on the file's vnode. | ||||
* This is the safe way, since it is difficult to identify | * This is the safe way, since it is difficult to identify | ||||
* which open the close is for and I/O can be performed after the | * which open the close is for and I/O can be performed after the | ||||
* close(2) system call when a file is mmap'd. | * close(2) system call when a file is mmap'd. | ||||
* If it returns 0 for success, there will be a referenced | * If it returns 0 for success, there will be a referenced | ||||
* clp returned via clpp. | * clp returned via clpp. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_getclose(vnode_t vp, struct nfsclclient **clpp) | nfscl_getclose(vnode_t vp, struct nfsclclient **clpp) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfsclowner *owp; | struct nfsclowner *owp; | ||||
struct nfsclopen *op; | struct nfsclopen *op; | ||||
struct nfscldeleg *dp; | struct nfscldeleg *dp; | ||||
struct nfsfh *nfhp; | struct nfsfh *nfhp; | ||||
int error, notdecr; | int error, notdecr; | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | LIST_FOREACH(owp, &clp->nfsc_owner, nfsow_list) { | ||||
} | } | ||||
} | } | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
if (notdecr) | if (notdecr) | ||||
printf("nfscl: never fnd open\n"); | printf("nfscl: never fnd open\n"); | ||||
return (0); | return (0); | ||||
} | } | ||||
APPLESTATIC int | int | ||||
nfscl_doclose(vnode_t vp, struct nfsclclient **clpp, NFSPROC_T *p) | nfscl_doclose(vnode_t vp, struct nfsclclient **clpp, NFSPROC_T *p) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfsclowner *owp, *nowp; | struct nfsclowner *owp, *nowp; | ||||
struct nfsclopen *op; | struct nfsclopen *op; | ||||
struct nfscldeleg *dp; | struct nfscldeleg *dp; | ||||
struct nfsfh *nfhp; | struct nfsfh *nfhp; | ||||
struct nfsclrecalllayout *recallp; | struct nfsclrecalllayout *recallp; | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | TAILQ_FOREACH_SAFE(dp, &clp->nfsc_deleg, nfsdl_list, ndp) { | ||||
nfscl_freedeleg(&clp->nfsc_deleg, dp); | nfscl_freedeleg(&clp->nfsc_deleg, dp); | ||||
} | } | ||||
NFSFREECRED(cred); | NFSFREECRED(cred); | ||||
} | } | ||||
/* | /* | ||||
* Do a callback RPC. | * Do a callback RPC. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_docb(struct nfsrv_descript *nd, NFSPROC_T *p) | nfscl_docb(struct nfsrv_descript *nd, NFSPROC_T *p) | ||||
{ | { | ||||
int clist, gotseq_ok, i, j, k, op, rcalls; | int clist, gotseq_ok, i, j, k, op, rcalls; | ||||
u_int32_t *tl; | u_int32_t *tl; | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfscldeleg *dp = NULL; | struct nfscldeleg *dp = NULL; | ||||
int numops, taglen = -1, error = 0, trunc __unused; | int numops, taglen = -1, error = 0, trunc __unused; | ||||
u_int32_t minorvers = 0, retops = 0, *retopsp = NULL, *repp, cbident; | u_int32_t minorvers = 0, retops = 0, *retopsp = NULL, *repp, cbident; | ||||
▲ Show 20 Lines • Show All 593 Lines • ▼ Show 20 Lines | LIST_FOREACH(lp, lhp, nfsl_list) { | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Check for a local conflicting lock. | * Check for a local conflicting lock. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_lockt(vnode_t vp, struct nfsclclient *clp, u_int64_t off, | nfscl_lockt(vnode_t vp, struct nfsclclient *clp, u_int64_t off, | ||||
u_int64_t len, struct flock *fl, NFSPROC_T *p, void *id, int flags) | u_int64_t len, struct flock *fl, NFSPROC_T *p, void *id, int flags) | ||||
{ | { | ||||
struct nfscllock *lop, nlck; | struct nfscllock *lop, nlck; | ||||
struct nfscldeleg *dp; | struct nfscldeleg *dp; | ||||
struct nfsnode *np; | struct nfsnode *np; | ||||
u_int8_t own[NFSV4CL_LOCKNAMELEN]; | u_int8_t own[NFSV4CL_LOCKNAMELEN]; | ||||
int error; | int error; | ||||
▲ Show 20 Lines • Show All 424 Lines • ▼ Show 20 Lines | nfscl_trydelegreturn(struct nfscldeleg *dp, struct ucred *cred, | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Try a close against the server. Just call nfsrpc_closerpc(), | * Try a close against the server. Just call nfsrpc_closerpc(), | ||||
* retrying while NFSERR_DELAY. Also, try system credentials, if the passed in | * retrying while NFSERR_DELAY. Also, try system credentials, if the passed in | ||||
* credentials fail. | * credentials fail. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_tryclose(struct nfsclopen *op, struct ucred *cred, | nfscl_tryclose(struct nfsclopen *op, struct ucred *cred, | ||||
struct nfsmount *nmp, NFSPROC_T *p) | struct nfsmount *nmp, NFSPROC_T *p) | ||||
{ | { | ||||
struct nfsrv_descript nfsd, *nd = &nfsd; | struct nfsrv_descript nfsd, *nd = &nfsd; | ||||
int error; | int error; | ||||
do { | do { | ||||
error = nfsrpc_closerpc(nd, nmp, op, cred, p, 0); | error = nfsrpc_closerpc(nd, nmp, op, cred, p, 0); | ||||
Show All 12 Lines | nfscl_tryclose(struct nfsclopen *op, struct ucred *cred, | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Decide if a delegation on a file permits close without flushing writes | * Decide if a delegation on a file permits close without flushing writes | ||||
* to the server. This might be a big performance win in some environments. | * to the server. This might be a big performance win in some environments. | ||||
* (Not useful until the client does caching on local stable storage.) | * (Not useful until the client does caching on local stable storage.) | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_mustflush(vnode_t vp) | nfscl_mustflush(vnode_t vp) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfscldeleg *dp; | struct nfscldeleg *dp; | ||||
struct nfsnode *np; | struct nfsnode *np; | ||||
struct nfsmount *nmp; | struct nfsmount *nmp; | ||||
np = VTONFS(vp); | np = VTONFS(vp); | ||||
Show All 17 Lines | nfscl_mustflush(vnode_t vp) | ||||
} | } | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
return (1); | return (1); | ||||
} | } | ||||
/* | /* | ||||
* See if a (write) delegation exists for this file. | * See if a (write) delegation exists for this file. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_nodeleg(vnode_t vp, int writedeleg) | nfscl_nodeleg(vnode_t vp, int writedeleg) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfscldeleg *dp; | struct nfscldeleg *dp; | ||||
struct nfsnode *np; | struct nfsnode *np; | ||||
struct nfsmount *nmp; | struct nfsmount *nmp; | ||||
np = VTONFS(vp); | np = VTONFS(vp); | ||||
Show All 16 Lines | nfscl_nodeleg(vnode_t vp, int writedeleg) | ||||
} | } | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
return (1); | return (1); | ||||
} | } | ||||
/* | /* | ||||
* Look for an associated delegation that should be DelegReturned. | * Look for an associated delegation that should be DelegReturned. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_removedeleg(vnode_t vp, NFSPROC_T *p, nfsv4stateid_t *stp) | nfscl_removedeleg(vnode_t vp, NFSPROC_T *p, nfsv4stateid_t *stp) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfscldeleg *dp; | struct nfscldeleg *dp; | ||||
struct nfsclowner *owp; | struct nfsclowner *owp; | ||||
struct nfscllockowner *lp; | struct nfscllockowner *lp; | ||||
struct nfsmount *nmp; | struct nfsmount *nmp; | ||||
struct ucred *cred; | struct ucred *cred; | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | while (1) { | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
return (retcnt); | return (retcnt); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Look for associated delegation(s) that should be DelegReturned. | * Look for associated delegation(s) that should be DelegReturned. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_renamedeleg(vnode_t fvp, nfsv4stateid_t *fstp, int *gotfdp, vnode_t tvp, | nfscl_renamedeleg(vnode_t fvp, nfsv4stateid_t *fstp, int *gotfdp, vnode_t tvp, | ||||
nfsv4stateid_t *tstp, int *gottdp, NFSPROC_T *p) | nfsv4stateid_t *tstp, int *gottdp, NFSPROC_T *p) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfscldeleg *dp; | struct nfscldeleg *dp; | ||||
struct nfsclowner *owp; | struct nfsclowner *owp; | ||||
struct nfscllockowner *lp; | struct nfscllockowner *lp; | ||||
struct nfsmount *nmp; | struct nfsmount *nmp; | ||||
▲ Show 20 Lines • Show All 119 Lines • ▼ Show 20 Lines | while (1) { | ||||
return (retcnt); | return (retcnt); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Get a reference on the clientid associated with the mount point. | * Get a reference on the clientid associated with the mount point. | ||||
* Return 1 if success, 0 otherwise. | * Return 1 if success, 0 otherwise. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_getref(struct nfsmount *nmp) | nfscl_getref(struct nfsmount *nmp) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
NFSLOCKCLSTATE(); | NFSLOCKCLSTATE(); | ||||
clp = nfscl_findcl(nmp); | clp = nfscl_findcl(nmp); | ||||
if (clp == NULL) { | if (clp == NULL) { | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
return (0); | return (0); | ||||
} | } | ||||
nfsv4_getref(&clp->nfsc_lock, NULL, NFSCLSTATEMUTEXPTR, NULL); | nfsv4_getref(&clp->nfsc_lock, NULL, NFSCLSTATEMUTEXPTR, NULL); | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
return (1); | return (1); | ||||
} | } | ||||
/* | /* | ||||
* Release a reference on a clientid acquired with the above call. | * Release a reference on a clientid acquired with the above call. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_relref(struct nfsmount *nmp) | nfscl_relref(struct nfsmount *nmp) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
NFSLOCKCLSTATE(); | NFSLOCKCLSTATE(); | ||||
clp = nfscl_findcl(nmp); | clp = nfscl_findcl(nmp); | ||||
if (clp == NULL) { | if (clp == NULL) { | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
return; | return; | ||||
} | } | ||||
nfsv4_relref(&clp->nfsc_lock); | nfsv4_relref(&clp->nfsc_lock); | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
} | } | ||||
/* | /* | ||||
* Save the size attribute in the delegation, since the nfsnode | * Save the size attribute in the delegation, since the nfsnode | ||||
* is going away. | * is going away. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_reclaimnode(vnode_t vp) | nfscl_reclaimnode(vnode_t vp) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfscldeleg *dp; | struct nfscldeleg *dp; | ||||
struct nfsnode *np = VTONFS(vp); | struct nfsnode *np = VTONFS(vp); | ||||
struct nfsmount *nmp; | struct nfsmount *nmp; | ||||
nmp = VFSTONFS(vnode_mount(vp)); | nmp = VFSTONFS(vnode_mount(vp)); | ||||
Show All 10 Lines | if (dp != NULL && (dp->nfsdl_flags & NFSCLDL_WRITE)) | ||||
dp->nfsdl_size = np->n_size; | dp->nfsdl_size = np->n_size; | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
} | } | ||||
/* | /* | ||||
* Get the saved size attribute in the delegation, since it is a | * Get the saved size attribute in the delegation, since it is a | ||||
* newly allocated nfsnode. | * newly allocated nfsnode. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_newnode(vnode_t vp) | nfscl_newnode(vnode_t vp) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfscldeleg *dp; | struct nfscldeleg *dp; | ||||
struct nfsnode *np = VTONFS(vp); | struct nfsnode *np = VTONFS(vp); | ||||
struct nfsmount *nmp; | struct nfsmount *nmp; | ||||
nmp = VFSTONFS(vnode_mount(vp)); | nmp = VFSTONFS(vnode_mount(vp)); | ||||
Show All 10 Lines | if (dp != NULL && (dp->nfsdl_flags & NFSCLDL_WRITE)) | ||||
np->n_size = dp->nfsdl_size; | np->n_size = dp->nfsdl_size; | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
} | } | ||||
/* | /* | ||||
* If there is a valid write delegation for this file, set the modtime | * If there is a valid write delegation for this file, set the modtime | ||||
* to the local clock time. | * to the local clock time. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_delegmodtime(vnode_t vp) | nfscl_delegmodtime(vnode_t vp) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfscldeleg *dp; | struct nfscldeleg *dp; | ||||
struct nfsnode *np = VTONFS(vp); | struct nfsnode *np = VTONFS(vp); | ||||
struct nfsmount *nmp; | struct nfsmount *nmp; | ||||
nmp = VFSTONFS(vnode_mount(vp)); | nmp = VFSTONFS(vnode_mount(vp)); | ||||
Show All 12 Lines | nfscl_delegmodtime(vnode_t vp) | ||||
} | } | ||||
NFSUNLOCKCLSTATE(); | NFSUNLOCKCLSTATE(); | ||||
} | } | ||||
/* | /* | ||||
* If there is a valid write delegation for this file with a modtime set, | * If there is a valid write delegation for this file with a modtime set, | ||||
* put that modtime in mtime. | * put that modtime in mtime. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_deleggetmodtime(vnode_t vp, struct timespec *mtime) | nfscl_deleggetmodtime(vnode_t vp, struct timespec *mtime) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfscldeleg *dp; | struct nfscldeleg *dp; | ||||
struct nfsnode *np = VTONFS(vp); | struct nfsnode *np = VTONFS(vp); | ||||
struct nfsmount *nmp; | struct nfsmount *nmp; | ||||
nmp = VFSTONFS(vnode_mount(vp)); | nmp = VFSTONFS(vnode_mount(vp)); | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Called to find/add a layout to a client. | * Called to find/add a layout to a client. | ||||
* This function returns the layout with a refcnt (shared lock) upon | * This function returns the layout with a refcnt (shared lock) upon | ||||
* success (returns 0) or with no lock/refcnt on the layout when an | * success (returns 0) or with no lock/refcnt on the layout when an | ||||
* error is returned. | * error is returned. | ||||
* If a layout is passed in via lypp, it is locked (exclusively locked). | * If a layout is passed in via lypp, it is locked (exclusively locked). | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_layout(struct nfsmount *nmp, vnode_t vp, u_int8_t *fhp, int fhlen, | nfscl_layout(struct nfsmount *nmp, vnode_t vp, u_int8_t *fhp, int fhlen, | ||||
nfsv4stateid_t *stateidp, int layouttype, int retonclose, | nfsv4stateid_t *stateidp, int layouttype, int retonclose, | ||||
struct nfsclflayouthead *fhlp, struct nfscllayout **lypp, | struct nfsclflayouthead *fhlp, struct nfscllayout **lypp, | ||||
struct ucred *cred, NFSPROC_T *p) | struct ucred *cred, NFSPROC_T *p) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfscllayout *lyp, *tlyp; | struct nfscllayout *lyp, *tlyp; | ||||
struct nfsclflayout *flp; | struct nfsclflayout *flp; | ||||
▲ Show 20 Lines • Show All 205 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* Cancel all RPCs for this "dsp" by closing the connection. | * Cancel all RPCs for this "dsp" by closing the connection. | ||||
* Also, mark the session as defunct. | * Also, mark the session as defunct. | ||||
* If NFSCLDS_SAMECONN is set, the connection is shared with other DSs and | * If NFSCLDS_SAMECONN is set, the connection is shared with other DSs and | ||||
* cannot be shut down. | * cannot be shut down. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_cancelreqs(struct nfsclds *dsp) | nfscl_cancelreqs(struct nfsclds *dsp) | ||||
{ | { | ||||
struct __rpc_client *cl; | struct __rpc_client *cl; | ||||
static int non_event; | static int non_event; | ||||
NFSLOCKDS(dsp); | NFSLOCKDS(dsp); | ||||
if ((dsp->nfsclds_flags & (NFSCLDS_CLOSED | NFSCLDS_SAMECONN)) == 0 && | if ((dsp->nfsclds_flags & (NFSCLDS_CLOSED | NFSCLDS_SAMECONN)) == 0 && | ||||
dsp->nfsclds_sockp != NULL && | dsp->nfsclds_sockp != NULL && | ||||
▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | LIST_FOREACH_SAFE(nflp, newfhlp, nfsfl_list, tflp) { | ||||
prevflp = nflp; | prevflp = nflp; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Add this nfscldevinfo to the client, if it doesn't already exist. | * Add this nfscldevinfo to the client, if it doesn't already exist. | ||||
* This function consumes the structure pointed at by dip, if not NULL. | * This function consumes the structure pointed at by dip, if not NULL. | ||||
*/ | */ | ||||
APPLESTATIC int | int | ||||
nfscl_adddevinfo(struct nfsmount *nmp, struct nfscldevinfo *dip, int ind, | nfscl_adddevinfo(struct nfsmount *nmp, struct nfscldevinfo *dip, int ind, | ||||
struct nfsclflayout *flp) | struct nfsclflayout *flp) | ||||
{ | { | ||||
struct nfsclclient *clp; | struct nfsclclient *clp; | ||||
struct nfscldevinfo *tdip; | struct nfscldevinfo *tdip; | ||||
uint8_t *dev; | uint8_t *dev; | ||||
NFSLOCKCLSTATE(); | NFSLOCKCLSTATE(); | ||||
Show All 33 Lines | nfscl_adddevinfo(struct nfsmount *nmp, struct nfscldevinfo *dip, int ind, | ||||
if (dip == NULL) | if (dip == NULL) | ||||
return (ENODEV); | return (ENODEV); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Free up a layout structure and associated file layout structure(s). | * Free up a layout structure and associated file layout structure(s). | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_freelayout(struct nfscllayout *layp) | nfscl_freelayout(struct nfscllayout *layp) | ||||
{ | { | ||||
struct nfsclflayout *flp, *nflp; | struct nfsclflayout *flp, *nflp; | ||||
struct nfsclrecalllayout *rp, *nrp; | struct nfsclrecalllayout *rp, *nrp; | ||||
LIST_FOREACH_SAFE(flp, &layp->nfsly_flayread, nfsfl_list, nflp) { | LIST_FOREACH_SAFE(flp, &layp->nfsly_flayread, nfsfl_list, nflp) { | ||||
LIST_REMOVE(flp, nfsfl_list); | LIST_REMOVE(flp, nfsfl_list); | ||||
nfscl_freeflayout(flp); | nfscl_freeflayout(flp); | ||||
} | } | ||||
LIST_FOREACH_SAFE(flp, &layp->nfsly_flayrw, nfsfl_list, nflp) { | LIST_FOREACH_SAFE(flp, &layp->nfsly_flayrw, nfsfl_list, nflp) { | ||||
LIST_REMOVE(flp, nfsfl_list); | LIST_REMOVE(flp, nfsfl_list); | ||||
nfscl_freeflayout(flp); | nfscl_freeflayout(flp); | ||||
} | } | ||||
LIST_FOREACH_SAFE(rp, &layp->nfsly_recall, nfsrecly_list, nrp) { | LIST_FOREACH_SAFE(rp, &layp->nfsly_recall, nfsrecly_list, nrp) { | ||||
LIST_REMOVE(rp, nfsrecly_list); | LIST_REMOVE(rp, nfsrecly_list); | ||||
free(rp, M_NFSLAYRECALL); | free(rp, M_NFSLAYRECALL); | ||||
} | } | ||||
nfscl_layoutcnt--; | nfscl_layoutcnt--; | ||||
free(layp, M_NFSLAYOUT); | free(layp, M_NFSLAYOUT); | ||||
} | } | ||||
/* | /* | ||||
* Free up a file layout structure. | * Free up a file layout structure. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_freeflayout(struct nfsclflayout *flp) | nfscl_freeflayout(struct nfsclflayout *flp) | ||||
{ | { | ||||
int i, j; | int i, j; | ||||
if ((flp->nfsfl_flags & NFSFL_FILE) != 0) { | if ((flp->nfsfl_flags & NFSFL_FILE) != 0) { | ||||
for (i = 0; i < flp->nfsfl_fhcnt; i++) | for (i = 0; i < flp->nfsfl_fhcnt; i++) | ||||
free(flp->nfsfl_fh[i], M_NFSFH); | free(flp->nfsfl_fh[i], M_NFSFH); | ||||
if (flp->nfsfl_devp != NULL) | if (flp->nfsfl_devp != NULL) | ||||
flp->nfsfl_devp->nfsdi_layoutrefs--; | flp->nfsfl_devp->nfsdi_layoutrefs--; | ||||
} | } | ||||
if ((flp->nfsfl_flags & NFSFL_FLEXFILE) != 0) | if ((flp->nfsfl_flags & NFSFL_FLEXFILE) != 0) | ||||
for (i = 0; i < flp->nfsfl_mirrorcnt; i++) { | for (i = 0; i < flp->nfsfl_mirrorcnt; i++) { | ||||
for (j = 0; j < flp->nfsfl_ffm[i].fhcnt; j++) | for (j = 0; j < flp->nfsfl_ffm[i].fhcnt; j++) | ||||
free(flp->nfsfl_ffm[i].fh[j], M_NFSFH); | free(flp->nfsfl_ffm[i].fh[j], M_NFSFH); | ||||
if (flp->nfsfl_ffm[i].devp != NULL) | if (flp->nfsfl_ffm[i].devp != NULL) | ||||
flp->nfsfl_ffm[i].devp->nfsdi_layoutrefs--; | flp->nfsfl_ffm[i].devp->nfsdi_layoutrefs--; | ||||
} | } | ||||
free(flp, M_NFSFLAYOUT); | free(flp, M_NFSFLAYOUT); | ||||
} | } | ||||
/* | /* | ||||
* Free up a file layout devinfo structure. | * Free up a file layout devinfo structure. | ||||
*/ | */ | ||||
APPLESTATIC void | void | ||||
nfscl_freedevinfo(struct nfscldevinfo *dip) | nfscl_freedevinfo(struct nfscldevinfo *dip) | ||||
{ | { | ||||
free(dip, M_NFSDEVINFO); | free(dip, M_NFSDEVINFO); | ||||
} | } | ||||
/* | /* | ||||
* Mark any layouts that match as recalled. | * Mark any layouts that match as recalled. | ||||
▲ Show 20 Lines • Show All 198 Lines • Show Last 20 Lines |