From: Derrick Brashear Date: Fri, 15 Apr 2011 17:45:57 +0000 (-0400) Subject: libafscp: add lock support X-Git-Tag: upstream/1.6.1.pre1^2~234 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=27b01dd436f9d6862eeb6633817ea8b9f4ec4a02;p=packages%2Fo%2Fopenafs.git libafscp: add lock support add support for locking as well as for tracking callbacks so a lock break can be detected Reviewed-on: http://gerrit.openafs.org/4476 Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear (cherry picked from commit f4ae9ef6531cb629e0bac2233d97cf8a0f3a698b) Change-Id: I2011486d6d604dbebf9f91afd7eebd50b5438e16 Reviewed-on: http://gerrit.openafs.org/5384 Tested-by: BuildBot Reviewed-by: Derrick Brashear --- diff --git a/src/libafscp/afscp.h b/src/libafscp/afscp.h index b9cc4284b..cd7fc9e57 100644 --- a/src/libafscp/afscp.h +++ b/src/libafscp/afscp.h @@ -9,6 +9,11 @@ #include #include +#ifdef AFS_NT40_ENV +/* not included elsewhere for Windows */ +#include +#endif + struct afscp_server { afsUUID id; int index; @@ -69,11 +74,18 @@ struct afscp_dircache { int buflen; char *dirbuffer; int dv; + int nwaiters; + pthread_mutex_t mtx; + pthread_cond_t cv; }; struct afscp_statent { struct afscp_venusfid me; struct AFSFetchStatus status; + int nwaiters; + int cleanup; + pthread_mutex_t mtx; + pthread_cond_t cv; }; struct afscp_openfile { @@ -112,6 +124,12 @@ struct afscp_server *afscp_ServerByIndex(int); struct rx_connection *afscp_ServerConnection(const struct afscp_server *, int); +int afscp_CheckCallBack(const struct afscp_venusfid *fid, + const struct afscp_server *server, + afs_uint32 *expiretime); +int afscp_FindCallBack(const struct afscp_venusfid *f, + const struct afscp_server *server, + struct afscp_callback *ret); int afscp_AddCallBack(const struct afscp_server *, const struct AFSFid *, const struct AFSFetchStatus *, @@ -120,6 +138,7 @@ int afscp_RemoveCallBack(const struct afscp_server *, const struct afscp_venusfid *); int afscp_ReturnCallBacks(const struct afscp_server *); int afscp_ReturnAllCallBacks(void); +int afscp_WaitForCallback(const struct afscp_venusfid *fid, int seconds); /* file metastuff */ /* frees with free() */ @@ -146,6 +165,7 @@ int afscp_GetStatus(const struct afscp_venusfid *, struct AFSFetchStatus *); int afscp_StoreStatus(const struct afscp_venusfid *, struct AFSStoreStatus *); int afscp_CreateFile(const struct afscp_venusfid *, char *, struct AFSStoreStatus *, struct afscp_venusfid **); +int afscp_Lock(const struct afscp_venusfid *, int locktype); int afscp_MakeDir(const struct afscp_venusfid *, char *, struct AFSStoreStatus *, struct afscp_venusfid **); int afscp_Symlink(const struct afscp_venusfid *, char *, diff --git a/src/libafscp/afscp_callback.c b/src/libafscp/afscp_callback.c index 8a0403f89..08e827de5 100644 --- a/src/libafscp/afscp_callback.c +++ b/src/libafscp/afscp_callback.c @@ -102,6 +102,48 @@ init_afs_cb(void) return 0; } /* init_afs_cb */ +int +afscp_FindCallBack(const struct afscp_venusfid *f, const struct afscp_server *server, struct afscp_callback *ret) +{ + int i; + struct afscp_callback *use = NULL, *cb; + time_t now; + struct afscp_venusfid fid; + + ret = NULL; + + time(&now); + for (i = 0; i < afscp_maxcallbacks; i++) { + cb = &allcallbacks[i]; + if ((f->fid.Volume == cb->fid.Volume) && + (f->fid.Vnode == cb->fid.Vnode) && + (f->fid.Unique == cb->fid.Unique)) { + if (server && (cb->server != server)) + continue; + use = cb; + break; + } + } + if (!use) + return -1; + + if (use->cb.ExpirationTime + use->as_of < now) { + if (use->valid) { + fid.cell = afscp_CellById(use->server->cell); + memcpy(&fid.fid, &use->fid, sizeof(struct AFSFid)); + _StatInvalidate(&fid); + } + use->valid = 0; + } + + if (use->valid) + ret = use; + else + return -1; + + return 0; +} + int afscp_AddCallBack(const struct afscp_server *server, const struct AFSFid *fid, @@ -112,37 +154,36 @@ afscp_AddCallBack(const struct afscp_server *server, struct afscp_callback *use = NULL, *newlist; struct afscp_venusfid f; time_t now; - + time(&now); - + for (i = 0; i < afscp_maxcallbacks; i++) { if (allcallbacks[i].cb.ExpirationTime + allcallbacks[i].as_of < now) { - if (allcallbacks[i].valid) { - f.cell = afscp_CellById(allcallbacks[i].server->cell); - memcpy(&f.fid, &allcallbacks[i].fid, sizeof(struct AFSFid)); - _StatInvalidate(&f); - } - allcallbacks[i].valid = 0; - - } - - if (allcallbacks[i].valid == 0) - use = &allcallbacks[i]; - if ((allcallbacks[i].server == server) && - (fid->Volume == allcallbacks[i].fid.Volume) && - (fid->Vnode == allcallbacks[i].fid.Vnode) && - (fid->Unique == allcallbacks[i].fid.Unique)) { - use = &allcallbacks[i]; - break; - } + if (allcallbacks[i].valid) { + f.cell = afscp_CellById(allcallbacks[i].server->cell); + memcpy(&f.fid, &allcallbacks[i].fid, sizeof(struct AFSFid)); + _StatInvalidate(&f); + } + allcallbacks[i].valid = 0; + } + + if (allcallbacks[i].valid == 0) + use = &allcallbacks[i]; + if ((allcallbacks[i].server == server) && + (fid->Volume == allcallbacks[i].fid.Volume) && + (fid->Vnode == allcallbacks[i].fid.Vnode) && + (fid->Unique == allcallbacks[i].fid.Unique)) { + use = &allcallbacks[i]; + break; + } } if (use == NULL) { - if (afscp_maxcallbacks >= afscp_cballoced) { - if (afscp_cballoced != 0) - afscp_cballoced = afscp_cballoced * 2; - else - afscp_cballoced = 4; - newlist = realloc(allcallbacks, afscp_cballoced * + if (afscp_maxcallbacks >= afscp_cballoced) { + if (afscp_cballoced != 0) + afscp_cballoced = afscp_cballoced * 2; + else + afscp_cballoced = 4; + newlist = realloc(allcallbacks, afscp_cballoced * sizeof(struct afscp_callback)); if (newlist == NULL) { return -1; diff --git a/src/libafscp/afscp_dir.c b/src/libafscp/afscp_dir.c index f80e8ef55..9d4acdd2f 100644 --- a/src/libafscp/afscp_dir.c +++ b/src/libafscp/afscp_dir.c @@ -106,7 +106,16 @@ _DirUpdate(struct afscp_dirstream *d) d->dv = stored->dv; return 0; } + pthread_mutex_lock(&(stored->mtx)); tdelete(&key, &v->dircache, dircompare); + stored->nwaiters++; + while (stored->nwaiters > 1) { + pthread_cond_wait(&(stored->cv), &(stored->mtx)); + } + stored->nwaiters--; + pthread_cond_destroy(&(stored->cv)); + pthread_mutex_unlock(&(stored->mtx)); + pthread_mutex_destroy(&(stored->mtx)); if (d->dirbuffer != stored->dirbuffer) free(stored->dirbuffer); free(stored); @@ -144,6 +153,9 @@ _DirUpdate(struct afscp_dirstream *d) stored->buflen = d->buflen; stored->dirbuffer = d->dirbuffer; stored->dv = d->dv; + stored->nwaiters = 0; + pthread_mutex_init(&(stored->mtx), NULL); + pthread_cond_init(&(stored->cv), NULL); *(struct afscp_dircache **)cached = stored; } else { tdelete(&key, &v->dircache, dircompare); diff --git a/src/libafscp/afscp_dirops.c b/src/libafscp/afscp_dirops.c index 6f3373749..476aaa76a 100644 --- a/src/libafscp/afscp_dirops.c +++ b/src/libafscp/afscp_dirops.c @@ -32,6 +32,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "afscp.h" #include "afscp_internal.h" +#include int afscp_CreateFile(const struct afscp_venusfid *dir, char *name, @@ -186,6 +187,51 @@ afscp_Symlink(const struct afscp_venusfid *dir, char *name, } +int +afscp_Lock(const struct afscp_venusfid *fid, int locktype) +{ + int code, i, j; + struct AFSFid ff = fid->fid; + struct afscp_volume *vol; + struct AFSVolSync vs; + struct afscp_server *server; + struct rx_connection *c; + + vol = afscp_VolumeById(fid->cell, fid->fid.Volume); + if (vol == NULL) { + afscp_errno = ENOENT; + return -1; + } + code = ENOENT; + for (i = 0; i < vol->nservers; i++) { + server = afscp_ServerByIndex(vol->servers[i]); + if (server && server->naddrs > 0) { + for (j = 0; j < server->naddrs; j++) { + c = afscp_ServerConnection(server, j); + if (c == NULL) + break; + if (locktype == LockRelease) + code = RXAFS_ReleaseLock(c, &ff, &vs); + /* read, write, extend */ + else if (locktype < LockRelease) + code = RXAFS_SetLock(c, &ff, locktype, &vs); + if (code >= 0) + break; + } + } + if (code >= 0) + break; + } + if (code != 0) { + if ((code == EAGAIN) || (code == UAEWOULDBLOCK) || (code == UAEAGAIN)) + code = EWOULDBLOCK; + afscp_errno = code; + return -1; + } + return 0; +} + + int afscp_RemoveFile(const struct afscp_venusfid *dir, char *name) { diff --git a/src/libafscp/afscp_fid.c b/src/libafscp/afscp_fid.c index 812e09a09..903d1238e 100644 --- a/src/libafscp/afscp_fid.c +++ b/src/libafscp/afscp_fid.c @@ -104,6 +104,61 @@ statcompare(const void *a, const void *b) return 0; } +static void +_StatCleanup(struct afscp_statent *stored) +{ + pthread_cond_destroy(&(stored->cv)); + pthread_mutex_unlock(&(stored->mtx)); + pthread_mutex_destroy(&(stored->mtx)); + free(stored); +} + +int +afscp_WaitForCallback(const struct afscp_venusfid *fid, int seconds) +{ + void **cached; + struct afscp_volume *v; + struct afscp_statent *stored, key; + int code = 0; + + v = afscp_VolumeById(fid->cell, fid->fid.Volume); + if (v == NULL) { + return -1; + } + memmove(&key.me, fid, sizeof(*fid)); + + cached = tfind(&key, &v->statcache, statcompare); + if (cached != NULL) { + struct timeval tv; + struct timespec ts; + + stored = *(struct afscp_statent **)cached; + + if (seconds) { + gettimeofday(&tv, NULL); + ts.tv_sec = tv.tv_sec + seconds; + ts.tv_nsec = 0; + } + + pthread_mutex_lock(&(stored->mtx)); + stored->nwaiters++; + if (seconds) + code = pthread_cond_timedwait(&(stored->cv), &(stored->mtx), &ts); + else + pthread_cond_wait(&(stored->cv), &(stored->mtx)); + if ((stored->nwaiters == 1) && stored->cleanup) + _StatCleanup(stored); + else + stored->nwaiters--; + pthread_mutex_unlock(&(stored->mtx)); + } + if ((code == EINTR) || (code == ETIMEDOUT)) { + afscp_errno = code; + code = -1; + } + return code; +} + int afscp_GetStatus(const struct afscp_venusfid *fid, struct AFSFetchStatus *s) { @@ -127,10 +182,14 @@ afscp_GetStatus(const struct afscp_venusfid *fid, struct AFSFetchStatus *s) cached = tfind(&key, &v->statcache, statcompare); if (cached != NULL) { stored = *(struct afscp_statent **)cached; + pthread_mutex_lock(&(stored->mtx)); memmove(s, &stored->status, sizeof(*s)); afs_dprintf(("Stat %u.%lu.%lu.%lu returning cached result\n", fid->cell->id, fid->fid.Volume, fid->fid.Vnode, fid->fid.Unique)); + if (stored->nwaiters) + pthread_cond_broadcast(&(stored->cv)); + pthread_mutex_unlock(&(stored->mtx)); return 0; } @@ -202,11 +261,42 @@ afscp_Stat(const struct afscp_venusfid *fid, struct stat *s) return 0; } +int +afscp_CheckCallBack(const struct afscp_venusfid *fid, const struct afscp_server *server, afs_uint32 *expiretime) +{ + struct AFSFetchStatus status; + struct afscp_callback *cb = NULL; + int code; + time_t now; + + if (expiretime == NULL || fid == NULL) { + fprintf(stderr, "NULL args given to afscp_CheckCallback, cannot continue\n"); + return -1; + } + + *expiretime = 0; + + code = afscp_GetStatus(fid, &status); + if (code != 0) + return code; + + code = afscp_FindCallBack(fid, server, cb); + if (code != 0) + return code; + + if (cb) { + time(&now); + *expiretime = cb->cb.ExpirationTime + cb->as_of - now; + } + + return 0; +} + int _StatInvalidate(const struct afscp_venusfid *fid) { struct afscp_volume *v; - struct afscp_statent key; + struct afscp_statent *stored, key; void **cached; v = afscp_VolumeById(fid->cell, fid->fid.Volume); @@ -217,8 +307,16 @@ _StatInvalidate(const struct afscp_venusfid *fid) cached = tfind(&key, &v->statcache, statcompare); if (cached != NULL) { - free(*cached); + stored = *(struct afscp_statent **)cached; + pthread_mutex_lock(&(stored->mtx)); tdelete(&key, &v->statcache, statcompare); + if (stored->nwaiters) { + /* avoid blocking callback thread */ + pthread_cond_broadcast(&(stored->cv)); + stored->cleanup = 1; + } else + _StatCleanup(stored); + pthread_mutex_unlock(&(stored->mtx)); } return 0; } @@ -240,6 +338,10 @@ _StatStuff(const struct afscp_venusfid *fid, const struct AFSFetchStatus *s) if (cached != NULL) { stored = malloc(sizeof(struct afscp_statent)); if (stored != NULL) { + pthread_mutex_init(&(stored->mtx), NULL); + pthread_cond_init(&(stored->cv), NULL); + stored->nwaiters = 0; + stored->cleanup = 0; memmove(&stored->me, fid, sizeof(*fid)); memmove(&stored->status, s, sizeof(*s)); *(struct afscp_statent **)cached = stored; diff --git a/src/libafscp/afscp_server.c b/src/libafscp/afscp_server.c index 0dc52503c..6ebd22bac 100644 --- a/src/libafscp/afscp_server.c +++ b/src/libafscp/afscp_server.c @@ -250,6 +250,7 @@ _xdr_bulkaddrs(XDR * xdrs, void *objp) return xdr_bulkaddrs(xdrs, objp); } +/* takes server in host byte order */ struct afscp_server * afscp_ServerById(struct afscp_cell *thecell, afsUUID * u) { @@ -460,6 +461,7 @@ afscp_AnyServerByAddr(afs_uint32 addr) return NULL; } +/* takes server in host byte order */ struct afscp_server * afscp_ServerByIndex(int i) { diff --git a/src/venus/afsio.c b/src/venus/afsio.c index e8e2e7a3e..de4f7f944 100644 --- a/src/venus/afsio.c +++ b/src/venus/afsio.c @@ -105,6 +105,7 @@ pthread_key_t uclient_key; #endif +static int lockFile(struct cmd_syndesc *, void *); static int readFile(struct cmd_syndesc *, void *); static int writeFile(struct cmd_syndesc *, void *); static void printDatarate(void); @@ -120,6 +121,8 @@ static char pnp[AFSPATHMAX]; /* filename of this program when called */ static int verbose = 0; /* Set if -verbose option given */ static int cellGiven = 0; /* Set if -cell option given */ static int force = 0; /* Set if -force option given */ +static int readlock = 0; /* Set if -readlock option given */ +static int waittime = 0; /* Set if -waittime option given */ static int useFid = 0; /* Set if fidwrite/fidread/fidappend invoked */ static int append = 0; /* Set if append/fidappend invoked */ static struct timeval starttime, opentime, readtime, writetime; @@ -273,6 +276,10 @@ CmdProlog(struct cmd_syndesc *as, char **cellp, char **realmp, *slp = pdp->items->data; else if (strcmp(pdp->name, "-realm") == 0) *realmp = pdp->items->data; + else if (strcmp(pdp->name, "-wait") == 0) + waittime = atoi(pdp->items->data); + else if (strcmp(pdp->name, "-readlock") == 0) + readlock = 1; } } return 0; @@ -294,7 +301,49 @@ main(int argc, char **argv) assert(pthread_key_create(&uclient_key, NULL) == 0); #endif - ts = cmd_CreateSyntax("read", readFile, CMD_REQUIRED, + ts = cmd_CreateSyntax("lock", lockFile, (void *)LockWrite, + "lock a file in AFS"); + cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_REQUIRED, "AFS-filename"); + cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname"); + cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *)0); + cmd_Seek(ts, 4); + cmd_AddParm(ts, "-realm", CMD_SINGLE, CMD_OPTIONAL, "REALMNAME"); + cmd_AddParm(ts, "-waitseconds", CMD_SINGLE, CMD_OPTIONAL, "seconds to wait before giving up"); + cmd_AddParm(ts, "-readlock", CMD_FLAG, CMD_OPTIONAL, "read lock only"); + + ts = cmd_CreateSyntax("fidlock", lockFile, (void *)LockWrite, + "lock by FID a file from AFS"); + cmd_IsAdministratorCommand(ts); + cmd_AddParm(ts, "-fid", CMD_SINGLE, CMD_REQUIRED, + "volume.vnode.uniquifier"); + cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname"); + cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *)0); + cmd_Seek(ts, 4); + cmd_AddParm(ts, "-realm", CMD_SINGLE, CMD_OPTIONAL, "REALMNAME"); + cmd_AddParm(ts, "-waitseconds", CMD_SINGLE, CMD_OPTIONAL, "seconds to wait before giving up"); + cmd_AddParm(ts, "-readlock", CMD_FLAG, CMD_OPTIONAL, "read lock only"); + + ts = cmd_CreateSyntax("unlock", lockFile, (void *)LockRelease, + "unlock a file in AFS"); + cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_REQUIRED, "AFS-filename"); + cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname"); + cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *)0); + cmd_Seek(ts, 4); + cmd_AddParm(ts, "-realm", CMD_SINGLE, CMD_OPTIONAL, "REALMNAME"); + cmd_AddParm(ts, "-waitseconds", CMD_SINGLE, CMD_OPTIONAL, "seconds to wait before giving up"); + + ts = cmd_CreateSyntax("fidunlock", lockFile, (void *)LockRelease, + "unlock by FID a file from AFS"); + cmd_IsAdministratorCommand(ts); + cmd_AddParm(ts, "-fid", CMD_SINGLE, CMD_REQUIRED, + "volume.vnode.uniquifier"); + cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname"); + cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *)0); + cmd_Seek(ts, 4); + cmd_AddParm(ts, "-realm", CMD_SINGLE, CMD_OPTIONAL, "REALMNAME"); + cmd_AddParm(ts, "-waitseconds", CMD_SINGLE, CMD_OPTIONAL, "seconds to wait before giving up"); + + ts = cmd_CreateSyntax("read", readFile, NULL, "read a file from AFS"); cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_REQUIRED, "AFS-filename"); cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname"); @@ -312,7 +361,7 @@ main(int argc, char **argv) cmd_AddParm(ts, "-md5", CMD_FLAG, CMD_OPTIONAL, "calculate md5 checksum"); cmd_AddParm(ts, "-realm", CMD_SINGLE, CMD_OPTIONAL, "REALMNAME"); - ts = cmd_CreateSyntax("write", writeFile, CMD_REQUIRED, + ts = cmd_CreateSyntax("write", writeFile, NULL, "write a file into AFS"); cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_REQUIRED, "AFS-filename"); cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname"); @@ -336,14 +385,14 @@ main(int argc, char **argv) "overwrite existing file"); cmd_AddParm(ts, "-realm", CMD_SINGLE, CMD_OPTIONAL, "REALMNAME"); - ts = cmd_CreateSyntax("append", writeFile, CMD_REQUIRED, + ts = cmd_CreateSyntax("append", writeFile, NULL, "append to a file in AFS"); cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_REQUIRED, "AFS-filename"); cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cellname"); cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, (char *)0); cmd_AddParm(ts, "-realm", CMD_SINGLE, CMD_OPTIONAL, "REALMNAME"); - ts = cmd_CreateSyntax("fidappend", writeFile, CMD_REQUIRED, + ts = cmd_CreateSyntax("fidappend", writeFile, NULL, "append to a file in AFS"); cmd_IsAdministratorCommand(ts); cmd_AddParm(ts, "-vnode", CMD_SINGLE, CMD_REQUIRED, @@ -586,6 +635,87 @@ GetVenusFidByPath(char *fullPath, char *cellName, return code; } /* GetVenusFidByPath */ +static int +lockFile(struct cmd_syndesc *as, void *arock) +{ + char *fname = NULL; + char *cell = NULL; + char *realm = NULL; + afs_int32 code = 0; + struct AFSFetchStatus OutStatus; + struct afscp_venusfid *avfp = NULL; + char *buf = 0; + char ipv4_addr[16]; + int locktype = (int)(intptr_t) arock; + +#ifdef AFS_NT40_ENV + /* stdout on Windows defaults to _O_TEXT mode */ + _setmode(1, _O_BINARY); +#endif + + gettimeofday(&starttime, &Timezone); + + CmdProlog(as, &cell, &realm, &fname, NULL); + afscp_AnonymousAuth(1); + + if ((locktype == LockWrite) && readlock) + locktype = LockRead; + + if (realm != NULL) + code = afscp_SetDefaultRealm(realm); + + if (cell != NULL) + code = afscp_SetDefaultCell(cell); + + if (useFid) + code = GetVenusFidByFid(fname, cell, 0, &avfp); + else + code = GetVenusFidByPath(fname, cell, &avfp); + if (code != 0) { + afs_com_err(pnp, code, "(file not found: %s)", fname); + return code; + } + +retry: + code = afscp_GetStatus(avfp, &OutStatus); + if (code != 0) { + afs_inet_ntoa_r(avfp->cell->fsservers[0]->addrs[0], ipv4_addr); + afs_com_err(pnp, code, "(failed to get status of file %s from" + "server %s, code = %d)", fname, ipv4_addr, code); + afscp_FreeFid(avfp); + return code; + } + + if (locktype != LockRelease) { + while (OutStatus.lockCount != 0) { + code = afscp_WaitForCallback(avfp, waittime); + if ((code == -1) && (afscp_errno == ETIMEDOUT)) + break; + if ((code = afscp_GetStatus(avfp, &OutStatus)) != 0) + break; + } + } else { + if (OutStatus.lockCount == 0) { + code = -1; + } + } + + if (!code) { + code = afscp_Lock(avfp, locktype); + if ((code == -1) && (afscp_errno == EWOULDBLOCK)) + goto retry; + } + afscp_FreeFid(avfp); + + if (buf != NULL) + free(buf); + + if (code != 0) + afs_com_err(pnp, code, "(failed to change lock status: %d)", afscp_errno); + + return code; +} /* lockFile */ + static int readFile(struct cmd_syndesc *as, void *unused) { @@ -804,6 +934,7 @@ writeFile(struct cmd_syndesc *as, void *unused) gettimeofday(&starttime, &Timezone); InStatus.UnixModeBits = 0644; + InStatus.Mask = AFS_SETMODE + AFS_FSYNC; if (newvfp == NULL) { code = afscp_CreateFile(dirvfp, baseName, &InStatus, &newvfp); if (code != 0) { @@ -839,7 +970,6 @@ writeFile(struct cmd_syndesc *as, void *unused) return code; } - InStatus.Mask = AFS_SETMODE + AFS_FSYNC; if (append) { Pos = OutStatus.Length_hi; Pos = (Pos << 32) | OutStatus.Length;