mirror of
https://git.openafs.org/openafs.git
synced 2025-01-31 13:38:01 +00:00
DEVEL15-dafs-vnode-locking-20080204
LICENSE IPL10 FIXES 84778 * Vnode package concurrency model was overhauled. Unlike the old model, where concurrency was controlled via reader/writer locks, the new model uses a per-vnode finite state automata. * add several new volume states to deal with volume vnode list operations * a new FSSYNC command code was added to allow volume utilities to close out a volume operation without causing the fileserver to mount the volume * a new FSSYNC command code was added to allow volume utilities to transition a volume into a hard error state * the salvageserver has been modified to keep volume group partition path data coherent with the fileserver (like many other parts of the volume package, this code assumes all members of the group are stored on the same vice partition) * make salvageserver correctly handle volume state when a child worker process terminates abnormally * update volume pre-attachment code to deal with move volumes across partitions on the same server * add volume state sanity checks to more volume package interfaces * original vos online patch introduced a race condition; rearchitect vos online/offline to eliminate race condition, and reduce i/o load caused by operation * unify duplicate code in volserver related to servicing vos examine and vos listvol requests * add doxygen formatted comment blocks to numerous volume package elements * various updates to fssync-debug to allow dumping vnode state, and updates to deal with added volume and vnode states * several 1.5-specific fixes related to fssync and salvsync (cherry picked from commit ed25934c1fe96b143715025b49104e75dce9a361)
This commit is contained in:
parent
3c104051a2
commit
343799a424
@ -231,8 +231,6 @@ extern struct host *h_Alloc(register struct rx_connection *r_con);
|
||||
extern struct host *h_Alloc_r(register struct rx_connection *r_con);
|
||||
extern struct host *h_Lookup_r(afs_uint32 hostaddr, afs_uint16 hport,
|
||||
int *heldp);
|
||||
extern void hashInsert_r(afs_uint32 addr, afs_uint16 port,
|
||||
struct host* host);
|
||||
extern struct host *h_LookupUuid_r(afsUUID * uuidp);
|
||||
extern void h_Enumerate(int (*proc) (), char *param);
|
||||
extern void h_Enumerate_r(int (*proc) (), struct host *enumstart, char *param);
|
||||
|
@ -18,8 +18,8 @@ LIBS=${TOP_LIBDIR}/libcmd.a vlib.a ${TOP_LIBDIR}/util.a \
|
||||
|
||||
CFLAGS = ${COMMON_CFLAGS} -D${SYS_NAME} ${FSINCLUDES} ${XCFLAGS} ${ARCHFLAGS} -DFSSYNC_BUILD_SERVER -DFSSYNC_BUILD_CLIENT
|
||||
|
||||
PUBLICHEADERS=nfs.h vnode.h viceinode.h volume.h voldefs.h partition.h \
|
||||
fssync.h ihandle.h namei_ops.h salvsync.h daemon_com.h
|
||||
PUBLICHEADERS=nfs.h vnode.h viceinode.h volume.h volume_inline.h voldefs.h partition.h \
|
||||
fssync.h ihandle.h namei_ops.h salvsync.h daemon_com.h vnode_inline.h
|
||||
|
||||
VLIBOBJS=vnode.o volume.o vutil.o partition.o fssync-server.o fssync-client.o \
|
||||
clone.o nuke.o devname.o listinodes.o common.o ihandle.o purge.o \
|
||||
@ -38,8 +38,10 @@ all: gi \
|
||||
$(FS_CONV_SOL26) \
|
||||
${TOP_INCDIR}/afs/nfs.h \
|
||||
${TOP_INCDIR}/afs/vnode.h \
|
||||
${TOP_INCDIR}/afs/vnode_inline.h \
|
||||
${TOP_INCDIR}/afs/viceinode.h \
|
||||
${TOP_INCDIR}/afs/volume.h \
|
||||
${TOP_INCDIR}/afs/volume_inline.h \
|
||||
${TOP_INCDIR}/afs/voldefs.h \
|
||||
${TOP_INCDIR}/afs/partition.h \
|
||||
${TOP_INCDIR}/afs/fssync.h \
|
||||
@ -62,8 +64,10 @@ install: \
|
||||
$(install_FS_CONV_SOL26) \
|
||||
${DESTDIR}${includedir}/afs/nfs.h \
|
||||
${DESTDIR}${includedir}/afs/vnode.h \
|
||||
${DESTDIR}${includedir}/afs/vnode_inline.h \
|
||||
${DESTDIR}${includedir}/afs/viceinode.h \
|
||||
${DESTDIR}${includedir}/afs/volume.h \
|
||||
${DESTDIR}${includedir}/afs/volume_inline.h \
|
||||
${DESTDIR}${includedir}/afs/voldefs.h \
|
||||
${DESTDIR}${includedir}/afs/partition.h \
|
||||
${DESTDIR}${includedir}/afs/fssync.h \
|
||||
@ -113,12 +117,18 @@ ${DEST}/include/afs/nfs.h: nfs.h
|
||||
${DEST}/include/afs/vnode.h: vnode.h
|
||||
${INSTALL} $? $@
|
||||
|
||||
${DEST}/include/afs/vnode_inline.h: vnode_inline.h
|
||||
${INSTALL} $? $@
|
||||
|
||||
${DEST}/include/afs/viceinode.h: viceinode.h
|
||||
${INSTALL} $? $@
|
||||
|
||||
${DEST}/include/afs/volume.h: volume.h
|
||||
${INSTALL} $? $@
|
||||
|
||||
${DEST}/include/afs/volume_inline.h: volume_inline.h
|
||||
${INSTALL} $? $@
|
||||
|
||||
${DEST}/include/afs/voldefs.h: voldefs.h
|
||||
${INSTALL} $? $@
|
||||
|
||||
@ -253,6 +263,12 @@ ${DESTDIR}${includedir}/afs/vnode.h: vnode.h
|
||||
${TOP_INCDIR}/afs/vnode.h: vnode.h
|
||||
${INSTALL} $? $@
|
||||
|
||||
${DESTDIR}${includedir}/afs/vnode_inline.h: vnode_inline.h
|
||||
${INSTALL} $? $@
|
||||
|
||||
${TOP_INCDIR}/afs/vnode_inline.h: vnode_inline.h
|
||||
${INSTALL} $? $@
|
||||
|
||||
${DESTDIR}${includedir}/afs/viceinode.h: viceinode.h
|
||||
${INSTALL} $? $@
|
||||
|
||||
@ -265,6 +281,12 @@ ${DESTDIR}${includedir}/afs/volume.h: volume.h
|
||||
${TOP_INCDIR}/afs/volume.h: volume.h
|
||||
${INSTALL} $? $@
|
||||
|
||||
${DESTDIR}${includedir}/afs/volume_inline.h: volume_inline.h
|
||||
${INSTALL} $? $@
|
||||
|
||||
${TOP_INCDIR}/afs/volume_inline.h: volume_inline.h
|
||||
${INSTALL} $? $@
|
||||
|
||||
${DESTDIR}${includedir}/afs/voldefs.h: voldefs.h
|
||||
${INSTALL} $? $@
|
||||
|
||||
@ -330,8 +352,10 @@ dest: \
|
||||
$(dest_FS_CONV_SOL26) \
|
||||
${DEST}/include/afs/nfs.h \
|
||||
${DEST}/include/afs/vnode.h \
|
||||
${DEST}/include/afs/vnode_inline.h \
|
||||
${DEST}/include/afs/viceinode.h \
|
||||
${DEST}/include/afs/volume.h \
|
||||
${DEST}/include/afs/volume_inline.h \
|
||||
${DEST}/include/afs/voldefs.h \
|
||||
${DEST}/include/afs/partition.h \
|
||||
${DEST}/include/afs/fssync.h \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Sine Nomine Associates and others.
|
||||
* Copyright 2006-2008, Sine Nomine Associates and others.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This software has been released under the terms of the IBM Public
|
||||
@ -75,24 +75,77 @@ int (*V_BreakVolumeCallbacks) ();
|
||||
|
||||
#define MAX_BIND_TRIES 5 /* Number of times to retry socket bind */
|
||||
|
||||
static int SYNC_ask_internal(SYNC_client_state * state, SYNC_command * com, SYNC_response * res);
|
||||
|
||||
/* daemon com SYNC general interfaces */
|
||||
|
||||
/**
|
||||
* fill in sockaddr structure.
|
||||
*
|
||||
* @param[in] endpoint pointer to sync endpoint object
|
||||
* @param[out] addr pointer to sockaddr structure
|
||||
*
|
||||
* @post sockaddr structure populated using information from
|
||||
* endpoint structure.
|
||||
*/
|
||||
void
|
||||
SYNC_getAddr(SYNC_endpoint_t * endpoint, SYNC_sockaddr_t * addr)
|
||||
{
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
static getport(SYNC_client_state * state, struct sockaddr_un *addr);
|
||||
#else /* USE_UNIX_SOCKETS */
|
||||
static getport(SYNC_client_state * state, struct sockaddr_in *addr);
|
||||
char tbuffer[AFSDIR_PATH_MAX];
|
||||
#endif /* USE_UNIX_SOCKETS */
|
||||
|
||||
static int SYNC_ask_internal(SYNC_client_state * state, SYNC_command * com, SYNC_response * res);
|
||||
memset(addr, 0, sizeof(*addr));
|
||||
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
|
||||
endpoint->un, NULL);
|
||||
addr->sun_family = AF_UNIX;
|
||||
strncpy(addr->sun_path, tbuffer, (sizeof(struct sockaddr_un) - sizeof(short)));
|
||||
#else /* !USE_UNIX_SOCKETS */
|
||||
#ifdef STRUCT_SOCKADDR_HAS_SA_LEN
|
||||
addr->sin_len = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
addr->sin_addr.s_addr = htonl(0x7f000001);
|
||||
addr->sin_family = AF_INET; /* was localhost->h_addrtype */
|
||||
addr->sin_port = htons(endpoint->in); /* XXXX htons not _really_ neccessary */
|
||||
#endif /* !USE_UNIX_SOCKETS */
|
||||
}
|
||||
|
||||
/**
|
||||
* get a socket descriptor of the appropriate domain.
|
||||
*
|
||||
* @param[in] endpoint pointer to sync endpoint object
|
||||
*
|
||||
* @return socket descriptor
|
||||
*
|
||||
* @post socket of domain specified in endpoint structure is created and
|
||||
* returned to caller.
|
||||
*/
|
||||
int
|
||||
SYNC_getSock(SYNC_endpoint_t * endpoint)
|
||||
{
|
||||
int sd;
|
||||
assert((sd = socket(endpoint->domain, SOCK_STREAM, 0)) >= 0);
|
||||
return sd;
|
||||
}
|
||||
|
||||
/* daemon com SYNC client interface */
|
||||
|
||||
/**
|
||||
* open a client connection to a sync server
|
||||
*
|
||||
* @param[in] state pointer to sync client handle
|
||||
*
|
||||
* @return operation status
|
||||
* @retval 1 success
|
||||
*
|
||||
* @note at present, this routine aborts rather than returning an error code
|
||||
*/
|
||||
int
|
||||
SYNC_connect(SYNC_client_state * state)
|
||||
{
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
struct sockaddr_un addr;
|
||||
#else /* USE_UNIX_SOCKETS */
|
||||
struct sockaddr_in addr;
|
||||
#endif /* USE_UNIX_SOCKETS */
|
||||
SYNC_sockaddr_t addr;
|
||||
/* I can't believe the following is needed for localhost connections!! */
|
||||
static time_t backoff[] =
|
||||
{ 3, 3, 3, 5, 5, 5, 7, 15, 16, 24, 32, 40, 48, 0 };
|
||||
@ -102,8 +155,10 @@ SYNC_connect(SYNC_client_state * state)
|
||||
return 1;
|
||||
}
|
||||
|
||||
SYNC_getAddr(&state->endpoint, &addr);
|
||||
|
||||
for (;;) {
|
||||
state->fd = getport(state, &addr);
|
||||
state->fd = SYNC_getSock(&state->endpoint);
|
||||
if (connect(state->fd, (struct sockaddr *)&addr, sizeof(addr)) >= 0)
|
||||
return 1;
|
||||
if (!*timeout)
|
||||
@ -118,6 +173,14 @@ SYNC_connect(SYNC_client_state * state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* forcibly disconnect a sync client handle.
|
||||
*
|
||||
* @param[in] state pointer to sync client handle
|
||||
*
|
||||
* @retval operation status
|
||||
* @retval 0 success
|
||||
*/
|
||||
int
|
||||
SYNC_disconnect(SYNC_client_state * state)
|
||||
{
|
||||
@ -130,6 +193,14 @@ SYNC_disconnect(SYNC_client_state * state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gracefully disconnect a sync client handle.
|
||||
*
|
||||
* @param[in] state pointer to sync client handle
|
||||
*
|
||||
* @return operation status
|
||||
* @retval SYNC_OK success
|
||||
*/
|
||||
afs_int32
|
||||
SYNC_closeChannel(SYNC_client_state * state)
|
||||
{
|
||||
@ -161,6 +232,15 @@ SYNC_closeChannel(SYNC_client_state * state)
|
||||
return SYNC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* forcibly break a client connection, and then create a new connection.
|
||||
*
|
||||
* @param[in] state pointer to sync client handle
|
||||
*
|
||||
* @post old connection dropped; new connection established
|
||||
*
|
||||
* @return @see SYNC_connect()
|
||||
*/
|
||||
int
|
||||
SYNC_reconnect(SYNC_client_state * state)
|
||||
{
|
||||
@ -168,39 +248,23 @@ SYNC_reconnect(SYNC_client_state * state)
|
||||
return SYNC_connect(state);
|
||||
}
|
||||
|
||||
/* private function to fill in the sockaddr struct for us */
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
static int
|
||||
getport(SYNC_client_state * state, struct sockaddr_un *addr)
|
||||
{
|
||||
int sd;
|
||||
char tbuffer[AFSDIR_PATH_MAX];
|
||||
|
||||
strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
|
||||
"fssync.sock", NULL);
|
||||
memset(addr, 0, sizeof(*addr));
|
||||
addr->sun_family = AF_UNIX;
|
||||
strncpy(addr->sun_path, tbuffer, (sizeof(struct sockaddr_un) - sizeof(short)));
|
||||
assert((sd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
|
||||
return sd;
|
||||
}
|
||||
#else /* USE_UNIX_SOCKETS */
|
||||
static int
|
||||
getport(SYNC_client_state * state, struct sockaddr_in *addr)
|
||||
{
|
||||
int sd;
|
||||
memset(addr, 0, sizeof(*addr));
|
||||
assert((sd = socket(AF_INET, SOCK_STREAM, 0)) >= 0);
|
||||
#ifdef STRUCT_SOCKADDR_HAS_SA_LEN
|
||||
addr->sin_len = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
addr->sin_addr.s_addr = htonl(0x7f000001);
|
||||
addr->sin_family = AF_INET; /* was localhost->h_addrtype */
|
||||
addr->sin_port = htons(state->port); /* XXXX htons not _really_ neccessary */
|
||||
return sd;
|
||||
}
|
||||
#endif /* USE_UNIX_SOCKETS */
|
||||
|
||||
/**
|
||||
* send a command to a sync server and wait for a response.
|
||||
*
|
||||
* @param[in] state pointer to sync client handle
|
||||
* @param[in] com command object
|
||||
* @param[out] res response object
|
||||
*
|
||||
* @return operation status
|
||||
* @retval SYNC_OK success
|
||||
* @retval SYNC_COM_ERROR communications error
|
||||
* @retval SYNC_BAD_COMMAND server did not recognize command code
|
||||
*
|
||||
* @note this routine merely handles error processing; SYNC_ask_internal()
|
||||
* handles the low-level details of communicating with the SYNC server.
|
||||
*
|
||||
* @see SYNC_ask_internal
|
||||
*/
|
||||
afs_int32
|
||||
SYNC_ask(SYNC_client_state * state, SYNC_command * com, SYNC_response * res)
|
||||
{
|
||||
@ -253,14 +317,27 @@ SYNC_ask(SYNC_client_state * state, SYNC_command * com, SYNC_response * res)
|
||||
|
||||
if (code == SYNC_COM_ERROR) {
|
||||
Log("SYNC_ask: fatal protocol error on circuit '%s'; disabling sync "
|
||||
"protocol to server running on port %d until next server restart\n",
|
||||
state->proto_name, state->port);
|
||||
"protocol until next server restart\n",
|
||||
state->proto_name);
|
||||
state->fatal_error = 1;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* send a command to a sync server and wait for a response.
|
||||
*
|
||||
* @param[in] state pointer to sync client handle
|
||||
* @param[in] com command object
|
||||
* @param[out] res response object
|
||||
*
|
||||
* @return operation status
|
||||
* @retval SYNC_OK success
|
||||
* @retval SYNC_COM_ERROR communications error
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
static afs_int32
|
||||
SYNC_ask_internal(SYNC_client_state * state, SYNC_command * com, SYNC_response * res)
|
||||
{
|
||||
@ -386,7 +463,16 @@ SYNC_ask_internal(SYNC_client_state * state, SYNC_command * com, SYNC_response *
|
||||
* daemon com SYNC server-side interfaces
|
||||
*/
|
||||
|
||||
/* get a command */
|
||||
/**
|
||||
* receive a command structure off a sync socket.
|
||||
*
|
||||
* @param[in] fd socket descriptor
|
||||
* @param[out] com sync command object to be populated
|
||||
*
|
||||
* @return operation status
|
||||
* @retval SYNC_OK command received
|
||||
* @retval SYNC_COM_ERROR there was a socket communications error
|
||||
*/
|
||||
afs_int32
|
||||
SYNC_getCom(int fd, SYNC_command * com)
|
||||
{
|
||||
@ -450,7 +536,16 @@ SYNC_getCom(int fd, SYNC_command * com)
|
||||
return code;
|
||||
}
|
||||
|
||||
/* put a response */
|
||||
/**
|
||||
* write a response structure to a sync socket.
|
||||
*
|
||||
* @param[in] fd
|
||||
* @param[in] res
|
||||
*
|
||||
* @return operation status
|
||||
* @retval SYNC_OK
|
||||
* @retval SYNC_COM_ERROR
|
||||
*/
|
||||
afs_int32
|
||||
SYNC_putRes(int fd, SYNC_response * res)
|
||||
{
|
||||
@ -508,3 +603,58 @@ SYNC_verifyProtocolString(char * buf, size_t len)
|
||||
|
||||
return (s_len == len) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* clean up old sockets.
|
||||
*
|
||||
* @param[in] state server state object
|
||||
*
|
||||
* @post unix domain sockets are cleaned up
|
||||
*/
|
||||
void
|
||||
SYNC_cleanupSock(SYNC_server_state_t * state)
|
||||
{
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
remove(state->addr.sun_path);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* bind socket and set it to listen state.
|
||||
*
|
||||
* @param[in] state server state object
|
||||
*
|
||||
* @return operation status
|
||||
* @retval 0 success
|
||||
* @retval nonzero failure
|
||||
*
|
||||
* @post socket bound and set to listen state
|
||||
*/
|
||||
int
|
||||
SYNC_bindSock(SYNC_server_state_t * state)
|
||||
{
|
||||
int code;
|
||||
int on = 1;
|
||||
int numTries;
|
||||
|
||||
/* Reuseaddr needed because system inexplicably leaves crud lying around */
|
||||
code =
|
||||
setsockopt(state->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
|
||||
sizeof(on));
|
||||
if (code)
|
||||
Log("SYNC_bindSock: setsockopt failed with (%d)\n", errno);
|
||||
|
||||
for (numTries = 0; numTries < state->bind_retry_limit; numTries++) {
|
||||
code = bind(state->fd,
|
||||
(struct sockaddr *)&state->addr,
|
||||
sizeof(state->addr));
|
||||
if (code == 0)
|
||||
break;
|
||||
Log("SYNC_bindSock: bind failed with (%d), will sleep and retry\n",
|
||||
errno);
|
||||
sleep(5);
|
||||
}
|
||||
listen(state->fd, state->listen_depth);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Sine Nomine Associates and others.
|
||||
* Copyright 2006-2008, Sine Nomine Associates and others.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This software has been released under the terms of the IBM Public
|
||||
@ -22,8 +22,12 @@
|
||||
#define SYNC_COM_CODE_USER_BASE 65536
|
||||
#define SYNC_COM_CODE_DECL(code) (SYNC_COM_CODE_USER_BASE+(code))
|
||||
|
||||
/* general command codes */
|
||||
#define SYNC_COM_CHANNEL_CLOSE 0
|
||||
/**
|
||||
* general command codes.
|
||||
*/
|
||||
enum SYNCOpCode {
|
||||
SYNC_COM_CHANNEL_CLOSE = 0, /**< request sync channel shutdown */
|
||||
};
|
||||
|
||||
|
||||
/* SYNC protocol response codes
|
||||
@ -34,13 +38,16 @@
|
||||
#define SYNC_RES_CODE_USER_BASE 65536
|
||||
#define SYNC_RES_CODE_DECL(code) (SYNC_RES_CODE_USER_BASE+(code))
|
||||
|
||||
/* general response codes */
|
||||
#define SYNC_OK 0 /* sync call returned ok */
|
||||
#define SYNC_DENIED 1 /* sync request denied by server */
|
||||
#define SYNC_COM_ERROR 2 /* sync protocol communicaions error */
|
||||
#define SYNC_BAD_COMMAND 3 /* sync command code not implemented by server */
|
||||
#define SYNC_FAILED 4 /* sync server-side procedure failed */
|
||||
|
||||
/**
|
||||
* general response codes.
|
||||
*/
|
||||
enum SYNCReasonCode {
|
||||
SYNC_OK = 0, /**< sync call returned ok */
|
||||
SYNC_DENIED = 1, /**< sync request denied by server */
|
||||
SYNC_COM_ERROR = 2, /**< sync protocol communicaions error */
|
||||
SYNC_BAD_COMMAND = 3, /**< sync command code not implemented by server */
|
||||
SYNC_FAILED = 4, /**< sync server-side procedure failed */
|
||||
};
|
||||
|
||||
/* SYNC protocol reason codes
|
||||
*
|
||||
@ -54,6 +61,7 @@
|
||||
#define SYNC_REASON_NONE 0
|
||||
#define SYNC_REASON_MALFORMED_PACKET 1
|
||||
#define SYNC_REASON_NOMEM 2
|
||||
#define SYNC_REASON_ENCODING_ERROR 3
|
||||
|
||||
/* SYNC protocol flags
|
||||
*
|
||||
@ -76,16 +84,53 @@
|
||||
afs_int64 _##buf##_l[SYNC_PROTO_MAX_LEN/sizeof(afs_int64)]; \
|
||||
char * buf = (char *)(_##buf##_l)
|
||||
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
#include <afs/afsutil.h>
|
||||
#include <sys/un.h>
|
||||
#define SYNC_SOCK_DOMAIN AF_UNIX
|
||||
typedef struct sockaddr_un SYNC_sockaddr_t;
|
||||
#else /* USE_UNIX_SOCKETS */
|
||||
#define SYNC_SOCK_DOMAIN AF_INET
|
||||
typedef struct sockaddr_in SYNC_sockaddr_t;
|
||||
#endif /* USE_UNIX_SOCKETS */
|
||||
|
||||
/* client-side state object */
|
||||
typedef struct SYNC_client_state {
|
||||
int fd;
|
||||
afs_uint16 port;
|
||||
afs_uint32 proto_version;
|
||||
int retry_limit; /* max number of times for SYNC_ask to retry */
|
||||
afs_int32 hard_timeout; /* upper limit on time to keep trying */
|
||||
/**
|
||||
* sync server endpoint address.
|
||||
*/
|
||||
typedef struct SYNC_endpoint {
|
||||
int domain; /**< socket domain */
|
||||
afs_uint16 in; /**< localhost ipv4 tcp port number */
|
||||
char * un; /**< unix domain socket filename (not a full path) */
|
||||
} SYNC_endpoint_t;
|
||||
|
||||
#define SYNC_ENDPOINT_DECL(in_port, un_path) \
|
||||
{ SYNC_SOCK_DOMAIN, in_port, un_path }
|
||||
|
||||
|
||||
/**
|
||||
* SYNC server state structure.
|
||||
*/
|
||||
typedef struct SYNC_server_state {
|
||||
int fd; /**< listening socket descriptor */
|
||||
SYNC_endpoint_t endpoint; /**< server endpoint address */
|
||||
afs_uint32 proto_version; /**< our protocol version */
|
||||
int bind_retry_limit; /**< upper limit on times to retry socket bind() */
|
||||
int listen_depth; /**< socket listen queue depth */
|
||||
char * proto_name; /**< sync protocol associated with this conn */
|
||||
byte fatal_error; /* fatal error on this client conn */
|
||||
SYNC_sockaddr_t addr; /**< server listen socket sockaddr */
|
||||
} SYNC_server_state_t;
|
||||
|
||||
/**
|
||||
* SYNC client state structure.
|
||||
*/
|
||||
typedef struct SYNC_client_state {
|
||||
int fd; /**< client socket descriptor */
|
||||
SYNC_endpoint_t endpoint; /**< address of sync server */
|
||||
afs_uint32 proto_version; /**< our protocol version */
|
||||
int retry_limit; /**< max number of times for SYNC_ask to retry */
|
||||
afs_int32 hard_timeout; /**< upper limit on time to keep trying */
|
||||
char * proto_name; /**< sync protocol associated with this conn */
|
||||
byte fatal_error; /**< nonzer if fatal error on this client conn */
|
||||
} SYNC_client_state;
|
||||
|
||||
/* wire types */
|
||||
@ -126,6 +171,9 @@ typedef struct SYNC_response {
|
||||
afs_int32 recv_len;
|
||||
} SYNC_response;
|
||||
|
||||
/* general prototypes */
|
||||
extern int SYNC_getSock(SYNC_endpoint_t * endpoint);
|
||||
extern void SYNC_getAddr(SYNC_endpoint_t * endpoint, SYNC_sockaddr_t * addr);
|
||||
|
||||
/* client-side prototypes */
|
||||
extern afs_int32 SYNC_ask(SYNC_client_state *, SYNC_command * com, SYNC_response * res);
|
||||
@ -138,5 +186,7 @@ extern int SYNC_reconnect(SYNC_client_state *); /* do a reconnect afte
|
||||
extern int SYNC_getCom(int fd, SYNC_command * com);
|
||||
extern int SYNC_putRes(int fd, SYNC_response * res);
|
||||
extern int SYNC_verifyProtocolString(char * buf, size_t len);
|
||||
extern void SYNC_cleanupSock(SYNC_server_state_t * state);
|
||||
extern int SYNC_bindSock(SYNC_server_state_t * state);
|
||||
|
||||
#endif /* _AFS_VOL_DAEMON_COM_H */
|
||||
|
@ -6,7 +6,7 @@
|
||||
* License. For details, see the LICENSE file in the top-level source
|
||||
* directory or online at http://www.openafs.org/dl/license10.html
|
||||
*
|
||||
* Portions Copyright (c) 2006 Sine Nomine Associates
|
||||
* Portions Copyright (c) 2006,2008 Sine Nomine Associates
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -94,7 +94,7 @@ extern int LogLevel;
|
||||
|
||||
static SYNC_client_state fssync_state =
|
||||
{ -1, /* file descriptor */
|
||||
2040, /* port number */
|
||||
FSSYNC_ENDPOINT_DECL, /* server endpoint */
|
||||
FSYNC_PROTO_VERSION, /* protocol version */
|
||||
5, /* connect retry limit */
|
||||
120, /* hard timeout */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006, Sine Nomine Associates and others.
|
||||
* Copyright 2006-2008, Sine Nomine Associates and others.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This software has been released under the terms of the IBM Public
|
||||
@ -71,6 +71,8 @@ int VolumeChanged; /* hack to make dir package happy */
|
||||
|
||||
struct volop_state {
|
||||
afs_uint32 volume;
|
||||
afs_uint32 vnode;
|
||||
afs_uint32 unique;
|
||||
char partName[16];
|
||||
};
|
||||
|
||||
@ -100,7 +102,7 @@ static int VolQuery(struct cmd_syndesc * as, void * rock);
|
||||
static int VolHdrQuery(struct cmd_syndesc * as, void * rock);
|
||||
static int VolOpQuery(struct cmd_syndesc * as, void * rock);
|
||||
static int StatsQuery(struct cmd_syndesc * as, void * rock);
|
||||
|
||||
static int VnQuery(struct cmd_syndesc * as, void * rock);
|
||||
|
||||
static void print_vol_stats_general(VolPkgStats * stats);
|
||||
static void print_vol_stats_viceP(struct DiskPartitionStats * stats);
|
||||
@ -190,6 +192,14 @@ main(int argc, char **argv)
|
||||
VOLOP_PARMS_DECL(ts);
|
||||
cmd_CreateAlias(ts, "vop");
|
||||
|
||||
ts = cmd_CreateSyntax("vnode", VnQuery, NULL, "get vnode structure (FSYNC_VOL_QUERY_VNODE opcode)");
|
||||
cmd_Seek(ts, CUSTOM_PARMS_OFFSET);
|
||||
cmd_AddParm(ts, "-volumeid", CMD_SINGLE, 0, "volume id");
|
||||
cmd_AddParm(ts, "-vnodeid", CMD_SINGLE, 0, "vnode id");
|
||||
cmd_AddParm(ts, "-unique", CMD_SINGLE, 0, "uniquifier");
|
||||
cmd_AddParm(ts, "-partition", CMD_SINGLE, 0, "paritition name");
|
||||
COMMON_PARMS_DECL(ts);
|
||||
|
||||
ts = cmd_CreateSyntax("stats", StatsQuery, NULL, "see 'stats help' for more information");
|
||||
cmd_Seek(ts, CUSTOM_PARMS_OFFSET);
|
||||
cmd_AddParm(ts, "-cmd", CMD_SINGLE, 0, "subcommand");
|
||||
@ -301,20 +311,33 @@ do_volop(struct state * state, afs_int32 command, SYNC_response * res)
|
||||
VDisconnectFS();
|
||||
}
|
||||
|
||||
|
||||
#define ENUMTOSTRING(en) #en
|
||||
#define ENUMCASE(en) \
|
||||
case en: \
|
||||
return ENUMTOSTRING(en); \
|
||||
break
|
||||
|
||||
#define FLAGTOSTRING(fl) #fl
|
||||
#define FLAGCASE(bitstr, fl, str, count) \
|
||||
do { \
|
||||
if ((bitstr) & (fl)) { \
|
||||
if (count) \
|
||||
strlcat((str), " | ", sizeof(str)); \
|
||||
strlcat((str), FLAGTOSTRING(fl), sizeof(str)); \
|
||||
(count)++; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static char *
|
||||
response_code_to_string(afs_int32 response)
|
||||
{
|
||||
switch (response) {
|
||||
case SYNC_OK:
|
||||
return "SYNC_OK";
|
||||
case SYNC_DENIED:
|
||||
return "SYNC_DENIED";
|
||||
case SYNC_COM_ERROR:
|
||||
return "SYNC_COM_ERROR";
|
||||
case SYNC_BAD_COMMAND:
|
||||
return "SYNC_BAD_COMMAND";
|
||||
case SYNC_FAILED:
|
||||
return "SYNC_FAILED";
|
||||
ENUMCASE(SYNC_OK);
|
||||
ENUMCASE(SYNC_DENIED);
|
||||
ENUMCASE(SYNC_COM_ERROR);
|
||||
ENUMCASE(SYNC_BAD_COMMAND);
|
||||
ENUMCASE(SYNC_FAILED);
|
||||
default:
|
||||
return "**UNKNOWN**";
|
||||
}
|
||||
@ -324,38 +347,26 @@ static char *
|
||||
command_code_to_string(afs_int32 command)
|
||||
{
|
||||
switch (command) {
|
||||
case SYNC_COM_CHANNEL_CLOSE:
|
||||
return "SYNC_COM_CHANNEL_CLOSE";
|
||||
case FSYNC_VOL_ON:
|
||||
return "FSYNC_VOL_ON";
|
||||
case FSYNC_VOL_OFF:
|
||||
return "FSYNC_VOL_OFF";
|
||||
case FSYNC_VOL_LISTVOLUMES:
|
||||
return "FSYNC_VOL_LISTVOLUMES";
|
||||
case FSYNC_VOL_NEEDVOLUME:
|
||||
return "FSYNC_VOL_NEEDVOLUME";
|
||||
case FSYNC_VOL_MOVE:
|
||||
return "FSYNC_VOL_MOVE";
|
||||
case FSYNC_VOL_BREAKCBKS:
|
||||
return "FSYNC_VOL_BREAKCBKS";
|
||||
case FSYNC_VOL_DONE:
|
||||
return "FSYNC_VOL_DONE";
|
||||
case FSYNC_VOL_QUERY:
|
||||
return "FSYNC_VOL_QUERY";
|
||||
case FSYNC_VOL_QUERY_HDR:
|
||||
return "FSYNC_VOL_QUERY_HDR";
|
||||
case FSYNC_VOL_QUERY_VOP:
|
||||
return "FSYNC_VOL_QUERY_VOP";
|
||||
case FSYNC_VOL_STATS_GENERAL:
|
||||
return "FSYNC_VOL_STATS_GENERAL";
|
||||
case FSYNC_VOL_STATS_VICEP:
|
||||
return "FSYNC_VOL_STATS_VICEP";
|
||||
case FSYNC_VOL_STATS_HASH:
|
||||
return "FSYNC_VOL_STATS_HASH";
|
||||
case FSYNC_VOL_STATS_HDR:
|
||||
return "FSYNC_VOL_STATS_HDR";
|
||||
case FSYNC_VOL_STATS_VLRU:
|
||||
return "FSYNC_VOL_STATS_VLRU";
|
||||
ENUMCASE(SYNC_COM_CHANNEL_CLOSE);
|
||||
ENUMCASE(FSYNC_VOL_ON);
|
||||
ENUMCASE(FSYNC_VOL_OFF);
|
||||
ENUMCASE(FSYNC_VOL_LISTVOLUMES);
|
||||
ENUMCASE(FSYNC_VOL_NEEDVOLUME);
|
||||
ENUMCASE(FSYNC_VOL_MOVE);
|
||||
ENUMCASE(FSYNC_VOL_BREAKCBKS);
|
||||
ENUMCASE(FSYNC_VOL_DONE);
|
||||
ENUMCASE(FSYNC_VOL_QUERY);
|
||||
ENUMCASE(FSYNC_VOL_QUERY_HDR);
|
||||
ENUMCASE(FSYNC_VOL_QUERY_VOP);
|
||||
ENUMCASE(FSYNC_VOL_STATS_GENERAL);
|
||||
ENUMCASE(FSYNC_VOL_STATS_VICEP);
|
||||
ENUMCASE(FSYNC_VOL_STATS_HASH);
|
||||
ENUMCASE(FSYNC_VOL_STATS_HDR);
|
||||
ENUMCASE(FSYNC_VOL_STATS_VLRU);
|
||||
ENUMCASE(FSYNC_VOL_ATTACH);
|
||||
ENUMCASE(FSYNC_VOL_FORCE_ERROR);
|
||||
ENUMCASE(FSYNC_VOL_LEAVE_OFF);
|
||||
ENUMCASE(FSYNC_VOL_QUERY_VNODE);
|
||||
default:
|
||||
return "**UNKNOWN**";
|
||||
}
|
||||
@ -365,28 +376,20 @@ static char *
|
||||
reason_code_to_string(afs_int32 reason)
|
||||
{
|
||||
switch (reason) {
|
||||
case SYNC_REASON_NONE:
|
||||
return "SYNC_REASON_NONE";
|
||||
case SYNC_REASON_MALFORMED_PACKET:
|
||||
return "SYNC_REASON_MALFORMED_PACKET";
|
||||
case FSYNC_WHATEVER:
|
||||
return "FSYNC_WHATEVER";
|
||||
case FSYNC_SALVAGE:
|
||||
return "FSYNC_SALVAGE";
|
||||
case FSYNC_MOVE:
|
||||
return "FSYNC_MOVE";
|
||||
case FSYNC_OPERATOR:
|
||||
return "FSYNC_OPERATOR";
|
||||
case FSYNC_EXCLUSIVE:
|
||||
return "FSYNC_EXCLUSIVE";
|
||||
case FSYNC_UNKNOWN_VOLID:
|
||||
return "FSYNC_UNKNOWN_VOLID";
|
||||
case FSYNC_HDR_NOT_ATTACHED:
|
||||
return "FSYNC_HDR_NOT_ATTACHED";
|
||||
case FSYNC_NO_PENDING_VOL_OP:
|
||||
return "FSYNC_NO_PENDING_VOL_OP";
|
||||
case FSYNC_VOL_PKG_ERROR:
|
||||
return "FSYNC_VOL_PKG_ERROR";
|
||||
ENUMCASE(SYNC_REASON_NONE);
|
||||
ENUMCASE(SYNC_REASON_MALFORMED_PACKET);
|
||||
ENUMCASE(SYNC_REASON_NOMEM);
|
||||
ENUMCASE(SYNC_REASON_ENCODING_ERROR);
|
||||
ENUMCASE(FSYNC_WHATEVER);
|
||||
ENUMCASE(FSYNC_SALVAGE);
|
||||
ENUMCASE(FSYNC_MOVE);
|
||||
ENUMCASE(FSYNC_OPERATOR);
|
||||
ENUMCASE(FSYNC_EXCLUSIVE);
|
||||
ENUMCASE(FSYNC_UNKNOWN_VOLID);
|
||||
ENUMCASE(FSYNC_HDR_NOT_ATTACHED);
|
||||
ENUMCASE(FSYNC_NO_PENDING_VOL_OP);
|
||||
ENUMCASE(FSYNC_VOL_PKG_ERROR);
|
||||
ENUMCASE(FSYNC_UNKNOWN_VNID);
|
||||
default:
|
||||
return "**UNKNOWN**";
|
||||
}
|
||||
@ -396,16 +399,11 @@ static char *
|
||||
program_type_to_string(afs_int32 type)
|
||||
{
|
||||
switch ((ProgramType)type) {
|
||||
case fileServer:
|
||||
return "fileServer";
|
||||
case volumeUtility:
|
||||
return "volumeUtility";
|
||||
case salvager:
|
||||
return "salvager";
|
||||
case salvageServer:
|
||||
return "salvageServer";
|
||||
case debugUtility:
|
||||
return "debugUtility";
|
||||
ENUMCASE(fileServer);
|
||||
ENUMCASE(volumeUtility);
|
||||
ENUMCASE(salvager);
|
||||
ENUMCASE(salvageServer);
|
||||
ENUMCASE(debugUtility);
|
||||
default:
|
||||
return "**UNKNOWN**";
|
||||
}
|
||||
@ -507,38 +505,27 @@ static char *
|
||||
vol_state_to_string(VolState state)
|
||||
{
|
||||
switch (state) {
|
||||
case VOL_STATE_UNATTACHED:
|
||||
return "VOL_STATE_UNATTACHED";
|
||||
case VOL_STATE_PREATTACHED:
|
||||
return "VOL_STATE_PREATTACHED";
|
||||
case VOL_STATE_ATTACHING:
|
||||
return "VOL_STATE_ATTACHING";
|
||||
case VOL_STATE_ATTACHED:
|
||||
return "VOL_STATE_ATTACHED";
|
||||
case VOL_STATE_UPDATING:
|
||||
return "VOL_STATE_UPDATING";
|
||||
case VOL_STATE_GET_BITMAP:
|
||||
return "VOL_STATE_GET_BITMAP";
|
||||
case VOL_STATE_HDR_LOADING:
|
||||
return "VOL_STATE_HDR_LOADING";
|
||||
case VOL_STATE_HDR_ATTACHING:
|
||||
return "VOL_STATE_HDR_ATTACHING";
|
||||
case VOL_STATE_SHUTTING_DOWN:
|
||||
return "VOL_STATE_SHUTTING_DOWN";
|
||||
case VOL_STATE_GOING_OFFLINE:
|
||||
return "VOL_STATE_GOING_OFFLINE";
|
||||
case VOL_STATE_OFFLINING:
|
||||
return "VOL_STATE_OFFLINING";
|
||||
case VOL_STATE_DETACHING:
|
||||
return "VOL_STATE_DETACHING";
|
||||
case VOL_STATE_SALVSYNC_REQ:
|
||||
return "VOL_STATE_SALVSYNC_REQ";
|
||||
case VOL_STATE_SALVAGING:
|
||||
return "VOL_STATE_SALVAGING";
|
||||
case VOL_STATE_ERROR:
|
||||
return "VOL_STATE_ERROR";
|
||||
case VOL_STATE_FREED:
|
||||
return "VOL_STATE_FREED";
|
||||
ENUMCASE(VOL_STATE_UNATTACHED);
|
||||
ENUMCASE(VOL_STATE_PREATTACHED);
|
||||
ENUMCASE(VOL_STATE_ATTACHING);
|
||||
ENUMCASE(VOL_STATE_ATTACHED);
|
||||
ENUMCASE(VOL_STATE_UPDATING);
|
||||
ENUMCASE(VOL_STATE_GET_BITMAP);
|
||||
ENUMCASE(VOL_STATE_HDR_LOADING);
|
||||
ENUMCASE(VOL_STATE_HDR_ATTACHING);
|
||||
ENUMCASE(VOL_STATE_SHUTTING_DOWN);
|
||||
ENUMCASE(VOL_STATE_GOING_OFFLINE);
|
||||
ENUMCASE(VOL_STATE_OFFLINING);
|
||||
ENUMCASE(VOL_STATE_DETACHING);
|
||||
ENUMCASE(VOL_STATE_SALVSYNC_REQ);
|
||||
ENUMCASE(VOL_STATE_SALVAGING);
|
||||
ENUMCASE(VOL_STATE_ERROR);
|
||||
ENUMCASE(VOL_STATE_VNODE_ALLOC);
|
||||
ENUMCASE(VOL_STATE_VNODE_GET);
|
||||
ENUMCASE(VOL_STATE_VNODE_CLOSE);
|
||||
ENUMCASE(VOL_STATE_VNODE_RELEASE);
|
||||
ENUMCASE(VOL_STATE_VLRU_ADD);
|
||||
ENUMCASE(VOL_STATE_FREED);
|
||||
default:
|
||||
return "**UNKNOWN**";
|
||||
}
|
||||
@ -551,64 +538,14 @@ vol_flags_to_string(afs_uint16 flags)
|
||||
int count = 0;
|
||||
str[0]='\0';
|
||||
|
||||
if (flags & VOL_HDR_ATTACHED) {
|
||||
strlcat(str, "VOL_HDR_ATTACHED", sizeof(str));
|
||||
count++;
|
||||
}
|
||||
|
||||
if (flags & VOL_HDR_LOADED) {
|
||||
if (count) {
|
||||
strlcat(str, " | ", sizeof(str));
|
||||
}
|
||||
strlcat(str, "VOL_HDR_LOADED", sizeof(str));
|
||||
count++;
|
||||
}
|
||||
|
||||
if (flags & VOL_HDR_IN_LRU) {
|
||||
if (count) {
|
||||
strlcat(str, " | ", sizeof(str));
|
||||
}
|
||||
strlcat(str, "VOL_HDR_IN_LRU", sizeof(str));
|
||||
count++;
|
||||
}
|
||||
|
||||
if (flags & VOL_IN_HASH) {
|
||||
if (count) {
|
||||
strlcat(str, " | ", sizeof(str));
|
||||
}
|
||||
strlcat(str, "VOL_IN_HASH", sizeof(str));
|
||||
count++;
|
||||
}
|
||||
|
||||
if (flags & VOL_ON_VBYP_LIST) {
|
||||
if (count) {
|
||||
strlcat(str, " | ", sizeof(str));
|
||||
}
|
||||
strlcat(str, "VOL_ON_VBYP_LIST", sizeof(str));
|
||||
count++;
|
||||
}
|
||||
|
||||
if (flags & VOL_IS_BUSY) {
|
||||
if (count) {
|
||||
strlcat(str, " | ", sizeof(str));
|
||||
}
|
||||
strlcat(str, "VOL_IS_BUSY", sizeof(str));
|
||||
count++;
|
||||
}
|
||||
|
||||
if (flags & VOL_ON_VLRU) {
|
||||
if (count) {
|
||||
strlcat(str, " | ", sizeof(str));
|
||||
}
|
||||
strlcat(str, "VOL_ON_VLRU", sizeof(str));
|
||||
}
|
||||
|
||||
if (flags & VOL_HDR_DONTSALV) {
|
||||
if (count) {
|
||||
strlcat(str, " | ", sizeof(str));
|
||||
}
|
||||
strlcat(str, "VOL_HDR_DONTSALV", sizeof(str));
|
||||
}
|
||||
FLAGCASE(flags, VOL_HDR_ATTACHED, str, count);
|
||||
FLAGCASE(flags, VOL_HDR_LOADED, str, count);
|
||||
FLAGCASE(flags, VOL_HDR_IN_LRU, str, count);
|
||||
FLAGCASE(flags, VOL_IN_HASH, str, count);
|
||||
FLAGCASE(flags, VOL_ON_VBYP_LIST, str, count);
|
||||
FLAGCASE(flags, VOL_IS_BUSY, str, count);
|
||||
FLAGCASE(flags, VOL_ON_VLRU, str, count);
|
||||
FLAGCASE(flags, VOL_HDR_DONTSALV, str, count);
|
||||
|
||||
return str;
|
||||
}
|
||||
@ -617,22 +554,50 @@ static char *
|
||||
vlru_idx_to_string(int idx)
|
||||
{
|
||||
switch (idx) {
|
||||
case VLRU_QUEUE_NEW:
|
||||
return "VLRU_QUEUE_NEW";
|
||||
case VLRU_QUEUE_MID:
|
||||
return "VLRU_QUEUE_MID";
|
||||
case VLRU_QUEUE_OLD:
|
||||
return "VLRU_QUEUE_OLD";
|
||||
case VLRU_QUEUE_CANDIDATE:
|
||||
return "VLRU_QUEUE_CANDIDATE";
|
||||
case VLRU_QUEUE_HELD:
|
||||
return "VLRU_QUEUE_HELD";
|
||||
case VLRU_QUEUE_INVALID:
|
||||
return "VLRU_QUEUE_INVALID";
|
||||
ENUMCASE(VLRU_QUEUE_NEW);
|
||||
ENUMCASE(VLRU_QUEUE_MID);
|
||||
ENUMCASE(VLRU_QUEUE_OLD);
|
||||
ENUMCASE(VLRU_QUEUE_CANDIDATE);
|
||||
ENUMCASE(VLRU_QUEUE_HELD);
|
||||
ENUMCASE(VLRU_QUEUE_INVALID);
|
||||
default:
|
||||
return "**UNKNOWN**";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
vn_state_to_string(VnState state)
|
||||
{
|
||||
switch (state) {
|
||||
ENUMCASE(VN_STATE_INVALID);
|
||||
ENUMCASE(VN_STATE_RELEASING);
|
||||
ENUMCASE(VN_STATE_CLOSING);
|
||||
ENUMCASE(VN_STATE_ALLOC);
|
||||
ENUMCASE(VN_STATE_ONLINE);
|
||||
ENUMCASE(VN_STATE_LOAD);
|
||||
ENUMCASE(VN_STATE_EXCLUSIVE);
|
||||
ENUMCASE(VN_STATE_STORE);
|
||||
ENUMCASE(VN_STATE_READ);
|
||||
ENUMCASE(VN_STATE_ERROR);
|
||||
default:
|
||||
return "**UNKNOWN**";
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
vn_flags_to_string(afs_uint32 flags)
|
||||
{
|
||||
static char str[128];
|
||||
int count = 0;
|
||||
str[0]='\0';
|
||||
|
||||
FLAGCASE(flags, VN_ON_HASH, str, count);
|
||||
FLAGCASE(flags, VN_ON_LRU, str, count);
|
||||
FLAGCASE(flags, VN_ON_VVN, str, count);
|
||||
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
@ -737,6 +702,7 @@ VolQuery(struct cmd_syndesc * as, void * rock)
|
||||
printf("\t\tlast_get = %u\n", v.stats.last_get);
|
||||
printf("\t\tlast_promote = %u\n", v.stats.last_promote);
|
||||
printf("\t\tlast_hdr_get = %u\n", v.stats.last_hdr_get);
|
||||
printf("\t\tlast_hdr_load = %u\n", v.stats.last_hdr_load);
|
||||
printf("\t\tlast_salvage = %u\n", v.stats.last_salvage);
|
||||
printf("\t\tlast_salvage_req = %u\n", v.stats.last_salvage_req);
|
||||
printf("\t\tlast_vol_op = %u\n", v.stats.last_vol_op);
|
||||
@ -891,6 +857,177 @@ VolOpQuery(struct cmd_syndesc * as, void * rock)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
vn_prolog(struct cmd_syndesc * as, struct state * state)
|
||||
{
|
||||
register struct cmd_item *ti;
|
||||
char pname[100], *temp;
|
||||
|
||||
state->vop = (struct volop_state *) calloc(1, sizeof(struct volop_state));
|
||||
assert(state->vop != NULL);
|
||||
|
||||
if ((ti = as->parms[CUSTOM_PARMS_OFFSET].items)) { /* -volumeid */
|
||||
state->vop->volume = atoi(ti->data);
|
||||
} else {
|
||||
fprintf(stderr, "required argument -volumeid not given\n");
|
||||
}
|
||||
|
||||
if ((ti = as->parms[CUSTOM_PARMS_OFFSET+1].items)) { /* -vnodeid */
|
||||
state->vop->vnode = atoi(ti->data);
|
||||
} else {
|
||||
fprintf(stderr, "required argument -vnodeid not given\n");
|
||||
}
|
||||
|
||||
if ((ti = as->parms[CUSTOM_PARMS_OFFSET+2].items)) { /* -unique */
|
||||
state->vop->unique = atoi(ti->data);
|
||||
} else {
|
||||
state->vop->unique = 0;
|
||||
}
|
||||
|
||||
if ((ti = as->parms[COMMON_VOLOP_PARMS_OFFSET+3].items)) { /* -partition */
|
||||
strlcpy(state->vop->partName, ti->data, sizeof(state->vop->partName));
|
||||
} else {
|
||||
memset(state->vop->partName, 0, sizeof(state->vop->partName));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_vnqry(struct state * state, SYNC_response * res)
|
||||
{
|
||||
afs_int32 code;
|
||||
int command = FSYNC_VOL_QUERY_VNODE;
|
||||
FSSYNC_VnQry_hdr qry;
|
||||
|
||||
qry.volume = state->vop->volume;
|
||||
qry.vnode = state->vop->vnode;
|
||||
qry.unique = state->vop->unique;
|
||||
qry.spare = 0;
|
||||
strlcpy(qry.partName, state->vop->partName, sizeof(qry.partName));
|
||||
|
||||
fprintf(stderr, "calling FSYNC_GenericOp with command code %d (%s)\n",
|
||||
command, command_code_to_string(command));
|
||||
|
||||
code = FSYNC_GenericOp(&qry, sizeof(qry), command, FSYNC_OPERATOR, res);
|
||||
|
||||
switch (code) {
|
||||
case SYNC_OK:
|
||||
case SYNC_DENIED:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "possible sync protocol error. return code was %d\n", code);
|
||||
}
|
||||
|
||||
fprintf(stderr, "FSYNC_GenericOp returned %d (%s)\n", code, response_code_to_string(code));
|
||||
fprintf(stderr, "protocol response code was %d (%s)\n",
|
||||
res->hdr.response, response_code_to_string(res->hdr.response));
|
||||
fprintf(stderr, "protocol reason code was %d (%s)\n",
|
||||
res->hdr.reason, reason_code_to_string(res->hdr.reason));
|
||||
|
||||
VDisconnectFS();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
VnQuery(struct cmd_syndesc * as, void * rock)
|
||||
{
|
||||
struct state state;
|
||||
SYNC_PROTO_BUF_DECL(res_buf);
|
||||
SYNC_response res;
|
||||
Vnode v;
|
||||
int hi, lo;
|
||||
|
||||
res.hdr.response_len = sizeof(res.hdr);
|
||||
res.payload.buf = res_buf;
|
||||
res.payload.len = SYNC_PROTO_MAX_LEN;
|
||||
|
||||
common_prolog(as, &state);
|
||||
vn_prolog(as, &state);
|
||||
|
||||
do_vnqry(&state, &res);
|
||||
|
||||
if (res.hdr.response == SYNC_OK) {
|
||||
memcpy(&v, res.payload.buf, sizeof(Volume));
|
||||
|
||||
printf("vnode = {\n");
|
||||
|
||||
printf("\tvid_hash = {\n");
|
||||
printf("\t\tnext = 0x%lx\n", v.vid_hash.next);
|
||||
printf("\t\tprev = 0x%lx\n", v.vid_hash.prev);
|
||||
printf("\t}\n");
|
||||
|
||||
printf("\thashNext = 0x%lx\n", v.hashNext);
|
||||
printf("\tlruNext = 0x%lx\n", v.lruNext);
|
||||
printf("\tlruPrev = 0x%lx\n", v.lruPrev);
|
||||
printf("\thashIndex = %hu\n", v.hashIndex);
|
||||
printf("\tchanged_newTime = %u\n", (unsigned int) v.changed_newTime);
|
||||
printf("\tchanged_oldTime = %u\n", (unsigned int) v.changed_oldTime);
|
||||
printf("\tdelete = %u\n", (unsigned int) v.delete);
|
||||
printf("\tvnodeNumber = %u\n", v.vnodeNumber);
|
||||
printf("\tvolumePtr = 0x%lx\n", v.volumePtr);
|
||||
printf("\tnUsers = %u\n", v.nUsers);
|
||||
printf("\tcacheCheck = %u\n", v.cacheCheck);
|
||||
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
if (!(res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS)) {
|
||||
printf("*** fssync-debug built to expect demand attach extensions. server asserted\n");
|
||||
printf("*** that it was not compiled with demand attach turned on. please recompile\n");
|
||||
printf("*** fssync-debug to match your server\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
printf("\tnReaders = %u\n", v.nReaders);
|
||||
printf("\tvn_state_flags = %s\n", vn_flags_to_string(v.vn_state_flags));
|
||||
printf("\tvn_state = %s\n", vn_state_to_string(v.vn_state));
|
||||
#else
|
||||
if (res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS) {
|
||||
printf("*** server asserted demand attach extensions. fssync-debug not built to\n");
|
||||
printf("*** recognize those extensions. please recompile fssync-debug if you need\n");
|
||||
printf("*** to dump dafs extended state\n");
|
||||
goto done;
|
||||
}
|
||||
#endif /* !AFS_DEMAND_ATTACH_FS */
|
||||
|
||||
printf("\twriter = %u\n", v.writer);
|
||||
printf("\tvcp = 0x%lx\n", v.vcp);
|
||||
printf("\thandle = 0x%lx\n", v.handle);
|
||||
|
||||
printf("\tdisk = {\n");
|
||||
printf("\t\ttype = %u\n", v.disk.type);
|
||||
printf("\t\tcloned = %u\n", v.disk.cloned);
|
||||
printf("\t\tmodeBits = %u\n", v.disk.modeBits);
|
||||
printf("\t\tlinkCount = %d\n", v.disk.linkCount);
|
||||
printf("\t\tlength = %u\n", v.disk.length);
|
||||
printf("\t\tuniquifier = %u\n", v.disk.uniquifier);
|
||||
printf("\t\tdataVersion = %u\n", v.disk.dataVersion);
|
||||
printf("\t\tvn_ino_lo = %u\n", v.disk.vn_ino_lo);
|
||||
printf("\t\tunixModifyTime = %u\n", v.disk.unixModifyTime);
|
||||
printf("\t\tauthor = %u\n", v.disk.author);
|
||||
printf("\t\towner = %u\n", v.disk.owner);
|
||||
printf("\t\tparent = %u\n", v.disk.parent);
|
||||
printf("\t\tvnodeMagic = %u\n", v.disk.vnodeMagic);
|
||||
|
||||
printf("\t\tlock = {\n");
|
||||
printf("\t\t\tlockCount = %d\n", v.disk.lock.lockCount);
|
||||
printf("\t\t\tlockTime = %d\n", v.disk.lock.lockTime);
|
||||
printf("\t\t}\n");
|
||||
|
||||
printf("\t\tserverModifyTime = %u\n", v.disk.serverModifyTime);
|
||||
printf("\t\tgroup = %d\n", v.disk.group);
|
||||
printf("\t\tvn_ino_hi = %d\n", v.disk.vn_ino_hi);
|
||||
printf("\t\treserved6 = %u\n", v.disk.reserved6);
|
||||
printf("\t}\n");
|
||||
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
StatsQuery(struct cmd_syndesc * as, void * rock)
|
||||
{
|
||||
|
@ -6,7 +6,7 @@
|
||||
* License. For details, see the LICENSE file in the top-level source
|
||||
* directory or online at http://www.openafs.org/dl/license10.html
|
||||
*
|
||||
* Portions Copyright (c) 2006-2007 Sine Nomine Associates
|
||||
* Portions Copyright (c) 2006-2008 Sine Nomine Associates
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -88,6 +88,7 @@ RCSID
|
||||
#include "ihandle.h"
|
||||
#include "vnode.h"
|
||||
#include "volume.h"
|
||||
#include "volume_inline.h"
|
||||
#include "partition.h"
|
||||
|
||||
#ifdef HAVE_POLL
|
||||
@ -118,18 +119,25 @@ int (*V_BreakVolumeCallbacks) ();
|
||||
* cloned read-only copies offline when salvaging
|
||||
* a single read-write volume */
|
||||
|
||||
#define MAX_BIND_TRIES 5 /* Number of times to retry socket bind */
|
||||
|
||||
|
||||
|
||||
static struct offlineInfo OfflineVolumes[MAXHANDLERS][MAXOFFLINEVOLUMES];
|
||||
|
||||
static int AcceptSd = -1; /* Socket used by server for accepting connections */
|
||||
/**
|
||||
* fssync server socket handle.
|
||||
*/
|
||||
static SYNC_server_state_t fssync_server_state =
|
||||
{ -1, /* file descriptor */
|
||||
FSSYNC_ENDPOINT_DECL, /* server endpoint */
|
||||
FSYNC_PROTO_VERSION, /* protocol version */
|
||||
5, /* bind() retry limit */
|
||||
100, /* listen() queue depth */
|
||||
"FSSYNC", /* protocol name string */
|
||||
};
|
||||
|
||||
static int getport();
|
||||
|
||||
/* Forward declarations */
|
||||
static void FSYNC_sync();
|
||||
static void * FSYNC_sync(void *);
|
||||
static void FSYNC_newconnection();
|
||||
static void FSYNC_com();
|
||||
static void FSYNC_Drop();
|
||||
@ -151,6 +159,7 @@ extern int LogLevel;
|
||||
|
||||
static afs_int32 FSYNC_com_VolOp(int fd, SYNC_command * com, SYNC_response * res);
|
||||
|
||||
static afs_int32 FSYNC_com_VolError(FSSYNC_VolOp_command * com, SYNC_response * res);
|
||||
static afs_int32 FSYNC_com_VolOn(FSSYNC_VolOp_command * com, SYNC_response * res);
|
||||
static afs_int32 FSYNC_com_VolOff(FSSYNC_VolOp_command * com, SYNC_response * res);
|
||||
static afs_int32 FSYNC_com_VolMove(FSSYNC_VolOp_command * com, SYNC_response * res);
|
||||
@ -162,6 +171,8 @@ static afs_int32 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * com, SYNC_response
|
||||
static afs_int32 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
|
||||
#endif /* AFS_DEMAND_ATTACH_FS */
|
||||
|
||||
static afs_int32 FSYNC_com_VnQry(int fd, SYNC_command * com, SYNC_response * res);
|
||||
|
||||
static afs_int32 FSYNC_com_StatsOp(int fd, SYNC_command * com, SYNC_response * res);
|
||||
|
||||
static afs_int32 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res);
|
||||
@ -209,50 +220,12 @@ static struct pollfd FSYNC_readfds[MAXHANDLERS];
|
||||
static fd_set FSYNC_readfds;
|
||||
#endif
|
||||
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
static int
|
||||
getport(struct sockaddr_un *addr)
|
||||
{
|
||||
int sd;
|
||||
char tbuffer[AFSDIR_PATH_MAX];
|
||||
|
||||
strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
|
||||
"fssync.sock", NULL);
|
||||
|
||||
memset(addr, 0, sizeof(*addr));
|
||||
addr->sun_family = AF_UNIX;
|
||||
strncpy(addr->sun_path, tbuffer, (sizeof(struct sockaddr_un) - sizeof(short)));
|
||||
assert((sd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
|
||||
return sd;
|
||||
}
|
||||
#else
|
||||
static int
|
||||
getport(struct sockaddr_in *addr)
|
||||
{
|
||||
int sd;
|
||||
|
||||
memset(addr, 0, sizeof(*addr));
|
||||
assert((sd = socket(AF_INET, SOCK_STREAM, 0)) >= 0);
|
||||
#ifdef STRUCT_SOCKADDR_HAS_SA_LEN
|
||||
addr->sin_len = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
addr->sin_addr.s_addr = htonl(0x7f000001);
|
||||
addr->sin_family = AF_INET; /* was localhost->h_addrtype */
|
||||
addr->sin_port = htons(2040); /* XXXX htons not _really_ neccessary */
|
||||
|
||||
return sd;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
FSYNC_sync()
|
||||
static void *
|
||||
FSYNC_sync(void * args)
|
||||
{
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
struct sockaddr_un addr;
|
||||
char tbuffer[AFSDIR_PATH_MAX];
|
||||
#else /* USE_UNIX_SOCKETS */
|
||||
struct sockaddr_in addr;
|
||||
#endif /* USE_UNIX_SOCKETS */
|
||||
int on = 1;
|
||||
extern int VInit;
|
||||
@ -261,6 +234,10 @@ FSYNC_sync()
|
||||
#ifdef AFS_PTHREAD_ENV
|
||||
int tid;
|
||||
#endif
|
||||
SYNC_server_state_t * state = &fssync_server_state;
|
||||
|
||||
SYNC_getAddr(&state->endpoint, &state->addr);
|
||||
SYNC_cleanupSock(state);
|
||||
|
||||
#ifndef AFS_NT40_ENV
|
||||
(void)signal(SIGPIPE, SIG_IGN);
|
||||
@ -275,14 +252,6 @@ FSYNC_sync()
|
||||
Log("Set thread id %d for FSYNC_sync\n", tid);
|
||||
#endif /* AFS_PTHREAD_ENV */
|
||||
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
/* ignore errors */
|
||||
strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
|
||||
"fssync.sock", NULL);
|
||||
|
||||
remove(tbuffer);
|
||||
#endif /* USE_UNIX_SOCKETS */
|
||||
|
||||
while (!VInit) {
|
||||
/* Let somebody else run until level > 0. That doesn't mean that
|
||||
* all volumes have been attached. */
|
||||
@ -292,26 +261,14 @@ FSYNC_sync()
|
||||
LWP_DispatchProcess();
|
||||
#endif /* AFS_PTHREAD_ENV */
|
||||
}
|
||||
AcceptSd = getport(&addr);
|
||||
/* Reuseaddr needed because system inexplicably leaves crud lying around */
|
||||
code =
|
||||
setsockopt(AcceptSd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
|
||||
sizeof(on));
|
||||
if (code)
|
||||
Log("FSYNC_sync: setsockopt failed with (%d)\n", errno);
|
||||
|
||||
for (numTries = 0; numTries < MAX_BIND_TRIES; numTries++) {
|
||||
if ((code =
|
||||
bind(AcceptSd, (struct sockaddr *)&addr, sizeof(addr))) == 0)
|
||||
break;
|
||||
Log("FSYNC_sync: bind failed with (%d), will sleep and retry\n",
|
||||
errno);
|
||||
sleep(5);
|
||||
}
|
||||
state->fd = SYNC_getSock(&state->endpoint);
|
||||
code = SYNC_bindSock(state);
|
||||
assert(!code);
|
||||
listen(AcceptSd, 100);
|
||||
|
||||
InitHandler();
|
||||
AcceptOn();
|
||||
|
||||
for (;;) {
|
||||
#if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
|
||||
int nfds;
|
||||
@ -405,7 +362,10 @@ FSYNC_com(int fd)
|
||||
VOL_LOCK;
|
||||
switch (com.hdr.command) {
|
||||
case FSYNC_VOL_ON:
|
||||
case FSYNC_VOL_ATTACH:
|
||||
case FSYNC_VOL_LEAVE_OFF:
|
||||
case FSYNC_VOL_OFF:
|
||||
case FSYNC_VOL_FORCE_ERROR:
|
||||
case FSYNC_VOL_LISTVOLUMES:
|
||||
case FSYNC_VOL_NEEDVOLUME:
|
||||
case FSYNC_VOL_MOVE:
|
||||
@ -423,6 +383,9 @@ FSYNC_com(int fd)
|
||||
case FSYNC_VOL_STATS_VLRU:
|
||||
res.hdr.response = FSYNC_com_StatsOp(fd, &com, &res);
|
||||
break;
|
||||
case FSYNC_VOL_QUERY_VNODE:
|
||||
res.hdr.response = FSYNC_com_VnQry(fd, &com, &res);
|
||||
break;
|
||||
default:
|
||||
res.hdr.response = SYNC_BAD_COMMAND;
|
||||
break;
|
||||
@ -465,6 +428,8 @@ FSYNC_com_VolOp(int fd, SYNC_command * com, SYNC_response * res)
|
||||
|
||||
switch (com->hdr.command) {
|
||||
case FSYNC_VOL_ON:
|
||||
case FSYNC_VOL_ATTACH:
|
||||
case FSYNC_VOL_LEAVE_OFF:
|
||||
code = FSYNC_com_VolOn(&vcom, res);
|
||||
break;
|
||||
case FSYNC_VOL_OFF:
|
||||
@ -490,6 +455,9 @@ FSYNC_com_VolOp(int fd, SYNC_command * com, SYNC_response * res)
|
||||
code = FSYNC_com_VolHdrQuery(&vcom, res);
|
||||
break;
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
case FSYNC_VOL_FORCE_ERROR:
|
||||
code = FSYNC_com_VolError(&vcom, res);
|
||||
break;
|
||||
case FSYNC_VOL_QUERY_VOP:
|
||||
code = FSYNC_com_VolOpQuery(&vcom, res);
|
||||
break;
|
||||
@ -554,29 +522,65 @@ FSYNC_com_VolOn(FSSYNC_VolOp_command * vcom, SYNC_response * res)
|
||||
|
||||
/* so, we need to attach the volume */
|
||||
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
/* check DAFS permissions */
|
||||
vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
|
||||
if (vp && !strcmp(VPartitionPath(V_partition(vp)), vcom->vop->partName) &&
|
||||
vp->pending_vol_op &&
|
||||
(vcom->hdr->programType != vp->pending_vol_op->com.programType)) {
|
||||
/* a different program has this volume checked out. deny. */
|
||||
Log("FSYNC_VolOn: WARNING: program type %u has attempted to manipulate "
|
||||
"state for volume %u using command code %u while the volume is "
|
||||
"checked out by program type %u for command code %u.\n",
|
||||
vcom->hdr->programType,
|
||||
vcom->vop->volume,
|
||||
vcom->hdr->command,
|
||||
vp->pending_vol_op->com.programType,
|
||||
vp->pending_vol_op->com.command);
|
||||
code = SYNC_DENIED;
|
||||
res->hdr.reason = FSYNC_EXCLUSIVE;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (vcom->v)
|
||||
vcom->v->volumeID = 0;
|
||||
|
||||
|
||||
if (vcom->hdr->command == FSYNC_VOL_LEAVE_OFF) {
|
||||
/* nothing much to do if we're leaving the volume offline */
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
if (vp &&
|
||||
!strcmp(VPartitionPath(V_partition(vp)), vcom->vop->partName)) {
|
||||
VDeregisterVolOp_r(vp);
|
||||
VChangeState_r(vp, VOL_STATE_UNATTACHED);
|
||||
}
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
/* first, check to see whether we have such a volume defined */
|
||||
vp = VPreAttachVolumeById_r(&error,
|
||||
vcom->vop->partName,
|
||||
vcom->vop->volume);
|
||||
if (vp) {
|
||||
VDeregisterVolOp_r(vp);
|
||||
}
|
||||
#else /* !AFS_DEMAND_ATTACH_FS */
|
||||
tvolName[0] = '/';
|
||||
snprintf(&tvolName[1], sizeof(tvolName)-1, VFORMAT, vcom->vop->volume);
|
||||
tvolName[sizeof(tvolName)-1] = '\0';
|
||||
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
vp = VPreAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
|
||||
V_VOLUPD);
|
||||
if (vp && vp->pending_vol_op) {
|
||||
VDeregisterVolOp_r(vp, vp->pending_vol_op);
|
||||
}
|
||||
#else /* AFS_DEMAND_ATTACH_FS */
|
||||
vp = VAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
|
||||
V_VOLUPD);
|
||||
if (vp)
|
||||
VPutVolume_r(vp);
|
||||
#endif /* AFS_DEMAND_ATTACH_FS */
|
||||
|
||||
if (error) {
|
||||
code = SYNC_DENIED;
|
||||
res->hdr.reason = error;
|
||||
}
|
||||
#endif /* !AFS_DEMAND_ATTACH_FS */
|
||||
|
||||
done:
|
||||
return code;
|
||||
@ -821,14 +825,38 @@ FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
|
||||
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
|
||||
if (vp && vp->pending_vol_op) {
|
||||
VDeregisterVolOp_r(vp, vp->pending_vol_op);
|
||||
if (vp) {
|
||||
VDeregisterVolOp_r(vp);
|
||||
}
|
||||
#endif
|
||||
|
||||
return SYNC_OK;
|
||||
}
|
||||
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
/**
|
||||
* force a volume into the hard error state.
|
||||
*/
|
||||
static afs_int32
|
||||
FSYNC_com_VolError(FSSYNC_VolOp_command * vcom, SYNC_response * res)
|
||||
{
|
||||
Error error;
|
||||
Volume * vp;
|
||||
afs_int32 code = SYNC_DENIED;
|
||||
|
||||
vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
|
||||
if (vp && !strcmp(VPartitionPath(V_partition(vp)), vcom->vop->partName)) {
|
||||
memset(&vp->salvage, 0, sizeof(vp->salvage));
|
||||
VChangeState_r(vp, VOL_STATE_ERROR);
|
||||
code = SYNC_OK;
|
||||
} else {
|
||||
res->hdr.reason = FSYNC_UNKNOWN_VOLID;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
#endif
|
||||
|
||||
static afs_int32
|
||||
FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
|
||||
{
|
||||
@ -938,10 +966,61 @@ FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
|
||||
}
|
||||
#endif /* AFS_DEMAND_ATTACH_FS */
|
||||
|
||||
static afs_int32
|
||||
FSYNC_com_VnQry(int fd, SYNC_command * com, SYNC_response * res)
|
||||
{
|
||||
afs_int32 code = SYNC_OK;
|
||||
FSSYNC_VnQry_hdr * qry = com->payload.buf;
|
||||
Volume * vp;
|
||||
Vnode * vnp;
|
||||
Error error;
|
||||
|
||||
if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VnQry_hdr))) {
|
||||
res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
|
||||
res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
|
||||
return SYNC_COM_ERROR;
|
||||
}
|
||||
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
vp = VLookupVolume_r(&error, qry->volume, NULL);
|
||||
#else /* !AFS_DEMAND_ATTACH_FS */
|
||||
vp = VGetVolume_r(&error, qry->volume);
|
||||
#endif /* !AFS_DEMAND_ATTACH_FS */
|
||||
|
||||
if (!vp) {
|
||||
res->hdr.reason = FSYNC_UNKNOWN_VOLID;
|
||||
code = SYNC_FAILED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
vnp = VLookupVnode(vp, qry->vnode);
|
||||
if (!vnp) {
|
||||
res->hdr.reason = FSYNC_UNKNOWN_VNID;
|
||||
code = SYNC_FAILED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (Vn_class(vnp)->residentSize > res->payload.len) {
|
||||
res->hdr.reason = SYNC_REASON_ENCODING_ERROR;
|
||||
code = SYNC_FAILED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
memcpy(res->payload.buf, vnp, Vn_class(vnp)->residentSize);
|
||||
res->hdr.response_len += Vn_class(vnp)->residentSize;
|
||||
|
||||
cleanup:
|
||||
#ifndef AFS_DEMAND_ATTACH_FS
|
||||
VPutVolume_r(vp);
|
||||
#endif
|
||||
|
||||
done:
|
||||
return code;
|
||||
}
|
||||
|
||||
static afs_int32
|
||||
FSYNC_com_StatsOp(int fd, SYNC_command * com, SYNC_response * res)
|
||||
{
|
||||
int i;
|
||||
afs_int32 code = SYNC_OK;
|
||||
FSSYNC_StatsOp_command scom;
|
||||
|
||||
@ -1120,8 +1199,8 @@ static void
|
||||
AcceptOn()
|
||||
{
|
||||
if (AcceptHandler == -1) {
|
||||
assert(AddHandler(AcceptSd, FSYNC_newconnection));
|
||||
AcceptHandler = FindHandler(AcceptSd);
|
||||
assert(AddHandler(fssync_server_state.fd, FSYNC_newconnection));
|
||||
AcceptHandler = FindHandler(fssync_server_state.fd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1129,7 +1208,7 @@ static void
|
||||
AcceptOff()
|
||||
{
|
||||
if (AcceptHandler != -1) {
|
||||
assert(RemoveHandler(AcceptSd));
|
||||
assert(RemoveHandler(fssync_server_state.fd));
|
||||
AcceptHandler = -1;
|
||||
}
|
||||
}
|
||||
|
115
src/vol/fssync.h
115
src/vol/fssync.h
@ -6,7 +6,7 @@
|
||||
* License. For details, see the LICENSE file in the top-level source
|
||||
* directory or online at http://www.openafs.org/dl/license10.html
|
||||
*
|
||||
* Portions Copyright (c) 2006 Sine Nomine Associates
|
||||
* Portions Copyright (c) 2006-2008 Sine Nomine Associates
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -23,37 +23,50 @@
|
||||
#define FSYNC_PROTO_VERSION 2
|
||||
|
||||
|
||||
/* FSYNC command codes */
|
||||
#define FSYNC_VOL_ON SYNC_COM_CODE_DECL(0) /* Volume online */
|
||||
#define FSYNC_VOL_OFF SYNC_COM_CODE_DECL(1) /* Volume offline */
|
||||
#define FSYNC_VOL_LISTVOLUMES SYNC_COM_CODE_DECL(2) /* Update local volume list */
|
||||
#define FSYNC_VOL_NEEDVOLUME SYNC_COM_CODE_DECL(3) /* Put volume in whatever mode (offline, or whatever)
|
||||
* best fits the attachment mode provided in reason */
|
||||
#define FSYNC_VOL_MOVE SYNC_COM_CODE_DECL(4) /* Generate temporary relocation information
|
||||
* for this volume to another site, to be used
|
||||
* if this volume disappears */
|
||||
#define FSYNC_VOL_BREAKCBKS SYNC_COM_CODE_DECL(5) /* Break all the callbacks on this volume */
|
||||
#define FSYNC_VOL_DONE SYNC_COM_CODE_DECL(6) /* Done with this volume (used after a delete).
|
||||
* Don't put online, but remove from list */
|
||||
#define FSYNC_VOL_QUERY SYNC_COM_CODE_DECL(7) /* query the volume state */
|
||||
#define FSYNC_VOL_QUERY_HDR SYNC_COM_CODE_DECL(8) /* query the volume disk data structure */
|
||||
#define FSYNC_VOL_QUERY_VOP SYNC_COM_CODE_DECL(9) /* query the volume for pending vol op info */
|
||||
#define FSYNC_VOL_STATS_GENERAL SYNC_COM_CODE_DECL(10) /* query the general volume package statistics */
|
||||
#define FSYNC_VOL_STATS_VICEP SYNC_COM_CODE_DECL(11) /* query the per-partition volume package stats */
|
||||
#define FSYNC_VOL_STATS_HASH SYNC_COM_CODE_DECL(12) /* query the per hash-chain volume package stats */
|
||||
#define FSYNC_VOL_STATS_HDR SYNC_COM_CODE_DECL(13) /* query the volume header cache statistics */
|
||||
#define FSYNC_VOL_STATS_VLRU SYNC_COM_CODE_DECL(14) /* query the VLRU statistics */
|
||||
/**
|
||||
* FSYNC command codes.
|
||||
*/
|
||||
enum FSYNCOpCode {
|
||||
FSYNC_VOL_ON = SYNC_COM_CODE_DECL(0), /**< bring Volume online */
|
||||
FSYNC_VOL_OFF = SYNC_COM_CODE_DECL(1), /**< take Volume offline */
|
||||
FSYNC_VOL_LISTVOLUMES = SYNC_COM_CODE_DECL(2), /**< Update local volume list */
|
||||
FSYNC_VOL_NEEDVOLUME = SYNC_COM_CODE_DECL(3), /**< Put volume in whatever mode (offline, or whatever)
|
||||
* best fits the attachment mode provided in reason */
|
||||
FSYNC_VOL_MOVE = SYNC_COM_CODE_DECL(4), /**< Generate temporary relocation information
|
||||
* for this volume to another site, to be used
|
||||
* if this volume disappears */
|
||||
FSYNC_VOL_BREAKCBKS = SYNC_COM_CODE_DECL(5), /**< Break all the callbacks on this volume */
|
||||
FSYNC_VOL_DONE = SYNC_COM_CODE_DECL(6), /**< Done with this volume (used after a delete).
|
||||
* Don't put online, but remove from list */
|
||||
FSYNC_VOL_QUERY = SYNC_COM_CODE_DECL(7), /**< query the volume state */
|
||||
FSYNC_VOL_QUERY_HDR = SYNC_COM_CODE_DECL(8), /**< query the volume disk data structure */
|
||||
FSYNC_VOL_QUERY_VOP = SYNC_COM_CODE_DECL(9), /**< query the volume for pending vol op info */
|
||||
FSYNC_VOL_STATS_GENERAL = SYNC_COM_CODE_DECL(10), /**< query the general volume package statistics */
|
||||
FSYNC_VOL_STATS_VICEP = SYNC_COM_CODE_DECL(11), /**< query the per-partition volume package stats */
|
||||
FSYNC_VOL_STATS_HASH = SYNC_COM_CODE_DECL(12), /**< query the per hash-chain volume package stats */
|
||||
FSYNC_VOL_STATS_HDR = SYNC_COM_CODE_DECL(13), /**< query the volume header cache statistics */
|
||||
FSYNC_VOL_STATS_VLRU = SYNC_COM_CODE_DECL(14), /**< query the VLRU statistics */
|
||||
FSYNC_VOL_ATTACH = SYNC_COM_CODE_DECL(15), /**< Force volume online */
|
||||
FSYNC_VOL_FORCE_ERROR = SYNC_COM_CODE_DECL(16), /**< force volume into error state */
|
||||
FSYNC_VOL_LEAVE_OFF = SYNC_COM_CODE_DECL(17), /**< end vol op, but leave volume offline */
|
||||
FSYNC_VOL_QUERY_VNODE = SYNC_COM_CODE_DECL(18), /**< query vnode state */
|
||||
};
|
||||
|
||||
/* FSYNC reason codes */
|
||||
#define FSYNC_WHATEVER SYNC_REASON_CODE_DECL(0) /* XXXX */
|
||||
#define FSYNC_SALVAGE SYNC_REASON_CODE_DECL(1) /* volume is being salvaged */
|
||||
#define FSYNC_MOVE SYNC_REASON_CODE_DECL(2) /* volume is being moved */
|
||||
#define FSYNC_OPERATOR SYNC_REASON_CODE_DECL(3) /* operator forced volume offline */
|
||||
#define FSYNC_EXCLUSIVE SYNC_REASON_CODE_DECL(4) /* somebody else has the volume offline */
|
||||
#define FSYNC_UNKNOWN_VOLID SYNC_REASON_CODE_DECL(5) /* volume id not known by fileserver */
|
||||
#define FSYNC_HDR_NOT_ATTACHED SYNC_REASON_CODE_DECL(6) /* volume header not currently attached */
|
||||
#define FSYNC_NO_PENDING_VOL_OP SYNC_REASON_CODE_DECL(7) /* no volume operation pending */
|
||||
#define FSYNC_VOL_PKG_ERROR SYNC_REASON_CODE_DECL(8) /* error in the volume package */
|
||||
/**
|
||||
* FSYNC reason codes.
|
||||
*/
|
||||
enum FSYNCReasonCode {
|
||||
FSYNC_WHATEVER = SYNC_REASON_CODE_DECL(0), /**< XXXX */
|
||||
FSYNC_SALVAGE = SYNC_REASON_CODE_DECL(1), /**< volume is being salvaged */
|
||||
FSYNC_MOVE = SYNC_REASON_CODE_DECL(2), /**< volume is being moved */
|
||||
FSYNC_OPERATOR = SYNC_REASON_CODE_DECL(3), /**< operator forced volume offline */
|
||||
FSYNC_EXCLUSIVE = SYNC_REASON_CODE_DECL(4), /**< somebody else has the volume offline */
|
||||
FSYNC_UNKNOWN_VOLID = SYNC_REASON_CODE_DECL(5), /**< volume id not known by fileserver */
|
||||
FSYNC_HDR_NOT_ATTACHED = SYNC_REASON_CODE_DECL(6), /**< volume header not currently attached */
|
||||
FSYNC_NO_PENDING_VOL_OP = SYNC_REASON_CODE_DECL(7), /**< no volume operation pending */
|
||||
FSYNC_VOL_PKG_ERROR = SYNC_REASON_CODE_DECL(8), /**< error in the volume package */
|
||||
FSYNC_UNKNOWN_VNID = SYNC_REASON_CODE_DECL(9), /**< vnode id not known by fileserver */
|
||||
};
|
||||
|
||||
/* FSYNC response codes */
|
||||
|
||||
@ -64,9 +77,12 @@ struct offlineInfo {
|
||||
char partName[16];
|
||||
};
|
||||
|
||||
/**
|
||||
* fssync protocol volume operation request message.
|
||||
*/
|
||||
typedef struct FSSYNC_VolOp_hdr {
|
||||
afs_uint32 volume; /* volume id associated with request */
|
||||
char partName[16]; /* partition name, e.g. /vicepa */
|
||||
afs_uint32 volume; /**< volume id associated with request */
|
||||
char partName[16]; /**< partition name, e.g. /vicepa */
|
||||
} FSSYNC_VolOp_hdr;
|
||||
|
||||
typedef struct FSSYNC_VolOp_command {
|
||||
@ -77,17 +93,30 @@ typedef struct FSSYNC_VolOp_command {
|
||||
struct offlineInfo * volumes;
|
||||
} FSSYNC_VolOp_command;
|
||||
|
||||
/**
|
||||
* volume operation information node.
|
||||
*
|
||||
* @note this structure is attached to a struct Volume to signify that
|
||||
* a volume operation is in-progress.
|
||||
*
|
||||
* @see Volume
|
||||
* @see VRegisterVolOp_r
|
||||
* @see VDeregisterVolOp_r
|
||||
*/
|
||||
typedef struct FSSYNC_VolOp_info {
|
||||
SYNC_command_hdr com;
|
||||
FSSYNC_VolOp_hdr vop;
|
||||
} FSSYNC_VolOp_info;
|
||||
|
||||
|
||||
/**
|
||||
* fssync protocol volume package statistics request node.
|
||||
*/
|
||||
typedef struct FSSYNC_StatsOp_hdr {
|
||||
union {
|
||||
afs_uint32 vlru_generation;
|
||||
afs_uint32 hash_bucket;
|
||||
char partName[16];
|
||||
afs_uint32 vlru_generation; /**< vlru generation id */
|
||||
afs_uint32 hash_bucket; /**< volume hash bucket */
|
||||
char partName[16]; /**< partition name */
|
||||
} args;
|
||||
} FSSYNC_StatsOp_hdr;
|
||||
|
||||
@ -97,8 +126,22 @@ typedef struct FSSYNC_StatsOp_command {
|
||||
SYNC_command * com;
|
||||
} FSSYNC_StatsOp_command;
|
||||
|
||||
/**
|
||||
* fssync protocol vnode query request message.
|
||||
*/
|
||||
typedef struct FSSYNC_VnQry_hdr {
|
||||
afs_uint32 volume; /**< volume id */
|
||||
afs_uint32 vnode; /**< vnode id */
|
||||
afs_uint32 unique; /**< uniqifier */
|
||||
afs_uint32 spare; /**< reserved for future use */
|
||||
char partName[16]; /**< partition name */
|
||||
} FSSYNC_VnQry_hdr;
|
||||
|
||||
|
||||
#define FSSYNC_IN_PORT 2040
|
||||
#define FSSYNC_UN_PATH "fssync.sock"
|
||||
#define FSSYNC_ENDPOINT_DECL SYNC_ENDPOINT_DECL(FSSYNC_IN_PORT, FSSYNC_UN_PATH)
|
||||
|
||||
/*
|
||||
* common interfaces
|
||||
*/
|
||||
|
@ -160,6 +160,8 @@ static int DoSalvageVolume(struct SalvageQueueNode * node, int slot);
|
||||
static void SalvageServer(void);
|
||||
static void SalvageClient(VolumeId vid, char * pname);
|
||||
|
||||
static int ChildFailed(int status);
|
||||
|
||||
static int Reap_Child(char * prog, int * pid, int * status);
|
||||
|
||||
static void * SalvageLogCleanupThread(void *);
|
||||
@ -541,14 +543,16 @@ SalvageServer(void)
|
||||
}
|
||||
assert (slot < Parallel);
|
||||
|
||||
do_fork:
|
||||
pid = Fork();
|
||||
if (pid == 0) {
|
||||
VOL_UNLOCK;
|
||||
ret = DoSalvageVolume(node, slot);
|
||||
Exit(ret);
|
||||
} else if (pid < 0) {
|
||||
VOL_UNLOCK;
|
||||
SALVSYNC_doneWork(node, 1);
|
||||
Log("failed to fork child worker process\n");
|
||||
sleep(1);
|
||||
goto do_fork;
|
||||
} else {
|
||||
child_slot[slot] = pid;
|
||||
node->pid = pid;
|
||||
@ -618,6 +622,7 @@ SalvageChildReaperThread(void * args)
|
||||
int slot, pid, status, code, found;
|
||||
struct SalvageQueueNode *qp, *nqp;
|
||||
struct log_cleanup_node * cleanup;
|
||||
SALVSYNC_command_info info;
|
||||
|
||||
assert(pthread_mutex_lock(&worker_lock) == 0);
|
||||
|
||||
@ -647,6 +652,8 @@ SalvageChildReaperThread(void * args)
|
||||
child_slot[slot] = 0;
|
||||
VOL_UNLOCK;
|
||||
|
||||
SALVSYNC_doneWorkByPid(pid, status);
|
||||
|
||||
assert(pthread_mutex_lock(&worker_lock) == 0);
|
||||
|
||||
if (cleanup) {
|
||||
@ -657,7 +664,6 @@ SalvageChildReaperThread(void * args)
|
||||
|
||||
/* ok, we've reaped a child */
|
||||
current_workers--;
|
||||
SALVSYNC_doneWorkByPid(pid, WEXITSTATUS(status));
|
||||
assert(pthread_cond_broadcast(&worker_cv) == 0);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Sine Nomine Associates and others.
|
||||
* Copyright 2006-2008, Sine Nomine Associates and others.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This software has been released under the terms of the IBM Public
|
||||
@ -70,7 +70,7 @@ extern pthread_mutex_t vol_salvsync_mutex;
|
||||
|
||||
static SYNC_client_state salvsync_client_state =
|
||||
{ -1, /* file descriptor */
|
||||
2041, /* port */
|
||||
SALVSYNC_ENDPOINT_DECL, /* server endpoint */
|
||||
SALVSYNC_PROTO_VERSION, /* protocol version */
|
||||
5, /* connect retry limit */
|
||||
120, /* hard timeout */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Sine Nomine Associates and others.
|
||||
* Copyright 2006-2008, Sine Nomine Associates and others.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This software has been released under the terms of the IBM Public
|
||||
@ -60,6 +60,7 @@ RCSID
|
||||
#include "volume.h"
|
||||
#include "partition.h"
|
||||
#include <rx/rx_queue.h>
|
||||
#include <afs/procmgmt.h>
|
||||
|
||||
#if !defined(offsetof)
|
||||
#include <stddef.h>
|
||||
@ -81,10 +82,6 @@ RCSID
|
||||
#define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
|
||||
* move = dump+restore can run on single server */
|
||||
|
||||
#define MAX_BIND_TRIES 5 /* Number of times to retry socket bind */
|
||||
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
static void * SALVSYNC_syncThread(void *);
|
||||
static void SALVSYNC_newconnection(int fd);
|
||||
@ -146,7 +143,17 @@ extern int LogLevel;
|
||||
extern int VInit;
|
||||
extern pthread_mutex_t vol_salvsync_mutex;
|
||||
|
||||
static int AcceptSd = -1; /* Socket used by server for accepting connections */
|
||||
/**
|
||||
* salvsync server socket handle.
|
||||
*/
|
||||
static SYNC_server_state_t salvsync_server_state =
|
||||
{ -1, /* file descriptor */
|
||||
SALVSYNC_ENDPOINT_DECL, /* server endpoint */
|
||||
SALVSYNC_PROTO_VERSION, /* protocol version */
|
||||
5, /* bind() retry limit */
|
||||
100, /* listen() queue depth */
|
||||
"SALVSYNC", /* protocol name string */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@ -291,54 +298,20 @@ SALVSYNC_salvInit(void)
|
||||
assert(pthread_create(&tid, &tattr, SALVSYNC_syncThread, NULL) == 0);
|
||||
}
|
||||
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
static int
|
||||
getport(struct sockaddr_un *addr)
|
||||
{
|
||||
int sd;
|
||||
char tbuffer[AFSDIR_PATH_MAX];
|
||||
|
||||
strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
|
||||
"fssync.sock", NULL);
|
||||
|
||||
memset(addr, 0, sizeof(*addr));
|
||||
addr->sun_family = AF_UNIX;
|
||||
strncpy(addr->sun_path, tbuffer, (sizeof(struct sockaddr_un) - sizeof(short)));
|
||||
assert((sd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
|
||||
return sd;
|
||||
}
|
||||
#else
|
||||
static int
|
||||
getport(struct sockaddr_in *addr)
|
||||
{
|
||||
int sd;
|
||||
|
||||
memset(addr, 0, sizeof(*addr));
|
||||
assert((sd = socket(AF_INET, SOCK_STREAM, 0)) >= 0);
|
||||
#ifdef STRUCT_SOCKADDR_HAS_SA_LEN
|
||||
addr->sin_len = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
addr->sin_addr.s_addr = htonl(0x7f000001);
|
||||
addr->sin_family = AF_INET; /* was localhost->h_addrtype */
|
||||
addr->sin_port = htons(2041); /* XXXX htons not _really_ neccessary */
|
||||
|
||||
return sd;
|
||||
}
|
||||
#endif
|
||||
|
||||
static fd_set SALVSYNC_readfds;
|
||||
|
||||
static void *
|
||||
SALVSYNC_syncThread(void * args)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int on = 1;
|
||||
int code;
|
||||
int numTries;
|
||||
int tid;
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
char tbuffer[AFSDIR_PATH_MAX];
|
||||
#endif
|
||||
SYNC_server_state_t * state = &salvsync_server_state;
|
||||
|
||||
SYNC_getAddr(&state->endpoint, &state->addr);
|
||||
SYNC_cleanupSock(state);
|
||||
|
||||
#ifndef AFS_NT40_ENV
|
||||
(void)signal(SIGPIPE, SIG_IGN);
|
||||
@ -351,31 +324,10 @@ SALVSYNC_syncThread(void * args)
|
||||
pthread_setspecific(rx_thread_id_key, (void *)tid);
|
||||
Log("Set thread id %d for SALVSYNC_syncThread\n", tid);
|
||||
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
|
||||
"fssync.sock", NULL);
|
||||
/* ignore errors */
|
||||
remove(tbuffer);
|
||||
#endif /* USE_UNIX_SOCKETS */
|
||||
|
||||
AcceptSd = getport(&addr);
|
||||
/* Reuseaddr needed because system inexplicably leaves crud lying around */
|
||||
code =
|
||||
setsockopt(AcceptSd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
|
||||
sizeof(on));
|
||||
if (code)
|
||||
Log("SALVSYNC_sync: setsockopt failed with (%d)\n", errno);
|
||||
|
||||
for (numTries = 0; numTries < MAX_BIND_TRIES; numTries++) {
|
||||
if ((code =
|
||||
bind(AcceptSd, (struct sockaddr *)&addr, sizeof(addr))) == 0)
|
||||
break;
|
||||
Log("SALVSYNC_sync: bind failed with (%d), will sleep and retry\n",
|
||||
errno);
|
||||
sleep(5);
|
||||
}
|
||||
state->fd = SYNC_getSock(&state->endpoint);
|
||||
code = SYNC_bindSock(state);
|
||||
assert(!code);
|
||||
listen(AcceptSd, 100);
|
||||
|
||||
InitHandler();
|
||||
AcceptOn();
|
||||
|
||||
@ -514,6 +466,26 @@ SALVSYNC_com(int fd)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* request that a volume be salvaged.
|
||||
*
|
||||
* @param[in] com inbound command object
|
||||
* @param[out] res outbound response object
|
||||
*
|
||||
* @return operation status
|
||||
* @retval SYNC_OK success
|
||||
* @retval SYNC_DENIED failed to enqueue request
|
||||
* @retval SYNC_FAILED malformed command packet
|
||||
*
|
||||
* @note this is a SALVSYNC protocol rpc handler
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @post the volume is enqueued in the to-be-salvaged queue.
|
||||
* if the volume was already in the salvage queue, its
|
||||
* priority (and thus its location in the queue) are
|
||||
* updated.
|
||||
*/
|
||||
static afs_int32
|
||||
SALVSYNC_com_Salvage(SALVSYNC_command * com, SALVSYNC_response * res)
|
||||
{
|
||||
@ -551,6 +523,19 @@ SALVSYNC_com_Salvage(SALVSYNC_command * com, SALVSYNC_response * res)
|
||||
case SALVSYNC_STATE_UNKNOWN:
|
||||
memcpy(&clone->command.com, com->hdr, sizeof(SYNC_command_hdr));
|
||||
memcpy(&clone->command.sop, com->sop, sizeof(SALVSYNC_command_hdr));
|
||||
|
||||
/*
|
||||
* make sure volgroup parent partition path is kept coherent
|
||||
*
|
||||
* If we ever want to support non-COW clones on a machine holding
|
||||
* the RW site, please note that this code does not work under the
|
||||
* conditions where someone zaps a COW clone on partition X, and
|
||||
* subsequently creates a full clone on partition Y -- we'd need
|
||||
* an inverse to SALVSYNC_com_Link.
|
||||
* -- tkeiser 11/28/2007
|
||||
*/
|
||||
strcpy(node->command.sop.partName, com->sop->partName);
|
||||
|
||||
if (AddToSalvageQueue(node)) {
|
||||
code = SYNC_DENIED;
|
||||
}
|
||||
@ -572,6 +557,20 @@ SALVSYNC_com_Salvage(SALVSYNC_command * com, SALVSYNC_response * res)
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* cancel a pending salvage request.
|
||||
*
|
||||
* @param[in] com inbound command object
|
||||
* @param[out] res outbound response object
|
||||
*
|
||||
* @return operation status
|
||||
* @retval SYNC_OK success
|
||||
* @retval SYNC_FAILED malformed command packet
|
||||
*
|
||||
* @note this is a SALVSYNC protocol rpc handler
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
static afs_int32
|
||||
SALVSYNC_com_Cancel(SALVSYNC_command * com, SALVSYNC_response * res)
|
||||
{
|
||||
@ -603,6 +602,19 @@ SALVSYNC_com_Cancel(SALVSYNC_command * com, SALVSYNC_response * res)
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* cancel all pending salvage requests.
|
||||
*
|
||||
* @param[in] com incoming command object
|
||||
* @param[out] res outbound response object
|
||||
*
|
||||
* @return operation status
|
||||
* @retval SYNC_OK success
|
||||
*
|
||||
* @note this is a SALVSYNC protocol rpc handler
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
static afs_int32
|
||||
SALVSYNC_com_CancelAll(SALVSYNC_command * com, SALVSYNC_response * res)
|
||||
{
|
||||
@ -620,6 +632,23 @@ SALVSYNC_com_CancelAll(SALVSYNC_command * com, SALVSYNC_response * res)
|
||||
|
||||
/**
|
||||
* link a queue node for a clone to its parent volume.
|
||||
*
|
||||
* @param[in] com inbound command object
|
||||
* @param[out] res outbound response object
|
||||
*
|
||||
* @return operation status
|
||||
* @retval SYNC_OK success
|
||||
* @retval SYNC_FAILED malformed command packet
|
||||
* @retval SYNC_DENIED the request could not be completed
|
||||
*
|
||||
* @note this is a SALVSYNC protocol rpc handler
|
||||
*
|
||||
* @post the requested volume is marked as a child of another volume.
|
||||
* thus, future salvage requests for this volume will result in the
|
||||
* parent of the volume group being scheduled for salvage instead
|
||||
* of this clone.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
static afs_int32
|
||||
SALVSYNC_com_Link(SALVSYNC_command * com, SALVSYNC_response * res)
|
||||
@ -664,6 +693,20 @@ SALVSYNC_com_Link(SALVSYNC_command * com, SALVSYNC_response * res)
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* query the status of a volume salvage request.
|
||||
*
|
||||
* @param[in] com inbound command object
|
||||
* @param[out] res outbound response object
|
||||
*
|
||||
* @return operation status
|
||||
* @retval SYNC_OK success
|
||||
* @retval SYNC_FAILED malformed command packet
|
||||
*
|
||||
* @note this is a SALVSYNC protocol rpc handler
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
static afs_int32
|
||||
SALVSYNC_com_Query(SALVSYNC_command * com, SALVSYNC_response * res)
|
||||
{
|
||||
@ -710,8 +753,8 @@ static void
|
||||
AcceptOn(void)
|
||||
{
|
||||
if (AcceptHandler == -1) {
|
||||
assert(AddHandler(AcceptSd, SALVSYNC_newconnection));
|
||||
AcceptHandler = FindHandler(AcceptSd);
|
||||
assert(AddHandler(salvsync_server_state.fd, SALVSYNC_newconnection));
|
||||
AcceptHandler = FindHandler(salvsync_server_state.fd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -719,7 +762,7 @@ static void
|
||||
AcceptOff(void)
|
||||
{
|
||||
if (AcceptHandler != -1) {
|
||||
assert(RemoveHandler(AcceptSd));
|
||||
assert(RemoveHandler(salvsync_server_state.fd));
|
||||
AcceptHandler = -1;
|
||||
}
|
||||
}
|
||||
@ -827,6 +870,17 @@ GetHandler(fd_set * fdsetp, int *maxfdp)
|
||||
ReleaseReadLock(&SALVSYNC_handler_lock); /* just in case */
|
||||
}
|
||||
|
||||
/**
|
||||
* allocate a salvage queue node.
|
||||
*
|
||||
* @param[out] node_out address in which to store new node pointer
|
||||
*
|
||||
* @return operation status
|
||||
* @retval 0 success
|
||||
* @retval 1 failed to allocate node
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
static int
|
||||
AllocNode(struct SalvageQueueNode ** node_out)
|
||||
{
|
||||
@ -848,6 +902,18 @@ AllocNode(struct SalvageQueueNode ** node_out)
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* link a salvage queue node to its parent.
|
||||
*
|
||||
* @param[in] parent pointer to queue node for parent of volume group
|
||||
* @param[in] clone pointer to queue node for a clone
|
||||
*
|
||||
* @return operation status
|
||||
* @retval 0 success
|
||||
* @retval 1 failure
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
static int
|
||||
LinkNode(struct SalvageQueueNode * parent,
|
||||
struct SalvageQueueNode * clone)
|
||||
@ -1093,7 +1159,7 @@ SALVSYNC_getWork(void)
|
||||
* if there are no disk partitions, just sit in this wait loop forever
|
||||
*/
|
||||
while (!salvageQueue.total_len || !DiskPartitionList) {
|
||||
assert(pthread_cond_wait(&salvageQueue.cv, &vol_glock_mutex) == 0);
|
||||
VOL_CV_WAIT(&salvageQueue.cv);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1168,6 +1234,16 @@ SALVSYNC_getWork(void)
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* update internal scheduler state to reflect completion of a work unit.
|
||||
*
|
||||
* @param[in] node salvage queue node object pointer
|
||||
* @param[in] result worker process result code
|
||||
*
|
||||
* @post scheduler state is updated.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
static void
|
||||
SALVSYNC_doneWork_r(struct SalvageQueueNode * node, int result)
|
||||
{
|
||||
@ -1194,25 +1270,86 @@ SALVSYNC_doneWork_r(struct SalvageQueueNode * node, int result)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SALVSYNC_doneWork(struct SalvageQueueNode * node, int result)
|
||||
/**
|
||||
* check whether worker child failed.
|
||||
*
|
||||
* @param[in] status status bitfield return by wait()
|
||||
*
|
||||
* @return boolean failure code
|
||||
* @retval 0 child succeeded
|
||||
* @retval 1 child failed
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
static int
|
||||
ChildFailed(int status)
|
||||
{
|
||||
VOL_LOCK;
|
||||
SALVSYNC_doneWork_r(node, result);
|
||||
VOL_UNLOCK;
|
||||
return (WCOREDUMP(status) ||
|
||||
WIFSIGNALED(status) ||
|
||||
((WEXITSTATUS(status) != 0) &&
|
||||
(WEXITSTATUS(status) != SALSRV_EXIT_VOLGROUP_LINK)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* notify salvsync scheduler of node completion, by child pid.
|
||||
*
|
||||
* @param[in] pid pid of worker child
|
||||
* @param[in] status worker status bitfield from wait()
|
||||
*
|
||||
* @post scheduler state is updated.
|
||||
* if status code is a failure, fileserver notification was attempted
|
||||
*
|
||||
* @see SALVSYNC_doneWork_r
|
||||
*/
|
||||
void
|
||||
SALVSYNC_doneWorkByPid(int pid, int result)
|
||||
SALVSYNC_doneWorkByPid(int pid, int status)
|
||||
{
|
||||
struct SalvageQueueNode * node;
|
||||
char partName[16];
|
||||
afs_uint32 volids[VOLMAXTYPES+1];
|
||||
unsigned int idx;
|
||||
|
||||
memset(volids, 0, sizeof(volids));
|
||||
|
||||
VOL_LOCK;
|
||||
node = LookupPendingCommandByPid(pid);
|
||||
if (node != NULL) {
|
||||
SALVSYNC_doneWork_r(node, result);
|
||||
SALVSYNC_doneWork_r(node, status);
|
||||
|
||||
if (ChildFailed(status)) {
|
||||
/* populate volume id list for later processing outside the glock */
|
||||
volids[0] = node->command.sop.volume;
|
||||
strcpy(partName, node->command.sop.partName);
|
||||
if (node->type == SALVSYNC_VOLGROUP_PARENT) {
|
||||
for (idx = 0; idx < VOLMAXTYPES; idx++) {
|
||||
if (node->volgroup.children[idx]) {
|
||||
volids[idx+1] = node->volgroup.children[idx]->command.sop.volume;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
VOL_UNLOCK;
|
||||
|
||||
/*
|
||||
* if necessary, notify fileserver of
|
||||
* failure to salvage volume group
|
||||
* [we cannot guarantee that the child made the
|
||||
* appropriate notifications (e.g. SIGSEGV)]
|
||||
* -- tkeiser 11/28/2007
|
||||
*/
|
||||
if (ChildFailed(status)) {
|
||||
for (idx = 0; idx <= VOLMAXTYPES; idx++) {
|
||||
if (volids[idx]) {
|
||||
FSYNC_VolOp(volids[idx],
|
||||
partName,
|
||||
FSYNC_VOL_FORCE_ERROR,
|
||||
FSYNC_WHATEVER,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* AFS_DEMAND_ATTACH_FS */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Sine Nomine Associates and others.
|
||||
* Copyright 2006-2008, Sine Nomine Associates and others.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This software has been released under the terms of the IBM Public
|
||||
@ -140,6 +140,9 @@ struct SalvageQueueNode {
|
||||
int pid;
|
||||
};
|
||||
|
||||
#define SALVSYNC_IN_PORT 2041
|
||||
#define SALVSYNC_UN_PATH "salvsync.sock"
|
||||
#define SALVSYNC_ENDPOINT_DECL SYNC_ENDPOINT_DECL(SALVSYNC_IN_PORT, SALVSYNC_UN_PATH)
|
||||
|
||||
/* Prototypes from salvsync.c */
|
||||
|
||||
@ -156,7 +159,6 @@ extern afs_int32 SALVSYNC_LinkVolume(VolumeId parent, VolumeId clone,
|
||||
/* salvage server interfaces */
|
||||
extern void SALVSYNC_salvInit(void);
|
||||
extern struct SalvageQueueNode * SALVSYNC_getWork(void);
|
||||
extern void SALVSYNC_doneWork(struct SalvageQueueNode *, int result);
|
||||
extern void SALVSYNC_doneWorkByPid(int pid, int result);
|
||||
|
||||
#endif /* AFS_DEMAND_ATTACH_FS */
|
||||
|
1459
src/vol/vnode.c
1459
src/vol/vnode.c
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,8 @@
|
||||
* This software has been released under the terms of the IBM Public
|
||||
* License. For details, see the LICENSE file in the top-level source
|
||||
* directory or online at http://www.openafs.org/dl/license10.html
|
||||
*
|
||||
* Portions Copyright (c) 2007-2008 Sine Nomine Associates
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -14,6 +16,9 @@
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _AFS_VOL_VNODE_H
|
||||
#define _AFS_VOL_VNODE_H 1
|
||||
|
||||
#define Date afs_uint32
|
||||
|
||||
struct Volume; /* Potentially forward definition. */
|
||||
@ -117,6 +122,42 @@ typedef struct VnodeDiskObject {
|
||||
(sizeof(VnodeDiskObject) == SIZEOF_SMALLDISKVNODE)
|
||||
#define SIZEOF_LARGEDISKVNODE 256
|
||||
|
||||
|
||||
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
/**
|
||||
* demand attach vnode state enumeration.
|
||||
*
|
||||
* @note values must be contiguous for VnIsValidState() to work
|
||||
*/
|
||||
typedef enum {
|
||||
VN_STATE_INVALID = 0, /**< vnode does not contain valid cache data */
|
||||
VN_STATE_RELEASING = 1, /**< vnode is busy releasing its ihandle ref */
|
||||
VN_STATE_CLOSING = 2, /**< vnode is busy closing its ihandle ref */
|
||||
VN_STATE_ALLOC = 3, /**< vnode is busy allocating disk entry */
|
||||
VN_STATE_ONLINE = 4, /**< vnode is ready for use */
|
||||
VN_STATE_LOAD = 5, /**< vnode is busy being loaded from disk */
|
||||
VN_STATE_EXCLUSIVE = 6, /**< something external to the vnode package
|
||||
* is operating exclusively on this vnode */
|
||||
VN_STATE_STORE = 7, /**< vnode is busy being stored to disk */
|
||||
VN_STATE_READ = 8, /**< a non-zero number of threads are executing
|
||||
* code external to the vnode package which
|
||||
* requires shared access */
|
||||
VN_STATE_ERROR = 10, /**< vnode hard error state */
|
||||
VN_STATE_COUNT
|
||||
} VnState;
|
||||
#endif /* AFS_DEMAND_ATTACH_FS */
|
||||
|
||||
/**
|
||||
* DAFS vnode state flags.
|
||||
*/
|
||||
enum VnFlags {
|
||||
VN_ON_HASH = 0x1, /**< vnode is on hash table */
|
||||
VN_ON_LRU = 0x2, /**< vnode is on lru list */
|
||||
VN_ON_VVN = 0x4, /**< vnode is on volume vnode list */
|
||||
};
|
||||
|
||||
|
||||
typedef struct Vnode {
|
||||
struct rx_queue vid_hash; /* for vnode by volume id hash */
|
||||
struct Vnode *hashNext; /* Next vnode on hash conflict chain */
|
||||
@ -142,12 +183,20 @@ typedef struct Vnode {
|
||||
bit32 nUsers; /* Number of lwp's who have done a VGetVnode */
|
||||
bit32 cacheCheck; /* Must equal the value in the volume Header
|
||||
* for the cache entry to be valid */
|
||||
bit32 vn_state_flags; /**< vnode state flags */
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
bit32 nReaders; /**< number of read locks held */
|
||||
VnState vn_state; /**< vnode state */
|
||||
pthread_cond_t vn_state_cv; /**< state change notification cv */
|
||||
#else /* !AFS_DEMAND_ATTACH_FS */
|
||||
struct Lock lock; /* Internal lock */
|
||||
#endif /* !AFS_DEMAND_ATTACH_FS */
|
||||
#ifdef AFS_PTHREAD_ENV
|
||||
pthread_t writer; /* thread holding write lock */
|
||||
#else /* AFS_PTHREAD_ENV */
|
||||
PROCESS writer; /* Process id having write lock */
|
||||
#endif /* AFS_PTHREAD_ENV */
|
||||
struct VnodeClassInfo * vcp; /**< our vnode class */
|
||||
IHandle_t *handle;
|
||||
VnodeDiskObject disk; /* The actual disk data for the vnode */
|
||||
} Vnode;
|
||||
@ -156,6 +205,21 @@ typedef struct Vnode {
|
||||
(sizeof(struct Vnode) - sizeof(VnodeDiskObject) + SIZEOF_LARGEDISKVNODE)
|
||||
#define SIZEOF_SMALLVNODE (sizeof (struct Vnode))
|
||||
|
||||
|
||||
/*
|
||||
* struct Vnode accessor abstraction
|
||||
*/
|
||||
#define Vn_refcount(vnp) ((vnp)->nUsers)
|
||||
#define Vn_state(vnp) ((vnp)->vn_state)
|
||||
#define Vn_stateFlags(vnp) ((vnp)->vn_state_flags)
|
||||
#define Vn_stateCV(vnp) ((vnp)->vn_state_cv)
|
||||
#define Vn_volume(vnp) ((vnp)->volumePtr)
|
||||
#define Vn_cacheCheck(vnp) ((vnp)->cacheCheck)
|
||||
#define Vn_class(vnp) ((vnp)->vcp)
|
||||
#define Vn_readers(vnp) ((vnp)->nReaders)
|
||||
#define Vn_id(vnp) ((vnp)->vnodeNumber)
|
||||
|
||||
|
||||
#ifdef AFS_LARGEFILE_ENV
|
||||
#define VN_GET_LEN(N, V) FillInt64(N, (V)->disk.reserved6, (V)->disk.length)
|
||||
#define VNDISK_GET_LEN(N, V) FillInt64(N, (V)->reserved6, (V)->length)
|
||||
@ -217,4 +281,13 @@ extern Vnode *VAllocVnode(Error * ec, struct Volume *vp, VnodeType type);
|
||||
extern Vnode *VAllocVnode_r(Error * ec, struct Volume *vp, VnodeType type);
|
||||
/*extern VFreeVnode();*/
|
||||
extern Vnode *VGetFreeVnode_r(struct VnodeClassInfo *vcp);
|
||||
extern void VInitVnHashByVolume(void);
|
||||
extern Vnode *VLookupVnode(struct Volume * vp, VnodeId vnodeId);
|
||||
|
||||
extern void AddToVVnList(struct Volume * vp, Vnode * vnp);
|
||||
extern void DeleteFromVVnList(register Vnode * vnp);
|
||||
extern void AddToVnLRU(struct VnodeClassInfo * vcp, Vnode * vnp);
|
||||
extern void DeleteFromVnLRU(struct VnodeClassInfo * vcp, Vnode * vnp);
|
||||
extern void AddToVnHash(Vnode * vnp);
|
||||
extern void DeleteFromVnHash(Vnode * vnp);
|
||||
|
||||
#endif /* _AFS_VOL_VNODE_H */
|
||||
|
373
src/vol/vnode_inline.h
Normal file
373
src/vol/vnode_inline.h
Normal file
@ -0,0 +1,373 @@
|
||||
/*
|
||||
* Copyright 2007-2008, Sine Nomine Associates and others.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This software has been released under the terms of the IBM Public
|
||||
* License. For details, see the LICENSE file in the top-level source
|
||||
* directory or online at http://www.openafs.org/dl/license10.html
|
||||
*/
|
||||
|
||||
#ifndef _AFS_VOL_VNODE_INLINE_H
|
||||
#define _AFS_VOL_VNODE_INLINE_H 1
|
||||
|
||||
#include "vnode.h"
|
||||
|
||||
#ifdef AFS_AIX_ENV
|
||||
#define static_inline inline
|
||||
#else
|
||||
#define static_inline static inline
|
||||
#endif
|
||||
|
||||
/***************************************************/
|
||||
/* demand attach vnode state machine routines */
|
||||
/***************************************************/
|
||||
|
||||
/**
|
||||
* get a reference to a vnode object.
|
||||
*
|
||||
* @param[in] vnp vnode object pointer
|
||||
*
|
||||
* @internal vnode package internal use only
|
||||
*
|
||||
* @pre VOL_LOCK must be held
|
||||
*
|
||||
* @post vnode refcount incremented
|
||||
*
|
||||
* @see VnCancelReservation_r
|
||||
*/
|
||||
static_inline void
|
||||
VnCreateReservation_r(Vnode * vnp)
|
||||
{
|
||||
Vn_refcount(vnp)++;
|
||||
if (Vn_refcount(vnp) == 1) {
|
||||
DeleteFromVnLRU(Vn_class(vnp), vnp);
|
||||
}
|
||||
}
|
||||
|
||||
extern int TrustVnodeCacheEntry;
|
||||
|
||||
/**
|
||||
* release a reference to a vnode object.
|
||||
*
|
||||
* @param[in] vnp vnode object pointer
|
||||
*
|
||||
* @pre VOL_LOCK held
|
||||
*
|
||||
* @post refcount decremented; possibly re-added to vn lru
|
||||
*
|
||||
* @internal vnode package internal use only
|
||||
*
|
||||
* @see VnCreateReservation_r
|
||||
*/
|
||||
static_inline void
|
||||
VnCancelReservation_r(Vnode * vnp)
|
||||
{
|
||||
if (--Vn_refcount(vnp) == 0) {
|
||||
AddToVnLRU(Vn_class(vnp), vnp);
|
||||
|
||||
/* If caching is turned off,
|
||||
* disassociate vnode cache entry from volume object */
|
||||
if (!TrustVnodeCacheEntry) {
|
||||
DeleteFromVVnList(vnp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef AFS_PTHREAD_ENV
|
||||
#define VN_SET_WRITER_THREAD_ID(v) (((v)->writer) = pthread_self())
|
||||
#else
|
||||
#define VN_SET_WRITER_THREAD_ID(v) (LWP_CurrentProcess(&((v)->writer)))
|
||||
#endif
|
||||
|
||||
#define VOL_LOCK_NOT_HELD 0
|
||||
#define VOL_LOCK_HELD 1
|
||||
#define MIGHT_DEADLOCK 0
|
||||
#define WILL_NOT_DEADLOCK 1
|
||||
|
||||
/**
|
||||
* acquire a lock on a vnode object.
|
||||
*
|
||||
* @param[in] vnp vnode object pointer
|
||||
* @param[in] type lock type
|
||||
* @param[in] held whether or not vol glock is held
|
||||
* @param[in] safe whether it it is safe to acquire without dropping vol glock
|
||||
*
|
||||
* @note caller must guarantee deadlock will not occur
|
||||
*
|
||||
* @post lock acquired.
|
||||
* for write case, thread owner field set.
|
||||
*
|
||||
* @note for DAFS, this is a no-op
|
||||
*
|
||||
* @internal vnode package internal use only
|
||||
*/
|
||||
static_inline void
|
||||
VnLock(Vnode * vnp, int type, int held, int safe)
|
||||
{
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
if (type == WRITE_LOCK) {
|
||||
VN_SET_WRITER_THREAD_ID(vnp);
|
||||
}
|
||||
#else /* !AFS_DEMAND_ATTACH_FS */
|
||||
if (held && !safe) {
|
||||
VOL_UNLOCK;
|
||||
}
|
||||
if (type == READ_LOCK) {
|
||||
ObtainReadLock(&vnp->lock);
|
||||
} else {
|
||||
ObtainWriteLock(&vnp->lock);
|
||||
VN_SET_WRITER_THREAD_ID(vnp);
|
||||
}
|
||||
if (held && !safe) {
|
||||
VOL_LOCK;
|
||||
}
|
||||
#endif /* !AFS_DEMAND_ATTACH_FS */
|
||||
}
|
||||
|
||||
/**
|
||||
* release a lock on a vnode object.
|
||||
*
|
||||
* @param[in] vnp vnode object pointer
|
||||
* @param[in] type lock type
|
||||
*
|
||||
* @note for DAFS, this is a no-op
|
||||
*
|
||||
* @internal vnode package internal use only
|
||||
*/
|
||||
static_inline void
|
||||
VnUnlock(Vnode * vnp, int type)
|
||||
{
|
||||
if (type == READ_LOCK) {
|
||||
#ifndef AFS_DEMAND_ATTACH_FS
|
||||
ReleaseReadLock(&vnp->lock);
|
||||
#endif
|
||||
} else {
|
||||
vnp->writer = 0;
|
||||
#ifndef AFS_DEMAND_ATTACH_FS
|
||||
ReleaseWriteLock(&vnp->lock);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
/**
|
||||
* change state, and notify other threads,
|
||||
* return previous state to caller.
|
||||
*
|
||||
* @param[in] vnp pointer to vnode object
|
||||
* @param[in] new_state new vnode state value
|
||||
*
|
||||
* @pre VOL_LOCK held
|
||||
*
|
||||
* @post vnode state changed
|
||||
*
|
||||
* @return previous vnode state
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*
|
||||
* @internal vnode package internal use only
|
||||
*/
|
||||
static_inline VnState
|
||||
VnChangeState_r(Vnode * vnp, VnState new_state)
|
||||
{
|
||||
VnState old_state = Vn_state(vnp);
|
||||
|
||||
Vn_state(vnp) = new_state;
|
||||
assert(pthread_cond_broadcast(&Vn_stateCV(vnp)) == 0);
|
||||
return old_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* tells caller whether or not the current state requires
|
||||
* exclusive access without holding glock.
|
||||
*
|
||||
* @param[in] state vnode state enumeration
|
||||
*
|
||||
* @return whether vnode state is a mutually exclusive state
|
||||
* @retval 0 no, state is re-entrant
|
||||
* @retval 1 yes, state is mutually exclusive
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*/
|
||||
static_inline int
|
||||
VnIsExclusiveState(VnState state)
|
||||
{
|
||||
switch (state) {
|
||||
case VN_STATE_RELEASING:
|
||||
case VN_STATE_CLOSING:
|
||||
case VN_STATE_ALLOC:
|
||||
case VN_STATE_LOAD:
|
||||
case VN_STATE_EXCLUSIVE:
|
||||
case VN_STATE_STORE:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tell caller whether vnode state is an error condition.
|
||||
*
|
||||
* @param[in] state vnode state enumeration
|
||||
*
|
||||
* @return whether vnode state is in error state
|
||||
* @retval 0 state is not an error state
|
||||
* @retval 1 state is an error state
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*/
|
||||
static_inline int
|
||||
VnIsErrorState(VnState state)
|
||||
{
|
||||
switch (state) {
|
||||
case VN_STATE_ERROR:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tell caller whether vnode state is valid.
|
||||
*
|
||||
* @param[in] state vnode state enumeration
|
||||
*
|
||||
* @return whether vnode state is a mutually exclusive state
|
||||
* @retval 0 no, state is not valid
|
||||
* @retval 1 yes, state is a valid enumeration member
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*/
|
||||
static_inline int
|
||||
VnIsValidState(VnState state)
|
||||
{
|
||||
if ((state >= 0) &&
|
||||
(state < VN_STATE_COUNT)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* wait for the vnode to change states.
|
||||
*
|
||||
* @param[in] vnp vnode object pointer
|
||||
*
|
||||
* @pre VOL_LOCK held; ref held on vnode
|
||||
*
|
||||
* @post VOL_LOCK held; vnode state has changed from previous value
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*/
|
||||
static_inline void
|
||||
VnWaitStateChange_r(Vnode * vnp)
|
||||
{
|
||||
VnState state_save = Vn_state(vnp);
|
||||
|
||||
assert(Vn_refcount(vnp));
|
||||
do {
|
||||
VOL_CV_WAIT(&Vn_stateCV(vnp));
|
||||
} while (Vn_state(vnp) == state_save);
|
||||
assert(!(Vn_stateFlags(vnp) & VN_ON_LRU));
|
||||
}
|
||||
|
||||
/**
|
||||
* wait for blocking ops to end.
|
||||
*
|
||||
* @pre VOL_LOCK held; ref held on vnode
|
||||
*
|
||||
* @post VOL_LOCK held; vnode not in exclusive state
|
||||
*
|
||||
* @param[in] vnp vnode object pointer
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*/
|
||||
static_inline void
|
||||
VnWaitExclusiveState_r(Vnode * vnp)
|
||||
{
|
||||
assert(Vn_refcount(vnp));
|
||||
while (VnIsExclusiveState(Vn_state(vnp))) {
|
||||
VOL_CV_WAIT(&Vn_stateCV(vnp));
|
||||
}
|
||||
assert(!(Vn_stateFlags(vnp) & VN_ON_LRU));
|
||||
}
|
||||
|
||||
/**
|
||||
* wait until vnode is in non-exclusive state, and there are no active readers.
|
||||
*
|
||||
* @param[in] vnp vnode object pointer
|
||||
*
|
||||
* @pre VOL_LOCK held; ref held on vnode
|
||||
*
|
||||
* @post VOL_LOCK held; vnode is in non-exclusive state and has no active readers
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*/
|
||||
static_inline void
|
||||
VnWaitQuiescent_r(Vnode * vnp)
|
||||
{
|
||||
assert(Vn_refcount(vnp));
|
||||
while (VnIsExclusiveState(Vn_state(vnp)) ||
|
||||
Vn_readers(vnp)) {
|
||||
VOL_CV_WAIT(&Vn_stateCV(vnp));
|
||||
}
|
||||
assert(!(Vn_stateFlags(vnp) & VN_ON_LRU));
|
||||
}
|
||||
|
||||
/**
|
||||
* register a new reader on a vnode.
|
||||
*
|
||||
* @param[in] vnp vnode object pointer
|
||||
*
|
||||
* @pre VOL_LOCK held.
|
||||
* ref held on vnode.
|
||||
* vnode in VN_STATE_READ or VN_STATE_ONLINE
|
||||
*
|
||||
* @post refcount incremented.
|
||||
* state set to VN_STATE_READ.
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*
|
||||
* @internal vnode package internal use only
|
||||
*/
|
||||
static_inline void
|
||||
VnBeginRead_r(Vnode * vnp)
|
||||
{
|
||||
if (!Vn_readers(vnp)) {
|
||||
assert(Vn_state(vnp) == VN_STATE_ONLINE);
|
||||
VnChangeState_r(vnp, VN_STATE_READ);
|
||||
}
|
||||
Vn_readers(vnp)++;
|
||||
assert(Vn_state(vnp) == VN_STATE_READ);
|
||||
}
|
||||
|
||||
/**
|
||||
* deregister a reader on a vnode.
|
||||
*
|
||||
* @param[in] vnp vnode object pointer
|
||||
*
|
||||
* @pre VOL_LOCK held.
|
||||
* ref held on vnode.
|
||||
* read ref held on vnode.
|
||||
* vnode in VN_STATE_READ.
|
||||
*
|
||||
* @post refcount decremented.
|
||||
* when count reaches zero, state set to VN_STATE_ONLINE.
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*
|
||||
* @internal vnode package internal use only
|
||||
*/
|
||||
static_inline void
|
||||
VnEndRead_r(Vnode * vnp)
|
||||
{
|
||||
assert(Vn_readers(vnp) > 0);
|
||||
Vn_readers(vnp)--;
|
||||
if (!Vn_readers(vnp)) {
|
||||
assert(pthread_cond_broadcast(&Vn_stateCV(vnp)) == 0);
|
||||
VnChangeState_r(vnp, VN_STATE_ONLINE);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* AFS_DEMAND_ATTACH_FS */
|
||||
|
||||
#endif /* _AFS_VOL_VNODE_INLINE_H */
|
1770
src/vol/volume.c
1770
src/vol/volume.c
File diff suppressed because it is too large
Load Diff
278
src/vol/volume.h
278
src/vol/volume.h
@ -6,7 +6,7 @@
|
||||
* License. For details, see the LICENSE file in the top-level source
|
||||
* directory or online at http://www.openafs.org/dl/license10.html
|
||||
*
|
||||
* Portions Copyright (c) 2006 Sine Nomine Associates
|
||||
* Portions Copyright (c) 2006-2008 Sine Nomine Associates
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -29,6 +29,38 @@ typedef bit32 FileOffset; /* Offset in this file */
|
||||
#include "daemon_com.h"
|
||||
#include "fssync.h"
|
||||
|
||||
#if 0
|
||||
/** turn this on if you suspect a volume package locking bug */
|
||||
#define VOL_LOCK_DEBUG 1
|
||||
#endif
|
||||
|
||||
#ifdef VOL_LOCK_DEBUG
|
||||
#define VOL_LOCK_ASSERT_HELD \
|
||||
assert(vol_glock_holder == pthread_self())
|
||||
#define VOL_LOCK_ASSERT_UNHELD \
|
||||
assert(vol_glock_holder == 0)
|
||||
#define _VOL_LOCK_SET_HELD \
|
||||
vol_glock_holder = pthread_self()
|
||||
#define _VOL_LOCK_SET_UNHELD \
|
||||
vol_glock_holder = 0
|
||||
#define VOL_LOCK_DBG_CV_WAIT_END \
|
||||
do { \
|
||||
VOL_LOCK_ASSERT_UNHELD; \
|
||||
_VOL_LOCK_SET_HELD; \
|
||||
} while(0)
|
||||
#define VOL_LOCK_DBG_CV_WAIT_BEGIN \
|
||||
do { \
|
||||
VOL_LOCK_ASSERT_HELD; \
|
||||
_VOL_LOCK_SET_UNHELD; \
|
||||
} while(0)
|
||||
#else
|
||||
#define VOL_LOCK_ASSERT_HELD
|
||||
#define VOL_LOCK_ASSERT_UNHELD
|
||||
#define VOL_LOCK_DBG_CV_WAIT_BEGIN
|
||||
#define VOL_LOCK_DBG_CV_WAIT_END
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef AFS_PTHREAD_ENV
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
@ -37,10 +69,33 @@ extern pthread_mutex_t vol_trans_mutex;
|
||||
extern pthread_cond_t vol_put_volume_cond;
|
||||
extern pthread_cond_t vol_sleep_cond;
|
||||
extern int vol_attach_threads;
|
||||
#ifdef VOL_LOCK_DEBUG
|
||||
extern pthread_t vol_glock_holder;
|
||||
#define VOL_LOCK \
|
||||
do { \
|
||||
assert(pthread_mutex_lock(&vol_glock_mutex) == 0); \
|
||||
assert(vol_glock_holder == 0); \
|
||||
vol_glock_holder = pthread_self(); \
|
||||
} while (0)
|
||||
#define VOL_UNLOCK \
|
||||
do { \
|
||||
VOL_LOCK_ASSERT_HELD; \
|
||||
vol_glock_holder = 0; \
|
||||
assert(pthread_mutex_unlock(&vol_glock_mutex) == 0); \
|
||||
} while (0)
|
||||
#define VOL_CV_WAIT(cv) \
|
||||
do { \
|
||||
VOL_LOCK_DBG_CV_WAIT_BEGIN; \
|
||||
assert(pthread_cond_wait((cv), &vol_glock_mutex) == 0); \
|
||||
VOL_LOCK_DBG_CV_WAIT_END; \
|
||||
} while (0)
|
||||
#else /* !VOL_LOCK_DEBUG */
|
||||
#define VOL_LOCK \
|
||||
assert(pthread_mutex_lock(&vol_glock_mutex) == 0)
|
||||
#define VOL_UNLOCK \
|
||||
assert(pthread_mutex_unlock(&vol_glock_mutex) == 0)
|
||||
#define VOL_CV_WAIT(cv) assert(pthread_cond_wait((cv), &vol_glock_mutex) == 0)
|
||||
#endif /* !VOL_LOCK_DEBUG */
|
||||
#define VSALVSYNC_LOCK \
|
||||
assert(pthread_mutex_lock(&vol_salvsync_mutex) == 0)
|
||||
#define VSALVSYNC_UNLOCK \
|
||||
@ -72,6 +127,15 @@ extern int (*V_BreakVolumeCallbacks) ();
|
||||
extern int (*vol_PollProc) ();
|
||||
#define DOPOLL ((vol_PollProc)? (*vol_PollProc)() : 0)
|
||||
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
/**
|
||||
* variable error return code based upon programType and DAFS presence
|
||||
*/
|
||||
#define DAFS_VSALVAGE ((programType == fileServer) ? VSALVAGING : VSALVAGE)
|
||||
#else
|
||||
#define DAFS_VSALVAGE (VSALVAGE)
|
||||
#endif
|
||||
|
||||
struct versionStamp { /* Version stamp for critical volume files */
|
||||
bit32 magic; /* Magic number */
|
||||
bit32 version; /* Version number of this file, or software
|
||||
@ -79,45 +143,55 @@ struct versionStamp { /* Version stamp for critical volume files */
|
||||
};
|
||||
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
/*
|
||||
* demand attach fs
|
||||
* volume state machine
|
||||
/**
|
||||
* demand attach volume state enumeration.
|
||||
*
|
||||
* these must be contiguous in order for IsValidState() to work correctly
|
||||
* @note values must be contiguous in order for VIsValidState() to work correctly
|
||||
*/
|
||||
#define VOL_STATE_UNATTACHED 0 /* volume is unattached */
|
||||
#define VOL_STATE_PREATTACHED 1 /* volume has been pre-attached */
|
||||
#define VOL_STATE_ATTACHING 2 /* volume is transitioning to fully attached */
|
||||
#define VOL_STATE_ATTACHED 3 /* volume has been fully attached */
|
||||
#define VOL_STATE_UPDATING 4 /* volume is updating on-disk structures */
|
||||
#define VOL_STATE_GET_BITMAP 5 /* volume is getting bitmap entries */
|
||||
#define VOL_STATE_HDR_LOADING 6 /* volume is loading disk header */
|
||||
#define VOL_STATE_HDR_ATTACHING 7 /* volume is getting a header from the LRU */
|
||||
#define VOL_STATE_SHUTTING_DOWN 8 /* volume is shutting down */
|
||||
#define VOL_STATE_GOING_OFFLINE 9 /* volume is going offline */
|
||||
#define VOL_STATE_OFFLINING 10 /* volume is transitioning to offline */
|
||||
#define VOL_STATE_DETACHING 11 /* volume is transitioning to detached */
|
||||
#define VOL_STATE_SALVSYNC_REQ 12 /* volume is blocked on a salvsync request */
|
||||
#define VOL_STATE_SALVAGING 13 /* volume is being salvaged */
|
||||
#define VOL_STATE_ERROR 14 /* volume is in an error state */
|
||||
#define VOL_STATE_FREED 15 /* debugging aid */
|
||||
typedef enum {
|
||||
VOL_STATE_UNATTACHED = 0, /**< volume is unattached */
|
||||
VOL_STATE_PREATTACHED = 1, /**< volume has been pre-attached */
|
||||
VOL_STATE_ATTACHING = 2, /**< volume is transitioning to fully attached */
|
||||
VOL_STATE_ATTACHED = 3, /**< volume has been fully attached */
|
||||
VOL_STATE_UPDATING = 4, /**< volume is updating on-disk structures */
|
||||
VOL_STATE_GET_BITMAP = 5, /**< volume is getting bitmap entries */
|
||||
VOL_STATE_HDR_LOADING = 6, /**< volume is loading disk header */
|
||||
VOL_STATE_HDR_ATTACHING = 7, /**< volume is getting a header from the LRU */
|
||||
VOL_STATE_SHUTTING_DOWN = 8, /**< volume is shutting down */
|
||||
VOL_STATE_GOING_OFFLINE = 9, /**< volume is going offline */
|
||||
VOL_STATE_OFFLINING = 10, /**< volume is transitioning to offline */
|
||||
VOL_STATE_DETACHING = 11, /**< volume is transitioning to detached */
|
||||
VOL_STATE_SALVSYNC_REQ = 12, /**< volume is blocked on a salvsync request */
|
||||
VOL_STATE_SALVAGING = 13, /**< volume is being salvaged */
|
||||
VOL_STATE_ERROR = 14, /**< volume is in an error state */
|
||||
VOL_STATE_VNODE_ALLOC = 15, /**< volume is busy allocating a new vnode */
|
||||
VOL_STATE_VNODE_GET = 16, /**< volume is busy getting vnode disk data */
|
||||
VOL_STATE_VNODE_CLOSE = 17, /**< volume is busy closing vnodes */
|
||||
VOL_STATE_VNODE_RELEASE = 18, /**< volume is busy releasing vnodes */
|
||||
VOL_STATE_VLRU_ADD = 19, /**< volume is busy being added to a VLRU queue */
|
||||
/* please add new states directly above this line */
|
||||
VOL_STATE_FREED = 20, /**< debugging aid */
|
||||
VOL_STATE_COUNT = 21, /**< total number of valid states */
|
||||
} VolState;
|
||||
|
||||
#define VOL_STATE_COUNT 16 /* total number of valid states */
|
||||
|
||||
/* V_attachFlags bits */
|
||||
#define VOL_HDR_ATTACHED 0x1 /* volume header is attached to Volume struct */
|
||||
#define VOL_HDR_LOADED 0x2 /* volume header contents are valid */
|
||||
#define VOL_HDR_IN_LRU 0x4 /* volume header is in LRU */
|
||||
#define VOL_IN_HASH 0x8 /* volume is in hash table */
|
||||
#define VOL_ON_VBYP_LIST 0x10 /* volume is on VByP list */
|
||||
#define VOL_IS_BUSY 0x20 /* volume is not to be free()d */
|
||||
#define VOL_ON_VLRU 0x40 /* volume is on the VLRU */
|
||||
#define VOL_HDR_DONTSALV 0x80 /* volume header DONTSALVAGE flag is set */
|
||||
/**
|
||||
* V_attachFlags bits.
|
||||
*/
|
||||
enum VolFlags {
|
||||
VOL_HDR_ATTACHED = 0x1, /**< volume header is attached to Volume struct */
|
||||
VOL_HDR_LOADED = 0x2, /**< volume header contents are valid */
|
||||
VOL_HDR_IN_LRU = 0x4, /**< volume header is in LRU */
|
||||
VOL_IN_HASH = 0x8, /**< volume is in hash table */
|
||||
VOL_ON_VBYP_LIST = 0x10, /**< volume is on VByP list */
|
||||
VOL_IS_BUSY = 0x20, /**< volume is not to be free()d */
|
||||
VOL_ON_VLRU = 0x40, /**< volume is on the VLRU */
|
||||
VOL_HDR_DONTSALV = 0x80, /**< volume header DONTSALVAGE flag is set */
|
||||
};
|
||||
|
||||
/* VPrintExtendedCacheStats flags */
|
||||
#define VOL_STATS_PER_CHAIN 0x1 /* compute simple per-chain stats */
|
||||
#define VOL_STATS_PER_CHAIN2 0x2 /* compute per-chain stats that require scanning
|
||||
* every element of the chain */
|
||||
#define VOL_STATS_PER_CHAIN 0x1 /**< compute simple per-chain stats */
|
||||
#define VOL_STATS_PER_CHAIN2 0x2 /**< compute per-chain stats that require scanning
|
||||
* every element of the chain */
|
||||
|
||||
/* VLRU_SetOptions options */
|
||||
#define VLRU_SET_THRESH 1
|
||||
@ -125,14 +199,18 @@ struct versionStamp { /* Version stamp for critical volume files */
|
||||
#define VLRU_SET_MAX 3
|
||||
#define VLRU_SET_ENABLED 4
|
||||
|
||||
/* valid VLRU queue names */
|
||||
#define VLRU_QUEUE_NEW 0 /* LRU queue for new volumes */
|
||||
#define VLRU_QUEUE_MID 1 /* survivor generation */
|
||||
#define VLRU_QUEUE_OLD 2 /* old generation */
|
||||
#define VLRU_QUEUE_CANDIDATE 3 /* soft detach candidate pool */
|
||||
#define VLRU_QUEUE_HELD 4 /* volumes which are not allowed
|
||||
* to be soft detached */
|
||||
#define VLRU_QUEUE_INVALID 5 /* invalid queue id */
|
||||
/**
|
||||
* VLRU queue names.
|
||||
*/
|
||||
typedef enum {
|
||||
VLRU_QUEUE_NEW = 0, /**< LRU queue for new volumes */
|
||||
VLRU_QUEUE_MID = 1, /**< survivor generation */
|
||||
VLRU_QUEUE_OLD = 2, /**< old generation */
|
||||
VLRU_QUEUE_CANDIDATE = 3, /**< soft detach candidate pool */
|
||||
VLRU_QUEUE_HELD = 4, /* volumes which are not allowed
|
||||
* to be soft detached */
|
||||
VLRU_QUEUE_INVALID = 5, /**< invalid queue id */
|
||||
} VLRUQueueName;
|
||||
|
||||
/* default scanner timing parameters */
|
||||
#define VLRU_DEFAULT_OFFLINE_THRESH (60*60*2) /* 2 hours */
|
||||
@ -364,7 +442,9 @@ typedef struct VolumeDiskData {
|
||||
/* Memory resident volume information */
|
||||
/**************************************/
|
||||
|
||||
/* global volume package stats */
|
||||
/**
|
||||
* global volume package stats.
|
||||
*/
|
||||
typedef struct VolPkgStats {
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
/*
|
||||
@ -373,41 +453,37 @@ typedef struct VolPkgStats {
|
||||
*/
|
||||
|
||||
/* levels */
|
||||
afs_uint32 state_levels[VOL_STATE_COUNT];
|
||||
afs_uint32 state_levels[VOL_STATE_COUNT]; /**< volume state transition counters */
|
||||
|
||||
/* counters */
|
||||
afs_uint64 hash_looks; /* number of hash chain element traversals */
|
||||
afs_uint64 hash_reorders; /* number of hash chain reorders */
|
||||
afs_uint64 salvages; /* online salvages since fileserver start */
|
||||
afs_uint64 vol_ops; /* volume operations since fileserver start */
|
||||
afs_uint64 hash_looks; /**< number of hash chain element traversals */
|
||||
afs_uint64 hash_reorders; /**< number of hash chain reorders */
|
||||
afs_uint64 salvages; /**< online salvages since fileserver start */
|
||||
afs_uint64 vol_ops; /**< volume operations since fileserver start */
|
||||
#endif /* AFS_DEMAND_ATTACH_FS */
|
||||
|
||||
afs_uint64 hdr_loads; /* header loads from disk */
|
||||
afs_uint64 hdr_gets; /* header pulls out of LRU */
|
||||
afs_uint64 attaches; /* volume attaches since fileserver start */
|
||||
afs_uint64 soft_detaches; /* soft detach ops since fileserver start */
|
||||
afs_uint64 hdr_loads; /**< header loads from disk */
|
||||
afs_uint64 hdr_gets; /**< header pulls out of LRU */
|
||||
afs_uint64 attaches; /**< volume attaches since fileserver start */
|
||||
afs_uint64 soft_detaches; /**< soft detach ops since fileserver start */
|
||||
|
||||
/* configuration parameters */
|
||||
afs_uint32 hdr_cache_size; /* size of volume header cache */
|
||||
afs_uint32 hdr_cache_size; /**< size of volume header cache */
|
||||
} VolPkgStats;
|
||||
extern VolPkgStats VStats;
|
||||
|
||||
/*
|
||||
* volume header cache supporting structures
|
||||
*/
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
struct volume_hdr_LRU_stats {
|
||||
afs_uint32 free;
|
||||
afs_uint32 used;
|
||||
afs_uint32 attached;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct volume_hdr_LRU_t {
|
||||
struct rx_queue lru;
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
struct volume_hdr_LRU_stats stats;
|
||||
#endif
|
||||
};
|
||||
extern struct volume_hdr_LRU_t volume_hdr_LRU;
|
||||
|
||||
@ -452,51 +528,52 @@ struct VolumeHashChainStats {
|
||||
|
||||
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
/* demand attach fs
|
||||
* extended per-volume statistics
|
||||
/**
|
||||
* DAFS extended per-volume statistics.
|
||||
*
|
||||
* please note that this structure lives across the entire
|
||||
* lifetime of the fileserver process
|
||||
* @note this data lives across the entire
|
||||
* lifetime of the fileserver process
|
||||
*/
|
||||
typedef struct VolumeStats {
|
||||
/* counters */
|
||||
afs_uint64 hash_lookups; /* hash table lookups */
|
||||
afs_uint64 hash_short_circuits; /* short circuited hash lookups (due to cacheCheck) */
|
||||
afs_uint64 hdr_loads; /* header loads from disk */
|
||||
afs_uint64 hdr_gets; /* header pulls out of LRU */
|
||||
afs_uint16 attaches; /* attaches of this volume since fileserver start */
|
||||
afs_uint16 soft_detaches; /* soft detaches of this volume */
|
||||
afs_uint16 salvages; /* online salvages since fileserver start */
|
||||
afs_uint16 vol_ops; /* volume operations since fileserver start */
|
||||
afs_uint64 hash_lookups; /**< hash table lookups */
|
||||
afs_uint64 hash_short_circuits; /**< short circuited hash lookups (due to cacheCheck) */
|
||||
afs_uint64 hdr_loads; /**< header loads from disk */
|
||||
afs_uint64 hdr_gets; /**< header pulls out of LRU */
|
||||
afs_uint16 attaches; /**< attaches of this volume since fileserver start */
|
||||
afs_uint16 soft_detaches; /**< soft detaches of this volume */
|
||||
afs_uint16 salvages; /**< online salvages since fileserver start */
|
||||
afs_uint16 vol_ops; /**< volume operations since fileserver start */
|
||||
|
||||
/* timestamps */
|
||||
afs_uint32 last_attach; /* unix timestamp of last VAttach */
|
||||
afs_uint32 last_get; /* unix timestamp of last VGet/VHold */
|
||||
afs_uint32 last_promote; /* unix timestamp of last VLRU promote/demote */
|
||||
afs_uint32 last_hdr_get; /* unix timestamp of last GetVolumeHeader() */
|
||||
afs_uint32 last_salvage; /* unix timestamp of last initiation of an online salvage */
|
||||
afs_uint32 last_salvage_req; /* unix timestamp of last SALVSYNC request */
|
||||
afs_uint32 last_vol_op; /* unix timestamp of last volume operation */
|
||||
afs_uint32 last_attach; /**< unix timestamp of last VAttach */
|
||||
afs_uint32 last_get; /**< unix timestamp of last VGet/VHold */
|
||||
afs_uint32 last_promote; /**< unix timestamp of last VLRU promote/demote */
|
||||
afs_uint32 last_hdr_get; /**< unix timestamp of last GetVolumeHeader() */
|
||||
afs_uint32 last_hdr_load; /**< unix timestamp of last LoadVolumeHeader() */
|
||||
afs_uint32 last_salvage; /**< unix timestamp of last initiation of an online salvage */
|
||||
afs_uint32 last_salvage_req; /**< unix timestamp of last SALVSYNC request */
|
||||
afs_uint32 last_vol_op; /**< unix timestamp of last volume operation */
|
||||
} VolumeStats;
|
||||
|
||||
/* demand attach fs
|
||||
* online salvager state */
|
||||
/**
|
||||
* DAFS online salvager state.
|
||||
*/
|
||||
typedef struct VolumeOnlineSalvage {
|
||||
afs_uint32 prio; /* number of VGetVolume's since salvage requested */
|
||||
int reason; /* reason for requesting online salvage */
|
||||
byte requested; /* flag specifying that salvage should be scheduled */
|
||||
byte scheduled; /* flag specifying whether online salvage scheduled */
|
||||
byte reserved[2]; /* padding */
|
||||
afs_uint32 prio; /**< number of VGetVolume's since salvage requested */
|
||||
int reason; /**< reason for requesting online salvage */
|
||||
byte requested; /**< flag specifying that salvage should be scheduled */
|
||||
byte scheduled; /**< flag specifying whether online salvage scheduled */
|
||||
byte reserved[2]; /**< padding */
|
||||
} VolumeOnlineSalvage;
|
||||
|
||||
/* demand attach fs
|
||||
* volume LRU state */
|
||||
/**
|
||||
* DAFS Volume LRU state.
|
||||
*/
|
||||
typedef struct VolumeVLRUState {
|
||||
struct rx_queue lru; /* VLRU queue pointers */
|
||||
int idx; /* VLRU generation index */
|
||||
struct rx_queue lru; /**< VLRU queue for this generation */
|
||||
VLRUQueueName idx; /**< VLRU generation index */
|
||||
} VolumeVLRUState;
|
||||
|
||||
typedef afs_uint16 VolState; /* attachment state type */
|
||||
#endif /* AFS_DEMAND_ATTACH_FS */
|
||||
|
||||
typedef struct Volume {
|
||||
@ -541,9 +618,10 @@ typedef struct Volume {
|
||||
afs_uint32 updateTime; /* Time that this volume was put on the updated
|
||||
* volume list--the list of volumes that will be
|
||||
* salvaged should the file server crash */
|
||||
struct rx_queue vnode_list; /**< linked list of cached vnodes for this volume */
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
VolState attach_state; /* what stage of attachment has been completed */
|
||||
afs_uint16 attach_flags; /* flags related to attachment state */
|
||||
afs_uint32 attach_flags; /* flags related to attachment state */
|
||||
pthread_cond_t attach_cv; /* state change condition variable */
|
||||
short nWaiters; /* volume package internal ref count */
|
||||
int chainCacheCheck; /* Volume hash chain cache check */
|
||||
@ -691,12 +769,12 @@ extern void VTakeOffline(register Volume * vp);
|
||||
extern Volume * VLookupVolume_r(Error * ec, VolId volumeId, Volume * hint);
|
||||
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
extern Volume *VPreAttachVolumeByName(Error * ec, char *partition, char *name,
|
||||
int mode);
|
||||
extern Volume *VPreAttachVolumeByName_r(Error * ec, char *partition, char *name,
|
||||
int mode);
|
||||
extern Volume *VPreAttachVolumeById_r(Error * ec, struct DiskPartition * partp,
|
||||
Volume * vp, int volume_id);
|
||||
extern Volume *VPreAttachVolumeByName(Error * ec, char *partition, char *name);
|
||||
extern Volume *VPreAttachVolumeByName_r(Error * ec, char *partition, char *name);
|
||||
extern Volume *VPreAttachVolumeById_r(Error * ec, char * partition,
|
||||
VolId volumeId);
|
||||
extern Volume *VPreAttachVolumeByVp_r(Error * ec, struct DiskPartition * partp,
|
||||
Volume * vp, VolId volume_id);
|
||||
extern Volume *VGetVolumeByVp_r(Error * ec, Volume * vp);
|
||||
extern int VShutdownByPartition_r(struct DiskPartition * dp);
|
||||
extern int VShutdownVolume_r(Volume * vp);
|
||||
@ -708,12 +786,12 @@ extern int VDisconnectSALV(void);
|
||||
extern int VDisconnectSALV_r(void);
|
||||
extern void VPrintExtendedCacheStats(int flags);
|
||||
extern void VPrintExtendedCacheStats_r(int flags);
|
||||
extern VolState VChangeState_r(Volume * vp, VolState new_state);
|
||||
extern void VLRU_SetOptions(int option, afs_uint32 val);
|
||||
extern int VSetVolHashSize(int logsize);
|
||||
extern int VRequestSalvage_r(Volume * vp, int reason, int flags);
|
||||
extern int VRequestSalvage_r(Error * ec, Volume * vp, int reason, int flags);
|
||||
extern int VRegisterVolOp_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
|
||||
extern int VDeregisterVolOp_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
|
||||
extern int VDeregisterVolOp_r(Volume * vp);
|
||||
extern void VCancelReservation_r(Volume * vp);
|
||||
#endif /* AFS_DEMAND_ATTACH_FS */
|
||||
extern int VVolOpLeaveOnline_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
|
||||
extern int VVolOpSetVBusy_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
|
||||
|
202
src/vol/volume_inline.h
Normal file
202
src/vol/volume_inline.h
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright 2005-2008, Sine Nomine Associates and others.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This software has been released under the terms of the IBM Public
|
||||
* License. For details, see the LICENSE file in the top-level source
|
||||
* directory or online at http://www.openafs.org/dl/license10.html
|
||||
*/
|
||||
|
||||
#ifndef _AFS_VOL_VOLUME_INLINE_H
|
||||
#define _AFS_VOL_VOLUME_INLINE_H 1
|
||||
|
||||
#include "volume.h"
|
||||
|
||||
#ifdef AFS_AIX_ENV
|
||||
#define static_inline inline
|
||||
#else
|
||||
#define static_inline static inline
|
||||
#endif
|
||||
|
||||
|
||||
/***************************************************/
|
||||
/* demand attach fs state machine routines */
|
||||
/***************************************************/
|
||||
|
||||
#ifdef AFS_DEMAND_ATTACH_FS
|
||||
/**
|
||||
* tells caller whether or not the current state requires
|
||||
* exclusive access without holding glock.
|
||||
*
|
||||
* @param state volume state enumeration
|
||||
*
|
||||
* @return whether volume state is a mutually exclusive state
|
||||
* @retval 0 no, state is re-entrant
|
||||
* @retval 1 yes, state is mutually exclusive
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*
|
||||
* @note should VOL_STATE_SALVSYNC_REQ be treated as exclusive?
|
||||
*/
|
||||
static_inline int
|
||||
VIsExclusiveState(VolState state)
|
||||
{
|
||||
switch (state) {
|
||||
case VOL_STATE_UPDATING:
|
||||
case VOL_STATE_ATTACHING:
|
||||
case VOL_STATE_GET_BITMAP:
|
||||
case VOL_STATE_HDR_LOADING:
|
||||
case VOL_STATE_HDR_ATTACHING:
|
||||
case VOL_STATE_OFFLINING:
|
||||
case VOL_STATE_DETACHING:
|
||||
case VOL_STATE_VNODE_ALLOC:
|
||||
case VOL_STATE_VNODE_GET:
|
||||
case VOL_STATE_VNODE_CLOSE:
|
||||
case VOL_STATE_VNODE_RELEASE:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tell caller whether V_attachState is an error condition.
|
||||
*
|
||||
* @param state volume state enumeration
|
||||
*
|
||||
* @return whether volume state is in error state
|
||||
* @retval 0 state is not an error state
|
||||
* @retval 1 state is an error state
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*/
|
||||
static_inline int
|
||||
VIsErrorState(VolState state)
|
||||
{
|
||||
switch (state) {
|
||||
case VOL_STATE_ERROR:
|
||||
case VOL_STATE_SALVAGING:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tell caller whether V_attachState is valid.
|
||||
*
|
||||
* @param state volume state enumeration
|
||||
*
|
||||
* @return whether volume state is a mutually exclusive state
|
||||
* @retval 0 no, state is not valid
|
||||
* @retval 1 yes, state is a valid enumeration member
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*
|
||||
* @note do we really want to treat VOL_STATE_FREED as valid?
|
||||
*/
|
||||
static_inline int
|
||||
VIsValidState(VolState state)
|
||||
{
|
||||
if ((state >= 0) &&
|
||||
(state < VOL_STATE_COUNT)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* increment volume-package internal refcount.
|
||||
*
|
||||
* @param vp volume object pointer
|
||||
*
|
||||
* @internal volume package internal use only
|
||||
*
|
||||
* @pre VOL_LOCK must be held
|
||||
*
|
||||
* @post volume waiters refcount is incremented
|
||||
*
|
||||
* @see VCancelReservation_r
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*/
|
||||
static_inline void
|
||||
VCreateReservation_r(Volume * vp)
|
||||
{
|
||||
vp->nWaiters++;
|
||||
}
|
||||
|
||||
/**
|
||||
* wait for the volume to change states.
|
||||
*
|
||||
* @param vp volume object pointer
|
||||
*
|
||||
* @pre VOL_LOCK held; ref held on volume
|
||||
*
|
||||
* @post VOL_LOCK held; volume state has changed from previous value
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*/
|
||||
static_inline void
|
||||
VWaitStateChange_r(Volume * vp)
|
||||
{
|
||||
VolState state_save = V_attachState(vp);
|
||||
|
||||
assert(vp->nWaiters || vp->nUsers);
|
||||
do {
|
||||
VOL_CV_WAIT(&V_attachCV(vp));
|
||||
} while (V_attachState(vp) == state_save);
|
||||
assert(V_attachState(vp) != VOL_STATE_FREED);
|
||||
}
|
||||
|
||||
/**
|
||||
* wait for blocking ops to end.
|
||||
*
|
||||
* @pre VOL_LOCK held; ref held on volume
|
||||
*
|
||||
* @post VOL_LOCK held; volume not in exclusive state
|
||||
*
|
||||
* @param vp volume object pointer
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*/
|
||||
static_inline void
|
||||
VWaitExclusiveState_r(Volume * vp)
|
||||
{
|
||||
assert(vp->nWaiters || vp->nUsers);
|
||||
while (VIsExclusiveState(V_attachState(vp))) {
|
||||
VOL_CV_WAIT(&V_attachCV(vp));
|
||||
}
|
||||
assert(V_attachState(vp) != VOL_STATE_FREED);
|
||||
}
|
||||
|
||||
/**
|
||||
* change state, and notify other threads,
|
||||
* return previous state to caller.
|
||||
*
|
||||
* @param vp pointer to volume object
|
||||
* @param new_state new volume state value
|
||||
* @pre VOL_LOCK held
|
||||
*
|
||||
* @post volume state changed; stats updated
|
||||
*
|
||||
* @return previous volume state
|
||||
*
|
||||
* @note DEMAND_ATTACH_FS only
|
||||
*/
|
||||
static_inline VolState
|
||||
VChangeState_r(Volume * vp, VolState new_state)
|
||||
{
|
||||
VolState old_state = V_attachState(vp);
|
||||
|
||||
/* XXX profiling need to make sure these counters
|
||||
* don't kill performance... */
|
||||
VStats.state_levels[old_state]--;
|
||||
VStats.state_levels[new_state]++;
|
||||
|
||||
V_attachState(vp) = new_state;
|
||||
assert(pthread_cond_broadcast(&V_attachCV(vp)) == 0);
|
||||
return old_state;
|
||||
}
|
||||
|
||||
#endif /* AFS_DEMAND_ATTACH_FS */
|
||||
|
||||
#endif /* _AFS_VOL_VOLUME_INLINE_H */
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user