/*
* Copyright (c) 2020 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* $Id: //eng/uds-releases/jasper/src/uds/volumeStore.c#2 $
*/
#include "geometry.h"
#include "indexLayout.h"
#include "logger.h"
#include "uds-error.h"
#include "volumeStore.h"
/*****************************************************************************/
void closeVolumeStore(struct volume_store *volumeStore)
{
#ifdef __KERNEL__
if (volumeStore->vs_client != NULL) {
dm_bufio_client_destroy(volumeStore->vs_client);
volumeStore->vs_client = NULL;
}
#else
if (volumeStore->vs_region != NULL) {
putIORegion(volumeStore->vs_region);
volumeStore->vs_region = NULL;
}
#endif
}
/*****************************************************************************/
void destroyVolumePage(struct volume_page *volumePage)
{
#ifdef __KERNEL__
releaseVolumePage(volumePage);
#else
FREE(volumePage->vp_data);
volumePage->vp_data = NULL;
#endif
}
/*****************************************************************************/
int initializeVolumePage(const struct geometry *geometry,
struct volume_page *volumePage)
{
#ifdef __KERNEL__
volumePage->vp_buffer = NULL;
return UDS_SUCCESS;
#else
return ALLOCATE_IO_ALIGNED(geometry->bytesPerPage, byte, __func__,
&volumePage->vp_data);
#endif
}
/*****************************************************************************/
int openVolumeStore(struct volume_store *volumeStore,
IndexLayout *layout,
unsigned int reservedBuffers __attribute__((unused)),
size_t bytesPerPage)
{
#ifdef __KERNEL__
return openVolumeBufio(layout, bytesPerPage, reservedBuffers,
&volumeStore->vs_client);
#else
volumeStore->vs_bytesPerPage = bytesPerPage;
return openVolumeRegion(layout, &volumeStore->vs_region);
#endif
}
/*****************************************************************************/
void prefetchVolumePages(const struct volume_store *vs __attribute__((unused)),
unsigned int physicalPage __attribute__((unused)),
unsigned int pageCount __attribute__((unused)))
{
#ifdef __KERNEL__
dm_bufio_prefetch(vs->vs_client, physicalPage, pageCount);
#else
// Nothing to do in user mode
#endif
}
/*****************************************************************************/
int prepareToWriteVolumePage(const struct volume_store *volumeStore
__attribute__((unused)),
unsigned int physicalPage
__attribute__((unused)),
struct volume_page *volumePage
__attribute__((unused)))
{
#ifdef __KERNEL__
releaseVolumePage(volumePage);
struct dm_buffer *buffer = NULL;
byte *data = dm_bufio_new(volumeStore->vs_client, physicalPage, &buffer);
if (IS_ERR(data)) {
return -PTR_ERR(data);
}
volumePage->vp_buffer = buffer;
#else
// Nothing to do in user mode
#endif
return UDS_SUCCESS;
}
/*****************************************************************************/
int readVolumePage(const struct volume_store *volumeStore,
unsigned int physicalPage,
struct volume_page *volumePage)
{
#ifdef __KERNEL__
releaseVolumePage(volumePage);
byte *data = dm_bufio_read(volumeStore->vs_client, physicalPage,
&volumePage->vp_buffer);
if (IS_ERR(data)) {
return logWarningWithStringError(-PTR_ERR(data),
"error reading physical page %u",
physicalPage);
}
#else
off_t offset = (off_t) physicalPage * volumeStore->vs_bytesPerPage;
int result = readFromRegion(volumeStore->vs_region, offset,
getPageData(volumePage),
volumeStore->vs_bytesPerPage, NULL);
if (result != UDS_SUCCESS) {
return logWarningWithStringError(result,
"error reading physical page %u",
physicalPage);
}
#endif
return UDS_SUCCESS;
}
/*****************************************************************************/
void releaseVolumePage(struct volume_page *volumePage __attribute__((unused)))
{
#ifdef __KERNEL__
if (volumePage->vp_buffer != NULL) {
dm_bufio_release(volumePage->vp_buffer);
volumePage->vp_buffer = NULL;
}
#else
// Nothing to do in user mode
#endif
}
/*****************************************************************************/
void swapVolumePages(struct volume_page *volumePage1,
struct volume_page *volumePage2)
{
struct volume_page temp = *volumePage1;
*volumePage1 = *volumePage2;
*volumePage2 = temp;
}
/*****************************************************************************/
int syncVolumeStore(const struct volume_store *volumeStore)
{
#ifdef __KERNEL__
int result = -dm_bufio_write_dirty_buffers(volumeStore->vs_client);
#else
int result = syncRegionContents(volumeStore->vs_region);
#endif
if (result != UDS_SUCCESS) {
return logErrorWithStringError(result, "cannot sync chapter to volume");
}
return UDS_SUCCESS;
}
/*****************************************************************************/
int writeVolumePage(const struct volume_store *volumeStore,
unsigned int physicalPage,
struct volume_page *volumePage)
{
#ifdef __KERNEL__
dm_bufio_mark_buffer_dirty(volumePage->vp_buffer);
return UDS_SUCCESS;
#else
off_t offset = (off_t) physicalPage * volumeStore->vs_bytesPerPage;
return writeToRegion(volumeStore->vs_region, offset, getPageData(volumePage),
volumeStore->vs_bytesPerPage,
volumeStore->vs_bytesPerPage);
#endif
}