blob: 070a8f55bc6f11f2e017e15863407dd0f26aa831 [file] [log] [blame]
/*
* Copyright (C) Red Hat Inc., 2015
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*
* ---------------------------------------
*/
/**
* @file fsal_up.c
*
* @author Soumya Koduri <skoduri@redhat.com>
*
* @brief Upcall Interface for FSAL_GLUSTER
*
*/
#include "config.h"
#include "fsal.h"
#include "fsal_up.h"
#include "gluster_internal.h"
#include "fsal_convert.h"
#include <sys/types.h>
#include <unistd.h>
#include <utime.h>
#include <sys/time.h>
int upcall_inode_invalidate(struct glusterfs_export *glfsexport,
struct glfs_object *object)
{
int rc = -1;
glfs_t *fs = NULL;
char vol_uuid[GLAPI_UUID_LENGTH] = {'\0'};
unsigned char globjhdl[GLAPI_HANDLE_LENGTH];
struct gsh_buffdesc key;
const struct fsal_up_vector *event_func;
fsal_status_t fsal_status = {0, 0};
fs = glfsexport->gl_fs;
if (!fs) {
LogCrit(COMPONENT_FSAL_UP,
"Invalid fs object of the glfsexport(%p)",
glfsexport);
goto out;
}
rc = glfs_h_extract_handle(object, globjhdl+GLAPI_UUID_LENGTH,
GFAPI_HANDLE_LENGTH);
if (rc < 0) {
LogDebug(COMPONENT_FSAL_UP,
"glfs_h_extract_handle failed %p",
fs);
goto out;
}
rc = glfs_get_volumeid(fs, vol_uuid,
GLAPI_UUID_LENGTH);
if (rc < 0) {
LogDebug(COMPONENT_FSAL_UP,
"glfs_get_volumeid failed %p",
fs);
goto out;
}
memcpy(globjhdl, vol_uuid, GLAPI_UUID_LENGTH);
key.addr = &globjhdl;
key.len = GLAPI_HANDLE_LENGTH;
LogDebug(COMPONENT_FSAL_UP, "Received event to process for %p",
fs);
event_func = glfsexport->export.up_ops;
fsal_status = event_func->invalidate_close(
event_func->up_export,
&key,
FSAL_UP_INVALIDATE_CACHE);
rc = fsal_status.major;
if (FSAL_IS_ERROR(fsal_status) && fsal_status.major != ERR_FSAL_NOENT) {
LogWarn(COMPONENT_FSAL_UP,
"Inode_Invalidate event could not be processed for fd %p, rc %d",
glfsexport->gl_fs, rc);
}
out:
glfs_h_close(object);
return rc;
}
void *GLUSTERFSAL_UP_Thread(void *Arg)
{
struct glusterfs_export *glfsexport = Arg;
const struct fsal_up_vector *event_func;
char thr_name[16];
int rc = 0;
struct callback_arg callback;
struct callback_inode_arg *cbk_inode_arg = NULL;
int reason = 0;
int retry = 0;
int errsv = 0;
snprintf(thr_name, sizeof(thr_name),
"fsal_up_%p",
glfsexport->gl_fs);
SetNameFunction(thr_name);
/* Set the FSAL UP functions that will be used to process events. */
event_func = glfsexport->export.up_ops;
if (event_func == NULL) {
LogFatal(COMPONENT_FSAL_UP,
"FSAL up vector does not exist. Can not continue.");
gsh_free(Arg);
return NULL;
}
LogFullDebug(COMPONENT_FSAL_UP,
"Initializing FSAL Callback context for %p.",
glfsexport->gl_fs);
if (!glfsexport->gl_fs) {
LogCrit(COMPONENT_FSAL_UP,
"FSAL Callback interface - Null glfs context.");
goto out;
}
callback.fs = glfsexport->gl_fs;
/* Start querying for events and processing. */
/** @todo : Do batch processing instead */
while (!atomic_fetch_int8_t(&glfsexport->destroy_mode)) {
LogFullDebug(COMPONENT_FSAL_UP,
"Requesting event from FSAL Callback interface for %p.",
glfsexport->gl_fs);
callback.reason = 0;
rc = glfs_h_poll_upcall(glfsexport->gl_fs, &callback);
errsv = errno;
reason = callback.reason;
if (rc != 0) {
/* if ENOMEM retry for couple of times
* and then exit
*/
if ((errsv == ENOMEM) && (retry < 10)) {
sleep(1);
retry++;
continue;
} else {
switch (errsv) {
case ENOMEM:
LogMajor(COMPONENT_FSAL_UP,
"Memory allocation failed during poll_upcall for (%p).",
glfsexport->gl_fs);
abort();
case ENOTSUP:
LogEvent(COMPONENT_FSAL_UP,
"Upcall feature is not supported for (%p).",
glfsexport->gl_fs);
break;
default:
LogCrit(COMPONENT_FSAL_UP,
"Poll upcall failed for %p. rc %d errno %d (%s) reason %d",
glfsexport->gl_fs, rc, errsv,
strerror(errsv), reason);
}
return NULL;
}
}
retry = 0;
LogFullDebug(COMPONENT_FSAL_UP,
"Received upcall event: reason(%d)",
reason);
/* Decide what type of event this is
* inode update / invalidate? */
switch (reason) {
case GFAPI_CBK_EVENT_NULL:
usleep(10);
continue;
case GFAPI_INODE_INVALIDATE:
cbk_inode_arg =
(struct callback_inode_arg *)callback.event_arg;
if (!cbk_inode_arg) {
/* Could be ENOMEM issues. continue */
LogWarn(COMPONENT_FSAL_UP,
"Received NULL upcall event arg");
break;
}
if (cbk_inode_arg->object)
upcall_inode_invalidate(glfsexport,
cbk_inode_arg->object);
if (cbk_inode_arg->p_object)
upcall_inode_invalidate(glfsexport,
cbk_inode_arg->p_object);
if (cbk_inode_arg->oldp_object)
upcall_inode_invalidate(glfsexport,
cbk_inode_arg->oldp_object);
break;
default:
LogWarn(COMPONENT_FSAL_UP, "Unknown event: %d", reason);
continue;
}
if (cbk_inode_arg) {
free(cbk_inode_arg);
cbk_inode_arg = NULL;
}
callback.event_arg = NULL;
}
out:
return NULL;
} /* GLUSTERFSFSAL_UP_Thread */