Blame usr/mntcheck.c

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