From 861cdf82de9f7fbaa28e87c5f26e97ddc30f3f9a Mon Sep 17 00:00:00 2001 From: Andrew Deason Date: Fri, 19 Feb 2010 17:04:29 -0600 Subject: [PATCH] Add FSYNC_VerifyCheckout Add the function FSYNC_VerifyCheckout, which can be used to verify that a previous checkout of a volume is still known by the fileserver, and hasn't been forgotten about (by e.g. the fileserver restarting). Change-Id: Ie3ec63d155fe16ca4929b370bbe55850075cec83 Reviewed-on: http://gerrit.openafs.org/1404 Tested-by: Andrew Deason Reviewed-by: Derrick Brashear --- src/vol/fssync-client.c | 93 +++++++++++++++++++++++++++++++++++++++++ src/vol/fssync.h | 3 ++ 2 files changed, 96 insertions(+) diff --git a/src/vol/fssync-client.c b/src/vol/fssync-client.c index 0520c0018..4fa64486c 100644 --- a/src/vol/fssync-client.c +++ b/src/vol/fssync-client.c @@ -208,6 +208,99 @@ FSYNC_VolOp(VolumeId volume, char * partition, return FSYNC_GenericOp(&vcom, sizeof(vcom), command, reason, res); } +/** + * verify that the fileserver still thinks we have a volume checked out. + * + * In DAFS, a non-fileserver program accesses a volume by checking it out from + * the fileserver (FSYNC_VOL_OFF or FSYNC_VOL_NEEDVOLUME), and then locks the + * volume. There is a possibility that the fileserver crashes or restarts for + * some reason between volume checkout and locking; if this happens, the + * fileserver could attach the volume before we had a chance to lock it. This + * function serves to detect if this has happened; it must be called after + * volume checkout and locking to make sure the fileserver still thinks we + * have the volume. (If it doesn't, we should try to check it out again.) + * + * @param[in] volume volume ID + * @param[in] partition partition name string + * @param[in] command the command that was used to checkout the volume + * @param[in] reason the reason code used to checkout the volume + * + * @return operation status + * @retval SYNC_OK the fileserver could not have attached the volume since + * it was checked out (either it thinks it is still checked + * out, or it doesn't know about the volume) + * @retval SYNC_DENIED fileserver may have restarted since checkout; checkout + * should be reattempted + * @retval SYNC_COM_ERROR internal/fatal error + */ +afs_int32 +FSYNC_VerifyCheckout(VolumeId volume, char * partition, + afs_int32 command, afs_int32 reason) +{ + SYNC_response res; + FSSYNC_VolOp_info vop; + afs_int32 code; + afs_int32 pid; + + res.hdr.response_len = sizeof(res.hdr); + res.payload.buf = &vop; + res.payload.len = sizeof(vop); + + code = FSYNC_VolOp(volume, partition, FSYNC_VOL_QUERY_VOP, FSYNC_WHATEVER, &res); + if (code != SYNC_OK) { + if (res.hdr.reason == FSYNC_NO_PENDING_VOL_OP) { + Log("FSYNC_VerifyCheckout: fileserver claims no vop for vol %lu " + "part %s; fileserver may have restarted since checkout\n", + afs_printable_uint32_lu(volume), partition); + return SYNC_DENIED; + } + + if (res.hdr.reason == FSYNC_UNKNOWN_VOLID) { + /* if the fileserver does not know about this volume, there's no + * way it could have attached it, so we're fine */ + return SYNC_OK; + } + + Log("FSYNC_VerifyCheckout: FSYNC_VOL_QUERY_VOP failed for vol %lu " + "part %s with code %ld reason %ld\n", + afs_printable_uint32_lu(volume), partition, + afs_printable_int32_ld(code), + afs_printable_int32_ld(res.hdr.reason)); + return SYNC_COM_ERROR; + } + + pid = getpid(); + + /* Check if the current vol op is us. Checking pid is probably enough, but + * be a little bit paranoid. We could also probably check tid, but I'm not + * completely confident of its reliability on all platforms (on pthread + * envs, we coerce a pthread_t to an afs_int32, which is not guaranteed + * to mean anything significant). */ + + if (vop.com.programType == programType && vop.com.pid == pid && + vop.com.command == command && vop.com.reason == reason) { + + /* looks like the current pending vol op is the same one as the one + * with which we checked it out. success. */ + return SYNC_OK; + } + + Log("FSYNC_VerifyCheckout: vop for vol %lu part %s does not match " + "expectations (got pt %ld pid %ld cmd %ld reason %ld, but expected " + "pt %ld pid %ld cmd %ld reason %ld); fileserver may have restarted " + "since checkout\n", afs_printable_uint32_lu(volume), partition, + afs_printable_int32_ld(vop.com.programType), + afs_printable_int32_ld(vop.com.pid), + afs_printable_int32_ld(vop.com.command), + afs_printable_int32_ld(vop.com.reason), + afs_printable_int32_ld(programType), + afs_printable_int32_ld(pid), + afs_printable_int32_ld(command), + afs_printable_int32_ld(reason)); + + return SYNC_DENIED; +} + afs_int32 FSYNC_StatsOp(FSSYNC_StatsOp_hdr * scom, int command, int reason, SYNC_response * res) diff --git a/src/vol/fssync.h b/src/vol/fssync.h index 9e49a5b58..638c743f6 100644 --- a/src/vol/fssync.h +++ b/src/vol/fssync.h @@ -226,4 +226,7 @@ extern afs_int32 FSYNC_VGCDel(char *part, VolumeId parent, VolumeId child, int reason, SYNC_response *res); extern afs_int32 FSYNC_VGCScan(char *part, int reason); +extern afs_int32 FSYNC_VerifyCheckout(VolumeId volume, char *partition, + afs_int32 command, afs_int32 reason); + #endif /* __fssync_h_ */ -- 2.39.5