Blame usr/mntcheck.c

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
}