// SPDX-License-Identifier: GPL-2.0 /* * linux/drivers/scsi/scsi_proc.c * * The functions in this file provide an interface between * the PROC file system and the SCSI device drivers * It is mainly used for debugging, statistics and to pass * information directly to the lowlevel driver. * * (c) 1995 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de * Version: 0.99.8 last change: 95/09/13 * * generic command parser provided by: * Andreas Heilwagen <crashcar@informatik.uni-koblenz.de> * * generic_proc_info() support of xxxx_info() by: * Michael A. Griffith <grif@acm.org>
*/
/** * scsi_proc_hostdir_add - Create directory in /proc for a scsi host * @sht: owner of this directory * * Sets sht->proc_dir to the new directory.
*/ int scsi_proc_hostdir_add(conststruct scsi_host_template *sht)
{ struct scsi_proc_entry *e; int ret;
if (!sht->show_info) return 0;
mutex_lock(&global_host_template_mutex);
e = __scsi_lookup_proc_entry(sht); if (!e) {
e = kzalloc(sizeof(*e), GFP_KERNEL); if (!e) {
ret = -ENOMEM; goto unlock;
}
} if (e->present++) goto success;
e->proc_dir = proc_mkdir(sht->proc_name, proc_scsi); if (!e->proc_dir) {
printk(KERN_ERR "%s: proc_mkdir failed for %s\n", __func__,
sht->proc_name);
ret = -ENOMEM; goto unlock;
}
e->sht = sht;
list_add_tail(&e->entry, &scsi_proc_list);
success:
e = NULL;
ret = 0;
unlock:
mutex_unlock(&global_host_template_mutex);
kfree(e); return ret;
}
/** * scsi_proc_hostdir_rm - remove directory in /proc for a scsi host * @sht: owner of directory
*/ void scsi_proc_hostdir_rm(conststruct scsi_host_template *sht)
{ struct scsi_proc_entry *e;
if (!sht->show_info) return;
mutex_lock(&global_host_template_mutex);
e = __scsi_lookup_proc_entry(sht); if (e && !--e->present) {
remove_proc_entry(sht->proc_name, proc_scsi);
list_del(&e->entry);
kfree(e);
}
mutex_unlock(&global_host_template_mutex);
}
/** * scsi_proc_host_add - Add entry for this host to appropriate /proc dir * @shost: host to add
*/ void scsi_proc_host_add(struct Scsi_Host *shost)
{ conststruct scsi_host_template *sht = shost->hostt; struct scsi_proc_entry *e; struct proc_dir_entry *p; char name[10];
if (!sht->show_info) return;
e = scsi_lookup_proc_entry(sht); if (!e) goto err;
sprintf(name,"%d", shost->host_no);
p = proc_create_data(name, S_IRUGO | S_IWUSR, e->proc_dir,
&proc_scsi_ops, shost); if (!p) goto err; return;
err:
shost_printk(KERN_ERR, shost, "%s: Failed to register host (%s failed)\n", __func__,
e ? "proc_create_data()" : "scsi_proc_hostdir_add()");
}
/** * scsi_proc_host_rm - remove this host's entry from /proc * @shost: which host
*/ void scsi_proc_host_rm(struct Scsi_Host *shost)
{ conststruct scsi_host_template *sht = shost->hostt; struct scsi_proc_entry *e; char name[10];
if (!sht->show_info) return;
e = scsi_lookup_proc_entry(sht); if (!e) return;
sprintf(name,"%d", shost->host_no);
remove_proc_entry(name, e->proc_dir);
} /** * proc_print_scsidevice - return data about this host * @dev: A scsi device * @data: &struct seq_file to output to. * * Description: prints Host, Channel, Id, Lun, Vendor, Model, Rev, Type, * and revision.
*/ staticint proc_print_scsidevice(struct device *dev, void *data)
{ struct scsi_device *sdev; struct seq_file *s = data; int i;
if (!scsi_is_sdev_device(dev)) goto out;
sdev = to_scsi_device(dev);
seq_printf(s, "Host: scsi%d Channel: %02d Id: %02d Lun: %02llu\n Vendor: ",
sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); for (i = 0; i < 8; i++) { if (sdev->vendor[i] >= 0x20)
seq_putc(s, sdev->vendor[i]); else
seq_putc(s, ' ');
}
seq_puts(s, " Model: "); for (i = 0; i < 16; i++) { if (sdev->model[i] >= 0x20)
seq_putc(s, sdev->model[i]); else
seq_putc(s, ' ');
}
seq_puts(s, " Rev: "); for (i = 0; i < 4; i++) { if (sdev->rev[i] >= 0x20)
seq_putc(s, sdev->rev[i]); else
seq_putc(s, ' ');
}
/** * scsi_add_single_device - Respond to user request to probe for/add device * @host: user-supplied decimal integer * @channel: user-supplied decimal integer * @id: user-supplied decimal integer * @lun: user-supplied decimal integer * * Description: called by writing "scsi add-single-device" to /proc/scsi/scsi. * * does scsi_host_lookup() and either user_scan() if that transport * type supports it, or else scsi_scan_host_selected() * * Note: this seems to be aimed exclusively at SCSI parallel busses.
*/
/** * proc_scsi_write - handle writes to /proc/scsi/scsi * @file: not used * @buf: buffer to write * @length: length of buf, at most PAGE_SIZE * @ppos: not used * * Description: this provides a legacy mechanism to add or remove devices by * Host, Channel, ID, and Lun. To use, * "echo 'scsi add-single-device 0 1 2 3' > /proc/scsi/scsi" or * "echo 'scsi remove-single-device 0 1 2 3' > /proc/scsi/scsi" with * "0 1 2 3" replaced by the Host, Channel, Id, and Lun. * * Note: this seems to be aimed at parallel SCSI. Most modern busses (USB, * SATA, Firewire, Fibre Channel, etc) dynamically assign these values to * provide a unique identifier and nothing more.
*/
/** * proc_scsi_open - glue function * @inode: not used * @file: passed to single_open() * * Associates proc_scsi_show with this file
*/ staticint proc_scsi_open(struct inode *inode, struct file *file)
{ /* * We don't really need this for the write case but it doesn't * harm either.
*/ return seq_open(file, &scsi_seq_ops);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.