#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/device.h>
-#include <sys/devfs.h>
#include <sys/disk.h>
#include <sys/disklabel.h>
#include <sys/dtype.h>
static void dmminphys(struct buf *);
#endif
-struct devfs_bitmap dm_minor_bitmap;
-
/* ***Variable-definitions*** */
struct dev_ops dm_ops = {
{ "dm", 0, D_DISK | D_MPSAFE },
{ .cmd = "names", .fn = dm_dev_list_ioctl},
{ .cmd = "suspend", .fn = dm_dev_suspend_ioctl},
{ .cmd = "remove", .fn = dm_dev_remove_ioctl},
+ { .cmd = "remove_all", .fn = dm_dev_remove_all_ioctl},
{ .cmd = "rename", .fn = dm_dev_rename_ioctl},
{ .cmd = "resume", .fn = dm_dev_resume_ioctl},
{ .cmd = "clear", .fn = dm_table_clear_ioctl},
switch (cmd) {
case MOD_LOAD:
- devfs_clone_bitmap_init(&dm_minor_bitmap);
dm_doinit();
kprintf("Device Mapper version %d.%d.%d loaded\n",
DM_VERSION_MAJOR, DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL);
return error;
}
-/*
- * dm_detach is called to completely destroy & remove a dm disk device.
- */
-int
-dm_detach(dm_dev_t *dmv)
-{
- int minor;
-
- /* Remove device from list and wait for refcnt to drop to zero */
- dm_dev_rem(dmv, NULL, NULL, -1);
-
- /* Destroy active table first. */
- dm_table_destroy(&dmv->table_head, DM_TABLE_ACTIVE);
-
- /* Destroy inactive table if exits, too. */
- dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE);
-
- dm_table_head_destroy(&dmv->table_head);
-
- minor = dkunit(dmv->devt);
- disk_destroy(dmv->diskp);
- devstat_remove_entry(&dmv->stats);
-
- release_dev(dmv->devt);
- devfs_clone_bitmap_put(&dm_minor_bitmap, minor);
-
- /* Destroy device */
- (void)dm_dev_free(dmv);
-
- /* Decrement device counter After removing device */
- --dm_dev_counter; /* XXX: was atomic 64 */
-
- return 0;
-}
-
static void
dm_doinit(void)
{
{
destroy_dev(dmcdev);
- dm_dev_destroy();
- dm_pdev_destroy();
- dm_target_destroy();
+ dm_dev_uninit();
+ dm_pdev_uninit();
+ dm_target_uninit();
return 0;
}
disk_setdiskinfo(disk, &info);
}
+/*
+ * Transform char s to uint64_t offset number.
+ */
+uint64_t
+atoi64(const char *s)
+{
+ uint64_t n;
+ n = 0;
+
+ while (*s != '\0') {
+ if (!isdigit(*s))
+ break;
+
+ n = (10 * n) + (*s - '0');
+ s++;
+ }
+
+ return n;
+}
+
void
dm_builtin_init(void *arg)
{
struct dm_dev_head upcalls;
struct disk *diskp;
- struct lock diskp_mtx;
struct devstat stats;
int dm_dev_create_ioctl(prop_dictionary_t);
int dm_dev_list_ioctl(prop_dictionary_t);
int dm_dev_remove_ioctl(prop_dictionary_t);
+int dm_dev_remove_all_ioctl(prop_dictionary_t);
int dm_dev_rename_ioctl(prop_dictionary_t);
int dm_dev_resume_ioctl(prop_dictionary_t);
int dm_dev_status_ioctl(prop_dictionary_t);
int dm_table_status_ioctl(prop_dictionary_t);
/* dm_target.c */
+int dm_target_init(void);
+int dm_target_uninit(void);
dm_target_t* dm_target_alloc(const char *);
dm_target_t* dm_target_autoload(const char *);
-int dm_target_destroy(void);
int dm_target_insert(dm_target_t *);
prop_array_t dm_target_prop_list(void);
dm_target_t* dm_target_lookup(const char *);
void dm_target_unbusy(dm_target_t *);
void dm_target_busy(dm_target_t *);
-/* XXX temporally add */
-int dm_target_init(void);
-
#define DM_MAX_PARAMS_SIZE 1024
/* Generic function used to convert char to string */
void dm_table_head_destroy(dm_table_head_t *);
/* dm_dev.c */
+int dm_dev_init(void);
+int dm_dev_uninit(void);
dm_dev_t* dm_dev_alloc(void);
void dm_dev_busy(dm_dev_t *);
-int dm_dev_destroy(void);
+int dm_dev_create(dm_dev_t **, const char *, const char *, int);
+int dm_dev_remove(dm_dev_t *);
+int dm_dev_remove_all(int);
+int dm_dev_destroy(dm_dev_t *);
int dm_dev_free(dm_dev_t *);
-int dm_dev_init(void);
int dm_dev_insert(dm_dev_t *);
dm_dev_t* dm_dev_lookup(const char *, const char *, int);
prop_array_t dm_dev_prop_list(void);
void dm_dev_unbusy(dm_dev_t *);
/* dm_pdev.c */
-int dm_pdev_decr(dm_pdev_t *);
-int dm_pdev_destroy(void);
int dm_pdev_init(void);
+int dm_pdev_uninit(void);
+int dm_pdev_decr(dm_pdev_t *);
dm_pdev_t* dm_pdev_insert(const char *);
off_t dm_pdev_correct_dump_offset(dm_pdev_t *, off_t);
#include <sys/types.h>
#include <sys/param.h>
+#include <machine/thread.h>
+#include <sys/thread2.h>
#include <sys/disk.h>
#include <sys/disklabel.h>
+#include <sys/devicestat.h>
+#include <sys/device.h>
+#include <sys/udev.h>
+#include <sys/devfs.h>
#include <sys/ioccom.h>
#include <sys/malloc.h>
#include <dev/disk/dm/dm.h>
#include "netbsd-dm.h"
+extern struct dev_ops dm_ops;
+
+struct devfs_bitmap dm_minor_bitmap;
+uint64_t dm_dev_counter;
+
static dm_dev_t *dm_dev_lookup_name(const char *);
static dm_dev_t *dm_dev_lookup_uuid(const char *);
static dm_dev_t *dm_dev_lookup_minor(int);
struct lock dm_dev_mutex;
-/* dm_dev_mutex must be holdby caller before using disable_dev. */
+/* dm_dev_mutex must be held by caller before using disable_dev. */
static void
disable_dev(dm_dev_t * dmv)
{
+ KKASSERT(lockstatus(&dm_dev_mutex, curthread) == LK_EXCLUSIVE);
+
TAILQ_REMOVE(&dm_dev_list, dmv, next_devlist);
+
lockmgr(&dmv->dev_mtx, LK_EXCLUSIVE);
- lockmgr(&dm_dev_mutex, LK_RELEASE);
while (dmv->ref_cnt != 0)
cv_wait(&dmv->dev_cv, &dmv->dev_mtx);
lockmgr(&dmv->dev_mtx, LK_RELEASE);
if (dmv != NULL) {
disable_dev(dmv);
- return dmv;
- }
-
- if (dm_dev_minor > 0)
- if ((dmv = dm_dev_lookup_minor(dm_dev_minor)) != NULL) {
+ } else if (dm_dev_minor > 0) {
+ if ((dmv = dm_dev_lookup_minor(dm_dev_minor)) != NULL)
disable_dev(dmv);
- return dmv;
- }
- if (dm_dev_name != NULL)
- if ((dmv = dm_dev_lookup_name(dm_dev_name)) != NULL) {
+ } else if (dm_dev_name != NULL) {
+ if ((dmv = dm_dev_lookup_name(dm_dev_name)) != NULL)
disable_dev(dmv);
- return dmv;
- }
- if (dm_dev_uuid != NULL)
- if ((dmv = dm_dev_lookup_name(dm_dev_uuid)) != NULL) {
+ } else if (dm_dev_uuid != NULL) {
+ if ((dmv = dm_dev_lookup_name(dm_dev_uuid)) != NULL)
disable_dev(dmv);
- return dmv;
- }
+ }
+
lockmgr(&dm_dev_mutex, LK_RELEASE);
- return NULL;
+ return dmv;
}
-/*
- * Destroy all devices created in device-mapper. Remove all tables
- * free all allocated memmory.
- */
+
int
-dm_dev_destroy(void)
+dm_dev_create(dm_dev_t **dmvp, const char *name, const char *uuid, int flags)
{
dm_dev_t *dmv;
- lockmgr(&dm_dev_mutex, LK_EXCLUSIVE);
+ char name_buf[MAXPATHLEN];
+ int r, dm_minor;
+
+ if ((dmv = dm_dev_alloc()) == NULL)
+ return ENOMEM;
+
+ if (uuid)
+ strncpy(dmv->uuid, uuid, DM_UUID_LEN);
+ else
+ dmv->uuid[0] = '\0';
+
+ if (name)
+ strlcpy(dmv->name, name, DM_NAME_LEN);
+
+ dm_minor = devfs_clone_bitmap_get(&dm_minor_bitmap, 0);
+
+ dm_table_head_init(&dmv->table_head);
+
+ lockinit(&dmv->dev_mtx, "dmdev", 0, LK_CANRECURSE);
+ cv_init(&dmv->dev_cv, "dm_dev");
- while (TAILQ_FIRST(&dm_dev_list) != NULL) {
+ if (flags & DM_READONLY_FLAG)
+ dmv->flags |= DM_READONLY_FLAG;
- dmv = TAILQ_FIRST(&dm_dev_list);
+ aprint_debug("Creating device dm/%s\n", name);
+ ksnprintf(name_buf, sizeof(name_buf), "mapper/%s", dmv->name);
- TAILQ_REMOVE(&dm_dev_list, TAILQ_FIRST(&dm_dev_list),
- next_devlist);
+ devstat_add_entry(&dmv->stats, name, 0, DEV_BSIZE,
+ DEVSTAT_NO_ORDERED_TAGS,
+ DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER,
+ DEVSTAT_PRIORITY_DISK);
- lockmgr(&dmv->dev_mtx, LK_EXCLUSIVE);
+ dmv->devt = disk_create_named(name_buf, dm_minor, dmv->diskp, &dm_ops);
+ reference_dev(dmv->devt);
- while (dmv->ref_cnt != 0)
- cv_wait(&dmv->dev_cv, &dmv->dev_mtx);
+ dmv->minor = minor(dmv->devt);
+ udev_dict_set_cstr(dmv->devt, "subsystem", "disk");
- /* Destroy active table first. */
- dm_table_destroy(&dmv->table_head, DM_TABLE_ACTIVE);
+ if ((r = dm_dev_insert(dmv)) != 0)
+ dm_dev_destroy(dmv);
- /* Destroy inactive table if exits, too. */
- dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE);
+ /* Increment device counter After creating device */
+ ++dm_dev_counter; /* XXX: was atomic 64 */
+ *dmvp = dmv;
- dm_table_head_destroy(&dmv->table_head);
+ return r;
+}
+
+int
+dm_dev_destroy(dm_dev_t *dmv)
+{
+ int minor;
+
+ /* Destroy active table first. */
+ dm_table_destroy(&dmv->table_head, DM_TABLE_ACTIVE);
- lockmgr(&dmv->dev_mtx, LK_RELEASE);
- lockuninit(&dmv->dev_mtx);
- cv_destroy(&dmv->dev_cv);
+ /* Destroy inactive table if exits, too. */
+ dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE);
- (void) kfree(dmv, M_DM);
+ dm_table_head_destroy(&dmv->table_head);
+
+ minor = dkunit(dmv->devt);
+ disk_destroy(dmv->diskp);
+ devstat_remove_entry(&dmv->stats);
+
+ release_dev(dmv->devt);
+ devfs_clone_bitmap_put(&dm_minor_bitmap, minor);
+
+ lockuninit(&dmv->dev_mtx);
+ cv_destroy(&dmv->dev_cv);
+
+ /* Destroy device */
+ (void)dm_dev_free(dmv);
+
+ /* Decrement device counter After removing device */
+ --dm_dev_counter; /* XXX: was atomic 64 */
+
+ return 0;
+}
+
+/*
+ * dm_detach is called to completely destroy & remove a dm disk device.
+ */
+int
+dm_dev_remove(dm_dev_t *dmv)
+{
+ /* Remove device from list and wait for refcnt to drop to zero */
+ dm_dev_rem(dmv, NULL, NULL, -1);
+
+ /* Destroy and free the device */
+ dm_dev_destroy(dmv);
+
+ return 0;
+}
+
+int
+dm_dev_remove_all(int gentle)
+{
+ dm_dev_t *dmv, *dmv2;
+ int r;
+
+ r = 0;
+
+ lockmgr(&dm_dev_mutex, LK_EXCLUSIVE);
+
+ TAILQ_FOREACH_MUTABLE(dmv, &dm_dev_list, next_devlist, dmv2) {
+ if (gentle && dmv->is_open) {
+ r = EBUSY;
+ continue;
+ }
+
+ disable_dev(dmv);
+ dm_dev_destroy(dmv);
}
lockmgr(&dm_dev_mutex, LK_RELEASE);
- lockuninit(&dm_dev_mutex);
- return 0;
+ return r;
}
+
/*
* Allocate new device entry.
*/
{
KKASSERT(dmv != NULL);
- lockuninit(&dmv->dev_mtx);
- lockuninit(&dmv->diskp_mtx);
- cv_destroy(&dmv->dev_cv);
-
if (dmv->diskp != NULL)
(void) kfree(dmv->diskp, M_DM);
{
TAILQ_INIT(&dm_dev_list); /* initialize global dev list */
lockinit(&dm_dev_mutex, "dmdevlist", 0, LK_CANRECURSE);
+ devfs_clone_bitmap_init(&dm_minor_bitmap);
+ return 0;
+}
+
+/*
+ * Destroy all devices created in device-mapper. Remove all tables
+ * free all allocated memmory.
+ */
+int
+dm_dev_uninit(void)
+{
+ /* Force removal of all devices */
+ dm_dev_remove_all(0);
+
+ lockuninit(&dm_dev_mutex);
return 0;
}
#include <sys/types.h>
#include <sys/param.h>
-
#include <sys/device.h>
-#include <sys/devicestat.h>
-#include <sys/devfs.h>
-#include <sys/disk.h>
-#include <sys/disklabel.h>
#include <sys/malloc.h>
-#include <sys/udev.h>
#include <sys/vnode.h>
#include <dev/disk/dm/dm.h>
#include "netbsd-dm.h"
-extern struct dev_ops dm_ops;
-extern struct devfs_bitmap dm_minor_bitmap;
-uint64_t dm_dev_counter;
-
#define DM_REMOVE_FLAG(flag, name) do { \
prop_dictionary_get_uint32(dm_dict,DM_IOCTL_FLAGS,&flag); \
flag &= ~name; \
{
dm_dev_t *dmv;
const char *name, *uuid;
- char name_buf[MAXPATHLEN];
- int r, flags, dm_minor;
+ int r, flags;
r = 0;
flags = 0;
return EEXIST;
}
- if ((dmv = dm_dev_alloc()) == NULL)
- return ENOMEM;
-
- if (uuid)
- strncpy(dmv->uuid, uuid, DM_UUID_LEN);
- else
- dmv->uuid[0] = '\0';
-
- if (name)
- strlcpy(dmv->name, name, DM_NAME_LEN);
-
- dm_minor = devfs_clone_bitmap_get(&dm_minor_bitmap, 0);
- dmv->flags = 0; /* device flags are set when needed */
- dmv->ref_cnt = 0;
- dmv->event_nr = 0;
- dmv->dev_type = 0;
- dmv->is_open = 0;
-
- dm_table_head_init(&dmv->table_head);
-
- lockinit(&dmv->dev_mtx, "dmdev", 0, LK_CANRECURSE);
- lockinit(&dmv->diskp_mtx, "dmdisk", 0, LK_CANRECURSE);
- cv_init(&dmv->dev_cv, "dm_dev");
-
- if (flags & DM_READONLY_FLAG)
- dmv->flags |= DM_READONLY_FLAG;
-
- aprint_debug("Creating device dm/%s\n", name);
- ksnprintf(name_buf, sizeof(name_buf), "mapper/%s", dmv->name);
-
- devstat_add_entry(&dmv->stats, name, 0, DEV_BSIZE,
- DEVSTAT_NO_ORDERED_TAGS,
- DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER,
- DEVSTAT_PRIORITY_DISK);
-
- dmv->devt = disk_create_named(name_buf, dm_minor, dmv->diskp, &dm_ops);
- reference_dev(dmv->devt);
-
- dmv->minor = minor(dmv->devt);
- prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmv->minor);
- udev_dict_set_cstr(dmv->devt, "subsystem", "disk");
-
- if ((r = dm_dev_insert(dmv)) != 0)
- dm_dev_free(dmv);
-
- DM_ADD_FLAG(flags, DM_EXISTS_FLAG);
- DM_REMOVE_FLAG(flags, DM_INACTIVE_PRESENT_FLAG);
-
- /* Increment device counter After creating device */
- ++dm_dev_counter; /* XXX: was atomic 64 */
+ r = dm_dev_create(&dmv, name, uuid, flags);
+
+ if (r == 0) {
+ prop_dictionary_set_uint32(dm_dict, DM_IOCTL_MINOR, dmv->minor);
+ DM_ADD_FLAG(flags, DM_EXISTS_FLAG);
+ DM_REMOVE_FLAG(flags, DM_INACTIVE_PRESENT_FLAG);
+ }
return r;
}
int
dm_dev_rename_ioctl(prop_dictionary_t dm_dict)
{
+#if 0
prop_array_t cmd_array;
dm_dev_t *dmv;
prop_dictionary_set_cstring(dm_dict, DM_IOCTL_UUID, dmv->uuid);
dm_dev_insert(dmv);
+#endif
+ /*
+ * XXX: the rename is not yet implemented. The main complication
+ * here is devfs. We'd probably need a new function, rename_dev()
+ * that would trigger a node rename in devfs.
+ */
+ kprintf("dm_dev_rename_ioctl called, but not implemented!\n");
return 0;
}
+
/*
- * Remove device from global list I have to remove active
- * and inactive tables first.
+ * Remove device
*/
int
dm_dev_remove_ioctl(prop_dictionary_t dm_dict)
return EBUSY;
/*
- * This will call dm_detach routine which will actually removes
+ * This will call dm_detach routine which will actually remove
* device.
*/
- return dm_detach(dmv);
+ return dm_dev_remove(dmv);
}
+
+/*
+ * Try to remove all devices
+ */
+int
+dm_dev_remove_all_ioctl(prop_dictionary_t dm_dict)
+{
+ uint32_t flags = 0;
+
+ /* Get needed values from dictionary. */
+ prop_dictionary_get_uint32(dm_dict, DM_IOCTL_FLAGS, &flags);
+
+ dm_dbg_print_flags(flags);
+
+ /* Gently remove all devices, if possible */
+ return dm_dev_remove_all(1);
+}
+
/*
* Return actual state of device to libdevmapper.
*/
return dmp;
}
-/*
- * Initialize pdev subsystem.
- */
-int
-dm_pdev_init(void)
-{
- SLIST_INIT(&dm_pdev_list); /* initialize global pdev list */
- lockinit(&dm_pdev_mutex, "dmpdev", 0, LK_CANRECURSE);
- return 0;
-}
/*
* Allocat new pdev structure if is not already present and
* set name.
return 0;
}
-/*
- * Destroy all existing pdev's in device-mapper.
- */
-int
-dm_pdev_destroy(void)
-{
- dm_pdev_t *dm_pdev;
- lockmgr(&dm_pdev_mutex, LK_EXCLUSIVE);
- while (!SLIST_EMPTY(&dm_pdev_list)) { /* List Deletion. */
-
- dm_pdev = SLIST_FIRST(&dm_pdev_list);
-
- SLIST_REMOVE_HEAD(&dm_pdev_list, next_pdev);
-
- dm_pdev_rem(dm_pdev);
- }
- lockmgr(&dm_pdev_mutex, LK_RELEASE);
-
- lockuninit(&dm_pdev_mutex);
- return 0;
-}
/*
* This funcion is called from dm_dev_remove_ioctl.
* When I'm removing device from list, I have to decrement
lockmgr(&dm_pdev_mutex, LK_RELEASE);
return 0;
}
+
+/*
+ * Initialize pdev subsystem.
+ */
+int
+dm_pdev_init(void)
+{
+ SLIST_INIT(&dm_pdev_list); /* initialize global pdev list */
+ lockinit(&dm_pdev_mutex, "dmpdev", 0, LK_CANRECURSE);
+
+ return 0;
+}
+
+/*
+ * Destroy all existing pdev's in device-mapper.
+ */
+int
+dm_pdev_uninit(void)
+{
+ dm_pdev_t *dm_pdev;
+
+ lockmgr(&dm_pdev_mutex, LK_EXCLUSIVE);
+ while (!SLIST_EMPTY(&dm_pdev_list)) { /* List Deletion. */
+
+ dm_pdev = SLIST_FIRST(&dm_pdev_list);
+
+ SLIST_REMOVE_HEAD(&dm_pdev_list, next_pdev);
+
+ dm_pdev_rem(dm_pdev);
+ }
+ lockmgr(&dm_pdev_mutex, LK_RELEASE);
+
+ lockuninit(&dm_pdev_mutex);
+ return 0;
+}
return 0;
}
-/*
- * Destroy all targets and remove them from queue.
- * This routine is called from dm_detach, before module
- * is unloaded.
- */
-int
-dm_target_destroy(void)
-{
- dm_target_t *dm_target;
-
- lockmgr(&dm_target_mutex, LK_EXCLUSIVE);
- while (TAILQ_FIRST(&dm_target_list) != NULL) {
-
- dm_target = TAILQ_FIRST(&dm_target_list);
- TAILQ_REMOVE(&dm_target_list, TAILQ_FIRST(&dm_target_list),
- dm_target_next);
-
- (void) kfree(dm_target, M_DM);
- }
- lockmgr(&dm_target_mutex, LK_RELEASE);
-
- lockuninit(&dm_target_mutex);
-
- return 0;
-}
/*
* Allocate new target entry.
*/
return 0;
}
+
+/*
+ * Destroy all targets and remove them from queue.
+ * This routine is called from dm_detach, before module
+ * is unloaded.
+ */
+int
+dm_target_uninit(void)
+{
+ dm_target_t *dm_target;
+
+ lockmgr(&dm_target_mutex, LK_EXCLUSIVE);
+ while (TAILQ_FIRST(&dm_target_list) != NULL) {
+
+ dm_target = TAILQ_FIRST(&dm_target_list);
+
+ TAILQ_REMOVE(&dm_target_list, TAILQ_FIRST(&dm_target_list),
+ dm_target_next);
+
+ (void) kfree(dm_target, M_DM);
+ }
+ lockmgr(&dm_target_mutex, LK_RELEASE);
+
+ lockuninit(&dm_target_mutex);
+
+ return 0;
+}
{
return 0;
}
-/*
- * Transform char s to uint64_t offset number.
- */
-uint64_t
-atoi64(const char *s)
-{
- uint64_t n;
- n = 0;
-
- while (*s != '\0') {
- if (!isdigit(*s))
- break;
-
- n = (10 * n) + (*s - '0');
- s++;
- }
-
- return n;
-}
static int
dmtl_mod_handler(module_t mod, int type, void *unused)