1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-02 01:18:26 +03:00

bcache: Move the utils to a separate file.

This makes it clearer that they don't access the cache internals.
This commit is contained in:
Joe Thornber 2018-05-03 09:34:41 +01:00
parent b3c41bce3d
commit efad84ebc2
3 changed files with 163 additions and 145 deletions

View File

@ -29,6 +29,7 @@ SOURCES =\
datastruct/btree.c \
datastruct/str_list.c \
device/bcache.c \
device/bcache-utils.c \
device/dev-cache.c \
device/dev-ext.c \
device/dev-io.c \

162
lib/device/bcache-utils.c Normal file
View File

@ -0,0 +1,162 @@
/*
* Copyright (C) 2018 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser 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
*/
#include "bcache.h"
// FIXME: need to define this in a common place (that doesn't pull in deps)
#ifndef SECTOR_SHIFT
#define SECTOR_SHIFT 9
#endif
//----------------------------------------------------------------
static void byte_range_to_block_range(struct bcache *cache, off_t start, size_t len,
block_address *bb, block_address *be)
{
block_address block_size = bcache_block_sectors(cache) << SECTOR_SHIFT;
*bb = start / block_size;
*be = (start + len + block_size - 1) / block_size;
}
void bcache_prefetch_bytes(struct bcache *cache, int fd, off_t start, size_t len)
{
block_address bb, be;
byte_range_to_block_range(cache, start, len, &bb, &be);
while (bb < be) {
bcache_prefetch(cache, fd, bb);
bb++;
}
}
static off_t _min(off_t lhs, off_t rhs)
{
if (rhs < lhs)
return rhs;
return lhs;
}
// These functions are all utilities, they should only use the public
// interface to bcache.
// FIXME: there's common code that can be factored out of these 3
bool bcache_read_bytes(struct bcache *cache, int fd, off_t start, size_t len, void *data)
{
struct block *b;
block_address bb, be, i;
unsigned char *udata = data;
off_t block_size = bcache_block_sectors(cache) << SECTOR_SHIFT;
int errors = 0;
byte_range_to_block_range(cache, start, len, &bb, &be);
for (i = bb; i < be; i++)
bcache_prefetch(cache, fd, i);
for (i = bb; i < be; i++) {
if (!bcache_get(cache, fd, i, 0, &b, NULL)) {
errors++;
continue;
}
if (i == bb) {
off_t block_offset = start % block_size;
size_t blen = _min(block_size - block_offset, len);
memcpy(udata, ((unsigned char *) b->data) + block_offset, blen);
len -= blen;
udata += blen;
} else {
size_t blen = _min(block_size, len);
memcpy(udata, b->data, blen);
len -= blen;
udata += blen;
}
bcache_put(b);
}
return errors ? false : true;
}
bool bcache_write_bytes(struct bcache *cache, int fd, off_t start, size_t len, void *data)
{
struct block *b;
block_address bb, be, i;
unsigned char *udata = data;
off_t block_size = bcache_block_sectors(cache) << SECTOR_SHIFT;
int errors = 0;
byte_range_to_block_range(cache, start, len, &bb, &be);
for (i = bb; i < be; i++)
bcache_prefetch(cache, fd, i);
for (i = bb; i < be; i++) {
if (!bcache_get(cache, fd, i, GF_DIRTY, &b, NULL)) {
errors++;
continue;
}
if (i == bb) {
off_t block_offset = start % block_size;
size_t blen = _min(block_size - block_offset, len);
memcpy(((unsigned char *) b->data) + block_offset, udata, blen);
len -= blen;
udata += blen;
} else {
size_t blen = _min(block_size, len);
memcpy(b->data, udata, blen);
len -= blen;
udata += blen;
}
bcache_put(b);
}
return errors ? false : true;
}
bool bcache_write_zeros(struct bcache *cache, int fd, off_t start, size_t len)
{
struct block *b;
block_address bb, be, i;
off_t block_size = bcache_block_sectors(cache) << SECTOR_SHIFT;
int errors = 0;
byte_range_to_block_range(cache, start, len, &bb, &be);
for (i = bb; i < be; i++)
bcache_prefetch(cache, fd, i);
for (i = bb; i < be; i++) {
if (!bcache_get(cache, fd, i, GF_DIRTY, &b, NULL)) {
errors++;
continue;
}
if (i == bb) {
off_t block_offset = start % block_size;
size_t blen = _min(block_size - block_offset, len);
memset(((unsigned char *) b->data) + block_offset, 0, blen);
len -= blen;
} else {
size_t blen = _min(block_size, len);
memset(b->data, 0, blen);
len -= blen;
}
bcache_put(b);
}
return errors ? false : true;
}
//----------------------------------------------------------------

View File

@ -1034,150 +1034,5 @@ bool bcache_invalidate_fd(struct bcache *cache, int fd)
return r;
}
static void byte_range_to_block_range(struct bcache *cache, off_t start, size_t len,
block_address *bb, block_address *be)
{
block_address block_size = cache->block_sectors << SECTOR_SHIFT;
*bb = start / block_size;
*be = (start + len + block_size - 1) / block_size;
}
void bcache_prefetch_bytes(struct bcache *cache, int fd, off_t start, size_t len)
{
block_address bb, be;
byte_range_to_block_range(cache, start, len, &bb, &be);
while (bb < be) {
bcache_prefetch(cache, fd, bb);
bb++;
}
}
static off_t _min(off_t lhs, off_t rhs)
{
if (rhs < lhs)
return rhs;
return lhs;
}
// These functions are all utilities, they should only use the public
// interface to bcache.
// FIXME: there's common code that can be factored out of these 3
bool bcache_read_bytes(struct bcache *cache, int fd, off_t start, size_t len, void *data)
{
struct block *b;
block_address bb, be, i;
unsigned char *udata = data;
off_t block_size = cache->block_sectors << SECTOR_SHIFT;
int errors = 0;
byte_range_to_block_range(cache, start, len, &bb, &be);
for (i = bb; i < be; i++)
bcache_prefetch(cache, fd, i);
for (i = bb; i < be; i++) {
if (!bcache_get(cache, fd, i, 0, &b, NULL)) {
log_error("bcache_read_bytes failed to get block %u fd %d bb %u be %u",
(uint32_t)i, fd, (uint32_t)bb, (uint32_t)be);
errors++;
continue;
}
if (i == bb) {
off_t block_offset = start % block_size;
size_t blen = _min(block_size - block_offset, len);
memcpy(udata, ((unsigned char *) b->data) + block_offset, blen);
len -= blen;
udata += blen;
} else {
size_t blen = _min(block_size, len);
memcpy(udata, b->data, blen);
len -= blen;
udata += blen;
}
bcache_put(b);
}
return errors ? false : true;
}
bool bcache_write_bytes(struct bcache *cache, int fd, off_t start, size_t len, void *data)
{
struct block *b;
block_address bb, be, i;
unsigned char *udata = data;
off_t block_size = cache->block_sectors << SECTOR_SHIFT;
int errors = 0;
byte_range_to_block_range(cache, start, len, &bb, &be);
for (i = bb; i < be; i++)
bcache_prefetch(cache, fd, i);
for (i = bb; i < be; i++) {
if (!bcache_get(cache, fd, i, GF_DIRTY, &b, NULL)) {
log_error("bcache_write_bytes failed to get block %u fd %d bb %u be %u",
(uint32_t)i, fd, (uint32_t)bb, (uint32_t)be);
errors++;
continue;
}
if (i == bb) {
off_t block_offset = start % block_size;
size_t blen = _min(block_size - block_offset, len);
memcpy(((unsigned char *) b->data) + block_offset, udata, blen);
len -= blen;
udata += blen;
} else {
size_t blen = _min(block_size, len);
memcpy(b->data, udata, blen);
len -= blen;
udata += blen;
}
bcache_put(b);
}
return errors ? false : true;
}
bool bcache_write_zeros(struct bcache *cache, int fd, off_t start, size_t len)
{
struct block *b;
block_address bb, be, i;
off_t block_size = cache->block_sectors << SECTOR_SHIFT;
int errors = 0;
byte_range_to_block_range(cache, start, len, &bb, &be);
for (i = bb; i < be; i++)
bcache_prefetch(cache, fd, i);
for (i = bb; i < be; i++) {
if (!bcache_get(cache, fd, i, GF_DIRTY, &b, NULL)) {
log_error("bcache_write_bytes failed to get block %u fd %d bb %u be %u",
(uint32_t)i, fd, (uint32_t)bb, (uint32_t)be);
errors++;
continue;
}
if (i == bb) {
off_t block_offset = start % block_size;
size_t blen = _min(block_size - block_offset, len);
memset(((unsigned char *) b->data) + block_offset, 0, blen);
len -= blen;
} else {
size_t blen = _min(block_size, len);
memset(b->data, 0, blen);
len -= blen;
}
bcache_put(b);
}
return errors ? false : true;
}
//----------------------------------------------------------------