/*
- * tools/lib/lvm_config.c
- *
- * Copyright (C) 2001 Sistina Software
- *
- *
- * This LVM library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This LVM library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this LVM library; if not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA
- *
- */
-
-/*
- * Changelog
- *
- * 17/04/2001 - First version [Joe Thornber]
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
*
+ * This file is released under the GPL.
*/
#include <sys/types.h>
/*
- * Copyright (C) 2001 Sistina Software
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
*
- * This LVM library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This LVM library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this LVM library; if not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA
+ * This file is released under the GPL.
*/
#ifndef _LVM_CONFIG_H
f(c->data);
}
+void *hash_get_data(struct hash_table *t, struct hash_node *n)
+{
+ return n->data;
+}
+
+static struct hash_node *_next_slot(struct hash_table *t, unsigned int s)
+{
+ struct hash_node *c = 0;
+ int i;
+
+ for (i = s; i < t->num_slots && !c; i++)
+ c = t->slots[i];
+
+ return c;
+}
+
+struct hash_node *hash_get_first(struct hash_table *t)
+{
+ return _next_slot(t, 0);
+}
+
+struct hash_node *hash_get_next(struct hash_table *t, struct hash_node *n)
+{
+ return n->next ? n->next : _next_slot(t, _hash(n->key) + 1);
+}
#define _LVM_HASH_H
struct hash_table;
+struct hash_node;
+
typedef void (*iterate_fn)(void *data);
-struct hash_table *create_hash_table(unsigned size_hint);
-void destroy_hash_table(struct hash_table *t);
+struct hash_table *hash_create(unsigned size_hint);
+void hash_destroy(struct hash_table *t);
char *hash_lookup(struct hash_table *t, const char *key);
void hash_insert(struct hash_table *t, const char *key, void *data);
unsigned hash_get_num_entries(struct hash_table *t);
void hash_iterate(struct hash_table *t, iterate_fn f);
+void *hash_get_data(struct hash_table *t, struct hash_node *n);
+struct hash_node *hash_get_first(struct hash_table *t);
+struct hash_node *hash_get_next(struct hash_table *t, struct hash_node *n);
+
#endif
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
-static __inline__ void __list_add(struct list_head * new,
- struct list_head * prev,
- struct list_head * next)
+static __inline__ void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
{
next->prev = new;
new->next = next;
/*
- * Copyright (C) 2001 Sistina Software
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
*/
#include <stdlib.h>
-#define DEV_PATH_LEN 256
-
-struct d_internal {
- struct device dev;
+/*
+ * FIXME: really need to seperate names from the devices since
+ * multiple names can point to the same device.
+ */
- int count;
+struct dev_iter {
+ struct hash_node *current;
+ struct dev_filter *filter;
+};
- int rw;
- FILE *fp;
+struct dir_list {
+ struct list_head dir_list;
+ char *dir[0];
};
-struct {
- static pool *mem;
+static struct {
+ struct pool *mem;
struct hash_table *devices;
+
+ int has_scanned;
+ struct list_head dirs;
+
} _cache;
-static inline struct d_internal *_alloc_dev()
+
+#define _alloc(x) pool_alloc(_cache.mem, (x))
+#define _free(x) pool_free(_cache.mem, (x))
+
+/*
+ * return a new path for the destination of the path.
+ */
+static char * _follow_link(const char *path, struct stat *info)
+{
+ char buffer[PATH_MAX + 1], *r;
+ int n;
+ n = readlink(path, buffer);
+
+ if (n <= 0)
+ return NULL;
+
+ buffer[n] = '\0';
+
+ if (stat(buffer, info) < 0) {
+ log_sys_err("stat");
+ return NULL;
+ }
+
+ return pool_strdup(_cache.mem, buffer);
+}
+
+/*
+ * Get rid of extra slashes in the path string.
+ */
+static void _collapse_slashes(char *str)
{
- return pool_alloc(_cache.mem, sizeof(struct d_internal));
+ char *ptr;
+ int was_slash = 0;
+
+ for (ptr = str; *ptr; ptr++) {
+ if (*ptr == '/') {
+ if (was_slash)
+ continue;
+
+ was_slash = 1;
+ } else
+ was_slash = 0;
+ *str++ = *ptr;
+ }
+
+ *str = *ptr;
}
-static struct d_internal *_create_dev(const char *path)
+static struct device *_create_dev(const char *path)
{
- /* FIXME: follow sym links */
struct stat info;
- char norm[DEV_PATH_LEN];
- _normalise_path(norm, path);
+ struct device *dev;
+ char *normed = _collapse_slashes(path);
- if (stat(path, &info) < 0) {
+ if (!normed) {
+ stack;
+ return NULL;
+ }
+
+ if (stat(normed, &info) < 0) {
log_sys_error("stat");
- return 0;
+ return NULL;
}
- /* FIXME: lost the will to program */
- if () {
+ if (S_ISLNK(info.st_mode)) {
+ char *new_path;
+ log_debug("%s is a symbolic link, following\n", normed);
+ normed = _follow_link(normed, &info);
+ if (!normed)
+ return NULL;
+ }
+ if (!S_ISBLK(info.st_mode)) {
+ log_debug("%s is not a block device\n", normed);
+ return NULL;
}
-}
+ if (!(dev = _alloc(sizeof(*dev)))) {
+ stack;
+ return NULL;
+ }
-#define DEV_READ 0
-#define DEV_WRITE 1
-static inline struct FILE *_open_read(const char *path)
+ dev->name = normed;
+ dev->dev = info.st_rdev;
+ return dev;
+}
+
+static struct device *_add(const char *dir, const char *path)
{
- return fopen(path, "r");
+ struct device *d;
+ int len = strlen(dir) + strlen(path) + 2;
+ char *buffer = _alloc(len);
+
+ snprintf(buffer, len, "%s/%s", path);
+ d = dev_cache_get(path);
+
+ if (!d)
+ _free(buffer); /* pool_free is safe in this case */
+
+ return d;
}
-static inline struct FILE *_open_write(const char *path)
+static int _dir_scan(const char *dir)
{
- return fopen(path, "rw");
+ int n, dirent_count;
+ struct dirent **dirent;
+
+ dirent_count = scandir(dir, &dirent, NULL, alphasort);
+ if (dirent_count > 0) {
+ for (n = 0; n < dirent_count; n++) {
+ _add(dir, dirent[n]->d_name);
+ free(dirent[n]);
+ }
+ free(dirent);
+ }
+
+ return 1;
}
-static int _check_open(struct d_internal *di, int rw)
+static void _full_scan(void)
{
- /* is it already open ? */
- if (dev->fp)
- return 0;
+ struct dir_list *dl;
- 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;
+ if (_cache.has_scanned)
+ return;
- 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);
+ for (dl = _cache.dirs.next; dl != &_cache.dirs; dl = dl->next)
+ _dir_scan(dl.dir);
- return di->fp ? 1 : 0;
+ _cache.has_scanned = 1;
}
-int init_dev_cache()
+int dev_cache_init(void)
{
if (!(_cache.mem = pool_create(10 * 1024))) {
stack;
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()
+void dev_cache_exit(void)
{
pool_destroy(_cache.mem);
- hash_iterate(_cache.devices, _close_devices);
hash_destroy(_cache.devices);
}
-struct device *get_device(const char *name)
+int dev_cache_add_dir(const char *path)
{
- 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);
- }
+ struct dir_list *dl;
- return di ? &di->d : 0;
+ if (!(dl = _alloc(sizeof(*dl) + strlen(path) + 1)))
+ return 0;
+
+ strcpy(dl->dir, path);
+ list_add(dl, _cache.directories);
+ return 1;
}
-void put_device(struct device *d)
+struct device *dev_cache_get(const char *name)
{
- struct d_internal *di = (struct d_internal *) d;
- if (--di->count < 0)
- log_error("device reference count < 0");
+ struct device *d = hash_lookup(_cache.devices, name);
+ if (!d && (d = _create_device(name)))
+ hash_insert(t, name, d);
- else if (di->count == 0)
- _close_device(di);
+ return d;
}
-ssize_t dev_read(struct device *dev, size_t offset, size_t len, void *buffer)
+struct dev_iter *dev_iter_create(struct dev_filter *f)
{
- struct d_internal *di = (struct d_internal *) dev;
+ struct dev_iter *di = dbg_malloc(sizeof(*di));
- if (!_check_open(di, DEV_READ)) {
- stack;
- return -EPERM;
- }
+ if (!di)
+ return NULL;
- fseek(dev->fp, offset, SEEK_SET);
- return fread(buffer, 1, len, dev->fp);
+ _full_scan();
+ di->current = hash_get_first();
+ di->filter = f;
+ return di;
}
-ssize_t dev_write(struct device *dev, size_t offset, size_t len, void *buffer)
+void dev_iter_destroy(struct dev_iter *iter)
{
- struct d_internal *di = (struct d_internal *) dev;
+ dbg_free(iter);
+}
- if (!_check_open(di, DEV_WRITE)) {
- stack;
- return -EPERM;
+static inline struct device *_iter_next(struct dev_iter *iter)
+{
+ struct device *d = hash_get_data(_cache.devices, iter->current);
+ iter->current = hash_next(_cache.devices, iter->current);
+ return d;
+}
+
+struct device *dev_iter_get(struct dev_iter *iter)
+{
+ while (iter->current) {
+ struct device *d = _iter_next(iter);
+ if (!iter->filter ||
+ iter->filter->pass_filter(iter->filter, d))
+ return d;
}
- fseek(dev->fp, offset, SEEK_SET);
- return fwrite(buffer, 1, len, dev->fp);
+ return NULL;
}
+
+
+
/*
- * Copyright (C) 2001 Sistina Software
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
*/
void dev_cache_exit(void);
int dev_cache_add_dir(const char *path);
-struct device *dev_cache_get(const char *name);
+struct device *dev_cache_get(const char *name, struct dev_filter *f);
/*
/*
* All io should use these routines, rather than opening the devices
- * by hand. You do not have to call an open routine.
+ * by hand. You do not have to call an open routine. ATM all io is
+ * immediately flushed.
*/
-__uint64_t dev_get_size(struct device *dev); /* in 512 byte sectors */
-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);
+int dev_get_size(struct device *dev, uint64_t *size); /* in k */
+int64_t dev_read(struct device *dev, uint64_t offset,
+ int64_t len, void *buffer);
+int64_t dev_write(struct device *dev, uint64_t offset,
+ int64_t len, void *buffer);
#endif
memset(dm, 0, sizeof(*dm));
dm->pool = pool;
- if(cn)
+ if(cn)
base_dir = find_config_str(cn, "dev-mgr/base_dir", '/', 0);
- if(!base_dir)
+ if(!base_dir)
base_dir = DEFAULT_BASE_DIR;
dm->devdir = pool_alloc(dm->pool, sizeof(char*));
i = 0;
while (line[i] == ' ' && line[i] != '\0')
i++;
-
+
/* If its not a number it may be name of section */
line_maj = atoi(((char *) (line + i)));
if (line_maj == 0) {
/* We only want block devices ... */
if (!blocksection)
continue;
-
+
/* Find the start of the device major name */
while (line[i] != ' ' && line[i] != '\0')
i++;
match, set the array member corresponding to the
major number to !0 */
for (j = 0; device_names[j] != NULL; j++) {
-
+
dev_len = strlen(device_names[j]);
if (dev_len <= strlen(line + i)) {
if (strncmp (device_names[j],
line + i,
dev_len) == 0) {
-
+
dm->valid_majors[line_maj]='1';
ret++;
break;
#ifndef _LVM_DEV_MANAGER_H
#define _LVM_DEV_MANAGER_H
+#include <stdio.h>
#include <sys/types.h>
#include "config.h"
-struct device {
- char *name;
- dev_t dev;
-};
+struct dev_manager;
+struct dev_iter;
-struct dev_mgr;
-typedef struct _dummy_counter *dev_counter_t;
-
-struct dev_mgr *init_dev_manager(struct config_node *cfg_node);
+struct dev_manager *create_dev_manager();
void fin_dev_manager(struct dev_mgr *dm);
-struct device *dev_by_name(struct dev_mgr *dm, const char *name);
-struct device *dev_by_dev(struct dev_mgr *dm, dev_t d);
+struct device *get_dev_by_name(struct dev_mgr *dm, const char *name);
+struct device *get_dev_by_dev(struct dev_mgr *dm, dev_t d);
+void put_dev(struct dev_mgr *dm, const char *name);
/* either of these trigger a full scan, the first time they're run */
dev_counter_t init_dev_scan(struct dev_mgr *dm);
/*
- * Copyright (C) 2001 Sistina Software
- *
- *
- * This LVM library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This LVM library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this LVM library; if not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
*
+ * This file is released under the GPL.
*/
#include "log.h"
/*
- * Copyright (C) 2001 Sistina Software
- *
- * This LVM library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This LVM library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this LVM library; if not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
*
+ * This file is released under the GPL.
*/
#ifndef _LVM_LOG_H
#define _LOG_FATAL 2
void init_log(FILE *fp);
-void fin_log();
+void fin_log(void);
void init_syslog(int facility);
void fin_syslog(void);
int test_mode(void);
int debug_level(void);
-void print_log(int level, const char *file, int line, const char *format, ...);
+void print_log(int level, const char *file, int line, const char *format, ...)
+ __attribute__ (( format (printf, 4, 5) ));
#define plog(l, x...) print_log(l, __FILE__, __LINE__ , ## x)
#define stack log_debug( "stack trace" )
-/*
+/*
* Macros to use for messages:
*
* log_error - always print to stderr
*
* In addition, messages will be logged to file or syslog if they
* are more serious than the log level specified with -d.
- *
*/
#define log_error(fmt, args...) log_err(fmt , ## args)
/*
- * Copyright (C) 2000, 2001 Sistina Software
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
*
- * lvm is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * lvm is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU CC; see the file COPYING. If not, write to
- * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * TODO:
- *
- * Thread safety seems to have fallen out, put lock back in.
+ * This file is released under the GPL.
*/
#include <assert.h>
/*
- * Copyright (C) 2001 Sistina Software
- *
- * lvm is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * lvm is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU CC; see the file COPYING. If not, write to
- * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
*
+ * This file is released under the GPL.
*/
#ifndef _LVM_DBG_MALLOC_H
/*
- * Copyright (C) 2001 Sistina Software
- *
- * LVM is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * LVM is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with LVM; see the file COPYING. If not, write to
- * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
*
+ * This file is released under the GPL.
*/
+
#include <stdlib.h>
#include <string.h>
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
-static __inline__ void __list_add(struct list_head * new,
- struct list_head * prev,
- struct list_head * next)
+static __inline__ void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
{
next->prev = new;
new->next = next;