⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iscsid.c

📁 iSCSI协议在LINUX下的源码.源代码是IBM公布的.主要是结合其OSD设备用的.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * iSCSI driver for Linux * Copyright (C) 2002 Cisco Systems, Inc. * maintained by linux-iscsi-devel@lists.sourceforge.net * * This program 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 of the License, or * (at your option) any later version. * * This program 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. * * See the file COPYING included with this distribution for more details. * * $Id: iscsid.c,v 1.7 2005/01/11 03:47:09 mikenc Exp $ * * iSCSI Daemon * */#include <stdint.h>#include <unistd.h>#include <errno.h>#include <poll.h>#include <sys/wait.h>#include <sysfs/libsysfs.h>#include "iscsi-sfnet.h"#include "iscsi-protocol.h"#include "iscsi-discovery.h"#include "iscsi-hooks.h"#define ISCSI_TRANSPORT_CLASS "iscsi_transport_class"/* global config info */struct iscsi_daemon_config daemon_config;/* global so that the signal handlers can reset the pids */static struct iscsi_discovery_process_list discovery_processes;static struct iscsi_session_process_list session_processes;static struct iscsi_target_list targets;static voidsigpipe_handler(int unused){	debugmsg(1, "received sigpipe");}voidsigchld_handler(int unused){	pid_t pid = 0;	int status = 0;	struct iscsi_discovery_process *discovery;	struct iscsi_session_process *session;      wait_pid:	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {		if (WIFEXITED(status))			debugmsg(1, "child %d exited with status %d", pid,				 WEXITSTATUS(status));		if (WIFSIGNALED(status))			debugmsg(1, "child %d exited on signal %d", pid,				 WTERMSIG(status));		if (WIFSTOPPED(status))			debugmsg(1, "child %d stopped on signal %d", pid,				 WSTOPSIG(status));		/* reset pids if the child was a discovery or target process */		for (discovery = discovery_processes.head; discovery;		     discovery = discovery->next) {			if (discovery->pid == pid) {				discovery->pid = 0;				if (WIFSIGNALED(status)) {					/* if the process doesn't want a					 * particular signal to restart it,					 * it should catch the signal and exit					 * (0);					 */					discovery->restart = 1;					discovery_processes.changed = 1;					debugmsg(1, "discovery process %p "						 "needs restart because pid %d"						 " killed by signal %d",						 discovery, pid,						 WTERMSIG(status));				} else if (WIFEXITED(status)					   && WEXITSTATUS(status)) {					/* abnormal exit, try again */					discovery->restart = 1;					discovery_processes.changed = 1;					debugmsg(1, "discovery process %p "						 "needs restart because pid %d"						 " exited with status 0x%x",						 discovery, pid,						 WEXITSTATUS(status));				} else {					/* normal exit. */					discovery->remove = 1;					discovery_processes.changed = 1;					debugmsg(1, "discovery process %p pid "						 "%d fd %d exited normally, "						 "marking for removal",						 discovery, pid,						 discovery->pipe_fd);				}				goto wait_pid;			}		}		for (session = session_processes.head; session;		     session = session->next) {			if (session->pid == pid) {				session->pid = 0;				if (WIFSIGNALED(status)) {					/* if the process doesn't want a					 * particular signal to restart it,					 * it should catch the signal and exit					 * (0);					 */					session_processes.changed = 1;					session->restart = 1;					debugmsg(1, "session process %p needs "						 "restart because pid %d "						 "killed by signal %d",						 session, pid,						 WTERMSIG(status));				} else if (WIFEXITED(status)) {					switch (WEXITSTATUS(status)) {					case 0:						/* normal exit.  we don't						 * remove session processes						 * that exit with status 0,						 * since that always happens						 * on Linux because the						 * session process exits as						 * soon as the kernel module						 * ioctl returns, and the						 * kernel module does all the						 * real work						 */						debugmsg(1, "session process "							 "%p with pid %d "							 "exited normally",							 session, pid);						session->pid = 0;						break;					case ISCSI_SESSION_FAILED_NO_RETRY:						/* the session process died						 * after the session failed,						 * but we don't want						 * to restart it unless the						 * user asks for a config						 * reload.  This can occur if						 * the session fails due to						 * authentication or						 * authorization failures to						 * all portals.						 * We don't want to retry						 * because we might have						 * discovered a target that we						 * aren't authorized to use,						 * and retrying forever would						 * fill the log.						 * We do want the user to be						 * able to request a retry, in						 * case they've changed						 * the access controls on the						 * target and we're now						 * authorized.						 */						debugmsg(1, "session process "							 "%p with pid %d "							 "exited, no retry",							 session, pid);						session->pid = 0;						session->failed = 1;						break;					default:						session_processes.changed = 1;						session->restart = 1;						debugmsg(1, "session process "							 "%p needs restart "							 "becaused pid %d "							 "exited with status "							 "0x%x", session, pid,							 WEXITSTATUS(status));						break;					}				}				goto wait_pid;			}		}	}}static voidfork_discovery_process(struct iscsi_discovery_process *discovery){	int pipes[2];	discovery->in_progress = 1;	/* make pipes */	if (pipe(pipes) < 0) {		discovery->restart = 1;		return;	}      fork_again:	if (iscsi_process_should_exit())		return;	discovery->pid = fork();	if (discovery->pid == 0) {		/* close the read side */		close(pipes[0]);		/* save the write side */		discovery->pipe_fd = pipes[1];		discovery->pid = getpid();		debugmsg(3, "started discovery process %p for entry %p",			 discovery, discovery->entry);		discovery_process(discovery);		exit(0);	} else if (discovery->pid < 0) {		errormsg("cannot fork discovery %p", discovery);		sleep(1);		goto fork_again;	} else {		/* close the write side */		close(pipes[1]);		/* save the read side */		discovery->pipe_fd = pipes[0];		debugmsg(3, "forked child %d for discovery %p, pipe fd %d",			 discovery->pid, discovery, discovery->pipe_fd);	}}static voidkill_discovery(struct iscsi_discovery_process *discovery){	pid_t pid = discovery->pid;	if (pid) {		debugmsg(3, "kill_discovery %p sending SIGTERM to pid %d",			 discovery, pid);		kill(pid, SIGTERM);	}}static voidtrigger_rediscovery(struct iscsi_discovery_process *discovery){	pid_t pid = discovery->pid;	debugmsg(1, "triggering rediscovery from process %p", discovery);	if (pid) {		kill(pid, SIGHUP);	}}static voidadd_discovery(struct iscsi_discovery_process_list *list,	      struct iscsi_discovery_process *discovery){	sigset_t chld;	debugmsg(7, "adding discovery %p, head %p, tail %p", discovery,		 list->head, list->tail);	/* block SIGCHLD while we're doing this */	sigemptyset(&chld);	sigaddset(&chld, SIGCHLD);	sigprocmask(SIG_BLOCK, &chld, NULL);	if (list->head) {		/* append at the tail */		discovery->next = NULL;		discovery->prev = list->tail;		list->tail->next = discovery;		list->tail = discovery;	} else {		/* become the only list element */		discovery->next = discovery->prev = NULL;		list->head = list->tail = discovery;	}	list->count++;	sigprocmask(SIG_UNBLOCK, &chld, NULL);}voidremove_discovery(struct iscsi_discovery_process_list *list,		 struct iscsi_discovery_process *discovery){	sigset_t chld;	/* block SIGCHLD while we're doing this */	sigemptyset(&chld);	sigaddset(&chld, SIGCHLD);	sigprocmask(SIG_BLOCK, &chld, NULL);	if (discovery == list->head) {		debugmsg(7, "removing discovery head %p, tail %p", discovery,			 list->tail);		list->head = discovery->next;		if (list->head == NULL)			list->tail = NULL;		discovery->next = discovery->prev = NULL;	} else if (discovery == list->tail) {		debugmsg(7, "removing discovery tail %p, head %p", discovery,			 list->head);		list->tail = discovery->prev;		list->tail->next = NULL;		discovery->next = discovery->prev = NULL;	} else if (discovery->next && discovery->prev) {		debugmsg(7, "removing interior discovery %p, head %p, tail %p",			 discovery, list->head, list->tail);		discovery->next->prev = discovery->prev;		discovery->prev->next = discovery->next;		discovery->next = discovery->prev = NULL;	} else {		logmsg(AS_ERROR,		       "couldn't remove discovery process %p from list %p",		       discovery, list);	}	list->count--;	sigprocmask(SIG_UNBLOCK, &chld, NULL);}/* recursively free dynamically allocated memory */static voidfree_discovery(struct iscsi_discovery_process *discovery){	if (discovery->entry) {		debugmsg(6, "freeing discovery %p with config %p", discovery,			 discovery->entry);		free_config_entry(discovery->entry);		discovery->entry = NULL;	} else {		debugmsg(6, "freeing discovery %p with no config", discovery);	}	free(discovery);}voidshow_target(struct iscsi_target *target){	int p = 0;	struct iscsi_portal_descriptor *portal;	debugmsg(1, "target %p name %s", target, target->TargetName);	for (portal = target->current_portals; portal; portal = portal->next) {		debugmsg(1, "target %p portal[%d]=%p, address %s, ip %u.%u.%u."			 "%u, port %d, tag %d", target, p++, portal, portal->			 address, portal->ip[0], portal->ip[1], portal->ip[2],			 portal->ip[3], portal->port, portal->tag);	}}static voidfork_session_process(struct iscsi_session_process *process){	struct iscsi_session_config *config = process->config;      fork_again:	if (iscsi_process_should_exit())		return;	process->pid = fork();	if (process->pid == 0) {		process->pid = getpid();		debugmsg(2, "starting iSCSI session process %p config %p for "			 "bus %d target %d, TargetName %s", process, config,			 config->iscsi_bus, config->target_id,			 config->target->TargetName);		iscsi_session_process(process, process->config);		exit(0);	} else if (process->pid < 0) {		errormsg("cannot fork session process %p", process);		sleep(1);		goto fork_again;	} else {		debugmsg(2, "forked pid %d for session process %p",			 process->pid, process);	}}voidadd_session_process(struct iscsi_session_process_list *list,		    struct iscsi_session_process *process){	sigset_t chld;	/* block SIGCHLD while we're doing this */	sigemptyset(&chld);	sigaddset(&chld, SIGCHLD);	sigprocmask(SIG_BLOCK, &chld, NULL);	debugmsg(7, "adding session process %p, head %p, tail %p", process,		 list->head, list->tail);	if (list->head) {		/* append at the tail */		process->next = NULL;		process->prev = list->tail;		list->tail->next = process;		list->tail = process;	} else {		/* become the only list element */		process->next = process->prev = NULL;		list->head = list->tail = process;	}	list->count++;	sigprocmask(SIG_UNBLOCK, &chld, NULL);}voidremove_session_process(struct iscsi_session_process_list *list,		       struct iscsi_session_process *process){	sigset_t chld;	/* block SIGCHLD while we're doing this */	sigemptyset(&chld);	sigaddset(&chld, SIGCHLD);	sigprocmask(SIG_BLOCK, &chld, NULL);	if (process == list->head) {		debugmsg(7, "removing session process head %p, tail %p",			 process, list->tail);		list->head = process->next;		if (list->head == NULL)			list->tail = NULL;		process->next = process->prev = NULL;	} else if (process == list->tail) {		debugmsg(7, "removing session process tail %p, head %p",			 process, list->head);		list->tail = process->prev;		list->tail->next = NULL;		process->next = process->prev = NULL;	} else if (process->next && process->prev) {		debugmsg(7, "removing interior process %p, head %p, tail %p",			 process, list->head, list->tail);		process->next->prev = process->prev;		process->prev->next = process->next;		process->next = process->prev = NULL;	} else {		logmsg(AS_ERROR,		       "couldn't remove session process %p from list %p",		       process, list);	}	list->count--;	sigprocmask(SIG_UNBLOCK, &chld, NULL);}voidfree_session_process(struct iscsi_session_process *process){	if (process->config) {		debugmsg(6, "freeing session process %p with config %p",			 process, process->config);		/* Note: caller must free the config if appropriate to do so */		process->config->process = NULL;		process->config = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -