📄 iscsi-probe.c
字号:
set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(MSECS_TO_JIFFIES(20)); return 1; } return rc;}/* caller must hold the iscsi_lun_probe_mutex */static int iscsi_probe_lun(iscsi_session_t *session, int lun){ char str[80]; int rc; if (lun >= ISCSI_MAX_LUN) return 0; sprintf(str, "scsi add-single-device %d %d %d %d\n", session->host_no, session->channel, session->target_id, lun); str[sizeof(str) - 1] = '\0'; rc = write_proc_scsi_scsi(session, str); if (rc < 0) { /* clear the newline */ str[strlen(str) - 1] = '\0'; printk("iSCSI: session %p error %d writing '%s' to /proc/scsi/scsi\n", session, rc, str); return 0; } return rc;}static int iscsi_remove_lun(iscsi_session_t *session, int lun){ char str[88]; int rc = 0; sprintf(str, "scsi remove-single-device %d %d %d %d\n", session->host_no, session->channel, session->target_id, lun); str[sizeof(str) - 1] = '\0'; rc = write_proc_scsi_scsi(session, str); if (rc < 0) { /* clear the newline */ str[strlen(str) - 1] = '\0'; printk("iSCSI: session %p error %d writing '%s' to /proc/scsi/scsi\n", session, rc, str); return 0; } else { /* removed it */ clear_bit(lun, session->luns_activated); return 1; } return rc;}static void empty_directory(char *dir, char *data, int size){ int fd; struct dirent dent; int rc, processed; char *name = dir + strlen(dir); /* there should only be directories in the target dir */ if ((fd = open(dir, O_DIRECTORY|O_RDONLY, 0)) >= 0) { /* loop doing getdents, and unlinking files */ do { rc = getdents(fd, (struct dirent *)data, size); DEBUG_FLOW3("iSCSI: getdents %s, size %d, returned %d\n", dir, size, rc); processed = 0; while (processed < rc) { memcpy(&dent, &data[processed], sizeof(dent)); strcpy(name, &data[processed] + offsetof(struct dirent, d_name)); if (strcmp(name, ".") && strcmp(name, "..")) { DEBUG_FLOW1("iSCSI: unlink %s\n", dir); unlink(dir); } processed += dent.d_reclen; } } while (rc > 0); name[0] = '\0'; close(fd); }}void iscsi_remove_luns(iscsi_session_t *session){ int l; mm_segment_t oldfs; char *data = session->RxBuf; int size = sizeof(session->RxBuf) - 1; char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); char *bus_dir = lun_dir - 2; /* before the slash */ char c; /* try to release the kernel's SCSI device structures for every LUN */ down(&iscsi_lun_probe_mutex); oldfs = get_fs(); set_fs( get_ds() ); for (l = 0; l < ISCSI_MAX_LUN; l++) { if (session->target_link_dir[0] == '/') { sprintf(lun_dir, "lun%d/", l); /* this assumes the session isn't using the RxBuf right now */ empty_directory(session->target_link_dir, data, size); rmdir(session->target_link_dir); } if (test_bit(l, session->luns_activated)) { /* tell Linux to release the Scsi_Devices */ iscsi_remove_lun(session, l); } } if (session->target_link_dir[0] == '/') { /* and get rid of the target dir itself */ *lun_dir = '\0'; DEBUG_FLOW1("iSCSI: rmdir %s\n", session->target_link_dir); rmdir(session->target_link_dir); /* if the bus dir is empty now, get rid of it too, but don't corrupt the session's target dir */ while (*bus_dir != '/') bus_dir--; bus_dir++; /* leave the slash */ c = *bus_dir; *bus_dir = '\0'; DEBUG_FLOW1("iSCSI: rmdir %s\n", session->target_link_dir); rmdir(session->target_link_dir); *bus_dir = c; } set_fs( oldfs ); up(&iscsi_lun_probe_mutex);}/* find all dir prefixes of pathname, and make them all if they don't exist */static void ensure_directories_exist(char *pathname, mode_t dir_mode){ char *end = pathname; /* skip leading slashes */ while (end && *end && (*end == '/')) end++; while (end && (*end != '\0')) { /* if there is another slash, make the dir. * FIXME: we ought to ignore errors when the directory exists, * but report errors where the directory doesn't exist and * we failed to create it. */ while ((*end != '/') && (*end != '\0')) end++; if (*end == '/') { *end = '\0'; mkdir(pathname, dir_mode); *end = '/'; end++; } }}static int get_device_scsi_quad(char *device_name, int *host, int *channel, int *target, int *lun){ int ret = 0; u_long info[2]; struct file *filp = NULL; struct inode *inode = NULL; filp = filp_open(device_name, O_RDONLY|O_NONBLOCK, 0); if (IS_ERR(filp)) { return 0; } memset(info, 0, sizeof(info)); inode = filp->f_dentry->d_inode; if (filp->f_op->ioctl(inode, filp, SCSI_IOCTL_GET_IDLUN, (unsigned long)info) == 0) { if (target) *target = info[0] & 0xff; if (lun) *lun = (info[0] >> 8) & 0xff; if (channel) *channel = (info[0] >> 16) & 0xff;#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ) /* 2.4 kernels give us all the info we need with that ioctl. */ if (host) *host = ((info[0] >> 24) & 0xff); ret = 1;#else /* 2.2 kernels have another ioctl to get the host number, and set the host * above to something useless to us. */ memset(info, 0, sizeof(info)); if (filp->f_op->ioctl(inode, filp, SCSI_IOCTL_GET_BUS_NUMBER, (unsigned long)info) == 0) { if (host) *host = info[0]; ret = 1; }#endif } filp_close(filp, 0); return ret;}static void iscsi_update_disk_links(iscsi_session_t *session, int max_sd_devices, int max_sd_partitions, mode_t dir_mode){ int i; char devname[20]; /* we've reserved enough space in session->target_link_dir so that we can use it to build pathnames */ char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); /* FIXME: can we get the number of devices supported from the running kernel? */ for (i=0; i < max_sd_devices; i++) { int host = -1, channel = -1, id = -1, lun = -1; if (i < 26) { sprintf(devname, "/dev/sd%c", 'a' + i); } else { /* double char names for disknum 26+ */ sprintf(devname, "/dev/sd%c%c", 'a' + (i / 26) - 1, 'a' + (i % 26)); } if (get_device_scsi_quad(devname, &host, &channel, &id, &lun)) { if ((host == session->host_no) && (channel == session->channel) && (id == session->target_id)) { char *partition = devname + strlen(devname); char *link; int p; DEBUG_INIT4("iSCSI: disk device node %s = bus %d target %d LUN %d\n", devname, session->iscsi_bus, id, lun); /* ensure the LUN dir exists */ sprintf(lun_dir, "lun%d/", lun); ensure_directories_exist(session->target_link_dir, dir_mode); link = lun_dir + strlen(lun_dir); /* symlink the whole-disk device */ strcpy(link, "disk"); unlink(session->target_link_dir); /* remove any existing symlink */ symlink(devname, session->target_link_dir); /* make a new symlink */ /* and make links for each possible disk partition as well, * since we don't want to have to track what partitions get added or removed. * This works just like the normal partition device nodes, which * are always present, but may or may not be openable. */ for (p = 1; p <= max_sd_partitions; p++) { sprintf(partition, "%d", p); sprintf(link, "part%d", p); unlink(session->target_link_dir); symlink(devname, session->target_link_dir); } } } } /* restore the session's target dir */ *lun_dir = '\0';}static void iscsi_update_tape_links(iscsi_session_t *session, int max_st_devices, mode_t dir_mode){ int i; char devname[20]; /* we've reserved enough space in session->target_link_dir so that we can use it to build pathnames */ char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); /* FIXME: can we get the number of devices supported from the running kernel? */ for (i=0; i < max_st_devices; i++) { int host = -1, channel = -1, id = -1, lun = -1; /* we check the no-rewind device to avoid having side-effects */ sprintf(devname, "/dev/nst%d", i); if (get_device_scsi_quad(devname, &host, &channel, &id, &lun)) { if ((host == session->host_no) && (channel == session->channel) && (id == session->target_id)) { char *link; DEBUG_INIT4("iSCSI: tape device node %s = bus %d target %d LUN %d\n", devname, session->iscsi_bus, id, lun); /* ensure the LUN dir exists */ sprintf(lun_dir, "lun%d/", lun); ensure_directories_exist(session->target_link_dir, dir_mode); link = lun_dir + strlen(lun_dir); /* auto-rewind nodes */ strcpy(link, "mt"); unlink(session->target_link_dir); /* remove any existing symlink */ sprintf(devname, "/dev/st%d", i); symlink(devname, session->target_link_dir); /* make a new symlink */ strcpy(link, "mtl"); unlink(session->target_link_dir); /* remove any existing symlink */ sprintf(devname, "/dev/st%dl", i); symlink(devname, session->target_link_dir); /* make a new symlink */ strcpy(link, "mtm"); unlink(session->target_link_dir); /* remove any existing symlink */ sprintf(devname, "/dev/st%dm", i); symlink(devname, session->target_link_dir); /* make a new symlink */ strcpy(link, "mta"); unlink(session->target_link_dir); /* remove any existing symlink */ sprintf(devname, "/dev/st%da", i); symlink(devname, session->target_link_dir); /* make a new symlink */ /* no rewind nodes */ strcpy(link, "mtn"); unlink(session->target_link_dir); /* remove any existing symlink */ sprintf(devname, "/dev/nst%d", i); symlink(devname, session->target_link_dir); /* make a new symlink */ strcpy(link, "mtln"); unlink(session->target_link_dir); /* remove any existing symlink */ sprintf(devname, "/dev/nst%dl", i); symlink(devname, session->target_link_dir); /* make a new symlink */ strcpy(link, "mtmn"); unlink(session->target_link_dir); /* remove any existing symlink */ sprintf(devname, "/dev/nst%dm", i); symlink(devname, session->target_link_dir); /* make a new symlink */ strcpy(link, "mtan"); unlink(session->target_link_dir); /* remove any existing symlink */ sprintf(devname, "/dev/nst%da", i); symlink(devname, session->target_link_dir); /* make a new symlink */ } } } /* restore the session's target dir */ *lun_dir = '\0';}static void iscsi_update_generic_links(iscsi_session_t *session, int max_sg_devices, mode_t dir_mode){ int i; char devname[20]; /* we've reserved enough space in session->target_link_dir so that we can use it to build pathnames */ char *lun_dir = session->target_link_dir + strlen(session->target_link_dir); char *link; /* FIXME: can we get the number of devices supported from the running kernel? */ for (i=0; i < max_sg_devices; i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -