|
Packit |
eace71 |
/*
|
|
Packit |
eace71 |
* Common code for checking sessions for mnt use
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* Copyright (C) 2014 - 2015 Chris Leech
|
|
Packit |
eace71 |
* Copyright (C) 2014 - 2015 Red Hat, Inc. All rights reserved.
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
eace71 |
* it under the terms of the GNU General Public License as published
|
|
Packit |
eace71 |
* by the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
eace71 |
* (at your option) any later version.
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
eace71 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
eace71 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
eace71 |
* General Public License for more details.
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* See the file COPYING included with this distribution for more details.
|
|
Packit |
eace71 |
*/
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
#include <string.h>
|
|
Packit |
eace71 |
#include <stdio.h>
|
|
Packit |
eace71 |
#include <stdlib.h>
|
|
Packit |
eace71 |
#include <errno.h>
|
|
Packit |
eace71 |
#include <dirent.h>
|
|
Packit |
eace71 |
#include <libmount/libmount.h>
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
#include "initiator.h"
|
|
Packit |
eace71 |
#include "transport.h"
|
|
Packit |
eace71 |
#include "iscsid.h"
|
|
Packit |
eace71 |
#include "iscsi_ipc.h"
|
|
Packit |
eace71 |
#include "log.h"
|
|
Packit |
eace71 |
#include "iscsi_sysfs.h"
|
|
Packit |
eace71 |
#include "iscsi_settings.h"
|
|
Packit |
eace71 |
#include "iface.h"
|
|
Packit |
eace71 |
#include "host.h"
|
|
Packit |
eace71 |
#include "sysdeps.h"
|
|
Packit |
eace71 |
#include "iscsi_err.h"
|
|
Packit |
eace71 |
#include "iscsi_net_util.h"
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static struct libmnt_table *mtab, *swaps;
|
|
Packit |
eace71 |
static struct libmnt_cache *mntcache;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static void libmount_cleanup(void)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
mnt_free_table(mtab);
|
|
Packit |
eace71 |
mnt_free_table(swaps);
|
|
Packit |
eace71 |
mnt_free_cache(mntcache);
|
|
Packit |
eace71 |
mtab = NULL;
|
|
Packit |
eace71 |
swaps = NULL;
|
|
Packit |
eace71 |
mntcache = NULL;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static int libmount_init(void)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
mnt_init_debug(0);
|
|
Packit |
eace71 |
mtab = mnt_new_table();
|
|
Packit |
eace71 |
swaps = mnt_new_table();
|
|
Packit |
eace71 |
mntcache = mnt_new_cache();
|
|
Packit |
eace71 |
if (!mtab || !swaps || !mntcache) {
|
|
Packit |
eace71 |
libmount_cleanup();
|
|
Packit |
eace71 |
return -ENOMEM;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
mnt_table_set_cache(mtab, mntcache);
|
|
Packit |
eace71 |
mnt_table_set_cache(swaps, mntcache);
|
|
Packit |
eace71 |
mnt_table_parse_mtab(mtab, NULL);
|
|
Packit |
eace71 |
mnt_table_parse_swaps(swaps, NULL);
|
|
Packit |
eace71 |
return 0;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static int trans_filter(const struct dirent *d)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
if (!strcmp(".", d->d_name) || !strcmp("..", d->d_name))
|
|
Packit |
eace71 |
return 0;
|
|
Packit |
eace71 |
return 1;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static int subdir_filter(const struct dirent *d)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
if (!(d->d_type & DT_DIR))
|
|
Packit |
eace71 |
return 0;
|
|
Packit |
eace71 |
return trans_filter(d);
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static int is_partition(const char *path)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
char *devtype;
|
|
Packit |
eace71 |
int rc = 0;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
devtype = sysfs_get_uevent_devtype(path);
|
|
Packit |
eace71 |
if (!devtype)
|
|
Packit |
eace71 |
return 0;
|
|
Packit |
eace71 |
if (strcmp(devtype, "partition") == 0)
|
|
Packit |
eace71 |
rc = 1;
|
|
Packit |
eace71 |
free(devtype);
|
|
Packit |
eace71 |
return rc;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static int blockdev_check_mnts(char *syspath)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
struct libmnt_fs *fs;
|
|
Packit |
eace71 |
char *devname = NULL;
|
|
Packit |
eace71 |
char *_devname = NULL;
|
|
Packit |
eace71 |
int rc = 0;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
devname = sysfs_get_uevent_devname(syspath);
|
|
Packit |
eace71 |
if (!devname)
|
|
Packit |
eace71 |
goto out;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
_devname = calloc(1, PATH_MAX);
|
|
Packit |
eace71 |
if (!_devname)
|
|
Packit |
eace71 |
goto out;
|
|
Packit |
eace71 |
snprintf(_devname, PATH_MAX, "/dev/%s", devname);
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
fs = mnt_table_find_source(mtab, _devname, MNT_ITER_FORWARD);
|
|
Packit |
eace71 |
if (fs) {
|
|
Packit |
eace71 |
rc = 1;
|
|
Packit |
eace71 |
goto out;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
fs = mnt_table_find_source(swaps, _devname, MNT_ITER_FORWARD);
|
|
Packit |
eace71 |
if (fs)
|
|
Packit |
eace71 |
rc = 1;
|
|
Packit |
eace71 |
out:
|
|
Packit |
eace71 |
free(devname);
|
|
Packit |
eace71 |
free(_devname);
|
|
Packit |
eace71 |
return rc;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static int count_device_users(char *syspath);
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static int blockdev_get_partitions(char *syspath)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
struct dirent **parts = NULL;
|
|
Packit |
eace71 |
int n, i;
|
|
Packit |
eace71 |
int count = 0;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
n = scandir(syspath, &parts, subdir_filter, alphasort);
|
|
Packit |
eace71 |
for (i = 0; i < n; i++) {
|
|
Packit |
eace71 |
char *newpath;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
newpath = calloc(1, PATH_MAX);
|
|
Packit |
eace71 |
if (!newpath)
|
|
Packit |
eace71 |
continue;
|
|
Packit |
eace71 |
snprintf(newpath, PATH_MAX, "%s/%s", syspath, parts[i]->d_name);
|
|
Packit |
eace71 |
free(parts[i]);
|
|
Packit |
eace71 |
if (is_partition(newpath)) {
|
|
Packit |
eace71 |
count += count_device_users(newpath);
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
free(newpath);
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
free(parts);
|
|
Packit |
eace71 |
return count;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static int blockdev_get_holders(char *syspath)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
char *path = NULL;
|
|
Packit |
eace71 |
struct dirent **holds = NULL;
|
|
Packit |
eace71 |
int n, i;
|
|
Packit |
eace71 |
int count = 0;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
path = calloc(1, PATH_MAX);
|
|
Packit |
eace71 |
if (!path)
|
|
Packit |
eace71 |
return 0;
|
|
Packit |
eace71 |
snprintf(path, PATH_MAX, "%s/holders", syspath);
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
n = scandir(path, &holds, trans_filter, alphasort);
|
|
Packit |
eace71 |
for (i = 0; i < n; i++) {
|
|
Packit |
eace71 |
char *newpath;
|
|
Packit |
eace71 |
char *rp;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
newpath = calloc(1, PATH_MAX);
|
|
Packit |
eace71 |
if (!newpath)
|
|
Packit |
eace71 |
continue;
|
|
Packit |
eace71 |
snprintf(newpath, PATH_MAX, "%s/%s", path, holds[i]->d_name);
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
free(holds[i]);
|
|
Packit |
eace71 |
rp = realpath(newpath, NULL);
|
|
Packit |
eace71 |
if (rp)
|
|
Packit |
eace71 |
count += count_device_users(rp);
|
|
Packit |
eace71 |
free(newpath);
|
|
Packit |
eace71 |
free(rp);
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
free(path);
|
|
Packit |
eace71 |
free(holds);
|
|
Packit |
eace71 |
return count;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static int count_device_users(char *syspath)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
int count = 0;
|
|
Packit |
eace71 |
count += blockdev_check_mnts(syspath);
|
|
Packit |
eace71 |
count += blockdev_get_partitions(syspath);
|
|
Packit |
eace71 |
count += blockdev_get_holders(syspath);
|
|
Packit |
eace71 |
return count;
|
|
Packit |
eace71 |
};
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static void device_in_use(void *data, int host_no, int target, int lun)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
char *syspath = NULL;
|
|
Packit |
eace71 |
char *devname = NULL;
|
|
Packit |
eace71 |
int *count = data;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
devname = iscsi_sysfs_get_blockdev_from_lun(host_no, target, lun);
|
|
Packit |
eace71 |
if (!devname)
|
|
Packit |
eace71 |
goto out;
|
|
Packit |
eace71 |
syspath = calloc(1, PATH_MAX);
|
|
Packit |
eace71 |
if (!syspath)
|
|
Packit |
eace71 |
goto out;
|
|
Packit |
eace71 |
snprintf(syspath, PATH_MAX, "/sys/class/block/%s", devname);
|
|
Packit |
eace71 |
*count += count_device_users(syspath);
|
|
Packit |
eace71 |
out:
|
|
Packit |
eace71 |
free(syspath);
|
|
Packit |
eace71 |
free(devname);
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
int session_in_use(int sid)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
int host_no = -1, err = 0;
|
|
Packit |
eace71 |
int count = 0;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
if (libmount_init()) {
|
|
Packit |
eace71 |
log_error("Failed to initialize libmount, "
|
|
Packit |
eace71 |
"not checking for active mounts on session [%d].", sid);
|
|
Packit |
eace71 |
return 0;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
host_no = iscsi_sysfs_get_host_no_from_sid(sid, &err;;
|
|
Packit |
eace71 |
if (!err)
|
|
Packit |
eace71 |
iscsi_sysfs_for_each_device(&count, host_no, sid, device_in_use);
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
libmount_cleanup();
|
|
Packit |
eace71 |
return count;
|
|
Packit |
eace71 |
}
|