#include "volume.h"
#include "partition.h"
-#ifdef AFS_DEMAND_ATTACH_FS
+#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
# include "lock.h"
#endif
+#ifdef AFS_PTHREAD_ENV
+/**
+ * @param[in] cv cond var
+ * @param[in] ts deadline, or NULL to wait forever
+ * @param[out] timedout set to 1 if we returned due to the deadline, 0 if we
+ * returned due to the cond var getting signalled. If
+ * NULL, it is ignored.
+ */
+static_inline void
+VOL_CV_TIMEDWAIT(pthread_cond_t *cv, const struct timespec *ts, int *timedout)
+{
+ int code;
+ if (timedout) {
+ *timedout = 0;
+ }
+ if (!ts) {
+ VOL_CV_WAIT(cv);
+ return;
+ }
+ VOL_LOCK_DBG_CV_WAIT_BEGIN;
+ code = CV_TIMEDWAIT(cv, &vol_glock_mutex, ts);
+ VOL_LOCK_DBG_CV_WAIT_END;
+ if (code == ETIMEDOUT) {
+ code = 0;
+ if (timedout) {
+ *timedout = 1;
+ }
+ }
+ osi_Assert(code == 0);
+}
+#endif /* AFS_PTHREAD_ENV */
+
/**
* tell caller whether the given program type represents a salvaging
* program.
static_inline int
VRequiresPartLock(void)
{
-#ifdef AFS_DEMAND_ATTACH_FS
+#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
return 0;
#else
switch (programType) {
default:
return 0;
}
-#endif /* AFS_DEMAND_ATTACH_FS */
+#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
}
/**
return 0;
}
-#ifdef AFS_DEMAND_ATTACH_FS
+#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
/**
* acquire a non-blocking disk lock for a particular volume id.
*
return 0;
default:
- assert(0 /* unknown checkout mode */);
+ osi_Assert(0 /* unknown checkout mode */);
return 0;
}
}
}
+#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
+
+#ifdef AFS_DEMAND_ATTACH_FS
+
+/**
+ * tells caller whether or not the volume is effectively salvaging.
+ *
+ * @param vp volume pointer
+ *
+ * @return whether volume is salvaging or not
+ * @retval 0 no, volume is not salvaging
+ * @retval 1 yes, volume is salvaging
+ *
+ * @note The volume may not actually be getting salvaged at the moment if
+ * this returns 1, but may have just been requested or scheduled to be
+ * salvaged. Callers should treat these cases as pretty much the same
+ * anyway, since we should not touch a volume that is busy salvaging or
+ * waiting to be salvaged.
+ */
+static_inline int
+VIsSalvaging(struct Volume *vp)
+{
+ /* these tests are a bit redundant, but to be safe... */
+ switch(V_attachState(vp)) {
+ case VOL_STATE_SALVAGING:
+ case VOL_STATE_SALVAGE_REQ:
+ return 1;
+ default:
+ if (vp->salvage.requested || vp->salvage.scheduled) {
+ return 1;
+ }
+ }
+ return 0;
+}
/**
* tells caller whether or not the current state requires
case VOL_STATE_VNODE_CLOSE:
case VOL_STATE_VNODE_RELEASE:
case VOL_STATE_VLRU_ADD:
+ case VOL_STATE_SCANNING_RXCALLS:
return 1;
default:
return 0;
switch (state) {
case VOL_STATE_ERROR:
case VOL_STATE_SALVAGING:
+ case VOL_STATE_SALVAGE_REQ:
return 1;
default:
return 0;
{
VolState state_save = V_attachState(vp);
- assert(vp->nWaiters || vp->nUsers);
+ osi_Assert(vp->nWaiters || vp->nUsers);
do {
VOL_CV_WAIT(&V_attachCV(vp));
} while (V_attachState(vp) == state_save);
+ osi_Assert(V_attachState(vp) != VOL_STATE_FREED);
+}
+
+/**
+ * wait for the volume to change states within a certain amount of time
+ *
+ * @param[in] vp volume object pointer
+ * @param[in] ts deadline (absolute time) or NULL to wait forever
+ *
+ * @pre VOL_LOCK held; ref held on volume
+ * @post VOL_LOCK held; volume state has changed and/or it is after the time
+ * specified in ts
+ *
+ * @note DEMAND_ATTACH_FS only
+ * @note if ts is NULL, this is identical to VWaitStateChange_r
+ */
+static_inline void
+VTimedWaitStateChange_r(Volume * vp, const struct timespec *ts, int *atimedout)
+{
+ VolState state_save;
+ int timeout;
+
+ if (atimedout) {
+ *atimedout = 0;
+ }
+
+ if (!ts) {
+ VWaitStateChange_r(vp);
+ return;
+ }
+
+ state_save = V_attachState(vp);
+
+ assert(vp->nWaiters || vp->nUsers);
+ do {
+ VOL_CV_TIMEDWAIT(&V_attachCV(vp), ts, &timeout);
+ } while (V_attachState(vp) == state_save && !timeout);
assert(V_attachState(vp) != VOL_STATE_FREED);
+
+ if (atimedout && timeout) {
+ *atimedout = 1;
+ }
}
/**
static_inline void
VWaitExclusiveState_r(Volume * vp)
{
- assert(vp->nWaiters || vp->nUsers);
+ osi_Assert(vp->nWaiters || vp->nUsers);
while (VIsExclusiveState(V_attachState(vp))) {
VOL_CV_WAIT(&V_attachCV(vp));
}
- assert(V_attachState(vp) != VOL_STATE_FREED);
+ osi_Assert(V_attachState(vp) != VOL_STATE_FREED);
}
/**
VStats.state_levels[new_state]++;
V_attachState(vp) = new_state;
- assert(pthread_cond_broadcast(&V_attachCV(vp)) == 0);
+ CV_BROADCAST(&V_attachCV(vp));
return old_state;
}
#endif /* AFS_DEMAND_ATTACH_FS */
#define VENUMCASE(en) \
- case en: \
- return #en; \
- break
+ case en: return #en
/**
* translate a ProgramType code to a string.