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

📄 iscsi-probe.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * iSCSI driver for Linux * Copyright (C) 2001 Cisco Systems, Inc. * maintained by linux-iscsi@cisco.com * * 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: iscsi-probe.c,v 1.14 2002/10/14 22:54:11 smferris Exp $ * */#include <linux/config.h>#include <linux/version.h>#include <linux/sched.h>#include <asm/io.h>#include <asm/byteorder.h>#include <linux/stddef.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/file.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/proc_fs.h>#include <linux/blk.h>#include <linux/types.h>#include <linux/stat.h>#include <linux/config.h>#include <linux/poll.h>#include <linux/smp_lock.h>#include <linux/kernel.h>#include <linux/wait.h>#include <linux/net.h>#include <net/sock.h>#include <linux/socket.h>#include <linux/errno.h>#include <linux/unistd.h>#include <linux/timer.h>#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) )# include <asm/semaphore.h>#else# include <asm/spinlock.h>#endif#include <asm/uaccess.h>#include <scsi/sg.h>#include <sd.h>#include <scsi.h>#include <hosts.h>#include "iscsi-common.h"#include "iscsi-ioctl.h"#include "iscsi.h"/* LUN probing needs to be serialized across all HBA's, to keep a somewhat sane ordering */#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) )DECLARE_MUTEX(iscsi_lun_probe_mutex);#elsestruct semaphore               iscsi_lun_probe_mutex = MUTEX;#endifspinlock_t                     iscsi_lun_probe_lock = SPIN_LOCK_UNLOCKED;static iscsi_session_t         *iscsi_lun_probe_head = NULL;static iscsi_session_t         *iscsi_lun_probe_tail = NULL; static iscsi_session_t         *iscsi_currently_probing = NULL; static volatile int            iscsi_next_probe = 0;volatile unsigned long  iscsi_lun_probe_start = 0;struct dirent{    long d_ino;                 /* inode number */    off_t d_off;                /* offset to next dirent */    unsigned short d_reclen;    /* length of this dirent */    char d_name[1];             /* file name (null-terminated) */};/* we need to make some syscalls to create and destroy the device name tree. */static int errno = 0;static inline _syscall2(long, mkdir, const char *, dir, int, mode);static inline _syscall1(long, unlink, const char *, path);static inline _syscall2(long, symlink, const char *, oldname, const char *, newname);static inline _syscall3(int,open,const char *,file,int,flag,int,mode)static inline _syscall1(int,close,int,fd)static inline _syscall1(long, rmdir, const char *, path);static inline _syscall3(int, getdents, uint, fd, struct dirent *, dirp, uint, count);/* caller must hold iscsi_lun_probe_lock */static int enqueue_lun_probe(iscsi_session_t *session){    if (session->probe_next || session->probe_prev) {        DEBUG_INIT1("iSCSI: session %p already queued for LUN probing\n", session);        return 0;    }    if (iscsi_lun_probe_head) {        if (session->probe_order < iscsi_lun_probe_head->probe_order) {            /* insert before the current head */            session->probe_prev = NULL;            session->probe_next = iscsi_lun_probe_head;            iscsi_lun_probe_head->probe_prev = session;            iscsi_lun_probe_head = session;        }        else if (session->probe_order >= iscsi_lun_probe_tail->probe_order) {            /* insert after the tail */            session->probe_next = NULL;            session->probe_prev = iscsi_lun_probe_tail;            iscsi_lun_probe_tail->probe_next = session;            iscsi_lun_probe_tail = session;        }        else {            /* insert somewhere in the middle */            iscsi_session_t *search = iscsi_lun_probe_head;            while (search && search->probe_next) {                if (session->probe_order < search->probe_next->probe_order) {                    session->probe_next = search->probe_next;                    session->probe_prev = search;                    search->probe_next->probe_prev = session;                    search->probe_next = session;                    break;                }                search = search->probe_next;            }        }    }    else {        /* become the only session in the queue */        session->probe_next = session->probe_prev = NULL;        iscsi_lun_probe_head = iscsi_lun_probe_tail = session;    }    return 1;}/* caller must hold iscsi_lun_probe_lock */static void dequeue_lun_probe(iscsi_session_t *session){    if (iscsi_currently_probing == session) {        /* the timer may have tried to start us probing just before we gave up */        iscsi_currently_probing = NULL;    }    else {        if (iscsi_lun_probe_head == session) {            if ((iscsi_lun_probe_head = iscsi_lun_probe_head->probe_next))                iscsi_lun_probe_head->probe_prev = NULL;            else                iscsi_lun_probe_tail = NULL;        }        else if (iscsi_lun_probe_tail == session) {            iscsi_lun_probe_tail = iscsi_lun_probe_tail->probe_prev;            iscsi_lun_probe_tail->probe_next = NULL;        }        else {            /* in the middle */            if (session->probe_next && session->probe_prev) {                session->probe_prev->probe_next = session->probe_next;                session->probe_next->probe_prev = session->probe_prev;            }            else {                printk("iSCSI: bug - dequeue_lun_probe %p, prev %p, next %p\n",                        session, session->probe_prev, session->probe_next);            }        }            }}static int wait_for_probe_order(iscsi_session_t *session){    spin_lock(&iscsi_lun_probe_lock);    if ((iscsi_currently_probing == session) || session->probe_next || session->probe_prev) {        /* we're already probing or queued to be probed, ignore the 2nd probe request */        DEBUG_INIT2("iSCSI: session %p to %s ignoring duplicate probe request\n",                     session, session->log_name);        spin_unlock(&iscsi_lun_probe_lock);        return 0;    }    else if ((iscsi_currently_probing == NULL) && (session->probe_order <= iscsi_next_probe)) {        /* if there's no LUN being probed, and our probe_order can go now, start probing */        DEBUG_INIT4("iSCSI: session %p to %s, probe_order %d <= next %d, not waiting\n",                     session, session->log_name, session->probe_order, iscsi_next_probe);        iscsi_currently_probing = session;        /* let the timer know another sessions became ready for LUN probing. */        iscsi_lun_probe_start = (jiffies + (3 * HZ)) ? (jiffies + (3 * HZ)) : 1;        wmb();        spin_unlock(&iscsi_lun_probe_lock);        return 1;    }    else if (enqueue_lun_probe(session)) {        /* otherwise queue up based on our probe order */        /* tell the timer when to start the LUN probing, to handle gaps in the probe_order */        iscsi_lun_probe_start = (jiffies + (3 * HZ)) ? (jiffies + (3 * HZ)) : 1;        wmb();        DEBUG_INIT3("iSCSI: queued session %p for LUN probing, probe_order %d, probe_start at %lu\n",                     session, session->probe_order, iscsi_lun_probe_start);                spin_unlock(&iscsi_lun_probe_lock);                /* and wait for either the timer or the currently probing session to wake us up */        if (down_interruptible(&session->probe_sem)) {            printk("iSCSI: session %p to %s interrupted while waiting to probe LUNs\n", session, session->log_name);            /* give up and take ourselves out of the lun probing data structures */            spin_lock(&iscsi_lun_probe_lock);            dequeue_lun_probe(session);            spin_unlock(&iscsi_lun_probe_lock);            return 0;        }        /* give up if the session is terminating */        if (test_bit(SESSION_TERMINATING, &session->control_bits)) {            printk("iSCSI: session %p to %s terminated while waiting to probe LUNs\n", session, session->log_name);            /* give up and take ourselves out of the lun probing data structures */            spin_lock(&iscsi_lun_probe_lock);            dequeue_lun_probe(session);            spin_unlock(&iscsi_lun_probe_lock);            return 0;        }        #ifdef DEBUG        /* we should be out of the queue, and in iscsi_currently_probing */        spin_lock(&iscsi_lun_probe_lock);        if (iscsi_currently_probing != session)            printk("iSCSI: bug - currently probing should be %p, not %p\n", session, iscsi_currently_probing);        spin_unlock(&iscsi_lun_probe_lock);#endif        DEBUG_INIT1("iSCSI: wait_for_probe_order %p returning 1\n", session);        return 1;    }    /* silently fail, since the enqueue attempt will have logged any detailed messages needed */    spin_unlock(&iscsi_lun_probe_lock);    return 0;}/* caller must hold iscsi_lun_probe_lock */static void start_next_lun_probe(void){    /* if we're not probing anything currently, start probing the head of the queue */    if (iscsi_lun_probe_head && (iscsi_currently_probing == NULL)) {        /* pop one off the queue, and tell it to start probing */        iscsi_currently_probing = iscsi_lun_probe_head;        if ((iscsi_lun_probe_head = iscsi_currently_probing->probe_next))            iscsi_lun_probe_head->probe_prev = NULL;        else            iscsi_lun_probe_tail = NULL;        /* it's out of the queue now */        iscsi_currently_probing->probe_next = NULL;        iscsi_currently_probing->probe_prev = NULL;        /* skip over any gaps in the probe order */        if (iscsi_next_probe < iscsi_currently_probing->probe_order) {            DEBUG_INIT2("iSCSI: LUN probe_order skipping from %d to %d\n",                         iscsi_next_probe, iscsi_currently_probing->probe_order);            iscsi_next_probe = iscsi_currently_probing->probe_order;            wmb();        }                    /* wake up the ioctl which is waiting to do a probe */        DEBUG_INIT2("iSCSI: starting LUN probe for session %p to %s\n",                     iscsi_currently_probing, iscsi_currently_probing->log_name);        up(&iscsi_currently_probing->probe_sem);    }    else {        if (!iscsi_lun_probe_head) {            /* if there is nothing else queued, then we don't need the timer to keep checking */            iscsi_lun_probe_start = 0;            wmb();        }        DEBUG_INIT6("iSCSI: ignoring start_next_lun_probe at %lu, next %d, head %p, tail %p, current %p, start time %lu\n",                    jiffies, iscsi_next_probe, iscsi_lun_probe_head, iscsi_lun_probe_tail,                     iscsi_currently_probing, iscsi_lun_probe_start);    }}void iscsi_possibly_start_lun_probing(void) {    spin_lock(&iscsi_lun_probe_lock);    if (!iscsi_currently_probing) {        /* if we're not probing already, make sure we start */        DEBUG_INIT1("iSCSI: timer starting LUN probing at %lu\n", jiffies);        start_next_lun_probe();    }    spin_unlock(&iscsi_lun_probe_lock);}static void iscsi_probe_finished(iscsi_session_t *session){    spin_lock(&iscsi_lun_probe_lock);    if (iscsi_currently_probing == session) {        iscsi_currently_probing = NULL;        DEBUG_INIT3("iSCSI: session %p to %s finished probing LUNs at %lu\n", session, session->log_name, jiffies);        /* continue through the probe order */        if (iscsi_next_probe == session->probe_order)            iscsi_next_probe++;        /* and possibly start another session probing */        if (iscsi_lun_probe_head &&             ((iscsi_lun_probe_head->probe_order <= iscsi_next_probe) ||              (iscsi_lun_probe_start && time_before_eq(iscsi_lun_probe_start, jiffies))))        {            start_next_lun_probe();        }        else {#if DEBUG_INIT                        if (LOG_ENABLED(ISCSI_LOG_INIT))                printk("iSCSI: iscsi_probe_finished can't start_next_lun_probe at %lu, next %d, head %p (%d), tail %p (%d), current %p, start time %lu\n",                       jiffies, iscsi_next_probe,                        iscsi_lun_probe_head, iscsi_lun_probe_head ? iscsi_lun_probe_head->probe_order : -1,                       iscsi_lun_probe_tail, iscsi_lun_probe_tail ? iscsi_lun_probe_tail->probe_order : -1,                       iscsi_currently_probing, iscsi_lun_probe_start);#endif        }    }    else {        /* should be impossible */        printk("iSCSI: bug - session %p in iscsi_probe_finished, but currently probing %p\n", session, iscsi_currently_probing);    }    spin_unlock(&iscsi_lun_probe_lock);}/* try to write to /proc/scsi/scsi */static int write_proc_scsi_scsi(iscsi_session_t *session, char *str){    struct file *filp = NULL;    loff_t offset = 0;    int rc = 0;    mm_segment_t oldfs = get_fs();        set_fs( get_ds() );    filp = filp_open("/proc/scsi/scsi", O_WRONLY, 0);    if (IS_ERR(filp)) {        printk("iSCSI: session %p couldn't open /proc/scsi/scsi\n", session);        set_fs(oldfs);        return -ENOENT;    }    rc = filp->f_op->write(filp, str, strlen(str), &offset);    filp_close(filp, 0);    set_fs(oldfs);        if (rc >= 0) {        /* assume it worked, since the non-negative return codes aren't set very reliably.         * wait for 20 ms to avoid deadlocks on SMP systems.           * FIXME: figure out why the SMP systems need this wait, and fix the kernel.         */

⌨️ 快捷键说明

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