scsi: remove the SCSI OSD library

Now that all the users are gone the SCSI OSD library can be removed as
well.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Christoph Hellwig 2018-11-08 09:28:20 +01:00 коммит произвёл Martin K. Petersen
Родитель 80f2121380
Коммит 19fcae3d4f
11 изменённых файлов: 0 добавлений и 3659 удалений

Просмотреть файл

@ -1,192 +0,0 @@
The OSD Standard
================
OSD (Object-Based Storage Device) is a T10 SCSI command set that is designed
to provide efficient operation of input/output logical units that manage the
allocation, placement, and accessing of variable-size data-storage containers,
called objects. Objects are intended to contain operating system and application
constructs. Each object has associated attributes attached to it, which are
integral part of the object and provide metadata about the object. The standard
defines some common obligatory attributes, but user attributes can be added as
needed.
See: http://www.t10.org/ftp/t10/drafts/osd2/ for the latest draft for OSD 2
or search the web for "OSD SCSI"
OSD in the Linux Kernel
=======================
osd-initiator:
The main component of OSD in Kernel is the osd-initiator library. Its main
user is intended to be the pNFS-over-objects layout driver, which uses objects
as its back-end data storage. Other clients are the other osd parts listed below.
osd-uld:
This is a SCSI ULD that registers for OSD type devices and provides a testing
platform, both for the in-kernel initiator as well as connected targets. It
currently has no useful user-mode API, though it could have if need be.
osd target:
There are no current plans for an OSD target implementation in kernel. For all
needs, a user-mode target that is based on the scsi tgt target framework is
available from Ohio Supercomputer Center (OSC) at:
http://www.open-osd.org/bin/view/Main/OscOsdProject
There are several other target implementations. See http://open-osd.org for more
links.
Files and Folders
=================
This is the complete list of files included in this work:
include/scsi/
osd_initiator.h Main API for the initiator library
osd_types.h Common OSD types
osd_sec.h Security Manager API
osd_protocol.h Wire definitions of the OSD standard protocol
osd_attributes.h Wire definitions of OSD attributes
drivers/scsi/osd/
osd_initiator.c OSD-Initiator library implementation
osd_uld.c The OSD scsi ULD
osd_ktest.{h,c} In-kernel test suite (called by osd_uld)
osd_debug.h Some printk macros
Makefile For both in-tree and out-of-tree compilation
Kconfig Enables inclusion of the different pieces
osd_test.c User-mode application to call the kernel tests
The OSD-Initiator Library
=========================
osd_initiator is a low level implementation of an osd initiator encoder.
But even though, it should be intuitive and easy to use. Perhaps over time an
higher lever will form that automates some of the more common recipes.
init/fini:
- osd_dev_init() associates a scsi_device with an osd_dev structure
and initializes some global pools. This should be done once per scsi_device
(OSD LUN). The osd_dev structure is needed for calling osd_start_request().
- osd_dev_fini() cleans up before a osd_dev/scsi_device destruction.
OSD commands encoding, execution, and decoding of results:
struct osd_request's is used to iteratively encode an OSD command and carry
its state throughout execution. Each request goes through these stages:
a. osd_start_request() allocates the request.
b. Any of the osd_req_* methods is used to encode a request of the specified
type.
c. osd_req_add_{get,set}_attr_* may be called to add get/set attributes to the
CDB. "List" or "Page" mode can be used exclusively. The attribute-list API
can be called multiple times on the same request. However, only one
attribute-page can be read, as mandated by the OSD standard.
d. osd_finalize_request() computes offsets into the data-in and data-out buffers
and signs the request using the provided capability key and integrity-
check parameters.
e. osd_execute_request() may be called to execute the request via the block
layer and wait for its completion. The request can be executed
asynchronously by calling the block layer API directly.
f. After execution, osd_req_decode_sense() can be called to decode the request's
sense information.
g. osd_req_decode_get_attr() may be called to retrieve osd_add_get_attr_list()
values.
h. osd_end_request() must be called to deallocate the request and any resource
associated with it. Note that osd_end_request cleans up the request at any
stage and it must always be called after a successful osd_start_request().
osd_request's structure:
The OSD standard defines a complex structure of IO segments pointed to by
members in the CDB. Up to 3 segments can be deployed in the IN-Buffer and up to
4 in the OUT-Buffer. The ASCII illustration below depicts a secure-read with
associated get+set of attributes-lists. Other combinations very on the same
basic theme. From no-segments-used up to all-segments-used.
|________OSD-CDB__________|
| |
|read_len (offset=0) -|---------\
| | |
|get_attrs_list_length | |
|get_attrs_list_offset -|----\ |
| | | |
|retrieved_attrs_alloc_len| | |
|retrieved_attrs_offset -|----|----|-\
| | | | |
|set_attrs_list_length | | | |
|set_attrs_list_offset -|-\ | | |
| | | | | |
|in_data_integ_offset -|-|--|----|-|-\
|out_data_integ_offset -|-|--|--\ | | |
\_________________________/ | | | | | |
| | | | | |
|_______OUT-BUFFER________| | | | | | |
| Set attr list |</ | | | | |
| | | | | | |
|-------------------------| | | | | |
| Get attr descriptors |<---/ | | | |
| | | | | |
|-------------------------| | | | |
| Out-data integrity |<------/ | | |
| | | | |
\_________________________/ | | |
| | |
|________IN-BUFFER________| | | |
| In-Data read |<--------/ | |
| | | |
|-------------------------| | |
| Get attr list |<----------/ |
| | |
|-------------------------| |
| In-data integrity |<------------/
| |
\_________________________/
A block device request can carry bidirectional payload by means of associating
a bidi_read request with a main write-request. Each in/out request is described
by a chain of BIOs associated with each request.
The CDB is of a SCSI VARLEN CDB format, as described by OSD standard.
The OSD standard also mandates alignment restrictions at start of each segment.
In the code, in struct osd_request, there are two _osd_io_info structures to
describe the IN/OUT buffers above, two BIOs for the data payload and up to five
_osd_req_data_segment structures to hold the different segments allocation and
information.
Important: We have chosen to disregard the assumption that a BIO-chain (and
the resulting sg-list) describes a linear memory buffer. Meaning only first and
last scatter chain can be incomplete and all the middle chains are of PAGE_SIZE.
For us, a scatter-gather-list, as its name implies and as used by the Networking
layer, is to describe a vector of buffers that will be transferred to/from the
wire. It works very well with current iSCSI transport. iSCSI is currently the
only deployed OSD transport. In the future we anticipate SAS and FC attached OSD
devices as well.
The OSD Testing ULD
===================
TODO: More user-mode control on tests.
Authors, Mailing list
=====================
Please communicate with us on any deployment of osd, whether using this code
or not.
Any problems, questions, bug reports, lonely OSD nights, please email:
OSD Dev List <osd-dev@open-osd.org>
More up-to-date information can be found on:
http://open-osd.org
Boaz Harrosh <ooo@electrozaur.com>
References
==========
Weber, R., "SCSI Object-Based Storage Device Commands",
T10/1355-D ANSI/INCITS 400-2004,
http://www.t10.org/ftp/t10/drafts/osd/osd-r10.pdf
Weber, R., "SCSI Object-Based Storage Device Commands -2 (OSD-2)"
T10/1729-D, Working Draft, rev. 3
http://www.t10.org/ftp/t10/drafts/osd2/osd2r03.pdf

Просмотреть файл

@ -11385,12 +11385,6 @@ W: http://www.nongnu.org/orinoco/
S: Orphan
F: drivers/net/wireless/intersil/orinoco/
OSD LIBRARY and FILESYSTEM
M: Boaz Harrosh <ooo@electrozaur.com>
S: Maintained
F: drivers/scsi/osd/
F: include/scsi/osd_*
OV2659 OMNIVISION SENSOR DRIVER
M: "Lad, Prabhakar" <prabhakar.csengg@gmail.com>
L: linux-media@vger.kernel.org

Просмотреть файл

@ -1515,6 +1515,4 @@ source "drivers/scsi/pcmcia/Kconfig"
source "drivers/scsi/device_handler/Kconfig"
source "drivers/scsi/osd/Kconfig"
endmenu

Просмотреть файл

@ -150,7 +150,6 @@ obj-$(CONFIG_CHR_DEV_SG) += sg.o
obj-$(CONFIG_CHR_DEV_SCH) += ch.o
obj-$(CONFIG_SCSI_ENCLOSURE) += ses.o
obj-$(CONFIG_SCSI_OSD_INITIATOR) += osd/
obj-$(CONFIG_SCSI_HISI_SAS) += hisi_sas/
# This goes last, so that "real" scsi devices probe earlier

Просмотреть файл

@ -1,20 +0,0 @@
#
# Kbuild for the OSD modules
#
# Copyright (C) 2008 Panasas Inc. All rights reserved.
#
# Authors:
# Boaz Harrosh <ooo@electrozaur.com>
# Benny Halevy <bhalevy@panasas.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2
#
# libosd.ko - osd-initiator library
libosd-y := osd_initiator.o
obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
# osd.ko - SCSI ULD and char-device
osd-y := osd_uld.o
obj-$(CONFIG_SCSI_OSD_ULD) += osd.o

Просмотреть файл

@ -1,49 +0,0 @@
#
# Kernel configuration file for the OSD scsi protocol
#
# Copyright (C) 2008 Panasas Inc. All rights reserved.
#
# Authors:
# Boaz Harrosh <ooo@electrozaur.com>
# Benny Halevy <bhalevy@panasas.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public version 2 License as
# published by the Free Software Foundation
#
config SCSI_OSD_INITIATOR
tristate "OSD-Initiator library"
depends on SCSI
help
Enable the OSD-Initiator library (libosd.ko).
NOTE: You must also select CRYPTO_SHA1 + CRYPTO_HMAC and their
dependencies
config SCSI_OSD_ULD
tristate "OSD Upper Level driver"
depends on SCSI_OSD_INITIATOR
help
Build a SCSI upper layer driver that exports /dev/osdX devices
to user-mode for testing and controlling OSD devices. It is also
needed by exofs, for mounting an OSD based file system.
config SCSI_OSD_DPRINT_SENSE
int "(0-2) When sense is returned, DEBUG print all sense descriptors"
default 1
depends on SCSI_OSD_INITIATOR
help
When a CHECK_CONDITION status is returned from a target, and a
sense-buffer is retrieved, turning this on will dump a full
sense-decoding message. Setting to 2 will also print recoverable
errors that might be regularly returned for some filesystem
operations.
config SCSI_OSD_DEBUG
bool "Compile All OSD modules with lots of DEBUG prints"
default n
depends on SCSI_OSD_INITIATOR
help
OSD Code is populated with lots of OSD_DEBUG(..) printouts to
dmesg. Enable this if you found a bug and you want to help us
track the problem (see also MAINTAINERS). Setting this will also
force SCSI_OSD_DPRINT_SENSE=2.

Просмотреть файл

@ -1,30 +0,0 @@
/*
* osd_debug.h - Some kprintf macros
*
* Copyright (C) 2008 Panasas Inc. All rights reserved.
*
* Authors:
* Boaz Harrosh <ooo@electrozaur.com>
* Benny Halevy <bhalevy@panasas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
*
*/
#ifndef __OSD_DEBUG_H__
#define __OSD_DEBUG_H__
#define OSD_ERR(fmt, a...) printk(KERN_ERR "osd: " fmt, ##a)
#define OSD_INFO(fmt, a...) printk(KERN_NOTICE "osd: " fmt, ##a)
#ifdef CONFIG_SCSI_OSD_DEBUG
#define OSD_DEBUG(fmt, a...) \
printk(KERN_NOTICE "osd @%s:%d: " fmt, __func__, __LINE__, ##a)
#else
#define OSD_DEBUG(fmt, a...) do {} while (0)
#endif
/* u64 has problems with printk this will cast it to unsigned long long */
#define _LLU(x) (unsigned long long)(x)
#endif /* ndef __OSD_DEBUG_H__ */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,571 +0,0 @@
/*
* osd_uld.c - OSD Upper Layer Driver
*
* A Linux driver module that registers as a SCSI ULD and probes
* for OSD type SCSI devices.
* It's main function is to export osd devices to in-kernel users like
* osdfs and pNFS-objects-LD. It also provides one ioctl for running
* in Kernel tests.
*
* Copyright (C) 2008 Panasas Inc. All rights reserved.
*
* Authors:
* Boaz Harrosh <ooo@electrozaur.com>
* Benny Halevy <bhalevy@panasas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Panasas company nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/namei.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/idr.h>
#include <linux/major.h>
#include <linux/file.h>
#include <linux/slab.h>
#include <scsi/scsi.h>
#include <scsi/scsi_driver.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/osd_initiator.h>
#include <scsi/osd_sec.h>
#include "osd_debug.h"
#ifndef TYPE_OSD
# define TYPE_OSD 0x11
#endif
#ifndef SCSI_OSD_MAJOR
# define SCSI_OSD_MAJOR 260
#endif
#define SCSI_OSD_MAX_MINOR MINORMASK
static const char osd_name[] = "osd";
static const char *osd_version_string = "open-osd 0.2.1";
MODULE_AUTHOR("Boaz Harrosh <ooo@electrozaur.com>");
MODULE_DESCRIPTION("open-osd Upper-Layer-Driver osd.ko");
MODULE_LICENSE("GPL");
MODULE_ALIAS_CHARDEV_MAJOR(SCSI_OSD_MAJOR);
MODULE_ALIAS_SCSI_DEVICE(TYPE_OSD);
struct osd_uld_device {
int minor;
struct device class_dev;
struct cdev cdev;
struct osd_dev od;
struct osd_dev_info odi;
struct gendisk *disk;
};
struct osd_dev_handle {
struct osd_dev od;
struct file *file;
struct osd_uld_device *oud;
} ;
static DEFINE_IDA(osd_minor_ida);
/*
* scsi sysfs attribute operations
*/
static ssize_t osdname_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct osd_uld_device *ould = container_of(dev, struct osd_uld_device,
class_dev);
return sprintf(buf, "%s\n", ould->odi.osdname);
}
static DEVICE_ATTR_RO(osdname);
static ssize_t systemid_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct osd_uld_device *ould = container_of(dev, struct osd_uld_device,
class_dev);
memcpy(buf, ould->odi.systemid, ould->odi.systemid_len);
return ould->odi.systemid_len;
}
static DEVICE_ATTR_RO(systemid);
static struct attribute *osd_uld_attrs[] = {
&dev_attr_osdname.attr,
&dev_attr_systemid.attr,
NULL,
};
ATTRIBUTE_GROUPS(osd_uld);
static struct class osd_uld_class = {
.owner = THIS_MODULE,
.name = "scsi_osd",
.dev_groups = osd_uld_groups,
};
/*
* Char Device operations
*/
static int osd_uld_open(struct inode *inode, struct file *file)
{
struct osd_uld_device *oud = container_of(inode->i_cdev,
struct osd_uld_device, cdev);
get_device(&oud->class_dev);
/* cache osd_uld_device on file handle */
file->private_data = oud;
OSD_DEBUG("osd_uld_open %p\n", oud);
return 0;
}
static int osd_uld_release(struct inode *inode, struct file *file)
{
struct osd_uld_device *oud = file->private_data;
OSD_DEBUG("osd_uld_release %p\n", file->private_data);
file->private_data = NULL;
put_device(&oud->class_dev);
return 0;
}
/* FIXME: Only one vector for now */
unsigned g_test_ioctl;
do_test_fn *g_do_test;
int osduld_register_test(unsigned ioctl, do_test_fn *do_test)
{
if (g_test_ioctl)
return -EINVAL;
g_test_ioctl = ioctl;
g_do_test = do_test;
return 0;
}
EXPORT_SYMBOL(osduld_register_test);
void osduld_unregister_test(unsigned ioctl)
{
if (ioctl == g_test_ioctl) {
g_test_ioctl = 0;
g_do_test = NULL;
}
}
EXPORT_SYMBOL(osduld_unregister_test);
static do_test_fn *_find_ioctl(unsigned cmd)
{
if (g_test_ioctl == cmd)
return g_do_test;
else
return NULL;
}
static long osd_uld_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct osd_uld_device *oud = file->private_data;
int ret;
do_test_fn *do_test;
do_test = _find_ioctl(cmd);
if (do_test)
ret = do_test(&oud->od, cmd, arg);
else {
OSD_ERR("Unknown ioctl %d: osd_uld_device=%p\n", cmd, oud);
ret = -ENOIOCTLCMD;
}
return ret;
}
static const struct file_operations osd_fops = {
.owner = THIS_MODULE,
.open = osd_uld_open,
.release = osd_uld_release,
.unlocked_ioctl = osd_uld_ioctl,
.llseek = noop_llseek,
};
struct osd_dev *osduld_path_lookup(const char *name)
{
struct osd_uld_device *oud;
struct osd_dev_handle *odh;
struct file *file;
int error;
if (!name || !*name) {
OSD_ERR("Mount with !path || !*path\n");
return ERR_PTR(-EINVAL);
}
odh = kzalloc(sizeof(*odh), GFP_KERNEL);
if (unlikely(!odh))
return ERR_PTR(-ENOMEM);
file = filp_open(name, O_RDWR, 0);
if (IS_ERR(file)) {
error = PTR_ERR(file);
goto free_od;
}
if (file->f_op != &osd_fops){
error = -EINVAL;
goto close_file;
}
oud = file->private_data;
odh->od = oud->od;
odh->file = file;
odh->oud = oud;
return &odh->od;
close_file:
fput(file);
free_od:
kfree(odh);
return ERR_PTR(error);
}
EXPORT_SYMBOL(osduld_path_lookup);
static inline bool _the_same_or_null(const u8 *a1, unsigned a1_len,
const u8 *a2, unsigned a2_len)
{
if (!a2_len) /* User string is Empty means don't care */
return true;
if (a1_len != a2_len)
return false;
return 0 == memcmp(a1, a2, a1_len);
}
static int _match_odi(struct device *dev, const void *find_data)
{
struct osd_uld_device *oud = container_of(dev, struct osd_uld_device,
class_dev);
const struct osd_dev_info *odi = find_data;
if (_the_same_or_null(oud->odi.systemid, oud->odi.systemid_len,
odi->systemid, odi->systemid_len) &&
_the_same_or_null(oud->odi.osdname, oud->odi.osdname_len,
odi->osdname, odi->osdname_len)) {
OSD_DEBUG("found device sysid_len=%d osdname=%d\n",
odi->systemid_len, odi->osdname_len);
return 1;
} else {
return 0;
}
}
/* osduld_info_lookup - Loop through all devices, return the requested osd_dev.
*
* if @odi->systemid_len and/or @odi->osdname_len are zero, they act as a don't
* care. .e.g if they're both zero /dev/osd0 is returned.
*/
struct osd_dev *osduld_info_lookup(const struct osd_dev_info *odi)
{
struct device *dev = class_find_device(&osd_uld_class, NULL, odi, _match_odi);
if (likely(dev)) {
struct osd_dev_handle *odh = kzalloc(sizeof(*odh), GFP_KERNEL);
struct osd_uld_device *oud = container_of(dev,
struct osd_uld_device, class_dev);
if (unlikely(!odh)) {
put_device(dev);
return ERR_PTR(-ENOMEM);
}
odh->od = oud->od;
odh->oud = oud;
return &odh->od;
}
return ERR_PTR(-ENODEV);
}
EXPORT_SYMBOL(osduld_info_lookup);
void osduld_put_device(struct osd_dev *od)
{
if (od && !IS_ERR(od)) {
struct osd_dev_handle *odh =
container_of(od, struct osd_dev_handle, od);
struct osd_uld_device *oud = odh->oud;
BUG_ON(od->scsi_device != oud->od.scsi_device);
/* If scsi has released the device (logout), and exofs has last
* reference on oud it will be freed by above osd_uld_release
* within fput below. But this will oops in cdev_release which
* is called after the fops->release. A get_/put_ pair makes
* sure we have a cdev for the duration of fput
*/
if (odh->file) {
get_device(&oud->class_dev);
fput(odh->file);
}
put_device(&oud->class_dev);
kfree(odh);
}
}
EXPORT_SYMBOL(osduld_put_device);
const struct osd_dev_info *osduld_device_info(struct osd_dev *od)
{
struct osd_dev_handle *odh =
container_of(od, struct osd_dev_handle, od);
return &odh->oud->odi;
}
EXPORT_SYMBOL(osduld_device_info);
bool osduld_device_same(struct osd_dev *od, const struct osd_dev_info *odi)
{
struct osd_dev_handle *odh =
container_of(od, struct osd_dev_handle, od);
struct osd_uld_device *oud = odh->oud;
return (oud->odi.systemid_len == odi->systemid_len) &&
_the_same_or_null(oud->odi.systemid, oud->odi.systemid_len,
odi->systemid, odi->systemid_len) &&
(oud->odi.osdname_len == odi->osdname_len) &&
_the_same_or_null(oud->odi.osdname, oud->odi.osdname_len,
odi->osdname, odi->osdname_len);
}
EXPORT_SYMBOL(osduld_device_same);
/*
* Scsi Device operations
*/
static int __detect_osd(struct osd_uld_device *oud)
{
struct scsi_device *scsi_device = oud->od.scsi_device;
struct scsi_sense_hdr sense_hdr;
char caps[OSD_CAP_LEN];
int error;
/* sending a test_unit_ready as first command seems to be needed
* by some targets
*/
OSD_DEBUG("start scsi_test_unit_ready %p %p %p\n",
oud, scsi_device, scsi_device->request_queue);
error = scsi_test_unit_ready(scsi_device, 10*HZ, 5, &sense_hdr);
if (error)
OSD_ERR("warning: scsi_test_unit_ready failed\n");
osd_sec_init_nosec_doall_caps(caps, &osd_root_object, false, true);
if (osd_auto_detect_ver(&oud->od, caps, &oud->odi))
return -ENODEV;
return 0;
}
static void __remove(struct device *dev)
{
struct osd_uld_device *oud = container_of(dev, struct osd_uld_device,
class_dev);
struct scsi_device *scsi_device = oud->od.scsi_device;
kfree(oud->odi.osdname);
osd_dev_fini(&oud->od);
scsi_device_put(scsi_device);
OSD_INFO("osd_remove %s\n",
oud->disk ? oud->disk->disk_name : NULL);
if (oud->disk)
put_disk(oud->disk);
kfree(oud);
}
static int osd_probe(struct device *dev)
{
struct scsi_device *scsi_device = to_scsi_device(dev);
struct gendisk *disk;
struct osd_uld_device *oud;
int minor;
int error;
if (scsi_device->type != TYPE_OSD)
return -ENODEV;
minor = ida_alloc_max(&osd_minor_ida, SCSI_OSD_MAX_MINOR, GFP_KERNEL);
if (minor == -ENOSPC)
return -EBUSY;
if (minor < 0)
return -ENODEV;
error = -ENOMEM;
oud = kzalloc(sizeof(*oud), GFP_KERNEL);
if (NULL == oud)
goto err_retract_minor;
/* class device member */
device_initialize(&oud->class_dev);
dev_set_drvdata(dev, oud);
oud->minor = minor;
oud->class_dev.devt = MKDEV(SCSI_OSD_MAJOR, oud->minor);
oud->class_dev.class = &osd_uld_class;
oud->class_dev.parent = dev;
oud->class_dev.release = __remove;
/* hold one more reference to the scsi_device that will get released
* in __release, in case a logout is happening while fs is mounted
*/
if (scsi_device_get(scsi_device))
goto err_retract_minor;
osd_dev_init(&oud->od, scsi_device);
/* allocate a disk and set it up */
/* FIXME: do we need this since sg has already done that */
disk = alloc_disk(1);
if (!disk) {
OSD_ERR("alloc_disk failed\n");
goto err_free_osd;
}
disk->major = SCSI_OSD_MAJOR;
disk->first_minor = oud->minor;
sprintf(disk->disk_name, "osd%d", oud->minor);
oud->disk = disk;
/* Detect the OSD Version */
error = __detect_osd(oud);
if (error) {
OSD_ERR("osd detection failed, non-compatible OSD device\n");
goto err_free_osd;
}
/* init the char-device for communication with user-mode */
cdev_init(&oud->cdev, &osd_fops);
oud->cdev.owner = THIS_MODULE;
error = dev_set_name(&oud->class_dev, "%s", disk->disk_name);
if (error) {
OSD_ERR("dev_set_name failed => %d\n", error);
goto err_free_osd;
}
error = cdev_device_add(&oud->cdev, &oud->class_dev);
if (error) {
OSD_ERR("device_register failed => %d\n", error);
goto err_free_osd;
}
OSD_INFO("osd_probe %s\n", disk->disk_name);
return 0;
err_free_osd:
put_device(&oud->class_dev);
err_retract_minor:
ida_free(&osd_minor_ida, minor);
return error;
}
static int osd_remove(struct device *dev)
{
struct scsi_device *scsi_device = to_scsi_device(dev);
struct osd_uld_device *oud = dev_get_drvdata(dev);
if (oud->od.scsi_device != scsi_device) {
OSD_ERR("Half cooked osd-device %p, || %p!=%p",
dev, oud->od.scsi_device, scsi_device);
}
cdev_device_del(&oud->cdev, &oud->class_dev);
ida_free(&osd_minor_ida, oud->minor);
put_device(&oud->class_dev);
return 0;
}
/*
* Global driver and scsi registration
*/
static struct scsi_driver osd_driver = {
.gendrv = {
.name = osd_name,
.owner = THIS_MODULE,
.probe = osd_probe,
.remove = osd_remove,
}
};
static int __init osd_uld_init(void)
{
int err;
err = class_register(&osd_uld_class);
if (err) {
OSD_ERR("Unable to register sysfs class => %d\n", err);
return err;
}
err = register_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0),
SCSI_OSD_MAX_MINOR, osd_name);
if (err) {
OSD_ERR("Unable to register major %d for osd ULD => %d\n",
SCSI_OSD_MAJOR, err);
goto err_out;
}
err = scsi_register_driver(&osd_driver.gendrv);
if (err) {
OSD_ERR("scsi_register_driver failed => %d\n", err);
goto err_out_chrdev;
}
OSD_INFO("LOADED %s\n", osd_version_string);
return 0;
err_out_chrdev:
unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
err_out:
class_unregister(&osd_uld_class);
return err;
}
static void __exit osd_uld_exit(void)
{
scsi_unregister_driver(&osd_driver.gendrv);
unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
class_unregister(&osd_uld_class);
OSD_INFO("UNLOADED %s\n", osd_version_string);
}
module_init(osd_uld_init);
module_exit(osd_uld_exit);

Просмотреть файл

@ -1,511 +0,0 @@
/*
* osd_initiator.h - OSD initiator API definition
*
* Copyright (C) 2008 Panasas Inc. All rights reserved.
*
* Authors:
* Boaz Harrosh <ooo@electrozaur.com>
* Benny Halevy <bhalevy@panasas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
*
*/
#ifndef __OSD_INITIATOR_H__
#define __OSD_INITIATOR_H__
#include <scsi/osd_protocol.h>
#include <scsi/osd_types.h>
#include <linux/blkdev.h>
#include <scsi/scsi_device.h>
/* Note: "NI" in comments below means "Not Implemented yet" */
/* Configure of code:
* #undef if you *don't* want OSD v1 support in runtime.
* If #defined the initiator will dynamically configure to encode OSD v1
* CDB's if the target is detected to be OSD v1 only.
* OSD v2 only commands, options, and attributes will be ignored if target
* is v1 only.
* If #defined will result in bigger/slower code (OK Slower maybe not)
* Q: Should this be CONFIG_SCSI_OSD_VER1_SUPPORT and set from Kconfig?
*/
#define OSD_VER1_SUPPORT y
enum osd_std_version {
OSD_VER_NONE = 0,
OSD_VER1 = 1,
OSD_VER2 = 2,
};
/*
* Object-based Storage Device.
* This object represents an OSD device.
* It is not a full linux device in any way. It is only
* a place to hang resources associated with a Linux
* request Q and some default properties.
*/
struct osd_dev {
struct scsi_device *scsi_device;
unsigned def_timeout;
#ifdef OSD_VER1_SUPPORT
enum osd_std_version version;
#endif
};
/* Unique Identification of an OSD device */
struct osd_dev_info {
unsigned systemid_len;
u8 systemid[OSD_SYSTEMID_LEN];
unsigned osdname_len;
u8 *osdname;
};
/* Retrieve/return osd_dev(s) for use by Kernel clients
* Use IS_ERR/ERR_PTR on returned "osd_dev *".
*/
struct osd_dev *osduld_path_lookup(const char *dev_name);
struct osd_dev *osduld_info_lookup(const struct osd_dev_info *odi);
void osduld_put_device(struct osd_dev *od);
const struct osd_dev_info *osduld_device_info(struct osd_dev *od);
bool osduld_device_same(struct osd_dev *od, const struct osd_dev_info *odi);
/* Add/remove test ioctls from external modules */
typedef int (do_test_fn)(struct osd_dev *od, unsigned cmd, unsigned long arg);
int osduld_register_test(unsigned ioctl, do_test_fn *do_test);
void osduld_unregister_test(unsigned ioctl);
/* These are called by uld at probe time */
void osd_dev_init(struct osd_dev *od, struct scsi_device *scsi_device);
void osd_dev_fini(struct osd_dev *od);
/**
* osd_auto_detect_ver - Detect the OSD version, return Unique Identification
*
* @od: OSD target lun handle
* @caps: Capabilities authorizing OSD root read attributes access
* @odi: Retrieved information uniquely identifying the osd target lun
* Note: odi->osdname must be kfreed by caller.
*
* Auto detects the OSD version of the OSD target and sets the @od
* accordingly. Meanwhile also returns the "system id" and "osd name" root
* attributes which uniquely identify the OSD target. This member is usually
* called by the ULD. ULD users should call osduld_device_info().
* This rutine allocates osd requests and memory at GFP_KERNEL level and might
* sleep.
*/
int osd_auto_detect_ver(struct osd_dev *od,
void *caps, struct osd_dev_info *odi);
static inline struct request_queue *osd_request_queue(struct osd_dev *od)
{
return od->scsi_device->request_queue;
}
/* we might want to use function vector in the future */
static inline void osd_dev_set_ver(struct osd_dev *od, enum osd_std_version v)
{
#ifdef OSD_VER1_SUPPORT
od->version = v;
#endif
}
static inline bool osd_dev_is_ver1(struct osd_dev *od)
{
#ifdef OSD_VER1_SUPPORT
return od->version == OSD_VER1;
#else
return false;
#endif
}
struct osd_request;
typedef void (osd_req_done_fn)(struct osd_request *or, void *private);
struct osd_request {
struct osd_cdb cdb;
struct osd_data_out_integrity_info out_data_integ;
struct osd_data_in_integrity_info in_data_integ;
struct osd_dev *osd_dev;
struct request *request;
struct _osd_req_data_segment {
void *buff;
unsigned alloc_size; /* 0 here means: don't call kfree */
unsigned total_bytes;
} cdb_cont, set_attr, enc_get_attr, get_attr;
struct _osd_io_info {
struct bio *bio;
u64 total_bytes;
u64 residual;
struct request *req;
struct _osd_req_data_segment *last_seg;
u8 *pad_buff;
} out, in;
unsigned timeout;
unsigned retries;
unsigned sense_len;
u8 sense[OSD_MAX_SENSE_LEN];
enum osd_attributes_mode attributes_mode;
osd_req_done_fn *async_done;
void *async_private;
blk_status_t async_error;
int req_errors;
};
static inline bool osd_req_is_ver1(struct osd_request *or)
{
return osd_dev_is_ver1(or->osd_dev);
}
/*
* How to use the osd library:
*
* osd_start_request
* Allocates a request.
*
* osd_req_*
* Call one of, to encode the desired operation.
*
* osd_add_{get,set}_attr
* Optionally add attributes to the CDB, list or page mode.
*
* osd_finalize_request
* Computes final data out/in offsets and signs the request,
* making it ready for execution.
*
* osd_execute_request
* May be called to execute it through the block layer. Other wise submit
* the associated block request in some other way.
*
* After execution:
* osd_req_decode_sense
* Decodes sense information to verify execution results.
*
* osd_req_decode_get_attr
* Retrieve osd_add_get_attr_list() values if used.
*
* osd_end_request
* Must be called to deallocate the request.
*/
/**
* osd_start_request - Allocate and initialize an osd_request
*
* @osd_dev: OSD device that holds the scsi-device and default values
* that the request is associated with.
*
* Allocate osd_request and initialize all members to the
* default/initial state.
*/
struct osd_request *osd_start_request(struct osd_dev *od);
enum osd_req_options {
OSD_REQ_FUA = 0x08, /* Force Unit Access */
OSD_REQ_DPO = 0x10, /* Disable Page Out */
OSD_REQ_BYPASS_TIMESTAMPS = 0x80,
};
/**
* osd_finalize_request - Sign request and prepare request for execution
*
* @or: osd_request to prepare
* @options: combination of osd_req_options bit flags or 0.
* @cap: A Pointer to an OSD_CAP_LEN bytes buffer that is received from
* The security manager as capabilities for this cdb.
* @cap_key: The cryptographic key used to sign the cdb/data. Can be null
* if NOSEC is used.
*
* The actual request and bios are only allocated here, so are the get_attr
* buffers that will receive the returned attributes. Copy's @cap to cdb.
* Sign the cdb/data with @cap_key.
*/
int osd_finalize_request(struct osd_request *or,
u8 options, const void *cap, const u8 *cap_key);
/**
* osd_execute_request - Execute the request synchronously through block-layer
*
* @or: osd_request to Executed
*
* Calls blk_execute_rq to q the command and waits for completion.
*/
int osd_execute_request(struct osd_request *or);
/**
* osd_execute_request_async - Execute the request without waitting.
*
* @or: - osd_request to Executed
* @done: (Optional) - Called at end of execution
* @private: - Will be passed to @done function
*
* Calls blk_execute_rq_nowait to queue the command. When execution is done
* optionally calls @done with @private as parameter. @or->async_error will
* have the return code
*/
int osd_execute_request_async(struct osd_request *or,
osd_req_done_fn *done, void *private);
/**
* osd_req_decode_sense_full - Decode sense information after execution.
*
* @or: - osd_request to examine
* @osi - Receives a more detailed error report information (optional).
* @silent - Do not print to dmsg (Even if enabled)
* @bad_obj_list - Some commands act on multiple objects. Failed objects will
* be received here (optional)
* @max_obj - Size of @bad_obj_list.
* @bad_attr_list - List of failing attributes (optional)
* @max_attr - Size of @bad_attr_list.
*
* After execution, osd_request results are analyzed using this function. The
* return code is the final disposition on the error. So it is possible that a
* CHECK_CONDITION was returned from target but this will return NO_ERROR, for
* example on recovered errors. All parameters are optional if caller does
* not need any returned information.
* Note: This function will also dump the error to dmsg according to settings
* of the SCSI_OSD_DPRINT_SENSE Kconfig value. Set @silent if you know the
* command would routinely fail, to not spam the dmsg file.
*/
/**
* osd_err_priority - osd categorized return codes in ascending severity.
*
* The categories are borrowed from the pnfs_osd_errno enum.
* See comments for translated Linux codes returned by osd_req_decode_sense.
*/
enum osd_err_priority {
OSD_ERR_PRI_NO_ERROR = 0,
/* Recoverable, caller should clear_highpage() all pages */
OSD_ERR_PRI_CLEAR_PAGES = 1, /* -EFAULT */
OSD_ERR_PRI_RESOURCE = 2, /* -ENOMEM */
OSD_ERR_PRI_BAD_CRED = 3, /* -EINVAL */
OSD_ERR_PRI_NO_ACCESS = 4, /* -EACCES */
OSD_ERR_PRI_UNREACHABLE = 5, /* any other */
OSD_ERR_PRI_NOT_FOUND = 6, /* -ENOENT */
OSD_ERR_PRI_NO_SPACE = 7, /* -ENOSPC */
OSD_ERR_PRI_EIO = 8, /* -EIO */
};
struct osd_sense_info {
enum osd_err_priority osd_err_pri;
int key; /* one of enum scsi_sense_keys */
int additional_code ; /* enum osd_additional_sense_codes */
union { /* Sense specific information */
u16 sense_info;
u16 cdb_field_offset; /* scsi_invalid_field_in_cdb */
};
union { /* Command specific information */
u64 command_info;
};
u32 not_initiated_command_functions; /* osd_command_functions_bits */
u32 completed_command_functions; /* osd_command_functions_bits */
struct osd_obj_id obj;
struct osd_attr attr;
};
int osd_req_decode_sense_full(struct osd_request *or,
struct osd_sense_info *osi, bool silent,
struct osd_obj_id *bad_obj_list, int max_obj,
struct osd_attr *bad_attr_list, int max_attr);
static inline int osd_req_decode_sense(struct osd_request *or,
struct osd_sense_info *osi)
{
return osd_req_decode_sense_full(or, osi, false, NULL, 0, NULL, 0);
}
/**
* osd_end_request - return osd_request to free store
*
* @or: osd_request to free
*
* Deallocate all osd_request resources (struct req's, BIOs, buffers, etc.)
*/
void osd_end_request(struct osd_request *or);
/*
* CDB Encoding
*
* Note: call only one of the following methods.
*/
/*
* Device commands
*/
void osd_req_set_master_seed_xchg(struct osd_request *or, ...);/* NI */
void osd_req_set_master_key(struct osd_request *or, ...);/* NI */
void osd_req_format(struct osd_request *or, u64 tot_capacity);
/* list all partitions
* @list header must be initialized to zero on first run.
*
* Call osd_is_obj_list_done() to find if we got the complete list.
*/
int osd_req_list_dev_partitions(struct osd_request *or,
osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem);
void osd_req_flush_obsd(struct osd_request *or,
enum osd_options_flush_scope_values);
void osd_req_perform_scsi_command(struct osd_request *or,
const u8 *cdb, ...);/* NI */
void osd_req_task_management(struct osd_request *or, ...);/* NI */
/*
* Partition commands
*/
void osd_req_create_partition(struct osd_request *or, osd_id partition);
void osd_req_remove_partition(struct osd_request *or, osd_id partition);
void osd_req_set_partition_key(struct osd_request *or,
osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
u8 seed[OSD_CRYPTO_SEED_SIZE]);/* NI */
/* list all collections in the partition
* @list header must be init to zero on first run.
*
* Call osd_is_obj_list_done() to find if we got the complete list.
*/
int osd_req_list_partition_collections(struct osd_request *or,
osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
unsigned nelem);
/* list all objects in the partition
* @list header must be init to zero on first run.
*
* Call osd_is_obj_list_done() to find if we got the complete list.
*/
int osd_req_list_partition_objects(struct osd_request *or,
osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
unsigned nelem);
void osd_req_flush_partition(struct osd_request *or,
osd_id partition, enum osd_options_flush_scope_values);
/*
* Collection commands
*/
void osd_req_create_collection(struct osd_request *or,
const struct osd_obj_id *);/* NI */
void osd_req_remove_collection(struct osd_request *or,
const struct osd_obj_id *);/* NI */
/* list all objects in the collection */
int osd_req_list_collection_objects(struct osd_request *or,
const struct osd_obj_id *, osd_id initial_id,
struct osd_obj_id_list *list, unsigned nelem);
/* V2 only filtered list of objects in the collection */
void osd_req_query(struct osd_request *or, ...);/* NI */
void osd_req_flush_collection(struct osd_request *or,
const struct osd_obj_id *, enum osd_options_flush_scope_values);
void osd_req_get_member_attrs(struct osd_request *or, ...);/* V2-only NI */
void osd_req_set_member_attrs(struct osd_request *or, ...);/* V2-only NI */
/*
* Object commands
*/
void osd_req_create_object(struct osd_request *or, struct osd_obj_id *);
void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *);
void osd_req_write(struct osd_request *or,
const struct osd_obj_id *obj, u64 offset, struct bio *bio, u64 len);
int osd_req_write_kern(struct osd_request *or,
const struct osd_obj_id *obj, u64 offset, void *buff, u64 len);
void osd_req_append(struct osd_request *or,
const struct osd_obj_id *, struct bio *data_out);/* NI */
void osd_req_create_write(struct osd_request *or,
const struct osd_obj_id *, struct bio *data_out, u64 offset);/* NI */
void osd_req_clear(struct osd_request *or,
const struct osd_obj_id *, u64 offset, u64 len);/* NI */
void osd_req_punch(struct osd_request *or,
const struct osd_obj_id *, u64 offset, u64 len);/* V2-only NI */
void osd_req_flush_object(struct osd_request *or,
const struct osd_obj_id *, enum osd_options_flush_scope_values,
/*V2*/ u64 offset, /*V2*/ u64 len);
void osd_req_read(struct osd_request *or,
const struct osd_obj_id *obj, u64 offset, struct bio *bio, u64 len);
int osd_req_read_kern(struct osd_request *or,
const struct osd_obj_id *obj, u64 offset, void *buff, u64 len);
/* Scatter/Gather write/read commands */
int osd_req_write_sg(struct osd_request *or,
const struct osd_obj_id *obj, struct bio *bio,
const struct osd_sg_entry *sglist, unsigned numentries);
int osd_req_read_sg(struct osd_request *or,
const struct osd_obj_id *obj, struct bio *bio,
const struct osd_sg_entry *sglist, unsigned numentries);
int osd_req_write_sg_kern(struct osd_request *or,
const struct osd_obj_id *obj, void **buff,
const struct osd_sg_entry *sglist, unsigned numentries);
int osd_req_read_sg_kern(struct osd_request *or,
const struct osd_obj_id *obj, void **buff,
const struct osd_sg_entry *sglist, unsigned numentries);
/*
* Root/Partition/Collection/Object Attributes commands
*/
/* get before set */
void osd_req_get_attributes(struct osd_request *or, const struct osd_obj_id *);
/* set before get */
void osd_req_set_attributes(struct osd_request *or, const struct osd_obj_id *);
/*
* Attributes appended to most commands
*/
/* Attributes List mode (or V2 CDB) */
/*
* TODO: In ver2 if at finalize time only one attr was set and no gets,
* then the Attributes CDB mode is used automatically to save IO.
*/
/* set a list of attributes. */
int osd_req_add_set_attr_list(struct osd_request *or,
const struct osd_attr *, unsigned nelem);
/* get a list of attributes */
int osd_req_add_get_attr_list(struct osd_request *or,
const struct osd_attr *, unsigned nelem);
/*
* Attributes list decoding
* Must be called after osd_request.request was executed
* It is called in a loop to decode the returned get_attr
* (see osd_add_get_attr)
*/
int osd_req_decode_get_attr_list(struct osd_request *or,
struct osd_attr *, int *nelem, void **iterator);
/* Attributes Page mode */
/*
* Read an attribute page and optionally set one attribute
*
* Retrieves the attribute page directly to a user buffer.
* @attr_page_data shall stay valid until end of execution.
* See osd_attributes.h for common page structures
*/
int osd_req_add_get_attr_page(struct osd_request *or,
u32 page_id, void *attr_page_data, unsigned max_page_len,
const struct osd_attr *set_one);
#endif /* __OSD_LIB_H__ */

Просмотреть файл

@ -1,201 +0,0 @@
/*
* Copyright (C) 2011
* Boaz Harrosh <ooo@electrozaur.com>
*
* Public Declarations of the ORE API
*
* This file is part of the ORE (Object Raid Engine) library.
*
* ORE is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation. (GPL v2)
*
* ORE 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.
*
* You should have received a copy of the GNU General Public License
* along with the ORE; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __ORE_H__
#define __ORE_H__
#include <scsi/osd_initiator.h>
#include <scsi/osd_attributes.h>
#include <scsi/osd_sec.h>
#include <linux/pnfs_osd_xdr.h>
#include <linux/bug.h>
struct ore_comp {
struct osd_obj_id obj;
u8 cred[OSD_CAP_LEN];
};
struct ore_layout {
/* Our way of looking at the data_map */
enum pnfs_osd_raid_algorithm4
raid_algorithm;
unsigned stripe_unit;
unsigned mirrors_p1;
unsigned group_width;
unsigned parity;
u64 group_depth;
unsigned group_count;
/* Cached often needed calculations filled in by
* ore_verify_layout
*/
unsigned long max_io_length; /* Max length that should be passed to
* ore_get_rw_state
*/
};
struct ore_dev {
struct osd_dev *od;
};
struct ore_components {
unsigned first_dev; /* First logical device no */
unsigned numdevs; /* Num of devices in array */
/* If @single_comp == EC_SINGLE_COMP, @comps points to a single
* component. else there are @numdevs components
*/
enum EC_COMP_USAGE {
EC_SINGLE_COMP = 0, EC_MULTPLE_COMPS = 0xffffffff
} single_comp;
struct ore_comp *comps;
/* Array of pointers to ore_dev-* . User will usually have these pointed
* too a bigger struct which contain an "ore_dev ored" member and use
* container_of(oc->ods[i], struct foo_dev, ored) to access the bigger
* structure.
*/
struct ore_dev **ods;
};
/* ore_comp_dev Recievies a logical device index */
static inline struct osd_dev *ore_comp_dev(
const struct ore_components *oc, unsigned i)
{
BUG_ON((i < oc->first_dev) || (oc->first_dev + oc->numdevs <= i));
return oc->ods[i - oc->first_dev]->od;
}
static inline void ore_comp_set_dev(
struct ore_components *oc, unsigned i, struct osd_dev *od)
{
oc->ods[i - oc->first_dev]->od = od;
}
struct ore_striping_info {
u64 offset;
u64 obj_offset;
u64 length;
u64 first_stripe_start; /* only used in raid writes */
u64 M; /* for truncate */
unsigned bytes_in_stripe;
unsigned dev;
unsigned par_dev;
unsigned unit_off;
unsigned cur_pg;
unsigned cur_comp;
unsigned maxdevUnits;
};
struct ore_io_state;
typedef void (*ore_io_done_fn)(struct ore_io_state *ios, void *private);
struct _ore_r4w_op {
/* @Priv given here is passed ios->private */
struct page * (*get_page)(void *priv, u64 page_index, bool *uptodate);
void (*put_page)(void *priv, struct page *page);
};
struct ore_io_state {
struct kref kref;
struct ore_striping_info si;
void *private;
ore_io_done_fn done;
struct ore_layout *layout;
struct ore_components *oc;
/* Global read/write IO*/
loff_t offset;
unsigned long length;
void *kern_buff;
struct page **pages;
unsigned nr_pages;
unsigned pgbase;
unsigned pages_consumed;
/* Attributes */
unsigned in_attr_len;
struct osd_attr *in_attr;
unsigned out_attr_len;
struct osd_attr *out_attr;
bool reading;
/* House keeping of Parity pages */
bool extra_part_alloc;
struct page **parity_pages;
unsigned max_par_pages;
unsigned cur_par_page;
unsigned sgs_per_dev;
struct __stripe_pages_2d *sp2d;
struct ore_io_state *ios_read_4_write;
const struct _ore_r4w_op *r4w;
/* Variable array of size numdevs */
unsigned numdevs;
struct ore_per_dev_state {
struct osd_request *or;
struct bio *bio;
loff_t offset;
unsigned length;
unsigned last_sgs_total;
unsigned dev;
struct osd_sg_entry *sglist;
unsigned cur_sg;
} per_dev[];
};
static inline unsigned ore_io_state_size(unsigned numdevs)
{
return sizeof(struct ore_io_state) +
sizeof(struct ore_per_dev_state) * numdevs;
}
/* ore.c */
int ore_verify_layout(unsigned total_comps, struct ore_layout *layout);
void ore_calc_stripe_info(struct ore_layout *layout, u64 file_offset,
u64 length, struct ore_striping_info *si);
int ore_get_rw_state(struct ore_layout *layout, struct ore_components *comps,
bool is_reading, u64 offset, u64 length,
struct ore_io_state **ios);
int ore_get_io_state(struct ore_layout *layout, struct ore_components *comps,
struct ore_io_state **ios);
void ore_put_io_state(struct ore_io_state *ios);
typedef void (*ore_on_dev_error)(struct ore_io_state *ios, struct ore_dev *od,
unsigned dev_index, enum osd_err_priority oep,
u64 dev_offset, u64 dev_len);
int ore_check_io(struct ore_io_state *ios, ore_on_dev_error rep);
int ore_create(struct ore_io_state *ios);
int ore_remove(struct ore_io_state *ios);
int ore_write(struct ore_io_state *ios);
int ore_read(struct ore_io_state *ios);
int ore_truncate(struct ore_layout *layout, struct ore_components *comps,
u64 size);
int extract_attr_from_ios(struct ore_io_state *ios, struct osd_attr *attr);
extern const struct osd_attr g_attr_logical_length;
#endif