mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
o I'm splitting dev-manager in two. dev-cache is the bottom layer that
handles devices. Dev-manager will sit on this filtering the view.
This commit is contained in:
parent
03aee97527
commit
d41d4056ca
173
lib/dev-mgr/dev-cache.c
Normal file
173
lib/dev-mgr/dev-cache.c
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* tools/lib/dev-manager.h
|
||||
*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
*/
|
||||
|
||||
#include "dev-cache.h"
|
||||
#include "log.h"
|
||||
#include "pool.h"
|
||||
#include "hash.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DEV_PATH_LEN 256
|
||||
|
||||
struct d_internal {
|
||||
struct device dev;
|
||||
|
||||
int count;
|
||||
|
||||
int rw;
|
||||
FILE *fp;
|
||||
};
|
||||
|
||||
struct {
|
||||
static pool *mem;
|
||||
struct hash_table *devices;
|
||||
} _cache;
|
||||
|
||||
static inline struct d_internal *_alloc_dev()
|
||||
{
|
||||
return pool_alloc(_cache.mem, sizeof(struct d_internal));
|
||||
}
|
||||
|
||||
static struct d_internal *_create_dev(const char *path)
|
||||
{
|
||||
/* FIXME: follow sym links */
|
||||
struct stat info;
|
||||
char norm[DEV_PATH_LEN];
|
||||
_normalise_path(norm, path);
|
||||
|
||||
if (stat(path, &info) < 0) {
|
||||
log_sys_error("stat");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: lost the will to program */
|
||||
if () {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define DEV_READ 0
|
||||
#define DEV_WRITE 1
|
||||
static inline struct FILE *_open_read(const char *path)
|
||||
{
|
||||
return fopen(path, "r");
|
||||
}
|
||||
|
||||
static inline struct FILE *_open_write(const char *path)
|
||||
{
|
||||
return fopen(path, "rw");
|
||||
}
|
||||
|
||||
static int _check_open(struct d_internal *di, int rw)
|
||||
{
|
||||
/* is it already open ? */
|
||||
if (dev->fp)
|
||||
return 0;
|
||||
|
||||
if (di->fp) {
|
||||
/* do we need to upgrade a read ? */
|
||||
if (di->rw == DEV_READ && rw == DEV_WRITE) {
|
||||
struct FILE *fp = _open_write(di->dev.path);
|
||||
if (!fp)
|
||||
return 0;
|
||||
|
||||
fclose(di->fp);
|
||||
di->fp = fp;
|
||||
}
|
||||
} else if (rw == DEV_READ)
|
||||
di->fp = _open_read(di->dev.path);
|
||||
else
|
||||
di->fp = _open_write(di->dev.path);
|
||||
|
||||
return di->fp ? 1 : 0;
|
||||
}
|
||||
|
||||
int init_dev_cache()
|
||||
{
|
||||
if (!(_cache.mem = pool_create(10 * 1024))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(_cache.devices = hash_create(128))) {
|
||||
stack;
|
||||
pool_destroy(_cache.mem);
|
||||
_cache.mem = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _close_device(void *d)
|
||||
{
|
||||
struct d_internal *di = (struct d_internal *) d;
|
||||
if (di->fp)
|
||||
fclose(di->fp);
|
||||
}
|
||||
|
||||
void exit_dev_cache()
|
||||
{
|
||||
pool_destroy(_cache.mem);
|
||||
hash_iterate(_cache.devices, _close_devices);
|
||||
hash_destroy(_cache.devices);
|
||||
}
|
||||
|
||||
struct device *get_device(const char *name)
|
||||
{
|
||||
struct d_internal *di = hash_lookup(_cache.devices, name);
|
||||
if (di)
|
||||
di->count++;
|
||||
else {
|
||||
di = _create_device(name);
|
||||
|
||||
if (di)
|
||||
hash_insert(t, name, di);
|
||||
}
|
||||
|
||||
return di ? &di->d : 0;
|
||||
}
|
||||
|
||||
void put_device(struct device *d)
|
||||
{
|
||||
struct d_internal *di = (struct d_internal *) d;
|
||||
if (--di->count < 0)
|
||||
log_error("device reference count < 0");
|
||||
|
||||
else if (di->count == 0)
|
||||
_close_device(di);
|
||||
}
|
||||
|
||||
ssize_t dev_read(struct device *dev, size_t offset, size_t len, void *buffer)
|
||||
{
|
||||
struct d_internal *di = (struct d_internal *) dev;
|
||||
|
||||
if (!_check_open(di, DEV_READ)) {
|
||||
stack;
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
fseek(dev->fp, offset, SEEK_SET);
|
||||
return fread(buffer, 1, len, dev->fp);
|
||||
|
||||
}
|
||||
|
||||
ssize_t dev_write(struct device *dev, size_t offset, size_t len, void *buffer)
|
||||
{
|
||||
struct d_internal *di = (struct d_internal *) dev;
|
||||
|
||||
if (!_check_open(di, DEV_WRITE)) {
|
||||
stack;
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
fseek(dev->fp, offset, SEEK_SET);
|
||||
return fwrite(buffer, 1, len, dev->fp);
|
||||
}
|
30
lib/dev-mgr/dev-cache.h
Normal file
30
lib/dev-mgr/dev-cache.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* tools/lib/dev-manager.h
|
||||
*
|
||||
* Copyright (C) 2001 Sistina Software
|
||||
*
|
||||
* This file is released under the GPL.
|
||||
*/
|
||||
|
||||
#ifndef DEV_CACHE_H
|
||||
#define DEV_CACHE_H
|
||||
|
||||
struct device {
|
||||
char *name;
|
||||
dev_t dev;
|
||||
};
|
||||
|
||||
int init_dev_cache();
|
||||
void exit_dev_cache();
|
||||
|
||||
struct device *get_device(const char *name);
|
||||
void put_device(struct device *d);
|
||||
|
||||
/*
|
||||
* All io should use these routines, rather than opening the devices
|
||||
* by hand. You do not have to call an open routine.
|
||||
*/
|
||||
ssize_t dev_read(struct device *dev, size_t offset, size_t len, void *buffer);
|
||||
ssize_t dev_write(struct device *dev, size_t offset, size_t len, void *buffer);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user