Blame source/uds/ioFactoryLinuxKernel.c

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
}