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:
parent
b3c41bce3d
commit
efad84ebc2
@ -29,6 +29,7 @@ SOURCES =\
|
|||||||
datastruct/btree.c \
|
datastruct/btree.c \
|
||||||
datastruct/str_list.c \
|
datastruct/str_list.c \
|
||||||
device/bcache.c \
|
device/bcache.c \
|
||||||
|
device/bcache-utils.c \
|
||||||
device/dev-cache.c \
|
device/dev-cache.c \
|
||||||
device/dev-ext.c \
|
device/dev-ext.c \
|
||||||
device/dev-io.c \
|
device/dev-io.c \
|
||||||
|
162
lib/device/bcache-utils.c
Normal file
162
lib/device/bcache-utils.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
@ -1034,150 +1034,5 @@ bool bcache_invalidate_fd(struct bcache *cache, int fd)
|
|||||||
return r;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user