From b8e4e502d30977f0c09f444ab5f780fc5da104a7 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Wed, 3 Oct 2001 11:06:31 +0000 Subject: [PATCH] o code sync for dev-cache.c o made copyright headers the same o added __attribute ((format ... to print_log so we'll get better compile errors o added iterator to the hash table --- lib/config/config.c | 28 +--- lib/config/config.h | 17 +-- lib/datastruct/hash.c | 25 ++++ lib/datastruct/hash.h | 10 +- lib/datastruct/list.h | 6 +- lib/dev-mgr/dev-cache.c | 288 ++++++++++++++++++++++++-------------- lib/dev-mgr/dev-cache.h | 15 +- lib/dev-mgr/dev-manager.c | 12 +- lib/dev-mgr/dev-manager.h | 17 +-- lib/log/log.c | 19 +-- lib/log/log.h | 26 +--- lib/mm/dbg_malloc.c | 21 +-- lib/mm/dbg_malloc.h | 18 +-- lib/mm/pool.c | 19 +-- libdm/datastruct/list.h | 6 +- 15 files changed, 265 insertions(+), 262 deletions(-) diff --git a/lib/config/config.c b/lib/config/config.c index 3745994cd..47390a796 100644 --- a/lib/config/config.c +++ b/lib/config/config.c @@ -1,31 +1,7 @@ /* - * 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 diff --git a/lib/config/config.h b/lib/config/config.h index 470d77b79..6a2159a2c 100644 --- a/lib/config/config.h +++ b/lib/config/config.h @@ -1,20 +1,7 @@ /* - * 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 diff --git a/lib/datastruct/hash.c b/lib/datastruct/hash.c index c750e3b7a..0e5307023 100644 --- a/lib/datastruct/hash.c +++ b/lib/datastruct/hash.c @@ -181,4 +181,29 @@ void hash_iterate(struct hash_table *t, iterate_fn f) 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); +} diff --git a/lib/datastruct/hash.h b/lib/datastruct/hash.h index b3a063d01..0fd50e9e7 100644 --- a/lib/datastruct/hash.h +++ b/lib/datastruct/hash.h @@ -8,10 +8,12 @@ #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); @@ -20,5 +22,9 @@ void hash_remove(struct hash_table *t, const char *key); 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 diff --git a/lib/datastruct/list.h b/lib/datastruct/list.h index b0c0dd7a3..29b7ec3f8 100644 --- a/lib/datastruct/list.h +++ b/lib/datastruct/list.h @@ -32,9 +32,9 @@ struct list_head { * 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; diff --git a/lib/dev-mgr/dev-cache.c b/lib/dev-mgr/dev-cache.c index c088e2983..a2f8507a7 100644 --- a/lib/dev-mgr/dev-cache.c +++ b/lib/dev-mgr/dev-cache.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001 Sistina Software + * Copyright (C) 2001 Sistina Software (UK) Limited. * * This file is released under the GPL. */ @@ -11,83 +11,163 @@ #include -#define DEV_PATH_LEN 256 +/* + * FIXME: really need to seperate names from the devices since + * multiple names can point to the same device. + */ -struct d_internal { - struct device dev; - - int count; - - int rw; - FILE *fp; +struct dev_iter { + struct hash_node *current; + struct dev_filter *filter; }; -struct { - static pool *mem; +struct dir_list { + struct list_head dir_list; + char *dir[0]; +}; + +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) { - return pool_alloc(_cache.mem, sizeof(struct d_internal)); + 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); } -static struct d_internal *_create_dev(const char *path) +/* + * Get rid of extra slashes in the path string. + */ +static void _collapse_slashes(char *str) +{ + 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 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; + } + + dev->name = normed; + dev->dev = info.st_rdev; + return dev; } - -#define DEV_READ 0 -#define DEV_WRITE 1 -static inline struct FILE *_open_read(const char *path) +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; -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; + 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]); } - } else if (rw == DEV_READ) - di->fp = _open_read(di->dev.path); - else - di->fp = _open_write(di->dev.path); + free(dirent); + } - return di->fp ? 1 : 0; + return 1; } -int init_dev_cache() +static void _full_scan(void) +{ + struct dir_list *dl; + + if (_cache.has_scanned) + return; + + for (dl = _cache.dirs.next; dl != &_cache.dirs; dl = dl->next) + _dir_scan(dl.dir); + + _cache.has_scanned = 1; +} + +int dev_cache_init(void) { if (!(_cache.mem = pool_create(10 * 1024))) { stack; @@ -104,68 +184,70 @@ int init_dev_cache() 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); + struct dir_list *dl; - if (di) - hash_insert(t, name, di); + if (!(dl = _alloc(sizeof(*dl) + strlen(path) + 1))) + return 0; + + strcpy(dl->dir, path); + list_add(dl, _cache.directories); + return 1; +} + +struct device *dev_cache_get(const char *name) +{ + struct device *d = hash_lookup(_cache.devices, name); + if (!d && (d = _create_device(name))) + hash_insert(t, name, d); + + return d; +} + +struct dev_iter *dev_iter_create(struct dev_filter *f) +{ + struct dev_iter *di = dbg_malloc(sizeof(*di)); + + if (!di) + return NULL; + + _full_scan(); + di->current = hash_get_first(); + di->filter = f; + + return di; +} + +void dev_iter_destroy(struct dev_iter *iter) +{ + dbg_free(iter); +} + +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; } - return di ? &di->d : 0; + return NULL; } -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); -} diff --git a/lib/dev-mgr/dev-cache.h b/lib/dev-mgr/dev-cache.h index 074bee0d4..7b1bcc1af 100644 --- a/lib/dev-mgr/dev-cache.h +++ b/lib/dev-mgr/dev-cache.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001 Sistina Software + * Copyright (C) 2001 Sistina Software (UK) Limited. * * This file is released under the GPL. */ @@ -31,7 +31,7 @@ int dev_cache_init(void); 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); /* @@ -45,10 +45,13 @@ struct device *dev_iter_get(struct dev_iter *iter); /* * 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 diff --git a/lib/dev-mgr/dev-manager.c b/lib/dev-mgr/dev-manager.c index 7b79c3bed..2467ceae2 100644 --- a/lib/dev-mgr/dev-manager.c +++ b/lib/dev-mgr/dev-manager.c @@ -124,9 +124,9 @@ struct dev_mgr *init_dev_manager(struct config_node *cn) 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*)); @@ -447,7 +447,7 @@ static int _scan_proc_dev(struct dev_mgr *dm) 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) { @@ -457,7 +457,7 @@ static int _scan_proc_dev(struct dev_mgr *dm) /* We only want block devices ... */ if (!blocksection) continue; - + /* Find the start of the device major name */ while (line[i] != ' ' && line[i] != '\0') i++; @@ -468,13 +468,13 @@ static int _scan_proc_dev(struct dev_mgr *dm) 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; diff --git a/lib/dev-mgr/dev-manager.h b/lib/dev-mgr/dev-manager.h index c2f1c7019..427654dc5 100644 --- a/lib/dev-mgr/dev-manager.h +++ b/lib/dev-mgr/dev-manager.h @@ -20,22 +20,19 @@ #ifndef _LVM_DEV_MANAGER_H #define _LVM_DEV_MANAGER_H +#include #include #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); diff --git a/lib/log/log.c b/lib/log/log.c index b2529097b..cc92be5d7 100644 --- a/lib/log/log.c +++ b/lib/log/log.c @@ -1,22 +1,7 @@ /* - * 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" diff --git a/lib/log/log.h b/lib/log/log.h index 8d478f3db..4ece042c5 100644 --- a/lib/log/log.h +++ b/lib/log/log.h @@ -1,21 +1,7 @@ /* - * 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 @@ -31,7 +17,7 @@ #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); @@ -43,7 +29,8 @@ void init_debug(int level); 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) @@ -58,7 +45,7 @@ void print_log(int level, const char *file, int line, const char *format, ...); #define stack log_debug( "stack trace" ) -/* +/* * Macros to use for messages: * * log_error - always print to stderr @@ -69,7 +56,6 @@ void print_log(int level, const char *file, int line, const char *format, ...); * * 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) diff --git a/lib/mm/dbg_malloc.c b/lib/mm/dbg_malloc.c index 5db89ee51..186f568cd 100644 --- a/lib/mm/dbg_malloc.c +++ b/lib/mm/dbg_malloc.c @@ -1,24 +1,7 @@ /* - * 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 diff --git a/lib/mm/dbg_malloc.h b/lib/mm/dbg_malloc.h index 49ca4d4b5..40aa188cf 100644 --- a/lib/mm/dbg_malloc.h +++ b/lib/mm/dbg_malloc.h @@ -1,21 +1,7 @@ /* - * 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 diff --git a/lib/mm/pool.c b/lib/mm/pool.c index aaeb77edc..bb55ab3e0 100644 --- a/lib/mm/pool.c +++ b/lib/mm/pool.c @@ -1,22 +1,9 @@ /* - * 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 #include diff --git a/libdm/datastruct/list.h b/libdm/datastruct/list.h index b0c0dd7a3..29b7ec3f8 100644 --- a/libdm/datastruct/list.h +++ b/libdm/datastruct/list.h @@ -32,9 +32,9 @@ struct list_head { * 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;