|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
310c69 |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
310c69 |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
310c69 |
* of the License, or (at your option) any later version.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
310c69 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
310c69 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
310c69 |
* GNU General Public License for more details.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
310c69 |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
310c69 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
310c69 |
* 02110-1301, USA.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* $Id: //eng/uds-releases/jasper/kernelLinux/uds/ioFactoryLinuxKernel.c#9 $
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include <linux/blkdev.h>
|
|
Packit Service |
310c69 |
#include <linux/mount.h>
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "atomicDefs.h"
|
|
Packit Service |
310c69 |
#include "ioFactory.h"
|
|
Packit Service |
310c69 |
#include "logger.h"
|
|
Packit Service |
310c69 |
#include "memoryAlloc.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
enum { BLK_FMODE = FMODE_READ | FMODE_WRITE };
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* A kernel mode IOFactory object controls access to an index stored on a block
|
|
Packit Service |
310c69 |
* device.
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
struct ioFactory {
|
|
Packit Service |
310c69 |
struct block_device *bdev;
|
|
Packit Service |
310c69 |
atomic_t refCount;
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
void getIOFactory(IOFactory *factory)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
atomic_inc(&factory->refCount);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int makeIOFactory(const char *path, IOFactory **factoryPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
struct block_device *bdev;
|
|
Packit Service |
310c69 |
dev_t device = name_to_dev_t(path);
|
|
Packit Service |
310c69 |
if (device != 0) {
|
|
Packit Service |
310c69 |
bdev = blkdev_get_by_dev(device, BLK_FMODE, NULL);
|
|
Packit Service |
310c69 |
} else {
|
|
Packit Service |
310c69 |
bdev = blkdev_get_by_path(path, BLK_FMODE, NULL);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (IS_ERR(bdev)) {
|
|
Packit Service |
310c69 |
logErrorWithStringError(-PTR_ERR(bdev), "%s is not a block device", path);
|
|
Packit Service |
310c69 |
return UDS_INVALID_ARGUMENT;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
IOFactory *factory;
|
|
Packit Service |
310c69 |
int result = ALLOCATE(1, IOFactory, __func__, &factory);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
blkdev_put(bdev, BLK_FMODE);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
factory->bdev = bdev;
|
|
Packit Service |
310c69 |
atomic_set_release(&factory->refCount, 1);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
*factoryPtr = factory;
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
void putIOFactory(IOFactory *factory)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (atomic_add_return(-1, &factory->refCount) <= 0) {
|
|
Packit Service |
310c69 |
blkdev_put(factory->bdev, BLK_FMODE);
|
|
Packit Service |
310c69 |
FREE(factory);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
size_t getWritableSize(IOFactory *factory)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return i_size_read(factory->bdev->bd_inode);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int makeBufio(IOFactory *factory,
|
|
Packit Service |
310c69 |
off_t offset,
|
|
Packit Service |
310c69 |
size_t blockSize,
|
|
Packit Service |
310c69 |
unsigned int reservedBuffers,
|
|
Packit Service |
310c69 |
struct dm_bufio_client **clientPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (offset % SECTOR_SIZE != 0) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_INCORRECT_ALIGNMENT,
|
|
Packit Service |
310c69 |
"offset %zd not multiple of %d",
|
|
Packit Service |
310c69 |
offset, SECTOR_SIZE);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (blockSize % UDS_BLOCK_SIZE != 0) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_INCORRECT_ALIGNMENT,
|
|
Packit Service |
310c69 |
"blockSize %zd not multiple of %d",
|
|
Packit Service |
310c69 |
blockSize, UDS_BLOCK_SIZE);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
struct dm_bufio_client *client = dm_bufio_client_create(factory->bdev,
|
|
Packit Service |
310c69 |
blockSize,
|
|
Packit Service |
310c69 |
reservedBuffers, 0,
|
|
Packit Service |
310c69 |
NULL, NULL);
|
|
Packit Service |
310c69 |
if (IS_ERR(client)) {
|
|
Packit Service |
310c69 |
return -PTR_ERR(client);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
dm_bufio_set_sector_offset(client, offset >> SECTOR_SHIFT);
|
|
Packit Service |
310c69 |
*clientPtr = client;
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int openBufferedReader(IOFactory *factory,
|
|
Packit Service |
310c69 |
off_t offset,
|
|
Packit Service |
310c69 |
size_t size,
|
|
Packit Service |
310c69 |
BufferedReader **readerPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (size % UDS_BLOCK_SIZE != 0) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_INCORRECT_ALIGNMENT,
|
|
Packit Service |
310c69 |
"region size %zd is not multiple of %d",
|
|
Packit Service |
310c69 |
size, UDS_BLOCK_SIZE);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
struct dm_bufio_client *client = NULL;
|
|
Packit Service |
310c69 |
int result = makeBufio(factory, offset, UDS_BLOCK_SIZE, 1, &client);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = makeBufferedReader(factory, client, size / UDS_BLOCK_SIZE,
|
|
Packit Service |
310c69 |
readerPtr);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
dm_bufio_client_destroy(client);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*****************************************************************************/
|
|
Packit Service |
310c69 |
int openBufferedWriter(IOFactory *factory,
|
|
Packit Service |
310c69 |
off_t offset,
|
|
Packit Service |
310c69 |
size_t size,
|
|
Packit Service |
310c69 |
BufferedWriter **writerPtr)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (size % UDS_BLOCK_SIZE != 0) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_INCORRECT_ALIGNMENT,
|
|
Packit Service |
310c69 |
"region size %zd is not multiple of %d",
|
|
Packit Service |
310c69 |
size, UDS_BLOCK_SIZE);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
struct dm_bufio_client *client = NULL;
|
|
Packit Service |
310c69 |
int result = makeBufio(factory, offset, UDS_BLOCK_SIZE, 1, &client);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
result = makeBufferedWriter(factory, client, size / UDS_BLOCK_SIZE,
|
|
Packit Service |
310c69 |
writerPtr);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
dm_bufio_client_destroy(client);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|