: New SCSI target framework (SCST) with dev handlers and 2 target drivers
Subsystems (8)
Re: [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Vladislav BolkhovitinQuoted 28 lines · Vladislav Bolkhovitin
Quoted 20 lines · Boaz Harrosh, on 11/10/2010 12:58 PM wrote:
Quoted 9 lines · Vladislav Bolkhovitin
Sorry, but what is incorrect in the working implementation without any bugs doing its job in the simplest, smallest and clearest way?
If those objects remade to free themselves in the kobjects
release(), what value would it add to them? Would the implementation be simpler, smaller or clearer? Not, I believe, new implementation would be only bigger and less clear. So, what's the point to do it to make the code worse?Totally theoretically speaking, since I have not inspected the code.
If today you wait for the count to reach zero, then unregister and send an event to some other subsystem to free the object.
Is it not the same as if you take an extra refcount, unregister and send the event at count=1. Then at that other place decrement the last count to cause the object to be freed.
Quoted 6 lines
I agree that it is hard to do lockless. what some places do is have an extra kref. The kobj has a single ref on it. everything takes the other kref. when that reaches zero the unregister and event fires and at free you decrement the only kobj ref to deallocate. This is one way. In some situations you can manage with a single counter it all depends.
Quoted 4 lines
Thanks for sharing your thoughts with us. But the question isn't about if it's possible to implement what we need locklessly. The question is in two approaches how to synchronously delete objects with entries on SYSFS:
Thanks for putting up an example we can now speak more specifically. (And saved me the time to actually look at code)
I'll first comment on your code below and I have some questions, please see if I understood you correctly. Later below I'll try to explain what I meant.
Quoted 4 lines
1. struct object_x {
...
struct kobject kobj;
struct completion *release_completion; release_completion is only to be used by del_object!
Quoted 3 lines
};
static void
x_release(struct kobject *kobj)
This one is put on the kobj.release Right?
Quoted 10 lines
{
struct object_x *x;
struct completion *c;
x = container_of(kobj, struct object_x, kobj);
c = x->release_completion;
kfree(x);
complete_all(c);
}I don't see the unregister of the object_x.kobj, where do you do this one in x_release or del_object below?
Quoted 7 lines
void
del_object(struct object_x *x){ DECLARE_COMPLETION_ONSTACK(completion); ... x->release_completion = &completion; kobject_put(&x->kobj);
This put might not be the last put on the object, IOs in flight and/or open files might have extra reference on the object. We release our initial ref, and below wait for all operations to complete. (Is there a matter of timeout like files not closing?)
Quoted 19 lines
wait_for_completion(&completion); }and
2. struct object_x { ... struct kobject kobj; struct completion release_completion; };static void
x_release(struct kobject *kobj){ struct object_x *x; x = container_of(kobj, struct object_x, kobj); complete_all(&x->release_completion); }
Quoted 2 lines
void
del_object(struct object_x *x)
{
DECLARE_COMPLETION_ONSTACK(completion); x->release_completion = &completion;
Right?
Quoted 18 lines
... kobject_put(&x->kobj); wait_for_completion(&completion); ... kfree(x); }Greg asserts that (1) is the only correct approach while (2) is incorrect, and I'm trying to justify that (2) is correct too and sometimes could be better, i.e. simpler and clearer, because it decouples
object_xfrom SYSFS and its kobj. Then kobj becomes an ordinary member of structobject_xwithout any special treatment and with the same lifetime rules as other members of structobject_x. While in (1) all lifetime of structobject_xis strictly attached to kobj, so it needs be specially handled with additional code for that if structobject_xhas many other members which needed to be initialized/deleted_beforeandafter_kobj as we have in SCST.
Quoted 1 line
Vlad
One possibility (There are others)
3. struct object_x {
...
struct kref kref;
struct kobject kobj;
struct completion *release_completion;
};Every body takes kref_put(&object_x.kref) and kref_get(&object_x.kref) I hope you have x_get/x_put, Yes?
static void x_kref_release(struct kref *kref)
{
struct object_x *x = container_of(kref, struct object_x, kref);
complete_all(&x->release_completion);
}static void x_obj_release(struct kobject *kobj)
{
struct object_x *x = container_of(kobj, struct object_x, kobj);
kfree(x);
}int x_put(struct object_x *x)
{
return kref_put(&x->kref, x_kref_release);
}void del_object(struct object_x *x)
{
DECLARE_COMPLETION_ONSTACK(completion);
...
x->release_completion = &completion;
x_put(x)
wait_for_completion(&completion);
kobject_put(&x->kobj);
}Or
4. Exactly Like 3 but without the extra kref member Only x_put() changes and x_kref_release() now receives an x_object
int x_put(struct object_x *x)
{
if (kobject_put(&x->kobj) == 1)
// Like above [3] x_kref_release()
x_kref_release(x);
}Note that in 4 you don't actually have a kref member, and that you have one extra ref on kobj from the beginning. In del_object above the first x_put(x) makes it possible to reach the "1" count and then the final kobject_put(&x->kobj); frees the object.
(You need to be carfull with [4] because it must have a refcount==2 before you expose it to any IO or sysfs.)
So this is what I meant.
Cheers
Boaz
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 10 lines · Boaz Harrosh
4. Exactly Like 3 but without the extra kref member Only
x_put()changes andx_kref_release()now receives anx_objectint
x_put(struct object_x *x){ if (kobject_put(&x->kobj) == 1) // Like above [3] x_kref_release() x_kref_release(x); }
This is racy, please never do this.
thanks,
greg k-h
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 5 lines · Greg KH
Quoted 4 lines · Boaz Harrosh
4. Exactly Like 3 but without the extra kref member Only
x_put()changes andx_kref_release()now receives anx_object
Quoted 9 lines
Quoted 6 lines
int
x_put(struct object_x *x){ if (kobject_put(&x->kobj) == 1) // Like above [3] x_kref_release() x_kref_release(x); }This is racy, please never do this.
The last ref belongs to the core code. 1 means there are no more external clients on the object. So it can not race with decrements. But I guess there is a possibility that it can race with new increments. If it is the case that new increments can only come from, say, sysfs access, then if we call the x_put() == 1 after we are unregistered from sysfs and no new users are allowed then the counter can only go down and we have the last reference. No?
Like I said option 4 is delicate it must be done carefully.
Quoted 3 lines
thanks,
greg k-h
Thanks
Boaz
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 13 lines · Boaz Harrosh
Quoted 12 lines · Greg KH
Quoted 10 lines · Boaz Harrosh
4. Exactly Like 3 but without the extra kref member Only
x_put()changes andx_kref_release()now receives anx_objectint
x_put(struct object_x *x){ if (kobject_put(&x->kobj) == 1) // Like above [3] x_kref_release() x_kref_release(x); }
Quoted 7 lines
Quoted 2 lines
This is racy, please never do this.
The last ref belongs to the core code. 1 means there are no more external clients on the object. So it can not race with decrements. But I guess there is a possibility that it can race with new increments.
Exactly.
Quoted 5 lines
If it is the case that new increments
can only come from, say, sysfs access, then if we call thex_put()== 1 after we are unregistered from sysfs and no new users are allowed then the counter can only go down and we have the last reference. No?
Just don't do this, it's not worth it and will break over time when others mess with the code.
Also note that kobject_put() does not even return a value, so the code above will not even compile, let alone work.
thanks,
greg k-h
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 30 lines · Greg KH
Quoted 13 lines · Boaz Harrosh
Quoted 12 lines · Greg KH
Quoted 10 lines · Boaz Harrosh
4. Exactly Like 3 but without the extra kref member Only
x_put()changes andx_kref_release()now receives anx_objectint
x_put(struct object_x *x){ if (kobject_put(&x->kobj) == 1) // Like above [3] x_kref_release() x_kref_release(x); }Quoted 7 lines
Quoted 2 lines
This is racy, please never do this.
The last ref belongs to the core code. 1 means there are no more external clients on the object. So it can not race with decrements. But I guess there is a possibility that it can race with new increments.
Exactly.
Quoted 5 lines
If it is the case that new increments
can only come from, say, sysfs access, then if we call thex_put()== 1 after we are unregistered from sysfs and no new users are allowed then the counter can only go down and we have the last reference. No?
Quoted 6 lines
Just don't do this, it's not worth it and will break over time when others mess with the code.
Also note that
kobject_put()does not even return a value, so the code above will not even compile, let alone work.
OK Point taken, it is fragile. So there is option [3] then, with the extra kref. I think I've seen other places with this approach.
Quoted 3 lines
thanks,
greg k-h
Thanks
Boaz
Re: [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Boaz HarroshQuoted 1 line · Boaz Harrosh, on 11/11/2010 12:59 PM wrote:
Quoted 1 line
static void
x_release(struct kobject *kobj)
Yes. Precisely speaking, of its kobj_type.
Quoted 13 lines
This one is put on the kobj.release Right?
Quoted 10 lines
{ struct object_x *x; struct completion *c; x = container_of(kobj, struct object_x, kobj); c = x->release_completion; kfree(x); complete_all(c); }
Quoted 2 lines
I don't see the unregister of the object_x.kobj, where do you do this one in
x_releaseordel_objectbelow?
Which unregister? Put for object_x.kobj is in del_object()
Quoted 4 lines
Quoted 4 lines
void
del_object(struct object_x *x){ DECLARE_COMPLETION_ONSTACK(completion);
Quoted 8 lines
Quoted 3 lines
... x->release_completion = &completion; kobject_put(&x->kobj);This put might not be the last put on the object, IOs in flight and/or open files might have extra reference on the object. We release our initial ref, and below wait for all operations to complete. (Is there a matter of timeout like files not closing?)
This is the last internal put. All other references are from outsiders. So, we are waiting for all them to put before we go on.
Quoted 55 lines
One possibility (There are others)
3. struct object_x { ... struct kref kref; struct kobject kobj; struct completion *release_completion; };Every body takes
kref_put(&object_x.kref)andkref_get(&object_x.kref)I hope you have x_get/x_put, Yes?static void
x_kref_release(struct kref *kref){ struct object_x *x = container_of(kref, struct object_x, kref); complete_all(&x->release_completion); }static void
x_obj_release(struct kobject *kobj){ struct object_x *x = container_of(kobj, struct object_x, kobj); kfree(x); }int
x_put(struct object_x *x){ return kref_put(&x->kref, x_kref_release); }void
del_object(struct object_x *x){ DECLARE_COMPLETION_ONSTACK(completion); ... x->release_completion = &completion; x_put(x) wait_for_completion(&completion); kobject_put(&x->kobj); }Or
4. Exactly Like 3 but without the extra kref member Only
x_put()changes andx_kref_release()now receives anx_objectint
x_put(struct object_x *x){ if (kobject_put(&x->kobj) == 1) // Like above [3] x_kref_release() x_kref_release(x); }
Quoted 8 lines
Note that in 4 you don't actually have a kref member, and that you have one extra ref on kobj from the beginning. In
del_objectabove the firstx_put(x)makes it possible to reach the "1" count and then the finalkobject_put(&x->kobj); frees the object.
(You need to be carfull with [4] because it must have a refcount==2 before you expose it to any IO or sysfs.)So this is what I meant.
OK, I see. You know, all non-trivial things can be done in >1 correct way ;) (Although (4) is not too correct as Greg already wrote)
Vlad
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 31 lines · Vladislav Bolkhovitin
Quoted 1 line · Boaz Harrosh, on 11/11/2010 12:59 PM wrote:
Quoted 1 line
static void
x_release(struct kobject *kobj)Yes. Precisely speaking, of its
kobj_type.Quoted 13 lines
This one is put on the kobj.release Right?
Quoted 10 lines
{ struct object_x *x; struct completion *c; x = container_of(kobj, struct object_x, kobj); c = x->release_completion; kfree(x); complete_all(c); }Quoted 2 lines
I don't see the unregister of the object_x.kobj, where do you do this one in
x_releaseordel_objectbelow?Which unregister? Put for object_x.kobj is in
del_object()Quoted 8 lines
Quoted 7 lines
void
del_object(struct object_x *x){ DECLARE_COMPLETION_ONSTACK(completion); ... x->release_completion = &completion; kobject_put(&x->kobj);
Quoted 8 lines
Quoted 4 lines
This put might not be the last put on the object, IOs in flight and/or open files might have extra reference on the object. We release our initial ref, and below wait for all operations to complete. (Is there a matter of timeout like files not closing?)
This is the last internal put. All other references are from outsiders. So, we are waiting for all them to put before we go on.
The question is why do you need to wait here? I presume it is module unloading path, but then it is quite bad - you can easily wedge your subsystem if you make something to take a reference to your kobject while module is ytying to be unloaded. Back when sysfs attributes tied kobjects the easiest thing was to do:
rmmod <module> < / sys/devices/..../attribute
If you are done with the kobject - just proceed with what you were doing and let it die its own peaceful death some time later. You just need to make sure release code sticks around to free it and your subsystem core can be tasked with this. Use module counter to prevent unloading of the subsystem core until all kobjects belonging to the subsystem are destroyed.
Signature · 1 line
Dmitry
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 12 lines · Dmitry Torokhov
Quoted 4 lines · Vladislav Bolkhovitin
[ ... ]
This is the last internal put. All other references are from outsiders. So, we are waiting for all them to put before we go on.
The question is why do you need to wait here? I presume it is module unloading path, but then it is quite bad - you can easily wedge your subsystem if you make something to take a reference to your kobject while module is trying to be unloaded. Back when sysfs attributes tied kobjects the easiest thing was to do:
Quoted 8 lines
rmmod <module> < / sys/devices/..../attribute
If you are done with the kobject - just proceed with what you were doing and let it die its own peaceful death some time later. You just need to make sure release code sticks around to free it and your subsystem core can be tasked with this. Use module counter to prevent unloading of the subsystem core until all kobjects belonging to the subsystem are destroyed.
Do you mean keeping a kref object in the kernel module, invoking kref_get() every time a kobject has been created and invoking kref_put() from the kobject/ktype release method ? That would help to reduce the race window but would not eliminate all races: as soon as the last kref_put() has been invoked from the release method, the module can get unloaded. And module unloading involves freeing all module code sections, including the section that contains the implementation of the release method. Which is a race condition.
I'm not sure that it is even possible with the current kobject implementation to solve this race. I haven't found any information about this race in Documentation/kobject.txt. And it seems to me that the code in samples/kobject/kobject-example.c is vulnerable to this
race: methods like foo_show() and foo_store() can access statically allocated memory ("static int foo") after the module has been unloaded. Although the race window is small, this makes me wonder whether module unloading been overlooked at the time the kobject subsystem has been designed and implemented ?
Bart.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 23 lines · Bart Van Assche
Quoted 12 lines · Dmitry Torokhov
Quoted 4 lines · Vladislav Bolkhovitin
[ ... ]
This is the last internal put. All other references are from outsiders. So, we are waiting for all them to put before we go on.
The question is why do you need to wait here? I presume it is module unloading path, but then it is quite bad - you can easily wedge your subsystem if you make something to take a reference to your kobject while module is trying to be unloaded. Back when sysfs attributes tied kobjects the easiest thing was to do:
Quoted 8 lines
rmmod <module> < / sys/devices/..../attribute
If you are done with the kobject - just proceed with what you were doing and let it die its own peaceful death some time later. You just need to make sure release code sticks around to free it and your subsystem core can be tasked with this. Use module counter to prevent unloading of the subsystem core until all kobjects belonging to the subsystem are destroyed.
Quoted 8 lines
Do you mean keeping a kref object in the kernel module, invoking
kref_get()every time a kobject has been created and invokingkref_put()from the kobject/ktype release method ? That would help to reduce the race window but would not eliminate all races: as soon as the lastkref_put()has been invoked from the release method, the module can get unloaded. And module unloading involves freeing all module code sections, including the section that contains the implementation of the release method. Which is a race condition.
No, you do not add a kref, but rather manipulate module use counter:
static void blah_blah_release(struct kobject *kobj)
{
struct blah_blah *b = to_blah_blah(kobj);
...
kfree(kobj);
module_put(THIS_MODULE);
}int blah_blah_register(struct blah_blah *blah)
{
...
__module_get(THIS_MODULE);
...
return 0;
}The above should reside in subsystem _core_ and it will pin the core module until last kobject belonging to the subsystem is released. Once all users are gone module counter will go to 0 and rmmod will allow core to unload. Note that no new kobjects will be created while module usage count is 0 because there are no users of the core - all of them have to be unloaded already, otherwise module loader would have bumped up usage count as well.
Quoted 3 lines
I'm not sure that it is even possible with the current kobject implementation to solve this race.
It is possible and it is solved in most (all?) mainline subsystems.
Quoted 10 lines
I haven't found any information
about this race inDocumentation/kobject.txt. And it seems to me that the code insamples/kobject/kobject-example.cis vulnerable to this
race: methods likefoo_show()andfoo_store()can access statically allocated memory ("static int foo") after the module has been unloaded. Although the race window is small, this makes me wonder whether module unloading been overlooked at the time the kobject subsystem has been designed and implemented ?Bart.
Signature · 1 line
Dmitry
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 33 lines · Dmitry Torokhov
[ ... ]
No, you do not add a kref, but rather manipulate module use counter:
static void
blah_blah_release(struct kobject *kobj){
structblah_blah*b =to_blah_blah(kobj);...
kfree(kobj);module_put(THIS_MODULE);
}int
blah_blah_register(struct blah_blah *blah)
{
...__module_get(THIS_MODULE);
...
return 0;
}The above should reside in subsystem _core_ and it will pin the core module until last kobject belonging to the subsystem is released. Once all users are gone module counter will go to 0 and rmmod will allow core to unload. Note that no new kobjects will be created while module usage count is 0 because there are no users of the core - all of them have to be unloaded already, otherwise module loader would have bumped up usage count as well.
Quoted 4 lines
Quoted 2 lines
I'm not sure that it is even possible with the current kobject implementation to solve this race.
It is possible and it is solved in most (all?) mainline subsystems.
Thanks for replying, but sorry, it's still not clear to me. The use counter of which module should be manipulated ? Manipulating the use counter of the module that contains the kobject/ktype callback function implementations would make it impossible to unload that module because rmmod refuses to unload any module whose use counter is above zero. And manipulating the use counter of a parent module would not help in any way.
It would help if you could tell us where in the kernel tree we can find a good example. I have tried to find such an example, but all I found are examples of kobject release method implementations in which no attempt is made to prevent the aforementioned race:
* iscsi_boot_kobj_release() in drivers/scsi/iscsi_boot_sysfs.c
* pkt_kobj_release() in drivers/block/pktcdvd.c
Bart.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Dmitry TorokhovQuoted 15 lines · Dmitry Torokhov, on 11/12/2010 04:23 AM wrote:
Quoted 8 lines
Quoted 4 lines
This put might not be the last put on the object, IOs in flight and/or open files might have extra reference on the object. We release our initial ref, and below wait for all operations to complete. (Is there a matter of timeout like files not closing?)
This is the last internal put. All other references are from outsiders. So, we are waiting for all them to put before we go on.
The question is why do you need to wait here? I presume it is module unloading path, but then it is quite bad - you can easily wedge your subsystem if you make something to take a reference to your kobject while module is ytying to be unloaded. Back when sysfs attributes tied kobjects the easiest thing was to do:
Quoted 8 lines
rmmod <module> < / sys/devices/..../attribute
If you are done with the kobject - just proceed with what you were doing and let it die its own peaceful death some time later. You just need to make sure release code sticks around to free it and your subsystem core can be tasked with this. Use module counter to prevent unloading of the subsystem core until all kobjects belonging to the subsystem are destroyed.
This is a very good question. During implementation I spent a lot of time working on it.
In fact, the first implementation was asynchronous similarly as you proposing, i.e. it just proceed with what you were doing and let it die its own peaceful death some time later. But soon the implementation was becoming so complicated, so it started getting out of control. For instance, some of the tasks to solve with this approach were:
1. What to do if another SCST object is being created with the same name as supposed to be deleted, but not completely dead yet?
2. What to do if a dieing object is found on some list and reference for is supposed to be taken? If the object deleted from the list before it marked dieing, i.e. the latest internal put() done, it made additional problems during deleting it after the latest external put done.
...
So, I decided to reimplement it to be completely synchronous. SYSFS authors did really great job and thanks to the excellent internal SYSFS design and implementation it is absolutely safe. See:
[root@tgt ~]# modprobe scst
[root@tgt ~]# cd /sys/kernel/scst_tgt/
[root@tgt scst_tgt]# ls -l
total 0
drwxr-xr-x 4 root root 0 Nov 13 21:31 devices
drwxr-xr-x 2 root root 0 Nov 13 21:31 handlers
-r--r--r-- 1 root root 4096 Nov 13 21:30 last_sysfs_mgmt_res -rw-r--r-- 1 root root 4096 Nov 13 21:30 setup_id
drwxr-xr-x 5 root root 0 Nov 13 21:31 sgv
drwxr-xr-x 2 root root 0 Nov 13 21:31 targets
-rw-r--r-- 1 root root 4096 Nov 13 21:30 threads -rw-r--r-- 1 root root 4096 Nov 13 21:30 trace_level -r--r--r-- 1 root root 4096 Nov 13 21:30 version [root@tgt scst_tgt]# cat version
2.1.0-pre1
EXTRACHECKS
DEBUG
[root@tgt scst_tgt]# rmmod scst </sys/kernel/scst_tgt/version [root@tgt scst_tgt]# ls -l
total 0
[root@tgt scst_tgt]# pwd/sys/kernel/scst_tgt
[root@tgt scst_tgt]# lsmod
Module Size Used by scsi_debug 65188 0 w83627hf 22424 0 hwmon_vid 2207 1 w83627hf adm1021 6189 0 binfmt_misc 6229 1 xfs 673142 1 exportfs 3143 1 xfs dm_mirror 12069 0 dm_region_hash 8703 1 dm_mirror dm_log 8345 2 dm_mirror,dm_region_hash dm_mod 63511 2 dm_mirror,dm_log pci_slot 3378 0 hed 1758 0 floppy 52718 0 uhci_hcd 21459 0 sg 25181 0 e1000 128475 0 i2c_i801 8756 0 pcspkr 1442 0 i2c_core 22319 2 adm1021,i2c_i801 e7xxx_edac 3463 0 parport_pc 25439 0 parport 29682 1 parport_pc
Everything works fine.
This is because SYSFS doesn't hold references for the corresponding kobjects for every open file handle. It holds references only when show() and store() functions called. So, everything is under control and a malicious user can do nothing to hold a reference forever.
Vlad
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 6 lines · Vladislav Bolkhovitin
So, I decided to reimplement it to be completely synchronous. SYSFS authors did really great job and thanks to the excellent internal SYSFS design and implementation it is absolutely safe. See:
[root@tgt ~]# modprobe scst
[root@tgt ~]# cd/sys/kernel/scst_tgt/
Sorry, but no, you can't put this in /sys/kernel/ without getting the approval of the sysfs maintainer.
I really don't understand why you are using kobjects in the first place, why isn't this in the main device tree in the kernel, using 'struct device'?
In the end, I guess it really doesn't matter as this code isn't getting merged so I shouldn't worry about it, right?
thanks,
greg k-h
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 8 lines · Greg KH
Quoted 6 lines · Vladislav Bolkhovitin
So, I decided to reimplement it to be completely synchronous. SYSFS authors did really great job and thanks to the excellent internal SYSFS design and implementation it is absolutely safe. See:
[root@tgt ~]# modprobe scst
[root@tgt ~]# cd/sys/kernel/scst_tgt/
Quoted 7 lines
Sorry, but no, you can't put this in
/sys/kernel/without getting the approval of the sysfs maintainer.I really don't understand why you are using kobjects in the first place, why isn't this in the main device tree in the kernel, using 'struct device'?
It is my understanding that Vlad is able to reflect the topology by manipulating sysfs objects there.
Quoted 3 lines
In the end, I guess it really doesn't matter as this code isn't getting merged so I shouldn't worry about it, right?
This is quite unfortunate as I still have not seen the public comparison of the 2 implementations and the lists of benefits and shortfalls for both of them.
Signature · 1 line
Dmitry
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 4 lines · Dmitry Torokhov
[ ... ]
This is quite unfortunate as I still have not seen the public comparison of the 2 implementations and the lists of benefits and shortfalls for both of them.
The reason why we are proposing SCST for upstream inclusion are:
- It has a large user base.
- The project is known for its high performance, low latency I/O and excellent stability.
- A feature-wise overview can be found here:
http://scst.sourceforge.net/comparison.html.
Bart.
Re: [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Dmitry TorokhovQuoted 12 lines · Dmitry Torokhov, on 11/15/2010 09:59 AM wrote:
Quoted 11 lines · Greg KH
Quoted 6 lines · Vladislav Bolkhovitin
So, I decided to reimplement it to be completely synchronous. SYSFS authors did really great job and thanks to the excellent internal SYSFS design and implementation it is absolutely safe. See:
[root@tgt ~]# modprobe scst
[root@tgt ~]# cd/sys/kernel/scst_tgt/Sorry, but no, you can't put this in
/sys/kernel/without getting the approval of the sysfs maintainer.
Quoted 6 lines
Quoted 3 lines
I really don't understand why you are using kobjects in the first place, why isn't this in the main device tree in the kernel, using 'struct device'?
It is my understanding that Vlad is able to reflect the topology by manipulating sysfs objects there.
Correct. As I wrote in the previous e-mail, SCST doesn't deal with devices, so doesn't have a need to use struct device.
Quoted 7 lines
Quoted 3 lines
In the end, I guess it really doesn't matter as this code isn't getting merged so I shouldn't worry about it, right?
This is quite unfortunate as I still have not seen the public comparison of the 2 implementations and the lists of benefits and shortfalls for both of them.
Indeed, it is unfortunate :(. Undercover political games continue...
Vlad
Re: [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Greg KHQuoted 3 lines · Greg KH
In the end, I guess it really doesn't matter as this code isn't getting merged so I shouldn't worry about it, right?
This is not nice and is uncharacteristic of you.
This project, even though out-of-tree, is an old and mature project that has many users. These are all *Linux* users. The authors and community have come to us for help, and advice on making this code acceptable for mainline and hardening the code the way, only one project on the planet can do, the Linux community. I think it is our courtesy and obligation to the Linux users of this Project to comment where they are doing wrong and where they should do better.
It is not of their choice to be out-of-tree. It is ours. The least we can do. Is give then some assistance if we can, and have 5 minutes of our time.
All these issues we were discussing are interesting and are real Kernel problems. For instance the last comment you made was that for such a dynamic system and life time problems, and functionality. A better and expected solution might be the device tree and not sysfs. And for such big additions the sysfs maintainer must give his blessings. This is most valuable information regardless of if we accept their code or not at the end.
(And we better explain ourselves well when we don't)
Quoted 3 lines
thanks,
greg k-h
Sincerely yours
Boaz
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 6 lines · Boaz Harrosh
Quoted 3 lines · Greg KH
In the end, I guess it really doesn't matter as this code isn't getting merged so I shouldn't worry about it, right?
This is not nice and is uncharacteristic of you.
Why, I'm not allowed to get frustrated at repeated attempts to get the original poster to change their code to something that is acceptable and just give up and walk away?
Why not?
Quoted 7 lines
This project, even though out-of-tree, is an old and mature project that has many users. These are all *Linux* users. The authors and community have come to us for help, and advice on making this code acceptable for mainline and hardening the code the way, only one project on the planet can do, the Linux community. I think it is our courtesy and obligation to the Linux users of this Project to comment where they are doing wrong and where they should do better.
It is also the job of the kernel community to say "No, what you are doing is wrong, please don't do that."
And that's what I'm doing here.
Quoted 2 lines
It is not of their choice to be out-of-tree. It is ours. The least we can do. Is give then some assistance if we can, and have 5 minutes of our time.
I have given _way_ more than 5 minutes of my time already.
Quoted 4 lines
All these issues we were discussing are interesting and are real Kernel problems. For instance the last comment you made was that for such a dynamic system and life time problems, and functionality. A better and expected solution might be the device tree and not sysfs.
Yes, that is what I have been saying for a while now.
Again:
This code is using kobjects incorrectly.
This code should not be using kobjects.
this is my last response to this thread now, and I'm sure you can understand why.
thanks,
greg k-h
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 12 lines · Greg KH
Quoted 4 lines · Boaz Harrosh
All these issues we were discussing are interesting and are real Kernel problems. For instance the last comment you made was that for such a dynamic system and life time problems, and functionality. A better and expected solution might be the device tree and not sysfs.
Yes, that is what I have been saying for a while now.
Again:
This code is using kobjects incorrectly.
This code should not be using kobjects.
Quoted 6 lines
this is my last response to this thread now, and I'm sure you can understand why.
thanks,
greg k-h
Thank you Greg for your time and most valuable input. I'm sorry for not understanding your position. I needed the clear cut statement:
This code should not be using kobjects. i.e not belong in sysfs
SCST guys. This sounds pretty clear cut to me. Sysfs was not built in mind for such dynamic systems, and it will cause never ending conflicts with future maintenance of sysfs vs SCST.
Perhaps consider a new alternative like the device tree as Greg suggested or maybe finally accept the harsh realities of ConfigFS, and come join us in the LIO project. SCST is a most valuable project and community which we would like to join forces with in making Linux the best.
Lets call it Linux-Target and unify all our efforts.
Boaz
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 3 lines · Boaz Harrosh
[ ... ]
Perhaps consider a new alternative like the device tree as Greg suggested or maybe finally accept the harsh realities of ConfigFS.
I think that Vlad has already explained several times why ConfigFS is not suited for the needs of a storage target: a storage target must not only be able to accept configuration information from userspace but must also be able to create new directories and file nodes itself. See e.g. this message from October 6:
http://kerneltrap.org/mailarchive/linux-kernel/2010/10/6/4628664.
Bart.
Re: [PATCH 8/19]: SCST SYSFS interface implementation
<Trimming CC list>
Quoted 5 lines · Bart Van Assche
Quoted 3 lines · Boaz Harrosh
[ ... ]
Perhaps consider a new alternative like the device tree as Greg suggested or maybe finally accept the harsh realities of ConfigFS.
Quoted 7 lines
I think that Vlad has already explained several times why ConfigFS is not suited for the needs of a storage target: a storage target must not only be able to accept configuration information from userspace but must also be able to create new directories and file nodes itself. See e.g. this message from October 6:
http://kerneltrap.org/mailarchive/linux-kernel/2010/10/6/4628664.
Sorry, but this post explains nothing but a single misguided and uninformed opinion, with no hard facts on the actual usage of a native configfs control plane within target mode infrastructure.
The hard facts are:
Using configfs works to drive the generation/release, real time configuration, dependancy relationships because:
*) configfs represents the individual target data structures who's creation/deletion are driven from enterily userspace.
*) The parent/child relationships of dependant data structures is handled transparently to the configfs consumer (eg: no hard requirement internal reference counting)
*) The module reference counting of target core -> fabric module is handled transparently to configfs consumers *and* TCM fabric modules
*) The current implementation of TCM/ConfigFS contains no global locks. Each /sys/kernel/config/target/$FABRIC_1 operates independently of /sys/kernel/config/target/$FABRIC_2
*) Expecting target fabric module developers to (by-hand) add struct config_groups, struct kobjects or anything else directly to their fabric module code is really clumsy and stupid. This problem was solved earlier this year in TCM v4.0 with the advent of:
What this code means is that target fabric module developers no longer has to duplicate complex control path code, and all of the interesting port attributes (like ALUA secondary access state for example) are transparent to new fabric modules, and 'just work'. We can even generate *functional* configfs skeletons for new fabric modules using tcm_mod_builder.py discussed here:
For the specific case of the target control path, until someone from SCST can present some hard facts *and* running code about the target mode configfs vs. sysfs debate, the discussion is like comparing oil and water.
Again, please do not take this as the LIO maintainer saying 'you should stop working on SCST code XYZ', because that is *not* what I am saying. We are simply stating that we already have a fully functional configfs backend and generic target fabric independent infrastrucutre that has not only been reviewed no less than five times this year on linux-scsi/LKML, it has actually been developed *on* linux-scsi, patch by patch in full view of the configfs maintainer and other interested parties.
This is the reason why the v4.0 code has progressed as fast as it has; a constant feedback loop from upstream developers who have been involved since the start of the development process. By virtue of this fact, we where able to make some early design decisions based on feedback from the community from the original proposed design and running prototype code.
So, while I can very much apperciate Boaz's desire to attempt to reconcile the relationship between myself + other TCM/LIO developers with the SCST development community, but I don't think this will happen without a definate change to the SCST development workflow and interaction with 'outside of project' developers.
--nab
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 10 lines · Nicholas A. Bellinger, on 11/15/2010 11:19 PM wrote:
Quoted 6 lines
I think that Vlad has already explained several times why ConfigFS is not suited for the needs of a storage target: a storage target must not only be able to accept configuration information from userspace but must also be able to create new directories and file nodes itself. See e.g. this message from October 6:
http://kerneltrap.org/mailarchive/linux-kernel/2010/10/6/4628664.Sorry, but this post explains nothing but a single misguided and uninformed opinion, with no hard facts on the actual usage of a native configfs control plane within target mode infrastructure.
What is "misguided and uninformed opinion"? That you can't with ConfigFS serve real life needs for target driver developers and can't create targets for hardware target ports from withing the kernel and instead enforce users to clumsy workarounds to somehow magically know their names to manually perform "mkdir target_name"?
The same problem exists for all other objects where you need to create ConfigFS entries (directories), like for per-session/per-initiator statistics or default ACLs.
ConfigFS is just too simple to serve real life needs of a SCSI target subsystem.
Vlad
Re: [Scst-devel] [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Bart Van AsscheI'm just an outsider - but maybe my perspective has value - it seems there are two sides to this debate:
1) sysfs is great for scst due to certain stability concerns and code concerns
2) sysfs is bad for scst due to the intended role of sysfs and its namespace
Maybe I misunderstand -
But if both sides have merit then wouldn't a compromise be appropriate?
Maybe the sensical compromise is to use sysfs code to create a new namespace that would fit this purpose? It seems that I am also hearing that the alternatives to sysfs aren't always adequate - so why not use sysfs, but have a place where it's appropriate to use it?
Apologies in advance if I'm just way off base here...
- Richard Williams
Re: [Scst-devel] [PATCH 8/19]: SCST SYSFS interface implementation
(Since this discussion goes to a quite fundamental scope, I let myself to add Joel Becker and Linus Torvalds on CC)
Quoted 7 lines · Richard Williams, on 11/16/2010 02:59 PM wrote:
I'm just an outsider - but maybe my perspective has value - it seems there are two sides to this debate:
1) sysfs is great for scst due to certain stability concerns and code concerns
2) sysfs is bad for scst due to the intended role of sysfs and its namespace
Your questions are very good, so let's summarize what we need to serve the needs of a SCSI target subsystem (not necessary SCST) and see what can fit them.
So, the needs:
1. Be capable to represent to user space internal configuration to let user space be able to see and analyze it, including various statistics.
2. Let user space manage the internal configuration.
3. Desired: possibility to send to user space events about important internal actions, like I/O failures, which may need user space intervention to recover, like switching from active to passive role in a cluster.
So, what can we do with ConfigFS:
(1): Only partially, because by design ConfigFS isn't supposed to represent internal configuration, it can only manage it. Extending ConfigFS to be capable to do that would be, in my understanding, a strong violation of its purpose and, hence, design and if went this way eventually ConfigFS would become just a duplication of the SYSFS functionality.
(2): ConfigFS can do that. This is exactly for what it was designed and implemented. But in this particular application it would have some limitations derived from (1): to manage harware-related entries a user should magically know from somewhen names of those entries to create them by "mkdir" command.
For instance, consider a user has a Fibre Channel HBA and want to use it in the target mode. Before he can configure it, he should somehow know its ports names and for each of them run:
# mkdir /sys/kernel/config/.../50:50:00:00:00:00:00:11 # mkdir /sys/kernel/config/.../50:50:00:00:00:00:00:12 ...
where 50:50:00:00:00:00:00:1x are the ports' names. Only after that those ports appear on the ConfigFS and can be managed.
(3): No events at all.
Now consider SYSFS:
(1): Easily. This is exactly for what it was designed and implemented.
(2): Possible without any limitations and side effects.
(3): Also possible.
So, why not use SYSFS if it suits all the needs _without_ any additional effort and patches?
Other alternatives? A set of custom IOCTLs? One more configuration FS? I believe, those would be quite disgusting for all.
Quoted 7 lines
Maybe I misunderstand - But if both sides have merit then wouldn't a compromise be appropriate?
Maybe the sensical compromise is to use sysfs code to create a new namespace that would fit this purpose? It seems that I am also hearing that the alternatives to sysfs aren't always adequate - so why not use sysfs, but have a place where it's appropriate to use it?
This is exactly what we are proposing: to use SYSFS in additional namespace /sys/kernel/scst_tgt.
As far as I can see, only Greg is against it. Greg keeps his reasons private, so I can only guess that Greg is against extending usage of SYSFS (note, _usage_, not implementation! Everything needed long ago implemented.) beyond the scope it was originally designed around 10 years ago. But SYSFS is already widely used this way in the kernel, as Joe illustrated, hence there is demand for it. People need it. So, why not to just acknowledge this fact and go ahead the simplest and most useful for both users and developers way?
Thanks,
Vlad
Re: [Scst-devel] [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 69 lines · Vladislav Bolkhovitin, on 11/16/2010 04:17 PM wrote:
Your questions are very good, so let's summarize what we need to serve the needs of a SCSI target subsystem (not necessary SCST) and see what can fit them.
So, the needs:
1. Be capable to represent to user space internal configuration to let user space be able to see and analyze it, including various statistics.
2. Let user space manage the internal configuration.
3. Desired: possibility to send to user space events about important internal actions, like I/O failures, which may need user space intervention to recover, like switching from active to passive role in a cluster.
So, what can we do with ConfigFS:
(1): Only partially, because by design ConfigFS isn't supposed to represent internal configuration, it can only manage it. Extending ConfigFS to be capable to do that would be, in my understanding, a strong violation of its purpose and, hence, design and if went this way eventually ConfigFS would become just a duplication of the SYSFS functionality.
(2): ConfigFS can do that. This is exactly for what it was designed and implemented. But in this particular application it would have some limitations derived from (1): to manage harware-related entries a user should magically know from somewhen names of those entries to create them by "mkdir" command.
For instance, consider a user has a Fibre Channel HBA and want to use it in the target mode. Before he can configure it, he should somehow know its ports names and for each of them run:
# mkdir /sys/kernel/config/.../50:50:00:00:00:00:00:11 # mkdir /sys/kernel/config/.../50:50:00:00:00:00:00:12 ...where 50:50:00:00:00:00:00:1x are the ports' names. Only after that those ports appear on the ConfigFS and can be managed.
(3): No events at all.
Now consider SYSFS:
(1): Easily. This is exactly for what it was designed and implemented.
(2): Possible without any limitations and side effects.
(3): Also possible.
So, why not use SYSFS if it suits all the needs _without_ any additional effort and patches?
Other alternatives? A set of custom IOCTLs? One more configuration FS? I believe, those would be quite disgusting for all.
Quoted 7 lines
Maybe I misunderstand - But if both sides have merit then wouldn't a compromise be appropriate?
Maybe the sensical compromise is to use sysfs code to create a new namespace that would fit this purpose? It seems that I am also hearing that the alternatives to sysfs aren't always adequate - so why not use sysfs, but have a place where it's appropriate to use it?
This is exactly what we are proposing: to use SYSFS in additional namespace
/sys/kernel/scst_tgt.
Quoted 8 lines
As far as I can see, only Greg is against it. Greg keeps his reasons private, so I can only guess that Greg is against extending usage of SYSFS (note, _usage_, not implementation! Everything needed long ago implemented.) beyond the scope it was originally designed around 10 years ago. But SYSFS is already widely used this way in the kernel, as Joe illustrated, hence there is demand for it. People need it. So, why not to just acknowledge this fact and go ahead the simplest and most useful for both users and developers way?
Since nobody objected, Greg, could you consider to ACK SCST SYSFS management interface in /sys/kernel/scst_tgt/, please? Please find the SCST SYSFS ABI documentation file you requested below.
We are also preparing a new patch to free our objects in kobjects.release() without explicit x_initialized flags as you requested.
Thank you for your effort,
Vlad
Documentation/ABI/testing/sysfs-scst:
What: /sys/kernel/scst_tgt/
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Contains SCST management interface entries.
What: /sys/kernel/scst_tgt/devices/
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Contains subdirectories for all SCST devices
What: /sys/kernel/scst_tgt/devices/<device>/exported/exportX
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Links to LUNs in the LUNs group where <device> exported, e.g. to /sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/11
What: /sys/kernel/scst_tgt/devices/<device>/handler
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Link to dev handler of this device, if assigned, e.g. to /sys/kernel/scst_tgt/handlers/dev_disk
What: /sys/kernel/scst_tgt/devices/<device>/type
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
SCSI type of this device as define by SAM.
What: /sys/kernel/scst_tgt/handlers/
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Contains all SCST dev handlers.
What: /sys/kernel/scst_tgt/handlers/<handler>/<device>
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Links to <device> managed by this dev handler, e.g. ext3_disk1_4K -> /sys/kernel/scst_tgt/devices/ext3_disk1_4K
What: /sys/kernel/scst_tgt/handlers/<handler>/mgmt
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Management entry, which allows to create and delete devices for this dev handler. See SysfsRules file for more info.
What: /sys/kernel/scst_tgt/handlers/<handler>/type
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
SCSI type of this dev handler as define by SAM.
What: /sys/kernel/scst_tgt/sgv/
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Contains SCST SGV caches statistics.
What: /sys/kernel/scst_tgt/sgv/global_stats
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Contains global SGV cache statistics.
What: /sys/kernel/scst_tgt/sgv/<cache>/stats
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Contains statistics for SGV cache <cache>
What: /sys/kernel/scst_tgt/targets/
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Contains all SCST target drivers
What: /sys/kernel/scst_tgt/targets/<target_driver>
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Contains all targets for <target_driver>
What: /sys/kernel/scst_tgt/targets/<target_driver>/mgmt
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Optional management entry, which allows to create and delete targets for this target driver. See SysfsRules file for more info.
What: /sys/kernel/scst_tgt/targets/<target_driver>/enable
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Optional attribute to enable <target_driver> and make it serve incoming connections from initiators. Possible values:
1 - enable
0 - disable
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/ini_groups/
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Contains security groups for <target>
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/ini_groups/mgmt
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Allows to create and delete security groups for <target>. See README.scst for more info.
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/ini_groups/<group>/initiators/mgmt
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Allows to add and delete initiators to/from <group>. See README.scst for more info.
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/ini_groups/<group>/initiators/<initiator_name>
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
One or more initiators in <group>. Contains initiator's name.
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/ini_groups/<group>/luns/mgmt
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Allows to add and delete LUNs to/from <group>. See README.scst for more info.
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/ini_groups/<group>/luns/<lun>/device
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Link to device for <lun>, e.g. to /sys/kernel/scst_tgt/devices/ext3_disk1_4K
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/ini_groups/<group>/luns/<lun>/read_only
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Sets if this LUN should be read only
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/ini_groups/<group>/addr_method
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Sets SCSI addressing method for <group>. See README.scst for more info.
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/ini_groups/<group>/cpu_mask
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Sets CPU mask for threads serving initiators in <group>. See README.scst for more info.
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/ini_groups/<group>/io_grouping_type
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Sets IO grouping types for threads serving initiators in <group>. See README.scst for more info.
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/luns/mgmt
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Allows to add and delete LUNs to/from the <target>'s default set of LUNs. See README.scst for more info.
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/luns/<lun>/device
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Link to device for <lun>, e.g. to /sys/kernel/scst_tgt/devices/ext3_disk1_4K
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/luns/<lun>/read_only
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Sets if this LUN should be read only
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/addr_method
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Sets SCSI addressing method for the <target>'s default set of LUNs. See README.scst for more info.
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/cpu_mask
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Sets CPU mask for threads serving initiators in the <target>'s default set of LUNs. See README.scst for more info.
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/io_grouping_type
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Sets IO grouping types for threads serving initiators in the <target>'s default set of LUNs. See README.scst for more info.
What: /sys/kernel/scst_tgt/targets/<target_driver>/<target>/enable
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Optional attribute to enable <target> and make it serve incoming connections from initiators. Possible values:
1 - enable
0 - disable
What: /sys/kernel/scst_tgt/last_sysfs_mgmt_res
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Returning completion status of the last management command. See README.scst for more info.
What: /sys/kernel/scst_tgt/setup_id
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Allows to read and write SCST setup ID. This ID can be used in cases, when the same SCST configuration should be installed on several targets, but exported from those targets devices should have different IDs and SNs. For instance, VDISK dev handler uses this ID to generate T10 vendor specific identifier and SN of the devices.
What: /sys/kernel/scst_tgt/threads
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Allows to read and set number of global SCST I/O threads. Those threads used with async. dev handlers, for instance, vdisk BLOCKIO or NULLIO
What: /sys/kernel/scst_tgt/version
Date: November 2010
Contact: Vladislav Bolkhovitin <[email protected]>
Description:
Allows to see version of SCST and enabled optional features.
Re: [Scst-devel] [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 3 lines · Vladislav Bolkhovitin
Since nobody objected, Greg, could you consider to ACK SCST SYSFS management interface in
/sys/kernel/scst_tgt/, please? Please find the SCST SYSFS ABI documentation file you requested below.
No, sorry, again, you should not be using kobjects, and do not polute the main /sys/kernel/ namespace with this.
Use 'struct device' please, that is what it is there for, and is what the rest of the kernel is using. And use the rest of the driver/bus/device infrastructure as your model will work with it just fine.
Yes, I know you said you didn't think you could use it, and that your code was different than everyone elses, but I still do not believe it, sorry.
good luck,
greg k-h
Re: [Scst-devel] [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 7 lines · Greg KH, on 11/19/2010 12:46 AM wrote:
Quoted 3 lines · Vladislav Bolkhovitin
Since nobody objected, Greg, could you consider to ACK SCST SYSFS management interface in
/sys/kernel/scst_tgt/, please? Please find the SCST SYSFS ABI documentation file you requested below.No, sorry, again, you should not be using kobjects, and do not polute the main
/sys/kernel/namespace with this.
Which other namespace should we "polute" then?
Quoted 4 lines
Use 'struct device' please, that is what it is there for, and is what the rest of the kernel is using. And use the rest of the driver/bus/device infrastructure as your model will work with it just fine.
Greg, sorry, I don't understand your requirements and, because of this, we can't go ahead implementing them. Could you explain your position, please?
None of the SCST objects are Linux devices. None of them has entries in /dev, none of them needs to send any events to udev and none of them sends or receives data from DMA, hence has any DMA parameters or restrictions. So, how can them fit into the driver/bus/device model you are enforcing?
For instance:
- struct sgv_pool (/sys/kernel/scst_tgt/sgv/<cache>) is an SG vectors
cache. Isn't it a nonsense to make it device?
- struct scst_acg
(/sys/kernel/scst_tgt/targets/<target_driver>/<target>/ini_groups/<group>/) is an access control group to define which initiators see which LUNs from target <target>. Same, isn't it a nonsense to make it device?
- struct scst_acn
(/sys/kernel/scst_tgt/targets/<target_driver>/<target>/ini_groups/<group>/initiators/<initiator_name>) is an entry in the access control group <group> to define which
initiators should use group <group>. Again, isn't it a nonsense to make
it device?
Etc.
How could they fit in the driver/bus/device model?
I guess, your confusion comes from word "device" you see in the SCST SYSFS tree and SCST supposed to work with "devices" and "dev handlers"? But those devices are not Linux devices, they are just objects to couple initiators' requests and backstorage which stores data.
In other words, SCST devices are just redirection points passing incoming requests to Linux files and devices.
SCST devices are the same as NFS exported directories. Do you believe, that struct device must be created for each NFS export?
In the cases when we need to present SCST devices as Linux devices we use scst_local driver [1], which performs it exactly as you requesting, i.e. doing:
root_device_register()bus_register()driver_register()
...
Quoted 3 lines
Yes, I know you said you didn't think you could use it, and that your code was different than everyone elses, but I still do not believe it, sorry.
What can we do to make you believe it? Shall we write a document describing all SCST objects and their relationship between each other? (Although looks like you haven't read even detailed docs we already written...)
Our position is based on careful study of all possible alternatives and 10+ years of Linux kernel development.
SCST is being developed for 7+ years and, despite of not being mainline, has proved those years being the right way to go, not the mainline STGT which was chosen 5 years ago as the right way, but now we are considering to replace it.
Sorry, but we have an impression that you are judging without seeing the full picture. Isn't it a duty of a subsystem's maintainer to see full picture before deciding if it's good or bad?
We appreciate your effort reviewing SCST and willing to make all the needed actions to help you.
The world of SCSI targets is pretty complex (I have been studying it for 7+ years), hence SCST is very big (20K LOC only core) and hard to understand. But is it a sufficient reason to force to convert elegant, nice and carefully thought design into something ugly, hardly usable and hardly maintainable? If we do it, that wouldn't make SCST simpler to review. Opposite, it would make it HARDER to review.
Thanks,
Vlad
[1] Patch for scst_local you can find in http://lkml.org/lkml/2010/10/1/131)
Re: [Scst-devel] [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 20 lines · Vladislav Bolkhovitin
Quoted 7 lines · Greg KH, on 11/19/2010 12:46 AM wrote:
Quoted 3 lines · Vladislav Bolkhovitin
Since nobody objected, Greg, could you consider to ACK SCST SYSFS management interface in
/sys/kernel/scst_tgt/, please? Please find the SCST SYSFS ABI documentation file you requested below.No, sorry, again, you should not be using kobjects, and do not polute the main
/sys/kernel/namespace with this.Which other namespace should we "polute" then?
Quoted 4 lines
Use 'struct device' please, that is what it is there for, and is what the rest of the kernel is using. And use the rest of the driver/bus/device infrastructure as your model will work with it just fine.
Greg, sorry, I don't understand your requirements and, because of this, we can't go ahead implementing them. Could you explain your position, please?
Quoted 6 lines
None of the SCST objects are Linux devices. None of them has entries in /dev, none of them needs to send any events to udev and none of them sends or receives data from DMA, hence has any DMA parameters or restrictions. So, how can them fit into the driver/bus/device model you are enforcing?
Note that the entities in /sys/devices/... tree and not necessarily physical devices bit rather interface abstractionss. Consider, for example, /sys/class/input/*. None of the "devices" there talk directly to hardware, do DMA or other things. Some of them don't even talk to usrespace directly but rather through additional interfaces (evdev. mousedev, ect). Still they are represented there and even have suspend and resume methods (because even for logical devices it makes sense to save and restore some state).
Quoted 16 lines
For instance:
- struct
sgv_pool(/sys/kernel/scst_tgt/sgv/<cache>) is an SG vectors
cache. Isn't it a nonsense to make it device?- struct
scst_acg
(/sys/kernel/scst_tgt/targets/<target_driver>/<target>/ini_groups/<group>/) is an access control group to define which initiators see which LUNs from target <target>. Same, isn't it a nonsense to make it device?- struct
scst_acn
(/sys/kernel/scst_tgt/targets/<target_driver>/<target>/ini_groups/<group>/initiators/<initiator_name>) is an entry in the access control group <group> to define which
initiators should use group <group>. Again, isn't it a nonsense to make
it device?
Quoted 3 lines
Etc.
How could they fit in the driver/bus/device model?
Maybe not all of them are. Some of them could probably be represented by attributes of other devices. And some of them are, fitting into the overall /sys/devices hierarchy and describing physical and logical relations between them.
Signature · 1 line
Dmitry
Re: [Scst-devel] [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 6 lines · Dmitry Torokhov, on 11/19/2010 11:22 PM wrote:
Quoted 5 lines
None of the SCST objects are Linux devices. None of them has entries in /dev, none of them needs to send any events to udev and none of them sends or receives data from DMA, hence has any DMA parameters or restrictions. So, how can them fit into the driver/bus/device model you are enforcing?
Quoted 8 lines
Note that the entities in
/sys/devices/... tree and not necessarily physical devices bit rather interface abstractionss. Consider, for example,/sys/class/input/*. None of the "devices" there talk directly to hardware, do DMA or other things. Some of them don't even talk to usrespace directly but rather through additional interfaces (evdev. mousedev, ect). Still they are represented there and even have suspend and resume methods (because even for logical devices it makes sense to save and restore some state).
But all of them still place from where to events received and where requests from Linux sent, aren't them?
SCST devices are not even logical devices. As I wrote, "devices" word is misleading. SCST devices are converse of what Linux means under this word. SCST devices are like NFS exports: a place where those events generated and those requests received.
Think of SCST device as if it sits on the opposite side of the PCI bus of the corresponding SCSI device Linux sees in /sys/class and /sys/bus.
So, if we need Linux devices for SCST devices, we create them using scst_local driver. And then, of course, all them have their place in /sys/class/ and /sys/bus. Although more common use of them from remote systems via iSCSI, Fibre Channel, InfiniBand, etc. The remote systems create devices in /sys/class/ and /sys/bus (if they are Linux), we serve them.
Vlad
Re: [Scst-devel] [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 7 lines · Vladislav Bolkhovitin
Quoted 6 lines · Dmitry Torokhov, on 11/19/2010 11:22 PM wrote:
Quoted 5 lines
None of the SCST objects are Linux devices. None of them has entries in /dev, none of them needs to send any events to udev and none of them sends or receives data from DMA, hence has any DMA parameters or restrictions. So, how can them fit into the driver/bus/device model you are enforcing?
Quoted 8 lines
Quoted 8 lines
Note that the entities in
/sys/devices/... tree and not necessarily physical devices bit rather interface abstractionss. Consider, for example,/sys/class/input/*. None of the "devices" there talk directly to hardware, do DMA or other things. Some of them don't even talk to usrespace directly but rather through additional interfaces (evdev. mousedev, ect). Still they are represented there and even have suspend and resume methods (because even for logical devices it makes sense to save and restore some state).
This is correct.
Quoted 4 lines
SCST devices are not even logical devices. As I wrote, "devices" word is misleading. SCST devices are converse of what Linux means under this word. SCST devices are like NFS exports: a place where those events generated and those requests received.
No, that's fine.
Quoted 2 lines
Think of SCST device as if it sits on the opposite side of the PCI bus of the corresponding SCSI device Linux sees in
/sys/classand/sys/bus.
Again, that's fine, look at usb gadgets, it's the same thing.
Quoted 3 lines
So, if we need Linux devices for SCST devices, we create them using
scst_localdriver. And then, of course, all them have their place in/sys/class/and/sys/bus.
No, just /sys/bus/ which will cause them to become part of the big device tree in /sys/devices/
Again, use this interface, it is what it is there for, to not use it is just wrong.
good luck,
greg k-h
Re: [Scst-devel] [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 15 lines · Greg KH, on 11/20/2010 12:16 AM wrote:
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines
None of the SCST objects are Linux devices. None of them has entries in /dev, none of them needs to send any events to udev and none of them sends or receives data from DMA, hence has any DMA parameters or restrictions. So, how can them fit into the driver/bus/device model you are enforcing?
Quoted 8 lines
Quoted 8 lines
Note that the entities in
/sys/devices/... tree and not necessarily physical devices bit rather interface abstractionss. Consider, for example,/sys/class/input/*. None of the "devices" there talk directly to hardware, do DMA or other things. Some of them don't even talk to usrespace directly but rather through additional interfaces (evdev. mousedev, ect). Still they are represented there and even have suspend and resume methods (because even for logical devices it makes sense to save and restore some state).
Quoted 8 lines
This is correct.
Quoted 4 lines
SCST devices are not even logical devices. As I wrote, "devices" word is misleading. SCST devices are converse of what Linux means under this word. SCST devices are like NFS exports: a place where those events generated and those requests received.
No, that's fine.
I'm surprised you would make NFS exports devices
Quoted 4 lines
Quoted 2 lines
Think of SCST device as if it sits on the opposite side of the PCI bus of the corresponding SCSI device Linux sees in
/sys/classand/sys/bus.Again, that's fine, look at usb gadgets, it's the same thing.
USB gadgets are a good example, but not quite.
I'm objecting not the possibility to implement SCST objects as devices. We are creating software, so all what hardware allows can be implemented.
I'm arguing usage of devices view for something which fundamentally not devices.
USB gadgets are subset of what SCST allows. On the external side they are tightly coupled to hardware, on the backend side they don't need any management interface, because (at least for storage) all devices configuration they have is static via module parameters. The only attributes file_storage has are to change FUA and file path, which can be placed anywhere, including /sys/module/g_file_storage/parameters.
So, for USB gadgets the config interface and place in /sys doesn't matter much. I guess, making its LUNs as Linux devices were just part of the ritual to get accepted into the kernel. On the USB gadgets developers place I wouldn't mind too to go this way.
But SCST is a _big_, _complete_, _new_ Linux subsystem. Actually, USB storage gadgets should be SCST targets to use full power of all possible virtual and real backends SCST provides, hence stay inside SCST subtree.
For SCST it is very important that all its functionality concentrated in one place and not confused with other client side devices Linux has. Important for clearness, easy to use, easy to understand, flexibility, maintainability, etc.
It's like as you created rules to keep and train dogs. Then you need to keep and train cats as well. Would it be wise to keep cats in the same place together with dogs and train them the same tricks using the same rules as dogs?
Quoted 8 lines
Quoted 5 lines
Quoted 5 lines
None of the SCST objects are Linux devices. None of them has entries in /dev, none of them needs to send any events to udev and none of them sends or receives data from DMA, hence has any DMA parameters or restrictions. So, how can them fit into the driver/bus/device model you are enforcing?
That doesn't matter. They are still "devices" that the kernel knows about and as such, fit into the device tree of everything in the kernel.
If you have such wide devices definition, why file systems have separate /sys/fs namespace? Or ksm place in /sys/kernel/mm/ksm? Or hugepages in /sys/kernel/mm/hugepages?
If NFS exports are devices, file systems must also be devices, correct?
Like /sys/fs/ext4/sda11. Isn't it a full analogy to NFS export /home/user/shared_dir?
Quoted 8 lines
Quoted 3 lines
Quoted 3 lines
Sorry, but we have an impression that you are judging without seeing the full picture. Isn't it a duty of a subsystem's maintainer to see full picture before deciding if it's good or bad?
It's the duty of a subsystem's maintainer to enforce the correct model of the kernel, and that is what I am doing.
Again, this is the last email I'm writing on this topic, as none of the previous ones seem to be sinking in.
Well, if I don't agree with you it doesn't mean I'm not listening to you. I do. Very carefully.
Thanks,
Vlad
Re: [Scst-devel] [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Vladislav BolkhovitinQuoted 10 lines · Vladislav Bolkhovitin
Quoted 7 lines · Greg KH, on 11/19/2010 12:46 AM wrote:
Quoted 3 lines · Vladislav Bolkhovitin
Since nobody objected, Greg, could you consider to ACK SCST SYSFS management interface in
/sys/kernel/scst_tgt/, please? Please find the SCST SYSFS ABI documentation file you requested below.No, sorry, again, you should not be using kobjects, and do not polute the main
/sys/kernel/namespace with this.Which other namespace should we "polute" then?
None. Use 'struct device'
Quoted 8 lines
Quoted 4 lines
Use 'struct device' please, that is what it is there for, and is what the rest of the kernel is using. And use the rest of the driver/bus/device infrastructure as your model will work with it just fine.
Greg, sorry, I don't understand your requirements and, because of this, we can't go ahead implementing them. Could you explain your position, please?
I have multiple times.
Quoted 5 lines
None of the SCST objects are Linux devices. None of them has entries in /dev, none of them needs to send any events to udev and none of them sends or receives data from DMA, hence has any DMA parameters or restrictions. So, how can them fit into the driver/bus/device model you are enforcing?
That doesn't matter. They are still "devices" that the kernel knows about and as such, fit into the device tree of everything in the kernel.
Quoted 3 lines
Sorry, but we have an impression that you are judging without seeing the full picture. Isn't it a duty of a subsystem's maintainer to see full picture before deciding if it's good or bad?
It's the duty of a subsystem's maintainer to enforce the correct model of the kernel, and that is what I am doing.
Again, this is the last email I'm writing on this topic, as none of the previous ones seem to be sinking in.
good luck,
greg k-h
Re: [Scst-devel] [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 3 lines · Greg KH
[ ... ]
None. Use 'struct device'
How about using 'struct device' as follows ?
* Move /sys/kernel/scst_tgt/targets to /sys/class/target_driver.
* Move /sys/kernel/scst_tgt/handlers to /sys/class/device_driver.
* Move /sys/kernel/scst_tgt/devices to /sys/class/target_device.
* Move the attributes of /sys/kernel/scst_tgt to /sys/devices/scst.
* Move /sys/kernel/scst_tgt/sgv to /sys/devices/scst/sgv
Some quickly hacked up code (that needs further polishing) that implements this scheme can be found here:
https://scst.svn.sourceforge.net/svnroot/scst/branches/sysfs-tree-changes.
An example of an SCST configuration file and the corresponding sysfs hierarchy:
# uname -r 2.6.37-rc5-scst+
# cat /etc/scst.conf
HANDLER vdisk_blockio {
DEVICE disk01 {
filename /dev/ram0
nv_cache 1
}
DEVICE disk02 {
filename /dev/ram1
nv_cache 1
}
}HANDLER vdisk_fileio {
DEVICE disk03 {
filename /dev/vdisk
nv_cache 1
}
DEVICE disk04 {
filename /dev/vdisk
nv_cache 1
}
}HANDLER vdisk_nullio {
DEVICE disk05
DEVICE disk06
}
TARGET_DRIVER scst_local {
TARGET local {
session_name local
LUN 0 disk01
LUN 1 disk02
LUN 2 disk03
LUN 3 disk04
LUN 4 disk05
LUN 5 disk06
}
}
TARGET_DRIVER ib_srpt {
TARGET ib_srpt_target_0 {
rel_tgt_id 1
enabled 1
LUN 0 disk01
LUN 1 disk02
LUN 2 disk03
LUN 3 disk04
LUN 4 disk05
LUN 5 disk06
}
TARGET ib_srpt_target_1 {
rel_tgt_id 2
enabled 1
LUN 0 disk01
LUN 1 disk02
LUN 2 disk03
LUN 3 disk04
LUN 4 disk05
LUN 5 disk06
}
}
TARGET_DRIVER iscsi {
enabled 1
TARGET iqn.2005-03.org.open-iscsi:dbc01e1792b:storage {
rel_tgt_id 4
LUN 0 disk01
LUN 1 disk02
LUN 2 disk03
LUN 3 disk04
LUN 4 disk05
LUN 5 disk06
enabled 1
}
}
# find /sys/{class,devices/virtual}/{target_driver,device_driver,target_device}
/sys/devices/scst | while read f; do if [ -h $f ]; then echo "$f ->
$(readlink $f)"; else echo "$f"; fi; done
/sys/class/target_driver
/sys/class/target_driver/iscsi -> ../../devices/virtual/target_driver/iscsi
/sys/class/target_driver/ib_srpt -> ../../devices/virtual/target_driver/ib_srpt
/sys/class/target_driver/scst_local ->
../../devices/virtual/target_driver/scst_local
/sys/class/device_driver
/sys/class/device_driver/dev_disk_perf ->
../../devices/virtual/device_driver/dev_disk_perf
/sys/class/device_driver/dev_disk ->
../../devices/virtual/device_driver/dev_disk
/sys/class/device_driver/vdisk_fileio ->
../../devices/virtual/device_driver/vdisk_fileio
/sys/class/device_driver/vdisk_blockio ->
../../devices/virtual/device_driver/vdisk_blockio
/sys/class/device_driver/vdisk_nullio ->
../../devices/virtual/device_driver/vdisk_nullio
/sys/class/device_driver/vcdrom -> ../../devices/virtual/device_driver/vcdrom
/sys/class/target_device
/sys/class/target_device/disk01 -> ../../devices/virtual/target_device/disk01
/sys/class/target_device/2:0:0:0 -> ../../devices/virtual/target_device/2:0:0:0
/sys/class/target_device/2:0:1:0 -> ../../devices/virtual/target_device/2:0:1:0
/sys/class/target_device/3:0:0:0 -> ../../devices/virtual/target_device/3:0:0:0
/sys/class/target_device/disk02 -> ../../devices/virtual/target_device/disk02
/sys/class/target_device/disk03 -> ../../devices/virtual/target_device/disk03
/sys/class/target_device/disk04 -> ../../devices/virtual/target_device/disk04
/sys/class/target_device/disk05 -> ../../devices/virtual/target_device/disk05
/sys/class/target_device/disk06 -> ../../devices/virtual/target_device/disk06
/sys/devices/virtual/target_driver
/sys/devices/virtual/target_driver/iscsi
/sys/devices/virtual/target_driver/iscsi/iSNSServer
/sys/devices/virtual/target_driver/iscsi/enabled
/sys/devices/virtual/target_driver/iscsi/uevent
/sys/devices/virtual/target_driver/iscsi/subsystem ->
../../../../class/target_driver
/sys/devices/virtual/target_driver/iscsi/power
/sys/devices/virtual/target_driver/iscsi/power/wakeup
/sys/devices/virtual/target_driver/iscsi/power/wakeup_count
/sys/devices/virtual/target_driver/iscsi/power/wakeup_active_count
/sys/devices/virtual/target_driver/iscsi/power/wakeup_hit_count
/sys/devices/virtual/target_driver/iscsi/power/wakeup_active
/sys/devices/virtual/target_driver/iscsi/power/wakeup_total_time_ms
/sys/devices/virtual/target_driver/iscsi/power/wakeup_max_time_ms
/sys/devices/virtual/target_driver/iscsi/power/wakeup_last_time_ms
/sys/devices/virtual/target_driver/iscsi/power/runtime_status
/sys/devices/virtual/target_driver/iscsi/power/control
/sys/devices/virtual/target_driver/iscsi/power/runtime_suspended_time
/sys/devices/virtual/target_driver/iscsi/power/runtime_active_time
/sys/devices/virtual/target_driver/iscsi/power/autosuspend_delay_ms
/sys/devices/virtual/target_driver/iscsi/add_target_parameters
/sys/devices/virtual/target_driver/iscsi/driver_attributes
/sys/devices/virtual/target_driver/iscsi/target_attributes
/sys/devices/virtual/target_driver/iscsi/version
/sys/devices/virtual/target_driver/iscsi/open_state
/sys/devices/virtual/target_driver/iscsi/trace_level
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/uevent
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/subsystem
-> ../../../../../class/target_instance
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/device
-> ../../iscsi
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/power
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/power/wakeup
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/power/wakeup_count
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/power/wakeup_active_count
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/power/wakeup_hit_count
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/power/wakeup_active
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/power/wakeup_total_time_ms
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/power/wakeup_max_time_ms
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/power/wakeup_last_time_ms
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/power/runtime_status
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/power/control
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/power/runtime_suspended_time
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/power/runtime_active_time
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/power/autosuspend_delay_ms
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/enabled
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/commands
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/active_commands
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/initiator_name
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/InitialR2T
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/ImmediateData
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/MaxRecvDataSegmentLength
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/MaxXmitDataSegmentLength
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/MaxBurstLength
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/FirstBurstLength
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/MaxOutstandingR2T
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/HeaderDigest
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/DataDigest
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/sid
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/reinstating
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/force_close
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/luns
-> ../../luns
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/lun0
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/lun0/active_commands
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/lun1
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/lun1/active_commands
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/lun2
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/lun2/active_commands
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/lun3
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/lun3/active_commands
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/lun4
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/lun4/active_commands
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/lun5
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/lun5/active_commands
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/192.168.2.6
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/192.168.2.6/state
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/192.168.2.6/cid
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions/iqn.1996-04.de.suse:01:e4bde122139a/192.168.2.6/ip
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/parameters
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/0
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/0/read_only
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/0/device
-> ../../../../../target_device/disk01
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/1
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/1/read_only
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/1/device
-> ../../../../../target_device/disk02
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/2
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/2/read_only
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/2/device
-> ../../../../../target_device/disk03
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/3
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/3/read_only
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/3/device
-> ../../../../../target_device/disk04
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/4
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/4/read_only
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/4/device
-> ../../../../../target_device/disk05
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/5
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/5/read_only
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/5/device
-> ../../../../../target_device/disk06
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/ini_groups
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/rel_tgt_id
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/addr_method
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/io_grouping_type
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/cpu_mask
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/tid
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/per_portal_acl
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/redirect
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/InitialR2T
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/ImmediateData
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/MaxRecvDataSegmentLength
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/MaxXmitDataSegmentLength
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/MaxBurstLength
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/FirstBurstLength
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/MaxOutstandingR2T
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/HeaderDigest
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/DataDigest
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/QueuedCommands
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/RspTimeout
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/NopInInterval
/sys/devices/virtual/target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/MaxSessions
/sys/devices/virtual/target_driver/ib_srpt
/sys/devices/virtual/target_driver/ib_srpt/uevent
/sys/devices/virtual/target_driver/ib_srpt/subsystem ->
../../../../class/target_driver
/sys/devices/virtual/target_driver/ib_srpt/power
/sys/devices/virtual/target_driver/ib_srpt/power/wakeup
/sys/devices/virtual/target_driver/ib_srpt/power/wakeup_count
/sys/devices/virtual/target_driver/ib_srpt/power/wakeup_active_count
/sys/devices/virtual/target_driver/ib_srpt/power/wakeup_hit_count
/sys/devices/virtual/target_driver/ib_srpt/power/wakeup_active
/sys/devices/virtual/target_driver/ib_srpt/power/wakeup_total_time_ms
/sys/devices/virtual/target_driver/ib_srpt/power/wakeup_max_time_ms
/sys/devices/virtual/target_driver/ib_srpt/power/wakeup_last_time_ms
/sys/devices/virtual/target_driver/ib_srpt/power/runtime_status
/sys/devices/virtual/target_driver/ib_srpt/power/control
/sys/devices/virtual/target_driver/ib_srpt/power/runtime_suspended_time
/sys/devices/virtual/target_driver/ib_srpt/power/runtime_active_time
/sys/devices/virtual/target_driver/ib_srpt/power/autosuspend_delay_ms
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/uevent
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/subsystem
-> ../../../../../class/target_instance
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/device ->
../../ib_srpt
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/power
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/power/wakeup
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/power/wakeup_count
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/power/wakeup_active_count
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/power/wakeup_hit_count
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/power/wakeup_active
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/power/wakeup_total_time_ms
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/power/wakeup_max_time_ms
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/power/wakeup_last_time_ms
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/power/runtime_status
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/power/control
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/power/runtime_suspended_time
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/power/runtime_active_time
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/power/autosuspend_delay_ms
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/enabled
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/commands
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/active_commands
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/initiator_name
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/req_lim
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/req_lim_delta
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/luns
-> ../../luns
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun0
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun0/active_commands
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun1
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun1/active_commands
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun2
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun2/active_commands
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun3
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun3/active_commands
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun4
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun4/active_commands
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun5
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun5/active_commands
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/parameters
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/0
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/0/read_only
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/0/device
-> ../../../../../target_device/disk01
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/1
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/1/read_only
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/1/device
-> ../../../../../target_device/disk02
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/2
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/2/read_only
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/2/device
-> ../../../../../target_device/disk03
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/3
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/3/read_only
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/3/device
-> ../../../../../target_device/disk04
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/4
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/4/read_only
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/4/device
-> ../../../../../target_device/disk05
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/5
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/5/read_only
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/luns/5/device
-> ../../../../../target_device/disk06
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/ini_groups
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/rel_tgt_id
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/addr_method
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/io_grouping_type
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/cpu_mask
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_0/login_info
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/uevent
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/subsystem
-> ../../../../../class/target_instance
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/device ->
../../ib_srpt
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/power
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/power/wakeup
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/power/wakeup_count
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/power/wakeup_active_count
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/power/wakeup_hit_count
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/power/wakeup_active
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/power/wakeup_total_time_ms
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/power/wakeup_max_time_ms
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/power/wakeup_last_time_ms
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/power/runtime_status
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/power/control
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/power/runtime_suspended_time
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/power/runtime_active_time
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/power/autosuspend_delay_ms
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/enabled
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/sessions
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/parameters
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/0
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/0/read_only
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/0/device
-> ../../../../../target_device/disk01
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/1
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/1/read_only
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/1/device
-> ../../../../../target_device/disk02
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/2
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/2/read_only
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/2/device
-> ../../../../../target_device/disk03
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/3
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/3/read_only
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/3/device
-> ../../../../../target_device/disk04
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/4
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/4/read_only
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/4/device
-> ../../../../../target_device/disk05
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/5
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/5/read_only
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/luns/5/device
-> ../../../../../target_device/disk06
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/ini_groups
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/rel_tgt_id
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/addr_method
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/io_grouping_type
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/cpu_mask
/sys/devices/virtual/target_driver/ib_srpt/ib_srpt_target_1/login_info
/sys/devices/virtual/target_driver/scst_local
/sys/devices/virtual/target_driver/scst_local/uevent
/sys/devices/virtual/target_driver/scst_local/subsystem ->
../../../../class/target_driver
/sys/devices/virtual/target_driver/scst_local/power
/sys/devices/virtual/target_driver/scst_local/power/wakeup
/sys/devices/virtual/target_driver/scst_local/power/wakeup_count
/sys/devices/virtual/target_driver/scst_local/power/wakeup_active_count
/sys/devices/virtual/target_driver/scst_local/power/wakeup_hit_count
/sys/devices/virtual/target_driver/scst_local/power/wakeup_active
/sys/devices/virtual/target_driver/scst_local/power/wakeup_total_time_ms
/sys/devices/virtual/target_driver/scst_local/power/wakeup_max_time_ms
/sys/devices/virtual/target_driver/scst_local/power/wakeup_last_time_ms
/sys/devices/virtual/target_driver/scst_local/power/runtime_status
/sys/devices/virtual/target_driver/scst_local/power/control
/sys/devices/virtual/target_driver/scst_local/power/runtime_suspended_time
/sys/devices/virtual/target_driver/scst_local/power/runtime_active_time
/sys/devices/virtual/target_driver/scst_local/power/autosuspend_delay_ms
/sys/devices/virtual/target_driver/scst_local/add_target_parameters
/sys/devices/virtual/target_driver/scst_local/version
/sys/devices/virtual/target_driver/scst_local/stats
/sys/devices/virtual/target_driver/scst_local/trace_level
/sys/devices/virtual/target_driver/scst_local/local
/sys/devices/virtual/target_driver/scst_local/local/uevent
/sys/devices/virtual/target_driver/scst_local/local/subsystem ->
../../../../../class/target_instance
/sys/devices/virtual/target_driver/scst_local/local/device -> ../../scst_local
/sys/devices/virtual/target_driver/scst_local/local/power
/sys/devices/virtual/target_driver/scst_local/local/power/wakeup
/sys/devices/virtual/target_driver/scst_local/local/power/wakeup_count
/sys/devices/virtual/target_driver/scst_local/local/power/wakeup_active_count
/sys/devices/virtual/target_driver/scst_local/local/power/wakeup_hit_count
/sys/devices/virtual/target_driver/scst_local/local/power/wakeup_active
/sys/devices/virtual/target_driver/scst_local/local/power/wakeup_total_time_ms
/sys/devices/virtual/target_driver/scst_local/local/power/wakeup_max_time_ms
/sys/devices/virtual/target_driver/scst_local/local/power/wakeup_last_time_ms
/sys/devices/virtual/target_driver/scst_local/local/power/runtime_status
/sys/devices/virtual/target_driver/scst_local/local/power/control
/sys/devices/virtual/target_driver/scst_local/local/power/runtime_suspended_time
/sys/devices/virtual/target_driver/scst_local/local/power/runtime_active_time
/sys/devices/virtual/target_driver/scst_local/local/power/autosuspend_delay_ms
/sys/devices/virtual/target_driver/scst_local/local/sessions
/sys/devices/virtual/target_driver/scst_local/local/sessions/local
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/commands
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/active_commands
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/initiator_name
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/transport_id
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/luns
-> ../../luns
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/host
-> ../../../../../../scst_local/local/host8/scsi_host/host8
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/lun0
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/lun0/active_commands
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/lun1
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/lun1/active_commands
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/lun2
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/lun2/active_commands
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/lun3
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/lun3/active_commands
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/lun4
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/lun4/active_commands
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/lun5
/sys/devices/virtual/target_driver/scst_local/local/sessions/local/lun5/active_commands
/sys/devices/virtual/target_driver/scst_local/local/luns
/sys/devices/virtual/target_driver/scst_local/local/luns/parameters
/sys/devices/virtual/target_driver/scst_local/local/luns/0
/sys/devices/virtual/target_driver/scst_local/local/luns/0/read_only
/sys/devices/virtual/target_driver/scst_local/local/luns/0/device ->
../../../../../target_device/disk01
/sys/devices/virtual/target_driver/scst_local/local/luns/1
/sys/devices/virtual/target_driver/scst_local/local/luns/1/read_only
/sys/devices/virtual/target_driver/scst_local/local/luns/1/device ->
../../../../../target_device/disk02
/sys/devices/virtual/target_driver/scst_local/local/luns/2
/sys/devices/virtual/target_driver/scst_local/local/luns/2/read_only
/sys/devices/virtual/target_driver/scst_local/local/luns/2/device ->
../../../../../target_device/disk03
/sys/devices/virtual/target_driver/scst_local/local/luns/3
/sys/devices/virtual/target_driver/scst_local/local/luns/3/read_only
/sys/devices/virtual/target_driver/scst_local/local/luns/3/device ->
../../../../../target_device/disk04
/sys/devices/virtual/target_driver/scst_local/local/luns/4
/sys/devices/virtual/target_driver/scst_local/local/luns/4/read_only
/sys/devices/virtual/target_driver/scst_local/local/luns/4/device ->
../../../../../target_device/disk05
/sys/devices/virtual/target_driver/scst_local/local/luns/5
/sys/devices/virtual/target_driver/scst_local/local/luns/5/read_only
/sys/devices/virtual/target_driver/scst_local/local/luns/5/device ->
../../../../../target_device/disk06
/sys/devices/virtual/target_driver/scst_local/local/ini_groups
/sys/devices/virtual/target_driver/scst_local/local/rel_tgt_id
/sys/devices/virtual/target_driver/scst_local/local/addr_method
/sys/devices/virtual/target_driver/scst_local/local/io_grouping_type
/sys/devices/virtual/target_driver/scst_local/local/cpu_mask
/sys/devices/virtual/target_driver/scst_local/local/scsi_transport_version
/sys/devices/virtual/target_driver/scst_local/local/phys_transport_version
/sys/devices/virtual/device_driver
/sys/devices/virtual/device_driver/dev_disk_perf
/sys/devices/virtual/device_driver/dev_disk_perf/uevent
/sys/devices/virtual/device_driver/dev_disk_perf/subsystem ->
../../../../class/device_driver
/sys/devices/virtual/device_driver/dev_disk_perf/type
/sys/devices/virtual/device_driver/dev_disk_perf/power
/sys/devices/virtual/device_driver/dev_disk_perf/power/wakeup
/sys/devices/virtual/device_driver/dev_disk_perf/power/wakeup_count
/sys/devices/virtual/device_driver/dev_disk_perf/power/wakeup_active_count
/sys/devices/virtual/device_driver/dev_disk_perf/power/wakeup_hit_count
/sys/devices/virtual/device_driver/dev_disk_perf/power/wakeup_active
/sys/devices/virtual/device_driver/dev_disk_perf/power/wakeup_total_time_ms
/sys/devices/virtual/device_driver/dev_disk_perf/power/wakeup_max_time_ms
/sys/devices/virtual/device_driver/dev_disk_perf/power/wakeup_last_time_ms
/sys/devices/virtual/device_driver/dev_disk_perf/power/runtime_status
/sys/devices/virtual/device_driver/dev_disk_perf/power/control
/sys/devices/virtual/device_driver/dev_disk_perf/power/runtime_suspended_time
/sys/devices/virtual/device_driver/dev_disk_perf/power/runtime_active_time
/sys/devices/virtual/device_driver/dev_disk_perf/power/autosuspend_delay_ms
/sys/devices/virtual/device_driver/dev_disk_perf/trace_level
/sys/devices/virtual/device_driver/dev_disk
/sys/devices/virtual/device_driver/dev_disk/trace_level
/sys/devices/virtual/device_driver/dev_disk/uevent
/sys/devices/virtual/device_driver/dev_disk/subsystem ->
../../../../class/device_driver
/sys/devices/virtual/device_driver/dev_disk/type
/sys/devices/virtual/device_driver/dev_disk/power
/sys/devices/virtual/device_driver/dev_disk/power/wakeup
/sys/devices/virtual/device_driver/dev_disk/power/wakeup_count
/sys/devices/virtual/device_driver/dev_disk/power/wakeup_active_count
/sys/devices/virtual/device_driver/dev_disk/power/wakeup_hit_count
/sys/devices/virtual/device_driver/dev_disk/power/wakeup_active
/sys/devices/virtual/device_driver/dev_disk/power/wakeup_total_time_ms
/sys/devices/virtual/device_driver/dev_disk/power/wakeup_max_time_ms
/sys/devices/virtual/device_driver/dev_disk/power/wakeup_last_time_ms
/sys/devices/virtual/device_driver/dev_disk/power/runtime_status
/sys/devices/virtual/device_driver/dev_disk/power/control
/sys/devices/virtual/device_driver/dev_disk/power/runtime_suspended_time
/sys/devices/virtual/device_driver/dev_disk/power/runtime_active_time
/sys/devices/virtual/device_driver/dev_disk/power/autosuspend_delay_ms
/sys/devices/virtual/device_driver/vdisk_fileio
/sys/devices/virtual/device_driver/vdisk_fileio/uevent
/sys/devices/virtual/device_driver/vdisk_fileio/subsystem ->
../../../../class/device_driver
/sys/devices/virtual/device_driver/vdisk_fileio/type
/sys/devices/virtual/device_driver/vdisk_fileio/power
/sys/devices/virtual/device_driver/vdisk_fileio/power/wakeup
/sys/devices/virtual/device_driver/vdisk_fileio/power/wakeup_count
/sys/devices/virtual/device_driver/vdisk_fileio/power/wakeup_active_count
/sys/devices/virtual/device_driver/vdisk_fileio/power/wakeup_hit_count
/sys/devices/virtual/device_driver/vdisk_fileio/power/wakeup_active
/sys/devices/virtual/device_driver/vdisk_fileio/power/wakeup_total_time_ms
/sys/devices/virtual/device_driver/vdisk_fileio/power/wakeup_max_time_ms
/sys/devices/virtual/device_driver/vdisk_fileio/power/wakeup_last_time_ms
/sys/devices/virtual/device_driver/vdisk_fileio/power/runtime_status
/sys/devices/virtual/device_driver/vdisk_fileio/power/control
/sys/devices/virtual/device_driver/vdisk_fileio/power/runtime_suspended_time
/sys/devices/virtual/device_driver/vdisk_fileio/power/runtime_active_time
/sys/devices/virtual/device_driver/vdisk_fileio/power/autosuspend_delay_ms
/sys/devices/virtual/device_driver/vdisk_fileio/add_device_parameters
/sys/devices/virtual/device_driver/vdisk_fileio/trace_level
/sys/devices/virtual/device_driver/vdisk_fileio/disk03 ->
../../target_device/disk03
/sys/devices/virtual/device_driver/vdisk_fileio/disk04 ->
../../target_device/disk04
/sys/devices/virtual/device_driver/vdisk_blockio
/sys/devices/virtual/device_driver/vdisk_blockio/uevent
/sys/devices/virtual/device_driver/vdisk_blockio/subsystem ->
../../../../class/device_driver
/sys/devices/virtual/device_driver/vdisk_blockio/type
/sys/devices/virtual/device_driver/vdisk_blockio/power
/sys/devices/virtual/device_driver/vdisk_blockio/power/wakeup
/sys/devices/virtual/device_driver/vdisk_blockio/power/wakeup_count
/sys/devices/virtual/device_driver/vdisk_blockio/power/wakeup_active_count
/sys/devices/virtual/device_driver/vdisk_blockio/power/wakeup_hit_count
/sys/devices/virtual/device_driver/vdisk_blockio/power/wakeup_active
/sys/devices/virtual/device_driver/vdisk_blockio/power/wakeup_total_time_ms
/sys/devices/virtual/device_driver/vdisk_blockio/power/wakeup_max_time_ms
/sys/devices/virtual/device_driver/vdisk_blockio/power/wakeup_last_time_ms
/sys/devices/virtual/device_driver/vdisk_blockio/power/runtime_status
/sys/devices/virtual/device_driver/vdisk_blockio/power/control
/sys/devices/virtual/device_driver/vdisk_blockio/power/runtime_suspended_time
/sys/devices/virtual/device_driver/vdisk_blockio/power/runtime_active_time
/sys/devices/virtual/device_driver/vdisk_blockio/power/autosuspend_delay_ms
/sys/devices/virtual/device_driver/vdisk_blockio/add_device_parameters
/sys/devices/virtual/device_driver/vdisk_blockio/trace_level
/sys/devices/virtual/device_driver/vdisk_blockio/disk01 ->
../../target_device/disk01
/sys/devices/virtual/device_driver/vdisk_blockio/disk02 ->
../../target_device/disk02
/sys/devices/virtual/device_driver/vdisk_nullio
/sys/devices/virtual/device_driver/vdisk_nullio/uevent
/sys/devices/virtual/device_driver/vdisk_nullio/subsystem ->
../../../../class/device_driver
/sys/devices/virtual/device_driver/vdisk_nullio/type
/sys/devices/virtual/device_driver/vdisk_nullio/power
/sys/devices/virtual/device_driver/vdisk_nullio/power/wakeup
/sys/devices/virtual/device_driver/vdisk_nullio/power/wakeup_count
/sys/devices/virtual/device_driver/vdisk_nullio/power/wakeup_active_count
/sys/devices/virtual/device_driver/vdisk_nullio/power/wakeup_hit_count
/sys/devices/virtual/device_driver/vdisk_nullio/power/wakeup_active
/sys/devices/virtual/device_driver/vdisk_nullio/power/wakeup_total_time_ms
/sys/devices/virtual/device_driver/vdisk_nullio/power/wakeup_max_time_ms
/sys/devices/virtual/device_driver/vdisk_nullio/power/wakeup_last_time_ms
/sys/devices/virtual/device_driver/vdisk_nullio/power/runtime_status
/sys/devices/virtual/device_driver/vdisk_nullio/power/control
/sys/devices/virtual/device_driver/vdisk_nullio/power/runtime_suspended_time
/sys/devices/virtual/device_driver/vdisk_nullio/power/runtime_active_time
/sys/devices/virtual/device_driver/vdisk_nullio/power/autosuspend_delay_ms
/sys/devices/virtual/device_driver/vdisk_nullio/add_device_parameters
/sys/devices/virtual/device_driver/vdisk_nullio/trace_level
/sys/devices/virtual/device_driver/vdisk_nullio/disk05 ->
../../target_device/disk05
/sys/devices/virtual/device_driver/vdisk_nullio/disk06 ->
../../target_device/disk06
/sys/devices/virtual/device_driver/vcdrom
/sys/devices/virtual/device_driver/vcdrom/uevent
/sys/devices/virtual/device_driver/vcdrom/subsystem ->
../../../../class/device_driver
/sys/devices/virtual/device_driver/vcdrom/type
/sys/devices/virtual/device_driver/vcdrom/power
/sys/devices/virtual/device_driver/vcdrom/power/wakeup
/sys/devices/virtual/device_driver/vcdrom/power/wakeup_count
/sys/devices/virtual/device_driver/vcdrom/power/wakeup_active_count
/sys/devices/virtual/device_driver/vcdrom/power/wakeup_hit_count
/sys/devices/virtual/device_driver/vcdrom/power/wakeup_active
/sys/devices/virtual/device_driver/vcdrom/power/wakeup_total_time_ms
/sys/devices/virtual/device_driver/vcdrom/power/wakeup_max_time_ms
/sys/devices/virtual/device_driver/vcdrom/power/wakeup_last_time_ms
/sys/devices/virtual/device_driver/vcdrom/power/runtime_status
/sys/devices/virtual/device_driver/vcdrom/power/control
/sys/devices/virtual/device_driver/vcdrom/power/runtime_suspended_time
/sys/devices/virtual/device_driver/vcdrom/power/runtime_active_time
/sys/devices/virtual/device_driver/vcdrom/power/autosuspend_delay_ms
/sys/devices/virtual/device_driver/vcdrom/trace_level
/sys/devices/virtual/target_device
/sys/devices/virtual/target_device/disk01
/sys/devices/virtual/target_device/disk01/uevent
/sys/devices/virtual/target_device/disk01/subsystem ->
../../../../class/target_device
/sys/devices/virtual/target_device/disk01/type
/sys/devices/virtual/target_device/disk01/power
/sys/devices/virtual/target_device/disk01/power/wakeup
/sys/devices/virtual/target_device/disk01/power/wakeup_count
/sys/devices/virtual/target_device/disk01/power/wakeup_active_count
/sys/devices/virtual/target_device/disk01/power/wakeup_hit_count
/sys/devices/virtual/target_device/disk01/power/wakeup_active
/sys/devices/virtual/target_device/disk01/power/wakeup_total_time_ms
/sys/devices/virtual/target_device/disk01/power/wakeup_max_time_ms
/sys/devices/virtual/target_device/disk01/power/wakeup_last_time_ms
/sys/devices/virtual/target_device/disk01/power/runtime_status
/sys/devices/virtual/target_device/disk01/power/control
/sys/devices/virtual/target_device/disk01/power/runtime_suspended_time
/sys/devices/virtual/target_device/disk01/power/runtime_active_time
/sys/devices/virtual/target_device/disk01/power/autosuspend_delay_ms
/sys/devices/virtual/target_device/disk01/exported
/sys/devices/virtual/target_device/disk01/exported/export0 ->
../../../target_driver/ib_srpt/ib_srpt_target_0/luns/0
/sys/devices/virtual/target_device/disk01/exported/export1 ->
../../../target_driver/ib_srpt/ib_srpt_target_1/luns/0
/sys/devices/virtual/target_device/disk01/exported/export2 ->
../../../target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/0
/sys/devices/virtual/target_device/disk01/exported/export3 ->
../../../target_driver/scst_local/local/luns/0
/sys/devices/virtual/target_device/disk01/dump_prs
/sys/devices/virtual/target_device/disk01/handler ->
../../device_driver/vdisk_blockio
/sys/devices/virtual/target_device/disk01/threads_num
/sys/devices/virtual/target_device/disk01/threads_pool_type
/sys/devices/virtual/target_device/disk01/size_mb
/sys/devices/virtual/target_device/disk01/blocksize
/sys/devices/virtual/target_device/disk01/read_only
/sys/devices/virtual/target_device/disk01/nv_cache
/sys/devices/virtual/target_device/disk01/removable
/sys/devices/virtual/target_device/disk01/filename
/sys/devices/virtual/target_device/disk01/resync_size
/sys/devices/virtual/target_device/disk01/t10_dev_id
/sys/devices/virtual/target_device/disk01/usn
/sys/devices/virtual/target_device/disk01/thin_provisioned
/sys/devices/virtual/target_device/2:0:0:0
/sys/devices/virtual/target_device/2:0:0:0/exported
/sys/devices/virtual/target_device/2:0:0:0/scsi_device ->
../../../pci0000:00/0000:00:1f.2/host2/target2:0:0/2:0:0:0/scsi_device/2:0:0:0
/sys/devices/virtual/target_device/2:0:0:0/uevent
/sys/devices/virtual/target_device/2:0:0:0/subsystem ->
../../../../class/target_device
/sys/devices/virtual/target_device/2:0:0:0/type
/sys/devices/virtual/target_device/2:0:0:0/power
/sys/devices/virtual/target_device/2:0:0:0/power/wakeup
/sys/devices/virtual/target_device/2:0:0:0/power/wakeup_count
/sys/devices/virtual/target_device/2:0:0:0/power/wakeup_active_count
/sys/devices/virtual/target_device/2:0:0:0/power/wakeup_hit_count
/sys/devices/virtual/target_device/2:0:0:0/power/wakeup_active
/sys/devices/virtual/target_device/2:0:0:0/power/wakeup_total_time_ms
/sys/devices/virtual/target_device/2:0:0:0/power/wakeup_max_time_ms
/sys/devices/virtual/target_device/2:0:0:0/power/wakeup_last_time_ms
/sys/devices/virtual/target_device/2:0:0:0/power/runtime_status
/sys/devices/virtual/target_device/2:0:0:0/power/control
/sys/devices/virtual/target_device/2:0:0:0/power/runtime_suspended_time
/sys/devices/virtual/target_device/2:0:0:0/power/runtime_active_time
/sys/devices/virtual/target_device/2:0:0:0/power/autosuspend_delay_ms
/sys/devices/virtual/target_device/2:0:1:0
/sys/devices/virtual/target_device/2:0:1:0/uevent
/sys/devices/virtual/target_device/2:0:1:0/subsystem ->
../../../../class/target_device
/sys/devices/virtual/target_device/2:0:1:0/type
/sys/devices/virtual/target_device/2:0:1:0/power
/sys/devices/virtual/target_device/2:0:1:0/power/wakeup
/sys/devices/virtual/target_device/2:0:1:0/power/wakeup_count
/sys/devices/virtual/target_device/2:0:1:0/power/wakeup_active_count
/sys/devices/virtual/target_device/2:0:1:0/power/wakeup_hit_count
/sys/devices/virtual/target_device/2:0:1:0/power/wakeup_active
/sys/devices/virtual/target_device/2:0:1:0/power/wakeup_total_time_ms
/sys/devices/virtual/target_device/2:0:1:0/power/wakeup_max_time_ms
/sys/devices/virtual/target_device/2:0:1:0/power/wakeup_last_time_ms
/sys/devices/virtual/target_device/2:0:1:0/power/runtime_status
/sys/devices/virtual/target_device/2:0:1:0/power/control
/sys/devices/virtual/target_device/2:0:1:0/power/runtime_suspended_time
/sys/devices/virtual/target_device/2:0:1:0/power/runtime_active_time
/sys/devices/virtual/target_device/2:0:1:0/power/autosuspend_delay_ms
/sys/devices/virtual/target_device/2:0:1:0/exported
/sys/devices/virtual/target_device/2:0:1:0/scsi_device ->
../../../pci0000:00/0000:00:1f.2/host2/target2:0:1/2:0:1:0/scsi_device/2:0:1:0
/sys/devices/virtual/target_device/3:0:0:0
/sys/devices/virtual/target_device/3:0:0:0/uevent
/sys/devices/virtual/target_device/3:0:0:0/subsystem ->
../../../../class/target_device
/sys/devices/virtual/target_device/3:0:0:0/type
/sys/devices/virtual/target_device/3:0:0:0/power
/sys/devices/virtual/target_device/3:0:0:0/power/wakeup
/sys/devices/virtual/target_device/3:0:0:0/power/wakeup_count
/sys/devices/virtual/target_device/3:0:0:0/power/wakeup_active_count
/sys/devices/virtual/target_device/3:0:0:0/power/wakeup_hit_count
/sys/devices/virtual/target_device/3:0:0:0/power/wakeup_active
/sys/devices/virtual/target_device/3:0:0:0/power/wakeup_total_time_ms
/sys/devices/virtual/target_device/3:0:0:0/power/wakeup_max_time_ms
/sys/devices/virtual/target_device/3:0:0:0/power/wakeup_last_time_ms
/sys/devices/virtual/target_device/3:0:0:0/power/runtime_status
/sys/devices/virtual/target_device/3:0:0:0/power/control
/sys/devices/virtual/target_device/3:0:0:0/power/runtime_suspended_time
/sys/devices/virtual/target_device/3:0:0:0/power/runtime_active_time
/sys/devices/virtual/target_device/3:0:0:0/power/autosuspend_delay_ms
/sys/devices/virtual/target_device/3:0:0:0/exported
/sys/devices/virtual/target_device/3:0:0:0/scsi_device ->
../../../pci0000:00/0000:00:1f.2/host3/target3:0:0/3:0:0:0/scsi_device/3:0:0:0
/sys/devices/virtual/target_device/disk02
/sys/devices/virtual/target_device/disk02/uevent
/sys/devices/virtual/target_device/disk02/subsystem ->
../../../../class/target_device
/sys/devices/virtual/target_device/disk02/type
/sys/devices/virtual/target_device/disk02/power
/sys/devices/virtual/target_device/disk02/power/wakeup
/sys/devices/virtual/target_device/disk02/power/wakeup_count
/sys/devices/virtual/target_device/disk02/power/wakeup_active_count
/sys/devices/virtual/target_device/disk02/power/wakeup_hit_count
/sys/devices/virtual/target_device/disk02/power/wakeup_active
/sys/devices/virtual/target_device/disk02/power/wakeup_total_time_ms
/sys/devices/virtual/target_device/disk02/power/wakeup_max_time_ms
/sys/devices/virtual/target_device/disk02/power/wakeup_last_time_ms
/sys/devices/virtual/target_device/disk02/power/runtime_status
/sys/devices/virtual/target_device/disk02/power/control
/sys/devices/virtual/target_device/disk02/power/runtime_suspended_time
/sys/devices/virtual/target_device/disk02/power/runtime_active_time
/sys/devices/virtual/target_device/disk02/power/autosuspend_delay_ms
/sys/devices/virtual/target_device/disk02/exported
/sys/devices/virtual/target_device/disk02/exported/export0 ->
../../../target_driver/ib_srpt/ib_srpt_target_0/luns/1
/sys/devices/virtual/target_device/disk02/exported/export1 ->
../../../target_driver/ib_srpt/ib_srpt_target_1/luns/1
/sys/devices/virtual/target_device/disk02/exported/export2 ->
../../../target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/1
/sys/devices/virtual/target_device/disk02/exported/export3 ->
../../../target_driver/scst_local/local/luns/1
/sys/devices/virtual/target_device/disk02/dump_prs
/sys/devices/virtual/target_device/disk02/handler ->
../../device_driver/vdisk_blockio
/sys/devices/virtual/target_device/disk02/threads_num
/sys/devices/virtual/target_device/disk02/threads_pool_type
/sys/devices/virtual/target_device/disk02/size_mb
/sys/devices/virtual/target_device/disk02/blocksize
/sys/devices/virtual/target_device/disk02/read_only
/sys/devices/virtual/target_device/disk02/nv_cache
/sys/devices/virtual/target_device/disk02/removable
/sys/devices/virtual/target_device/disk02/filename
/sys/devices/virtual/target_device/disk02/resync_size
/sys/devices/virtual/target_device/disk02/t10_dev_id
/sys/devices/virtual/target_device/disk02/usn
/sys/devices/virtual/target_device/disk02/thin_provisioned
/sys/devices/virtual/target_device/disk03
/sys/devices/virtual/target_device/disk03/uevent
/sys/devices/virtual/target_device/disk03/subsystem ->
../../../../class/target_device
/sys/devices/virtual/target_device/disk03/type
/sys/devices/virtual/target_device/disk03/power
/sys/devices/virtual/target_device/disk03/power/wakeup
/sys/devices/virtual/target_device/disk03/power/wakeup_count
/sys/devices/virtual/target_device/disk03/power/wakeup_active_count
/sys/devices/virtual/target_device/disk03/power/wakeup_hit_count
/sys/devices/virtual/target_device/disk03/power/wakeup_active
/sys/devices/virtual/target_device/disk03/power/wakeup_total_time_ms
/sys/devices/virtual/target_device/disk03/power/wakeup_max_time_ms
/sys/devices/virtual/target_device/disk03/power/wakeup_last_time_ms
/sys/devices/virtual/target_device/disk03/power/runtime_status
/sys/devices/virtual/target_device/disk03/power/control
/sys/devices/virtual/target_device/disk03/power/runtime_suspended_time
/sys/devices/virtual/target_device/disk03/power/runtime_active_time
/sys/devices/virtual/target_device/disk03/power/autosuspend_delay_ms
/sys/devices/virtual/target_device/disk03/exported
/sys/devices/virtual/target_device/disk03/exported/export0 ->
../../../target_driver/ib_srpt/ib_srpt_target_0/luns/2
/sys/devices/virtual/target_device/disk03/exported/export1 ->
../../../target_driver/ib_srpt/ib_srpt_target_1/luns/2
/sys/devices/virtual/target_device/disk03/exported/export2 ->
../../../target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/2
/sys/devices/virtual/target_device/disk03/exported/export3 ->
../../../target_driver/scst_local/local/luns/2
/sys/devices/virtual/target_device/disk03/dump_prs
/sys/devices/virtual/target_device/disk03/handler ->
../../device_driver/vdisk_fileio
/sys/devices/virtual/target_device/disk03/threads_num
/sys/devices/virtual/target_device/disk03/threads_pool_type
/sys/devices/virtual/target_device/disk03/size_mb
/sys/devices/virtual/target_device/disk03/blocksize
/sys/devices/virtual/target_device/disk03/read_only
/sys/devices/virtual/target_device/disk03/write_through
/sys/devices/virtual/target_device/disk03/thin_provisioned
/sys/devices/virtual/target_device/disk03/nv_cache
/sys/devices/virtual/target_device/disk03/o_direct
/sys/devices/virtual/target_device/disk03/removable
/sys/devices/virtual/target_device/disk03/filename
/sys/devices/virtual/target_device/disk03/resync_size
/sys/devices/virtual/target_device/disk03/t10_dev_id
/sys/devices/virtual/target_device/disk03/usn
/sys/devices/virtual/target_device/disk04
/sys/devices/virtual/target_device/disk04/uevent
/sys/devices/virtual/target_device/disk04/subsystem ->
../../../../class/target_device
/sys/devices/virtual/target_device/disk04/type
/sys/devices/virtual/target_device/disk04/power
/sys/devices/virtual/target_device/disk04/power/wakeup
/sys/devices/virtual/target_device/disk04/power/wakeup_count
/sys/devices/virtual/target_device/disk04/power/wakeup_active_count
/sys/devices/virtual/target_device/disk04/power/wakeup_hit_count
/sys/devices/virtual/target_device/disk04/power/wakeup_active
/sys/devices/virtual/target_device/disk04/power/wakeup_total_time_ms
/sys/devices/virtual/target_device/disk04/power/wakeup_max_time_ms
/sys/devices/virtual/target_device/disk04/power/wakeup_last_time_ms
/sys/devices/virtual/target_device/disk04/power/runtime_status
/sys/devices/virtual/target_device/disk04/power/control
/sys/devices/virtual/target_device/disk04/power/runtime_suspended_time
/sys/devices/virtual/target_device/disk04/power/runtime_active_time
/sys/devices/virtual/target_device/disk04/power/autosuspend_delay_ms
/sys/devices/virtual/target_device/disk04/exported
/sys/devices/virtual/target_device/disk04/exported/export0 ->
../../../target_driver/ib_srpt/ib_srpt_target_0/luns/3
/sys/devices/virtual/target_device/disk04/exported/export1 ->
../../../target_driver/ib_srpt/ib_srpt_target_1/luns/3
/sys/devices/virtual/target_device/disk04/exported/export2 ->
../../../target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/3
/sys/devices/virtual/target_device/disk04/exported/export3 ->
../../../target_driver/scst_local/local/luns/3
/sys/devices/virtual/target_device/disk04/dump_prs
/sys/devices/virtual/target_device/disk04/handler ->
../../device_driver/vdisk_fileio
/sys/devices/virtual/target_device/disk04/threads_num
/sys/devices/virtual/target_device/disk04/threads_pool_type
/sys/devices/virtual/target_device/disk04/size_mb
/sys/devices/virtual/target_device/disk04/blocksize
/sys/devices/virtual/target_device/disk04/read_only
/sys/devices/virtual/target_device/disk04/write_through
/sys/devices/virtual/target_device/disk04/thin_provisioned
/sys/devices/virtual/target_device/disk04/nv_cache
/sys/devices/virtual/target_device/disk04/o_direct
/sys/devices/virtual/target_device/disk04/removable
/sys/devices/virtual/target_device/disk04/filename
/sys/devices/virtual/target_device/disk04/resync_size
/sys/devices/virtual/target_device/disk04/t10_dev_id
/sys/devices/virtual/target_device/disk04/usn
/sys/devices/virtual/target_device/disk05
/sys/devices/virtual/target_device/disk05/uevent
/sys/devices/virtual/target_device/disk05/subsystem ->
../../../../class/target_device
/sys/devices/virtual/target_device/disk05/type
/sys/devices/virtual/target_device/disk05/power
/sys/devices/virtual/target_device/disk05/power/wakeup
/sys/devices/virtual/target_device/disk05/power/wakeup_count
/sys/devices/virtual/target_device/disk05/power/wakeup_active_count
/sys/devices/virtual/target_device/disk05/power/wakeup_hit_count
/sys/devices/virtual/target_device/disk05/power/wakeup_active
/sys/devices/virtual/target_device/disk05/power/wakeup_total_time_ms
/sys/devices/virtual/target_device/disk05/power/wakeup_max_time_ms
/sys/devices/virtual/target_device/disk05/power/wakeup_last_time_ms
/sys/devices/virtual/target_device/disk05/power/runtime_status
/sys/devices/virtual/target_device/disk05/power/control
/sys/devices/virtual/target_device/disk05/power/runtime_suspended_time
/sys/devices/virtual/target_device/disk05/power/runtime_active_time
/sys/devices/virtual/target_device/disk05/power/autosuspend_delay_ms
/sys/devices/virtual/target_device/disk05/exported
/sys/devices/virtual/target_device/disk05/exported/export0 ->
../../../target_driver/ib_srpt/ib_srpt_target_0/luns/4
/sys/devices/virtual/target_device/disk05/exported/export1 ->
../../../target_driver/ib_srpt/ib_srpt_target_1/luns/4
/sys/devices/virtual/target_device/disk05/exported/export2 ->
../../../target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/4
/sys/devices/virtual/target_device/disk05/exported/export3 ->
../../../target_driver/scst_local/local/luns/4
/sys/devices/virtual/target_device/disk05/dump_prs
/sys/devices/virtual/target_device/disk05/handler ->
../../device_driver/vdisk_nullio
/sys/devices/virtual/target_device/disk05/threads_num
/sys/devices/virtual/target_device/disk05/threads_pool_type
/sys/devices/virtual/target_device/disk05/size_mb
/sys/devices/virtual/target_device/disk05/blocksize
/sys/devices/virtual/target_device/disk05/read_only
/sys/devices/virtual/target_device/disk05/removable
/sys/devices/virtual/target_device/disk05/t10_dev_id
/sys/devices/virtual/target_device/disk05/usn
/sys/devices/virtual/target_device/disk06
/sys/devices/virtual/target_device/disk06/uevent
/sys/devices/virtual/target_device/disk06/subsystem ->
../../../../class/target_device
/sys/devices/virtual/target_device/disk06/type
/sys/devices/virtual/target_device/disk06/power
/sys/devices/virtual/target_device/disk06/power/wakeup
/sys/devices/virtual/target_device/disk06/power/wakeup_count
/sys/devices/virtual/target_device/disk06/power/wakeup_active_count
/sys/devices/virtual/target_device/disk06/power/wakeup_hit_count
/sys/devices/virtual/target_device/disk06/power/wakeup_active
/sys/devices/virtual/target_device/disk06/power/wakeup_total_time_ms
/sys/devices/virtual/target_device/disk06/power/wakeup_max_time_ms
/sys/devices/virtual/target_device/disk06/power/wakeup_last_time_ms
/sys/devices/virtual/target_device/disk06/power/runtime_status
/sys/devices/virtual/target_device/disk06/power/control
/sys/devices/virtual/target_device/disk06/power/runtime_suspended_time
/sys/devices/virtual/target_device/disk06/power/runtime_active_time
/sys/devices/virtual/target_device/disk06/power/autosuspend_delay_ms
/sys/devices/virtual/target_device/disk06/exported
/sys/devices/virtual/target_device/disk06/exported/export0 ->
../../../target_driver/ib_srpt/ib_srpt_target_0/luns/5
/sys/devices/virtual/target_device/disk06/exported/export1 ->
../../../target_driver/ib_srpt/ib_srpt_target_1/luns/5
/sys/devices/virtual/target_device/disk06/exported/export2 ->
../../../target_driver/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/5
/sys/devices/virtual/target_device/disk06/exported/export3 ->
../../../target_driver/scst_local/local/luns/5
/sys/devices/virtual/target_device/disk06/dump_prs
/sys/devices/virtual/target_device/disk06/handler ->
../../device_driver/vdisk_nullio
/sys/devices/virtual/target_device/disk06/threads_num
/sys/devices/virtual/target_device/disk06/threads_pool_type
/sys/devices/virtual/target_device/disk06/size_mb
/sys/devices/virtual/target_device/disk06/blocksize
/sys/devices/virtual/target_device/disk06/read_only
/sys/devices/virtual/target_device/disk06/removable
/sys/devices/virtual/target_device/disk06/t10_dev_id
/sys/devices/virtual/target_device/disk06/usn
/sys/devices/scst
/sys/devices/scst/uevent
/sys/devices/scst/power
/sys/devices/scst/power/control
/sys/devices/scst/power/wakeup
/sys/devices/scst/power/wakeup_count
/sys/devices/scst/power/wakeup_active_count
/sys/devices/scst/power/wakeup_hit_count
/sys/devices/scst/power/wakeup_active
/sys/devices/scst/power/wakeup_total_time_ms
/sys/devices/scst/power/wakeup_max_time_ms
/sys/devices/scst/power/wakeup_last_time_ms
/sys/devices/scst/power/runtime_status
/sys/devices/scst/power/runtime_suspended_time
/sys/devices/scst/power/runtime_active_time
/sys/devices/scst/power/autosuspend_delay_ms
/sys/devices/scst/mgmt
/sys/devices/scst/threads
/sys/devices/scst/setup_id
/sys/devices/scst/trace_level
/sys/devices/scst/version
/sys/devices/scst/sgv
/sys/devices/scst/sgv/global_stats
/sys/devices/scst/sgv/sgv-dma
/sys/devices/scst/sgv/sgv-dma/stats
/sys/devices/scst/sgv/sgv
/sys/devices/scst/sgv/sgv/stats
/sys/devices/scst/sgv/sgv-clust
/sys/devices/scst/sgv/sgv-clust/statsRe: [Scst-devel] [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 7 lines · Bart Van Assche
Quoted 3 lines · Greg KH
[ ... ]
None. Use 'struct device'
How about using 'struct device' as follows ?
* Move/sys/kernel/scst_tgt/targetsto/sys/class/target_driver.
Please never create a new class, use 'struct bus_type' instead and create a bus and have drivers and devices on it.
thanks,
greg k-h
Re: [Scst-devel] [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 5 lines · Greg KH
Quoted 3 lines · Bart Van Assche
Quoted 2 lines · Greg KH
[ ... ]
Quoted 7 lines
Quoted 4 lines
Quoted 1 line
None. Use 'struct device'
How about using 'struct device' as follows ?
* Move/sys/kernel/scst_tgt/targetsto/sys/class/target_driver.Please never create a new class, use 'struct
bus_type' instead and create a bus and have drivers and devices on it.
How about the hierarchy illustrated below, using the two new bus types scsi_tgt_dev and scsi_tgt_port ? Note: this time I neither have loaded the scst_local kernel module nor iscsi-scst in order to keep the output short.
# find /sys/bus/scsi_tgt_* /sys/devices/scst | while read f; do if [ -h $f ]; then echo "$f -> $(readlink $f)"; else echo $f; fi; done /sys/bus/scsi_tgt_dev /sys/bus/scsi_tgt_dev/uevent /sys/bus/scsi_tgt_dev/devices /sys/bus/scsi_tgt_dev/devices/2:0:0:0 -> ../../../devices/2:0:0:0 /sys/bus/scsi_tgt_dev/devices/2:0:1:0 -> ../../../devices/2:0:1:0 /sys/bus/scsi_tgt_dev/devices/3:0:0:0 -> ../../../devices/3:0:0:0 /sys/bus/scsi_tgt_dev/devices/disk01 -> ../../../devices/disk01 /sys/bus/scsi_tgt_dev/devices/disk02 -> ../../../devices/disk02 /sys/bus/scsi_tgt_dev/devices/disk03 -> ../../../devices/disk03 /sys/bus/scsi_tgt_dev/devices/disk04 -> ../../../devices/disk04 /sys/bus/scsi_tgt_dev/devices/disk05 -> ../../../devices/disk05 /sys/bus/scsi_tgt_dev/devices/disk06 -> ../../../devices/disk06 /sys/bus/scsi_tgt_dev/drivers /sys/bus/scsi_tgt_dev/drivers/dev_disk /sys/bus/scsi_tgt_dev/drivers/dev_disk/module -> ../../../../module/scst_disk /sys/bus/scsi_tgt_dev/drivers/dev_disk/uevent /sys/bus/scsi_tgt_dev/drivers/dev_disk/type /sys/bus/scsi_tgt_dev/drivers/dev_disk/trace_level /sys/bus/scsi_tgt_dev/drivers/dev_disk_perf /sys/bus/scsi_tgt_dev/drivers/dev_disk_perf/module -> ../../../../module/scst_disk /sys/bus/scsi_tgt_dev/drivers/dev_disk_perf/uevent /sys/bus/scsi_tgt_dev/drivers/dev_disk_perf/type /sys/bus/scsi_tgt_dev/drivers/dev_disk_perf/trace_level /sys/bus/scsi_tgt_dev/drivers/vdisk_fileio /sys/bus/scsi_tgt_dev/drivers/vdisk_fileio/module -> ../../../../module/scst_vdisk /sys/bus/scsi_tgt_dev/drivers/vdisk_fileio/uevent /sys/bus/scsi_tgt_dev/drivers/vdisk_fileio/type /sys/bus/scsi_tgt_dev/drivers/vdisk_fileio/add_device_parameters /sys/bus/scsi_tgt_dev/drivers/vdisk_fileio/trace_level /sys/bus/scsi_tgt_dev/drivers/vdisk_fileio/disk01 -> ../../../../devices/disk01 /sys/bus/scsi_tgt_dev/drivers/vdisk_fileio/disk02 -> ../../../../devices/disk02 /sys/bus/scsi_tgt_dev/drivers/vdisk_fileio/disk03 -> ../../../../devices/disk03 /sys/bus/scsi_tgt_dev/drivers/vdisk_fileio/disk04 -> ../../../../devices/disk04 /sys/bus/scsi_tgt_dev/drivers/vdisk_blockio /sys/bus/scsi_tgt_dev/drivers/vdisk_blockio/module -> ../../../../module/scst_vdisk /sys/bus/scsi_tgt_dev/drivers/vdisk_blockio/uevent /sys/bus/scsi_tgt_dev/drivers/vdisk_blockio/type /sys/bus/scsi_tgt_dev/drivers/vdisk_blockio/add_device_parameters /sys/bus/scsi_tgt_dev/drivers/vdisk_blockio/trace_level /sys/bus/scsi_tgt_dev/drivers/vdisk_nullio /sys/bus/scsi_tgt_dev/drivers/vdisk_nullio/module -> ../../../../module/scst_vdisk /sys/bus/scsi_tgt_dev/drivers/vdisk_nullio/uevent /sys/bus/scsi_tgt_dev/drivers/vdisk_nullio/type /sys/bus/scsi_tgt_dev/drivers/vdisk_nullio/add_device_parameters /sys/bus/scsi_tgt_dev/drivers/vdisk_nullio/trace_level /sys/bus/scsi_tgt_dev/drivers/vdisk_nullio/disk05 -> ../../../../devices/disk05 /sys/bus/scsi_tgt_dev/drivers/vdisk_nullio/disk06 -> ../../../../devices/disk06 /sys/bus/scsi_tgt_dev/drivers/vcdrom /sys/bus/scsi_tgt_dev/drivers/vcdrom/module -> ../../../../module/scst_vdisk /sys/bus/scsi_tgt_dev/drivers/vcdrom/uevent /sys/bus/scsi_tgt_dev/drivers/vcdrom/type /sys/bus/scsi_tgt_dev/drivers/vcdrom/trace_level /sys/bus/scsi_tgt_dev/drivers_probe /sys/bus/scsi_tgt_dev/drivers_autoprobe /sys/bus/scsi_tgt_port /sys/bus/scsi_tgt_port/uevent /sys/bus/scsi_tgt_port/devices /sys/bus/scsi_tgt_port/devices/ib_srpt_target_0 -> ../../../devices/ib_srpt_target_0 /sys/bus/scsi_tgt_port/devices/ib_srpt_target_1 -> ../../../devices/ib_srpt_target_1 /sys/bus/scsi_tgt_port/drivers /sys/bus/scsi_tgt_port/drivers/ib_srpt /sys/bus/scsi_tgt_port/drivers/ib_srpt/module -> ../../../../module/ib_srpt /sys/bus/scsi_tgt_port/drivers/ib_srpt/uevent /sys/bus/scsi_tgt_port/drivers/ib_srpt/add_target /sys/bus/scsi_tgt_port/drivers/ib_srpt/ib_srpt_target_0 -> ../../../../devices/ib_srpt_target_0 /sys/bus/scsi_tgt_port/drivers/ib_srpt/ib_srpt_target_1 -> ../../../../devices/ib_srpt_target_1 /sys/bus/scsi_tgt_port/drivers_probe /sys/bus/scsi_tgt_port/drivers_autoprobe /sys/devices/2:0:0:0 /sys/devices/2:0:0:0/uevent /sys/devices/2:0:0:0/subsystem -> ../../bus/scsi_tgt_dev /sys/devices/2:0:0:0/power /sys/devices/2:0:0:0/power/wakeup /sys/devices/2:0:0:0/power/wakeup_count /sys/devices/2:0:0:0/power/wakeup_active_count /sys/devices/2:0:0:0/power/wakeup_hit_count /sys/devices/2:0:0:0/power/wakeup_active /sys/devices/2:0:0:0/power/wakeup_total_time_ms /sys/devices/2:0:0:0/power/wakeup_max_time_ms /sys/devices/2:0:0:0/power/wakeup_last_time_ms /sys/devices/2:0:0:0/power/runtime_status /sys/devices/2:0:0:0/power/control /sys/devices/2:0:0:0/power/runtime_suspended_time /sys/devices/2:0:0:0/power/runtime_active_time /sys/devices/2:0:0:0/power/autosuspend_delay_ms /sys/devices/2:0:0:0/scsi_device /sys/devices/2:0:1:0 /sys/devices/2:0:1:0/uevent /sys/devices/2:0:1:0/subsystem -> ../../bus/scsi_tgt_dev /sys/devices/2:0:1:0/power /sys/devices/2:0:1:0/power/wakeup /sys/devices/2:0:1:0/power/wakeup_count /sys/devices/2:0:1:0/power/wakeup_active_count /sys/devices/2:0:1:0/power/wakeup_hit_count /sys/devices/2:0:1:0/power/wakeup_active /sys/devices/2:0:1:0/power/wakeup_total_time_ms /sys/devices/2:0:1:0/power/wakeup_max_time_ms /sys/devices/2:0:1:0/power/wakeup_last_time_ms /sys/devices/2:0:1:0/power/runtime_status /sys/devices/2:0:1:0/power/control /sys/devices/2:0:1:0/power/runtime_suspended_time /sys/devices/2:0:1:0/power/runtime_active_time /sys/devices/2:0:1:0/power/autosuspend_delay_ms /sys/devices/2:0:1:0/scsi_device /sys/devices/3:0:0:0 /sys/devices/3:0:0:0/uevent /sys/devices/3:0:0:0/subsystem -> ../../bus/scsi_tgt_dev /sys/devices/3:0:0:0/power /sys/devices/3:0:0:0/power/wakeup /sys/devices/3:0:0:0/power/wakeup_count /sys/devices/3:0:0:0/power/wakeup_active_count /sys/devices/3:0:0:0/power/wakeup_hit_count /sys/devices/3:0:0:0/power/wakeup_active /sys/devices/3:0:0:0/power/wakeup_total_time_ms /sys/devices/3:0:0:0/power/wakeup_max_time_ms /sys/devices/3:0:0:0/power/wakeup_last_time_ms /sys/devices/3:0:0:0/power/runtime_status /sys/devices/3:0:0:0/power/control /sys/devices/3:0:0:0/power/runtime_suspended_time /sys/devices/3:0:0:0/power/runtime_active_time /sys/devices/3:0:0:0/power/autosuspend_delay_ms /sys/devices/3:0:0:0/scsi_device /sys/devices/disk01 /sys/devices/disk01/uevent /sys/devices/disk01/subsystem -> ../../bus/scsi_tgt_dev /sys/devices/disk01/power /sys/devices/disk01/power/wakeup /sys/devices/disk01/power/wakeup_count /sys/devices/disk01/power/wakeup_active_count /sys/devices/disk01/power/wakeup_hit_count /sys/devices/disk01/power/wakeup_active /sys/devices/disk01/power/wakeup_total_time_ms /sys/devices/disk01/power/wakeup_max_time_ms /sys/devices/disk01/power/wakeup_last_time_ms /sys/devices/disk01/power/runtime_status /sys/devices/disk01/power/control /sys/devices/disk01/power/runtime_suspended_time /sys/devices/disk01/power/runtime_active_time /sys/devices/disk01/power/autosuspend_delay_ms /sys/devices/disk01/driver -> ../../bus/scsi_tgt_dev/drivers/vdisk_fileio /sys/devices/disk01/exported /sys/devices/disk01/exported/export0 -> ../../ib_srpt_target_0/luns/0 /sys/devices/disk01/exported/export1 -> ../../ib_srpt_target_1/luns/0 /sys/devices/disk01/type /sys/devices/disk01/threads_num /sys/devices/disk01/threads_pool_type /sys/devices/disk01/size_mb /sys/devices/disk01/blocksize /sys/devices/disk01/read_only /sys/devices/disk01/write_through /sys/devices/disk01/thin_provisioned /sys/devices/disk01/nv_cache /sys/devices/disk01/o_direct /sys/devices/disk01/removable /sys/devices/disk01/filename /sys/devices/disk01/resync_size /sys/devices/disk01/t10_dev_id /sys/devices/disk01/usn /sys/devices/disk02 /sys/devices/disk02/uevent /sys/devices/disk02/subsystem -> ../../bus/scsi_tgt_dev /sys/devices/disk02/power /sys/devices/disk02/power/wakeup /sys/devices/disk02/power/wakeup_count /sys/devices/disk02/power/wakeup_active_count /sys/devices/disk02/power/wakeup_hit_count /sys/devices/disk02/power/wakeup_active /sys/devices/disk02/power/wakeup_total_time_ms /sys/devices/disk02/power/wakeup_max_time_ms /sys/devices/disk02/power/wakeup_last_time_ms /sys/devices/disk02/power/runtime_status /sys/devices/disk02/power/control /sys/devices/disk02/power/runtime_suspended_time /sys/devices/disk02/power/runtime_active_time /sys/devices/disk02/power/autosuspend_delay_ms /sys/devices/disk02/driver -> ../../bus/scsi_tgt_dev/drivers/vdisk_fileio /sys/devices/disk02/exported /sys/devices/disk02/exported/export0 -> ../../ib_srpt_target_0/luns/1 /sys/devices/disk02/exported/export1 -> ../../ib_srpt_target_1/luns/1 /sys/devices/disk02/type /sys/devices/disk02/threads_num /sys/devices/disk02/threads_pool_type /sys/devices/disk02/size_mb /sys/devices/disk02/blocksize /sys/devices/disk02/read_only /sys/devices/disk02/write_through /sys/devices/disk02/thin_provisioned /sys/devices/disk02/nv_cache /sys/devices/disk02/o_direct /sys/devices/disk02/removable /sys/devices/disk02/filename /sys/devices/disk02/resync_size /sys/devices/disk02/t10_dev_id /sys/devices/disk02/usn /sys/devices/disk03 /sys/devices/disk03/uevent /sys/devices/disk03/subsystem -> ../../bus/scsi_tgt_dev /sys/devices/disk03/power /sys/devices/disk03/power/wakeup /sys/devices/disk03/power/wakeup_count /sys/devices/disk03/power/wakeup_active_count /sys/devices/disk03/power/wakeup_hit_count /sys/devices/disk03/power/wakeup_active /sys/devices/disk03/power/wakeup_total_time_ms /sys/devices/disk03/power/wakeup_max_time_ms /sys/devices/disk03/power/wakeup_last_time_ms /sys/devices/disk03/power/runtime_status /sys/devices/disk03/power/control /sys/devices/disk03/power/runtime_suspended_time /sys/devices/disk03/power/runtime_active_time /sys/devices/disk03/power/autosuspend_delay_ms /sys/devices/disk03/driver -> ../../bus/scsi_tgt_dev/drivers/vdisk_fileio /sys/devices/disk03/exported /sys/devices/disk03/exported/export0 -> ../../ib_srpt_target_0/luns/2 /sys/devices/disk03/exported/export1 -> ../../ib_srpt_target_1/luns/2 /sys/devices/disk03/type /sys/devices/disk03/threads_num /sys/devices/disk03/threads_pool_type /sys/devices/disk03/size_mb /sys/devices/disk03/blocksize /sys/devices/disk03/read_only /sys/devices/disk03/write_through /sys/devices/disk03/thin_provisioned /sys/devices/disk03/nv_cache /sys/devices/disk03/o_direct /sys/devices/disk03/removable /sys/devices/disk03/filename /sys/devices/disk03/resync_size /sys/devices/disk03/t10_dev_id /sys/devices/disk03/usn /sys/devices/disk04 /sys/devices/disk04/uevent /sys/devices/disk04/subsystem -> ../../bus/scsi_tgt_dev /sys/devices/disk04/power /sys/devices/disk04/power/wakeup /sys/devices/disk04/power/wakeup_count /sys/devices/disk04/power/wakeup_active_count /sys/devices/disk04/power/wakeup_hit_count /sys/devices/disk04/power/wakeup_active /sys/devices/disk04/power/wakeup_total_time_ms /sys/devices/disk04/power/wakeup_max_time_ms /sys/devices/disk04/power/wakeup_last_time_ms /sys/devices/disk04/power/runtime_status /sys/devices/disk04/power/control /sys/devices/disk04/power/runtime_suspended_time /sys/devices/disk04/power/runtime_active_time /sys/devices/disk04/power/autosuspend_delay_ms /sys/devices/disk04/driver -> ../../bus/scsi_tgt_dev/drivers/vdisk_fileio /sys/devices/disk04/exported /sys/devices/disk04/exported/export0 -> ../../ib_srpt_target_0/luns/3 /sys/devices/disk04/exported/export1 -> ../../ib_srpt_target_1/luns/3 /sys/devices/disk04/type /sys/devices/disk04/threads_num /sys/devices/disk04/threads_pool_type /sys/devices/disk04/size_mb /sys/devices/disk04/blocksize /sys/devices/disk04/read_only /sys/devices/disk04/write_through /sys/devices/disk04/thin_provisioned /sys/devices/disk04/nv_cache /sys/devices/disk04/o_direct /sys/devices/disk04/removable /sys/devices/disk04/filename /sys/devices/disk04/resync_size /sys/devices/disk04/t10_dev_id /sys/devices/disk04/usn /sys/devices/disk05 /sys/devices/disk05/uevent /sys/devices/disk05/subsystem -> ../../bus/scsi_tgt_dev /sys/devices/disk05/power /sys/devices/disk05/power/wakeup /sys/devices/disk05/power/wakeup_count /sys/devices/disk05/power/wakeup_active_count /sys/devices/disk05/power/wakeup_hit_count /sys/devices/disk05/power/wakeup_active /sys/devices/disk05/power/wakeup_total_time_ms /sys/devices/disk05/power/wakeup_max_time_ms /sys/devices/disk05/power/wakeup_last_time_ms /sys/devices/disk05/power/runtime_status /sys/devices/disk05/power/control /sys/devices/disk05/power/runtime_suspended_time /sys/devices/disk05/power/runtime_active_time /sys/devices/disk05/power/autosuspend_delay_ms /sys/devices/disk05/driver -> ../../bus/scsi_tgt_dev/drivers/vdisk_nullio /sys/devices/disk05/exported /sys/devices/disk05/exported/export0 -> ../../ib_srpt_target_0/luns/4 /sys/devices/disk05/exported/export1 -> ../../ib_srpt_target_1/luns/4 /sys/devices/disk05/type /sys/devices/disk05/threads_num /sys/devices/disk05/threads_pool_type /sys/devices/disk05/size_mb /sys/devices/disk05/blocksize /sys/devices/disk05/read_only /sys/devices/disk05/removable /sys/devices/disk05/t10_dev_id /sys/devices/disk05/usn /sys/devices/disk06 /sys/devices/disk06/uevent /sys/devices/disk06/subsystem -> ../../bus/scsi_tgt_dev /sys/devices/disk06/power /sys/devices/disk06/power/wakeup /sys/devices/disk06/power/wakeup_count /sys/devices/disk06/power/wakeup_active_count /sys/devices/disk06/power/wakeup_hit_count /sys/devices/disk06/power/wakeup_active /sys/devices/disk06/power/wakeup_total_time_ms /sys/devices/disk06/power/wakeup_max_time_ms /sys/devices/disk06/power/wakeup_last_time_ms /sys/devices/disk06/power/runtime_status /sys/devices/disk06/power/control /sys/devices/disk06/power/runtime_suspended_time /sys/devices/disk06/power/runtime_active_time /sys/devices/disk06/power/autosuspend_delay_ms /sys/devices/disk06/driver -> ../../bus/scsi_tgt_dev/drivers/vdisk_nullio /sys/devices/disk06/exported /sys/devices/disk06/exported/export0 -> ../../ib_srpt_target_0/luns/5 /sys/devices/disk06/exported/export1 -> ../../ib_srpt_target_1/luns/5 /sys/devices/disk06/type /sys/devices/disk06/threads_num /sys/devices/disk06/threads_pool_type /sys/devices/disk06/size_mb /sys/devices/disk06/blocksize /sys/devices/disk06/read_only /sys/devices/disk06/removable /sys/devices/disk06/t10_dev_id /sys/devices/disk06/usn /sys/devices/ib_srpt_target_0 /sys/devices/ib_srpt_target_0/uevent /sys/devices/ib_srpt_target_0/subsystem -> ../../bus/scsi_tgt_port /sys/devices/ib_srpt_target_0/power /sys/devices/ib_srpt_target_0/power/wakeup /sys/devices/ib_srpt_target_0/power/wakeup_count /sys/devices/ib_srpt_target_0/power/wakeup_active_count /sys/devices/ib_srpt_target_0/power/wakeup_hit_count /sys/devices/ib_srpt_target_0/power/wakeup_active /sys/devices/ib_srpt_target_0/power/wakeup_total_time_ms /sys/devices/ib_srpt_target_0/power/wakeup_max_time_ms /sys/devices/ib_srpt_target_0/power/wakeup_last_time_ms /sys/devices/ib_srpt_target_0/power/runtime_status /sys/devices/ib_srpt_target_0/power/control /sys/devices/ib_srpt_target_0/power/runtime_suspended_time /sys/devices/ib_srpt_target_0/power/runtime_active_time /sys/devices/ib_srpt_target_0/power/autosuspend_delay_ms /sys/devices/ib_srpt_target_0/driver -> ../../bus/scsi_tgt_port/drivers/ib_srpt /sys/devices/ib_srpt_target_0/enabled /sys/devices/ib_srpt_target_0/sessions /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/commands /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/active_commands /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/initiator_name /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/req_lim /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/req_lim_delta /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/luns -> ../../luns /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun0 /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun0/active_commands /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun1 /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun1/active_commands /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun2 /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun2/active_commands /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun3 /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun3/active_commands /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun4 /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun4/active_commands /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun5 /sys/devices/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun5/active_commands /sys/devices/ib_srpt_target_0/luns /sys/devices/ib_srpt_target_0/luns/parameters /sys/devices/ib_srpt_target_0/luns/0 /sys/devices/ib_srpt_target_0/luns/0/read_only /sys/devices/ib_srpt_target_0/luns/0/device -> ../../../disk01 /sys/devices/ib_srpt_target_0/luns/1 /sys/devices/ib_srpt_target_0/luns/1/read_only /sys/devices/ib_srpt_target_0/luns/1/device -> ../../../disk02 /sys/devices/ib_srpt_target_0/luns/2 /sys/devices/ib_srpt_target_0/luns/2/read_only /sys/devices/ib_srpt_target_0/luns/2/device -> ../../../disk03 /sys/devices/ib_srpt_target_0/luns/3 /sys/devices/ib_srpt_target_0/luns/3/read_only /sys/devices/ib_srpt_target_0/luns/3/device -> ../../../disk04 /sys/devices/ib_srpt_target_0/luns/4 /sys/devices/ib_srpt_target_0/luns/4/read_only /sys/devices/ib_srpt_target_0/luns/4/device -> ../../../disk05 /sys/devices/ib_srpt_target_0/luns/5 /sys/devices/ib_srpt_target_0/luns/5/read_only /sys/devices/ib_srpt_target_0/luns/5/device -> ../../../disk06 /sys/devices/ib_srpt_target_0/ini_groups /sys/devices/ib_srpt_target_0/rel_tgt_id /sys/devices/ib_srpt_target_0/addr_method /sys/devices/ib_srpt_target_0/io_grouping_type /sys/devices/ib_srpt_target_0/cpu_mask /sys/devices/ib_srpt_target_0/login_info /sys/devices/ib_srpt_target_1 /sys/devices/ib_srpt_target_1/uevent /sys/devices/ib_srpt_target_1/subsystem -> ../../bus/scsi_tgt_port /sys/devices/ib_srpt_target_1/power /sys/devices/ib_srpt_target_1/power/wakeup /sys/devices/ib_srpt_target_1/power/wakeup_count /sys/devices/ib_srpt_target_1/power/wakeup_active_count /sys/devices/ib_srpt_target_1/power/wakeup_hit_count /sys/devices/ib_srpt_target_1/power/wakeup_active /sys/devices/ib_srpt_target_1/power/wakeup_total_time_ms /sys/devices/ib_srpt_target_1/power/wakeup_max_time_ms /sys/devices/ib_srpt_target_1/power/wakeup_last_time_ms /sys/devices/ib_srpt_target_1/power/runtime_status /sys/devices/ib_srpt_target_1/power/control /sys/devices/ib_srpt_target_1/power/runtime_suspended_time /sys/devices/ib_srpt_target_1/power/runtime_active_time /sys/devices/ib_srpt_target_1/power/autosuspend_delay_ms /sys/devices/ib_srpt_target_1/driver -> ../../bus/scsi_tgt_port/drivers/ib_srpt /sys/devices/ib_srpt_target_1/enabled /sys/devices/ib_srpt_target_1/sessions /sys/devices/ib_srpt_target_1/luns /sys/devices/ib_srpt_target_1/luns/parameters /sys/devices/ib_srpt_target_1/luns/0 /sys/devices/ib_srpt_target_1/luns/0/read_only /sys/devices/ib_srpt_target_1/luns/0/device -> ../../../disk01 /sys/devices/ib_srpt_target_1/luns/1 /sys/devices/ib_srpt_target_1/luns/1/read_only /sys/devices/ib_srpt_target_1/luns/1/device -> ../../../disk02 /sys/devices/ib_srpt_target_1/luns/2 /sys/devices/ib_srpt_target_1/luns/2/read_only /sys/devices/ib_srpt_target_1/luns/2/device -> ../../../disk03 /sys/devices/ib_srpt_target_1/luns/3 /sys/devices/ib_srpt_target_1/luns/3/read_only /sys/devices/ib_srpt_target_1/luns/3/device -> ../../../disk04 /sys/devices/ib_srpt_target_1/luns/4 /sys/devices/ib_srpt_target_1/luns/4/read_only /sys/devices/ib_srpt_target_1/luns/4/device -> ../../../disk05 /sys/devices/ib_srpt_target_1/luns/5 /sys/devices/ib_srpt_target_1/luns/5/read_only /sys/devices/ib_srpt_target_1/luns/5/device -> ../../../disk06 /sys/devices/ib_srpt_target_1/ini_groups /sys/devices/ib_srpt_target_1/rel_tgt_id /sys/devices/ib_srpt_target_1/addr_method /sys/devices/ib_srpt_target_1/io_grouping_type /sys/devices/ib_srpt_target_1/cpu_mask /sys/devices/ib_srpt_target_1/login_info /sys/devices/scst /sys/devices/scst/uevent /sys/devices/scst/power /sys/devices/scst/power/wakeup /sys/devices/scst/power/wakeup_count /sys/devices/scst/power/wakeup_active_count /sys/devices/scst/power/wakeup_hit_count /sys/devices/scst/power/wakeup_active /sys/devices/scst/power/wakeup_total_time_ms /sys/devices/scst/power/wakeup_max_time_ms /sys/devices/scst/power/wakeup_last_time_ms /sys/devices/scst/power/runtime_status /sys/devices/scst/power/control /sys/devices/scst/power/runtime_suspended_time /sys/devices/scst/power/runtime_active_time /sys/devices/scst/power/autosuspend_delay_ms /sys/devices/scst/mgmt /sys/devices/scst/threads /sys/devices/scst/setup_id /sys/devices/scst/trace_level /sys/devices/scst/version /sys/devices/scst/sgv /sys/devices/scst/sgv/global_stats /sys/devices/scst/sgv/sgv /sys/devices/scst/sgv/sgv/stats /sys/devices/scst/sgv/sgv-clust /sys/devices/scst/sgv/sgv-clust/stats /sys/devices/scst/sgv/sgv-dma /sys/devices/scst/sgv/sgv-dma/stats
Bart.
Re: [Scst-devel] [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Greg KHQuoted 8 lines · Greg KH
Quoted 3 lines · Vladislav Bolkhovitin
Since nobody objected, Greg, could you consider to ACK SCST SYSFS management interface in
/sys/kernel/scst_tgt/, please? Please find the SCST SYSFS ABI documentation file you requested below.No, sorry, again, you should not be using kobjects, and do not pollute the main
/sys/kernel/namespace with this.
Quoted 8 lines
Use 'struct device' please, that is what it is there for, and is what the rest of the kernel is using. And use the rest of the driver/bus/device infrastructure as your model will work with it just fine.
Yes, I know you said you didn't think you could use it, and that your code was different than everyone elses, but I still do not believe it, sorry.
Hello Greg,
As you can see in recent messages (e.g.
http://lkml.org/lkml/2010/11/18/578 or
http://lkml.org/lkml/2010/11/15/296), the abstractions represented in SCST are:
* Target templates (scst_tgt_template), e.g. scst_local or ib_srpt. These are drivers that implement a storage protocol.
* Target ports (scst_tgt), e.g. ib_srpt_target_0, which represent a communication interface controlled by a storage protocol driver.
* Sessions (scst_session), e.g. 0x00000000000000000002c9030005f34b. A session corresponds to a single initiator-target nexus.
* Device handlers (scst_dev_type), e.g. scst_disk or scst_vdisk, which are drivers that allow SCST to export storage.
* Target devices (scst_device), e.g. disk01, which represent exported storage. Each instance is controlled by a single device handler. This concept includes e.g. block devices and files. Some but not all target devices have a corresponding device node in /dev.
* Access control groups (scst_acg), which allow e.g. to implement LUN masking.
* Device-specific information such as the SCSI LUN (scst_acg_dev).
As we all know the driver, bus and device abstractions were invented to model how peripheral devices are connected to a system. What a storage target does is the converse - define devices and make it possible for other systems to use these devices. As a result, unfortunately, the driver, bus and device abstractions do not map one-to-one on all of the concepts used in a storage target. So I'm still not sure whether it is a good idea to use the driver, bus and or/device concepts for all of the above concepts.
Also, using the driver, bus or device concept for one or more of the storage target concepts would open up a potential for naming conflicts. There is already e.g. the well-known null device. SCST e.g. defines a vdisk_nullio target template. Having these all as device nodes under /dev might not only confuse users but also creates a huge potential for naming conflicts. That's why we prefer separate namespaces instead of reusing one of the existing concepts.
In case you are still convinced that we should use the existing driver, bus and device abstractions, which concept should we map to which abstraction ?
Bart.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Boaz HarroshQuoted 24 lines · Boaz Harrosh, on 11/15/2010 08:19 PM wrote:
Quoted 12 lines · Greg KH
Quoted 4 lines · Boaz Harrosh
All these issues we were discussing are interesting and are real Kernel problems. For instance the last comment you made was that for such a dynamic system and life time problems, and functionality. A better and expected solution might be the device tree and not sysfs.
Yes, that is what I have been saying for a while now.
Again:
This code is using kobjects incorrectly.
This code should not be using kobjects.Quoted 6 lines
this is my last response to this thread now, and I'm sure you can understand why.
thanks,
greg k-h
Thank you Greg for your time and most valuable input. I'm sorry for not understanding your position. I needed the clear cut statement:
Quoted 5 lines
This code should not be using kobjects. i.e not belong in sysfs
SCST guys. This sounds pretty clear cut to me. Sysfs was not built in mind for such dynamic systems, and it will cause never ending conflicts with future maintenance of sysfs vs SCST.
As I explained in the previous e-mail, I believe, SYSFS perfectly suits SCST and SCST perfectly suits SYSFS.
If you think it isn't so, let's discuss each showstopper for that, one after one.
Quoted 1 line
Lets call it Linux-Target and unify all our efforts.
Looks like a great idea!
Thanks,
Vlad
Re: [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Greg KHQuoted 5 lines · Greg KH, on 11/15/2010 07:16 PM wrote:
Why, I'm not allowed to get frustrated at repeated attempts to get the original poster to change their code to something that is acceptable and just give up and walk away?
Why not?
Hmm, frankly, I decided that you agreed with my arguments..
As I wrote, I'm willing to make any changes you requests. I only asked why this should be done.
I really don't understand why we and other similar in-kernel developers should treat kobjects in the different way than any other subobjects of our outer objects and make for them _additional code_ to specially treat them as life-time center (http://lkml.org/lkml/2010/11/10/421)? You have not explained it anywhere in any doc I can find.
This is just small "why" question. Greg, don't we have a right to ask this before go on?
Quoted 11 lines
Quoted 7 lines
This project, even though out-of-tree, is an old and mature project that has many users. These are all *Linux* users. The authors and community have come to us for help, and advice on making this code acceptable for mainline and hardening the code the way, only one project on the planet can do, the Linux community. I think it is our courtesy and obligation to the Linux users of this Project to comment where they are doing wrong and where they should do better.
It is also the job of the kernel community to say "No, what you are doing is wrong, please don't do that."
Quoted 6 lines
And that's what I'm doing here.
Quoted 2 lines
It is not of their choice to be out-of-tree. It is ours. The least we can do. Is give then some assistance if we can, and have 5 minutes of our time.
I have given _way_ more than 5 minutes of my time already.
We appreciated it very much.
Quoted 5 lines
Quoted 4 lines
All these issues we were discussing are interesting and are real Kernel problems. For instance the last comment you made was that for such a dynamic system and life time problems, and functionality. A better and expected solution might be the device tree and not sysfs.
Quoted 8 lines
Yes, that is what I have been saying for a while now.
Again:
This code is using kobjects incorrectly.
This code should not be using kobjects.this is my last response to this thread now, and I'm sure you can understand why.
It is REALLY frustrating you are refusing to explain why. I guess, I'm too stupid to figure out that alone. Don't you want we rise as highly skilled kernel developers? I believe, not only SCST developers are very interested to know background behind particular moves in the kernel.
Thanks,
Vlad
Re: [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Greg KHQuoted 9 lines · Greg KH
Quoted 6 lines · Vladislav Bolkhovitin
So, I decided to reimplement it to be completely synchronous. SYSFS authors did really great job and thanks to the excellent internal SYSFS design and implementation it is absolutely safe. See:
[root@tgt ~]# modprobe scst
[root@tgt ~]# cd/sys/kernel/scst_tgt/
Quoted 6 lines
Sorry, but no, you can't put this in
/sys/kernel/without getting the approval of the sysfs maintainer.I really don't understand why you are using kobjects in the first place, why isn't this in the main device tree in the kernel, using 'struct device'?
We might have missed something, but as far as we know it has not yet been explained in this thread why using 'struct device' would be an advantage over using 'struct kobject'. All I can see are the disadvantages of such a transition: instead of having a single hierarchy that represents all SCST-related information, there would be multiple, and the hierarchical relationship between objects would be lost. Also, during startup, once all SCST-related kernel modules have been loaded, configuration happens by writing values to individual sysfs variables. There is a user-space tool included with SCST that not only can restore a configuration from a file but also can save an existing configuration to file. I'm afraid that saving an existing configuration would be made considerably more difficult by transforming the single SCST sysfs-tree into multiple. Below you can find an example of a sysfs-tree created by SCST:
# (cd /sys/kernel/scst_tgt && find | cut -c3-)
threadssetup_idtrace_level
versionlast_sysfs_mgmt_res
targets
targets/ib_srpt
targets/ib_srpt/ib_srpt_target_0
targets/ib_srpt/ib_srpt_target_0/enabled
targets/ib_srpt/ib_srpt_target_0/sessions targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/commands targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/active_commands targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/initiator_name targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/req_lim targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/req_lim_delta targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/luns targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun0 targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun0/active_commands targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun1 targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun1/active_commands targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun2 targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun2/active_commands targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun255 targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun255/active_commands targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun3 targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun3/active_commands targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun4 targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun4/active_commands targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun5 targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun5/active_commands targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun6 targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun6/active_commands targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun7 targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun7/active_commands targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun8 targets/ib_srpt/ib_srpt_target_0/sessions/0x00000000000000000002c9030005f34b/lun8/active_commands targets/ib_srpt/ib_srpt_target_0/luns
targets/ib_srpt/ib_srpt_target_0/luns/mgmt
targets/ib_srpt/ib_srpt_target_0/luns/0 targets/ib_srpt/ib_srpt_target_0/luns/0/read_only targets/ib_srpt/ib_srpt_target_0/luns/0/device targets/ib_srpt/ib_srpt_target_0/luns/1 targets/ib_srpt/ib_srpt_target_0/luns/1/read_only targets/ib_srpt/ib_srpt_target_0/luns/1/device targets/ib_srpt/ib_srpt_target_0/luns/2 targets/ib_srpt/ib_srpt_target_0/luns/2/read_only targets/ib_srpt/ib_srpt_target_0/luns/2/device targets/ib_srpt/ib_srpt_target_0/luns/255 targets/ib_srpt/ib_srpt_target_0/luns/255/read_only targets/ib_srpt/ib_srpt_target_0/luns/255/device targets/ib_srpt/ib_srpt_target_0/luns/3 targets/ib_srpt/ib_srpt_target_0/luns/3/read_only targets/ib_srpt/ib_srpt_target_0/luns/3/device targets/ib_srpt/ib_srpt_target_0/luns/4 targets/ib_srpt/ib_srpt_target_0/luns/4/read_only targets/ib_srpt/ib_srpt_target_0/luns/4/device targets/ib_srpt/ib_srpt_target_0/luns/5 targets/ib_srpt/ib_srpt_target_0/luns/5/read_only targets/ib_srpt/ib_srpt_target_0/luns/5/device targets/ib_srpt/ib_srpt_target_0/luns/6 targets/ib_srpt/ib_srpt_target_0/luns/6/read_only targets/ib_srpt/ib_srpt_target_0/luns/6/device targets/ib_srpt/ib_srpt_target_0/luns/7 targets/ib_srpt/ib_srpt_target_0/luns/7/read_only targets/ib_srpt/ib_srpt_target_0/luns/7/device targets/ib_srpt/ib_srpt_target_0/luns/8 targets/ib_srpt/ib_srpt_target_0/luns/8/read_only targets/ib_srpt/ib_srpt_target_0/luns/8/device targets/ib_srpt/ib_srpt_target_0/ini_groups targets/ib_srpt/ib_srpt_target_0/ini_groups/mgmt targets/ib_srpt/ib_srpt_target_0/rel_tgt_id targets/ib_srpt/ib_srpt_target_0/addr_method targets/ib_srpt/ib_srpt_target_0/io_grouping_type targets/ib_srpt/ib_srpt_target_0/cpu_mask
targets/ib_srpt/ib_srpt_target_1
targets/ib_srpt/ib_srpt_target_1/enabled
targets/ib_srpt/ib_srpt_target_1/sessions
targets/ib_srpt/ib_srpt_target_1/luns
targets/ib_srpt/ib_srpt_target_1/luns/mgmt
targets/ib_srpt/ib_srpt_target_1/luns/0 targets/ib_srpt/ib_srpt_target_1/luns/0/read_only targets/ib_srpt/ib_srpt_target_1/luns/0/device targets/ib_srpt/ib_srpt_target_1/luns/1 targets/ib_srpt/ib_srpt_target_1/luns/1/read_only targets/ib_srpt/ib_srpt_target_1/luns/1/device targets/ib_srpt/ib_srpt_target_1/luns/2 targets/ib_srpt/ib_srpt_target_1/luns/2/read_only targets/ib_srpt/ib_srpt_target_1/luns/2/device targets/ib_srpt/ib_srpt_target_1/luns/255 targets/ib_srpt/ib_srpt_target_1/luns/255/read_only targets/ib_srpt/ib_srpt_target_1/luns/255/device targets/ib_srpt/ib_srpt_target_1/luns/3 targets/ib_srpt/ib_srpt_target_1/luns/3/read_only targets/ib_srpt/ib_srpt_target_1/luns/3/device targets/ib_srpt/ib_srpt_target_1/luns/4 targets/ib_srpt/ib_srpt_target_1/luns/4/read_only targets/ib_srpt/ib_srpt_target_1/luns/4/device targets/ib_srpt/ib_srpt_target_1/luns/5 targets/ib_srpt/ib_srpt_target_1/luns/5/read_only targets/ib_srpt/ib_srpt_target_1/luns/5/device targets/ib_srpt/ib_srpt_target_1/luns/6 targets/ib_srpt/ib_srpt_target_1/luns/6/read_only targets/ib_srpt/ib_srpt_target_1/luns/6/device targets/ib_srpt/ib_srpt_target_1/luns/7 targets/ib_srpt/ib_srpt_target_1/luns/7/read_only targets/ib_srpt/ib_srpt_target_1/luns/7/device targets/ib_srpt/ib_srpt_target_1/luns/8 targets/ib_srpt/ib_srpt_target_1/luns/8/read_only targets/ib_srpt/ib_srpt_target_1/luns/8/device targets/ib_srpt/ib_srpt_target_1/ini_groups targets/ib_srpt/ib_srpt_target_1/ini_groups/mgmt targets/ib_srpt/ib_srpt_target_1/rel_tgt_id targets/ib_srpt/ib_srpt_target_1/addr_method targets/ib_srpt/ib_srpt_target_1/io_grouping_type targets/ib_srpt/ib_srpt_target_1/cpu_mask
targets/iscsi
targets/iscsi/mgmt
targets/iscsi/version
targets/iscsi/open_state
targets/iscsi/trace_level
targets/iscsi/iSNSServer
targets/iscsi/enabled
targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/enabled targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/sessions targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/0 targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/0/read_only targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/0/device targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/luns/mgmt targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/ini_groups targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/ini_groups/mgmt targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/rel_tgt_id targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/addr_method targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/io_grouping_type targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/cpu_mask targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/tid targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/per_portal_acl targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/redirect targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/InitialR2T targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/ImmediateData targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/MaxRecvDataSegmentLength targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/MaxXmitDataSegmentLength targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/MaxBurstLength targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/FirstBurstLength targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/MaxOutstandingR2T targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/HeaderDigest targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/DataDigest targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/QueuedCommands targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/RspTimeout targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/NopInInterval targets/iscsi/iqn.2005-03.org.open-iscsi:dbc01e1792b:storage/MaxSessions targets/scst_local
targets/scst_local/mgmt
targets/scst_local/version
targets/scst_local/stats
targets/scst_local/trace_level
targets/scst_local/scst_local_tgt
targets/scst_local/scst_local_tgt/sessions targets/scst_local/scst_local_tgt/sessions/scst_local_host targets/scst_local/scst_local_tgt/sessions/scst_local_host/commands targets/scst_local/scst_local_tgt/sessions/scst_local_host/active_commands targets/scst_local/scst_local_tgt/sessions/scst_local_host/initiator_name targets/scst_local/scst_local_tgt/sessions/scst_local_host/transport_id targets/scst_local/scst_local_tgt/sessions/scst_local_host/luns targets/scst_local/scst_local_tgt/sessions/scst_local_host/host targets/scst_local/scst_local_tgt/luns
targets/scst_local/scst_local_tgt/luns/mgmt targets/scst_local/scst_local_tgt/ini_groups targets/scst_local/scst_local_tgt/ini_groups/mgmt targets/scst_local/scst_local_tgt/rel_tgt_id targets/scst_local/scst_local_tgt/addr_method targets/scst_local/scst_local_tgt/io_grouping_type targets/scst_local/scst_local_tgt/cpu_mask targets/scst_local/scst_local_tgt/scsi_transport_version targets/scst_local/scst_local_tgt/phys_transport_version
devices
devices/2:0:0:0
devices/2:0:0:0/type
devices/2:0:0:0/exported
devices/2:0:0:0/scsi_device
devices/2:0:1:0
devices/2:0:1:0/type
devices/2:0:1:0/exported
devices/2:0:1:0/scsi_device
devices/3:0:0:0
devices/3:0:0:0/type
devices/3:0:0:0/exported
devices/3:0:0:0/scsi_device
devices/disk01
devices/disk01/type
devices/disk01/exported
devices/disk01/exported/export0
devices/disk01/exported/export1
devices/disk01/exported/export2
devices/disk01/dump_prs
devices/disk01/handler
devices/disk01/threads_num
devices/disk01/threads_pool_type
devices/disk01/size_mb
devices/disk01/blocksize
devices/disk01/read_only
devices/disk01/write_through
devices/disk01/thin_provisioned
devices/disk01/nv_cache
devices/disk01/o_direct
devices/disk01/removable
devices/disk01/filename
devices/disk01/resync_size
devices/disk01/t10_dev_id
devices/disk01/usn
devices/disk02
devices/disk02/type
devices/disk02/exported
devices/disk02/exported/export0
devices/disk02/exported/export1
devices/disk02/dump_prs
devices/disk02/handler
devices/disk02/threads_num
devices/disk02/threads_pool_type
devices/disk02/size_mb
devices/disk02/blocksize
devices/disk02/read_only
devices/disk02/write_through
devices/disk02/thin_provisioned
devices/disk02/nv_cache
devices/disk02/o_direct
devices/disk02/removable
devices/disk02/filename
devices/disk02/resync_size
devices/disk02/t10_dev_id
devices/disk02/usn
devices/disk03
devices/disk03/type
devices/disk03/exported
devices/disk03/exported/export0
devices/disk03/exported/export1
devices/disk03/dump_prs
devices/disk03/handler
devices/disk03/threads_num
devices/disk03/threads_pool_type
devices/disk03/size_mb
devices/disk03/blocksize
devices/disk03/read_only
devices/disk03/write_through
devices/disk03/thin_provisioned
devices/disk03/nv_cache
devices/disk03/o_direct
devices/disk03/removable
devices/disk03/filename
devices/disk03/resync_size
devices/disk03/t10_dev_id
devices/disk03/usn
devices/disk04
devices/disk04/type
devices/disk04/exported
devices/disk04/exported/export0
devices/disk04/exported/export1
devices/disk04/dump_prs
devices/disk04/handler
devices/disk04/threads_num
devices/disk04/threads_pool_type
devices/disk04/size_mb
devices/disk04/blocksize
devices/disk04/read_only
devices/disk04/write_through
devices/disk04/thin_provisioned
devices/disk04/nv_cache
devices/disk04/o_direct
devices/disk04/removable
devices/disk04/filename
devices/disk04/resync_size
devices/disk04/t10_dev_id
devices/disk04/usn
devices/disk05
devices/disk05/type
devices/disk05/exported
devices/disk05/exported/export0
devices/disk05/exported/export1
devices/disk05/dump_prs
devices/disk05/handler
devices/disk05/threads_num
devices/disk05/threads_pool_type
devices/disk05/size_mb
devices/disk05/blocksize
devices/disk05/read_only
devices/disk05/write_through
devices/disk05/thin_provisioned
devices/disk05/nv_cache
devices/disk05/o_direct
devices/disk05/removable
devices/disk05/filename
devices/disk05/resync_size
devices/disk05/t10_dev_id
devices/disk05/usn
devices/disk06
devices/disk06/type
devices/disk06/exported
devices/disk06/exported/export0
devices/disk06/exported/export1
devices/disk06/dump_prs
devices/disk06/handler
devices/disk06/threads_num
devices/disk06/threads_pool_type
devices/disk06/size_mb
devices/disk06/blocksize
devices/disk06/read_only
devices/disk06/write_through
devices/disk06/thin_provisioned
devices/disk06/nv_cache
devices/disk06/o_direct
devices/disk06/removable
devices/disk06/filename
devices/disk06/resync_size
devices/disk06/t10_dev_id
devices/disk06/usn
devices/disk07
devices/disk07/type
devices/disk07/exported
devices/disk07/exported/export0
devices/disk07/exported/export1
devices/disk07/dump_prs
devices/disk07/handler
devices/disk07/threads_num
devices/disk07/threads_pool_type
devices/disk07/size_mb
devices/disk07/blocksize
devices/disk07/read_only
devices/disk07/write_through
devices/disk07/thin_provisioned
devices/disk07/nv_cache
devices/disk07/o_direct
devices/disk07/removable
devices/disk07/filename
devices/disk07/resync_size
devices/disk07/t10_dev_id
devices/disk07/usn
devices/disk08
devices/disk08/type
devices/disk08/exported
devices/disk08/exported/export0
devices/disk08/exported/export1
devices/disk08/dump_prs
devices/disk08/handler
devices/disk08/threads_num
devices/disk08/threads_pool_type
devices/disk08/size_mb
devices/disk08/blocksize
devices/disk08/read_only
devices/disk08/write_through
devices/disk08/thin_provisioned
devices/disk08/nv_cache
devices/disk08/o_direct
devices/disk08/removable
devices/disk08/filename
devices/disk08/resync_size
devices/disk08/t10_dev_id
devices/disk08/usn
devices/disk09
devices/disk09/type
devices/disk09/exported
devices/disk09/exported/export0
devices/disk09/exported/export1
devices/disk09/dump_prs
devices/disk09/handler
devices/disk09/threads_num
devices/disk09/threads_pool_type
devices/disk09/size_mb
devices/disk09/blocksize
devices/disk09/read_only
devices/disk09/removable
devices/disk09/t10_dev_id
devices/disk09/usn
devices/disk10
devices/disk10/type
devices/disk10/exported
devices/disk10/exported/export0
devices/disk10/exported/export1
devices/disk10/dump_prs
devices/disk10/handler
devices/disk10/threads_num
devices/disk10/threads_pool_type
devices/disk10/size_mb
devices/disk10/blocksize
devices/disk10/read_only
devices/disk10/removable
devices/disk10/t10_dev_id
devices/disk10/usn
sgv
sgv/global_stats
sgv/sgv
sgv/sgv/stats
sgv/sgv-clust
sgv/sgv-clust/stats
sgv/sgv-dma
sgv/sgv-dma/stats
handlers
handlers/vdisk_fileio
handlers/vdisk_fileio/type
handlers/vdisk_fileio/mgmt
handlers/vdisk_fileio/trace_level
handlers/vdisk_fileio/disk01
handlers/vdisk_fileio/disk02
handlers/vdisk_fileio/disk03
handlers/vdisk_fileio/disk04
handlers/vdisk_fileio/disk05
handlers/vdisk_fileio/disk06
handlers/vdisk_fileio/disk07
handlers/vdisk_fileio/disk08
handlers/vdisk_blockio
handlers/vdisk_blockio/type
handlers/vdisk_blockio/mgmt
handlers/vdisk_blockio/trace_level
handlers/vdisk_nullio
handlers/vdisk_nullio/type
handlers/vdisk_nullio/mgmt
handlers/vdisk_nullio/trace_level
handlers/vdisk_nullio/disk09
handlers/vdisk_nullio/disk10
handlers/vcdrom
handlers/vcdrom/type
handlers/vcdrom/mgmt
handlers/vcdrom/trace_level
Bart.
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 13 lines · Bart Van Assche
Quoted 12 lines · Greg KH
Quoted 6 lines · Vladislav Bolkhovitin
So, I decided to reimplement it to be completely synchronous. SYSFS authors did really great job and thanks to the excellent internal SYSFS design and implementation it is absolutely safe. See:
[root@tgt ~]# modprobe scst
[root@tgt ~]# cd/sys/kernel/scst_tgt/Sorry, but no, you can't put this in
/sys/kernel/without getting the approval of the sysfs maintainer.
Quoted 7 lines
Quoted 3 lines
I really don't understand why you are using kobjects in the first place, why isn't this in the main device tree in the kernel, using 'struct device'?
We might have missed something, but as far as we know it has not yet been explained in this thread why using 'struct device' would be an advantage over using 'struct kobject'.
It's very simple.
You want your device to show up in the global device tree in the kernel, not off to one side, unconnected to anything else.
Please use 'struct device', it is what you want to do here.
good luck,
greg k-h
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 22 lines · Greg KH, on 11/15/2010 09:44 PM wrote:
Quoted 13 lines · Bart Van Assche
Quoted 12 lines · Greg KH
Quoted 6 lines · Vladislav Bolkhovitin
So, I decided to reimplement it to be completely synchronous. SYSFS authors did really great job and thanks to the excellent internal SYSFS design and implementation it is absolutely safe. See:
[root@tgt ~]# modprobe scst
[root@tgt ~]# cd/sys/kernel/scst_tgt/Sorry, but no, you can't put this in
/sys/kernel/without getting the approval of the sysfs maintainer.Quoted 7 lines
Quoted 3 lines
I really don't understand why you are using kobjects in the first place, why isn't this in the main device tree in the kernel, using 'struct device'?
We might have missed something, but as far as we know it has not yet been explained in this thread why using 'struct device' would be an advantage over using 'struct kobject'.
Quoted 6 lines
It's very simple.
You want your device to show up in the global device tree in the kernel, not off to one side, unconnected to anything else.
Please use 'struct device', it is what you want to do here.
But we don't have any device to show up in the global device tree! We don't have any devices in the struct device's understanding at all!
Vlad
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 23 lines · Vladislav Bolkhovitin
Quoted 22 lines · Greg KH, on 11/15/2010 09:44 PM wrote:
Quoted 20 lines · Bart Van Assche
Quoted 9 lines · Greg KH
Quoted 6 lines · Vladislav Bolkhovitin
So, I decided to reimplement it to be completely synchronous. SYSFS authors did really great job and thanks to the excellent internal SYSFS design and implementation it is absolutely safe. See:
[root@tgt ~]# modprobe scst
[root@tgt ~]# cd/sys/kernel/scst_tgt/Quoted 6 lines
Sorry, but no, you can't put this in
/sys/kernel/without getting the approval of the sysfs maintainer.I really don't understand why you are using kobjects in the first place, why isn't this in the main device tree in the kernel, using 'struct device'?
We might have missed something, but as far as we know it has not yet been explained in this thread why using 'struct device' would be an advantage over using 'struct kobject'.
Quoted 8 lines
Quoted 6 lines
It's very simple.
You want your device to show up in the global device tree in the kernel, not off to one side, unconnected to anything else.
Please use 'struct device', it is what you want to do here.
But we don't have any device to show up in the global device tree!
Not true at all.
Quoted 1 line
We don't have any devices in the struct device's understanding at all!
Then create them just like you are doing so for your kobject use.
The first device would be the root one, and then everything trickles down from there.
And use configfs for your configuration stuff, that's what it is there for, and if it doesn't somehow work properly for you, please work with the configfs developers to fix that up.
thanks,
greg k-h
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 42 lines · Greg KH
Quoted 23 lines · Vladislav Bolkhovitin
Quoted 22 lines · Greg KH, on 11/15/2010 09:44 PM wrote:
Quoted 20 lines · Bart Van Assche
Quoted 9 lines · Greg KH
Quoted 6 lines · Vladislav Bolkhovitin
So, I decided to reimplement it to be completely synchronous. SYSFS authors did really great job and thanks to the excellent internal SYSFS design and implementation it is absolutely safe. See:
[root@tgt ~]# modprobe scst
[root@tgt ~]# cd/sys/kernel/scst_tgt/Quoted 6 lines
Sorry, but no, you can't put this in
/sys/kernel/without getting the approval of the sysfs maintainer.I really don't understand why you are using kobjects in the first place, why isn't this in the main device tree in the kernel, using 'struct device'?
We might have missed something, but as far as we know it has not yet been explained in this thread why using 'struct device' would be an advantage over using 'struct kobject'.
Quoted 8 lines
Quoted 6 lines
It's very simple.
You want your device to show up in the global device tree in the kernel, not off to one side, unconnected to anything else.
Please use 'struct device', it is what you want to do here.
But we don't have any device to show up in the global device tree!
Not true at all.
Quoted 1 line
We don't have any devices in the struct device's understanding at all!
Then create them just like you are doing so for your kobject use.
The first device would be the root one, and then everything trickles down from there.
Quoted 7 lines
And use configfs for your configuration stuff, that's what it is there for, and if it doesn't somehow work properly for you, please work with the configfs developers to fix that up.
thanks,
greg k-h
I don't have any opinion on the above, but I don't see why sysfs can't be used for configuration as well as its other roles. It seems to me wasteful to require configfs to be used in order to change configuration when sysfs works fine for this.
Here are a couple of existing examples where sysfs is used in a role that would seem similar to SCST's usage:
1) scsi_transport_fc already has an sysfs file, fc_host/vport_create, which can be written to create new fc_host and scsi_host instances.
2) fcoe.ko uses a write to the sysfs file /sys/module/fcoe/parameters/create to start the protocol on a particular ethernet interface. There's another file for destroy.
I'll bet there are other examples in other subsystems, and I don't think there is anything wrong with the above usages of sysfs.
I agree with Vladislav's point that configfs doesn't work instead of sysfs because configs doesn't make it easy for the kernel side to create nodes for dynamic information like connected initiators and statistics. So, if the above examples are considered a misuse of sysfs,
SCST would need to use both sysfs and configfs. It would use configfs to do configuration, and sysfs to display and access the dynamic information like connected initiators. That seems a minor role for configfs, which is easily handled in sysfs as SCST currently does.
Just my two cents.
Joe
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 44 lines · Joe Eykholt
Quoted 42 lines · Greg KH
Quoted 23 lines · Vladislav Bolkhovitin
Quoted 22 lines · Greg KH, on 11/15/2010 09:44 PM wrote:
Quoted 20 lines · Bart Van Assche
Quoted 9 lines · Greg KH
Quoted 6 lines · Vladislav Bolkhovitin
So, I decided to reimplement it to be completely synchronous. SYSFS authors did really great job and thanks to the excellent internal SYSFS design and implementation it is absolutely safe. See:
[root@tgt ~]# modprobe scst
[root@tgt ~]# cd/sys/kernel/scst_tgt/Quoted 6 lines
Sorry, but no, you can't put this in
/sys/kernel/without getting the approval of the sysfs maintainer.I really don't understand why you are using kobjects in the first place, why isn't this in the main device tree in the kernel, using 'struct device'?
We might have missed something, but as far as we know it has not yet been explained in this thread why using 'struct device' would be an advantage over using 'struct kobject'.
Quoted 8 lines
Quoted 6 lines
It's very simple.
You want your device to show up in the global device tree in the kernel, not off to one side, unconnected to anything else.
Please use 'struct device', it is what you want to do here.
But we don't have any device to show up in the global device tree!
Not true at all.
Quoted 1 line
We don't have any devices in the struct device's understanding at all!
Then create them just like you are doing so for your kobject use.
The first device would be the root one, and then everything trickles down from there.
Quoted 8 lines
Quoted 7 lines
And use configfs for your configuration stuff, that's what it is there for, and if it doesn't somehow work properly for you, please work with the configfs developers to fix that up.
thanks,
greg k-h
Greetings Joe,
Quoted 15 lines
I don't have any opinion on the above, but I don't see why sysfs can't be used for configuration as well as its other roles. It seems to me wasteful to require configfs to be used in order to change configuration when sysfs works fine for this.
Here are a couple of existing examples where sysfs is used in a role that would seem similar to SCST's usage:
1)
scsi_transport_fcalready has an sysfs file, fc_host/vport_create, which can be written to create newfc_hostandscsi_hostinstances.2) fcoe.ko uses a write to the sysfs file
/sys/module/fcoe/parameters/createto start the protocol on a particular ethernet interface. There's another file for destroy.
Quoted 6 lines
I'll bet there are other examples in other subsystems, and I don't think there is anything wrong with the above usages of sysfs.
I agree with Vladislav's point that configfs doesn't work instead of sysfs because configs doesn't make it easy for the kernel side to create nodes for dynamic information like connected initiators and statistics.
I disagree that conversion of 'demo mode' struct se_node_acls to explict userspace syscall driven configfs registered struct se_node_acl->acl_group is overly complex, or otherwise difficult in context of a configfs consumer for a transition demo mode -> explict NodeACL via:
mkdir -p /sys/kernel/config/target/$FABRIC/$WWN/$TPGT/acls/$INITIATOR_WWPN.
Note the current v4.0 code supports this for LIO-Target and TCM/FC fabric module code, and will just work 'out of the box' for v4.0 compatible fabric modules using target_core_fabric_configfs.c logic.
As for statistics point, this is also currently handled by TCM in struct se_node_acl in target_core_mib.c:scsi_auth_intr_seq_show() for both explict NodeACL and TPG context 'demo-mode' generated struct se_node_acl attached to a struct se_portal_group fabric endpoint.
Quoted 8 lines
So, if the above examples are considered a misuse of sysfs, SCST would need to use both sysfs and configfs. It would use configfs to do configuration, and sysfs to display and access the dynamic information like connected initiators. That seems a minor role for configfs, which is easily handled in sysfs as SCST currently does.
Just my two cents.
I think the question is more along the lines of: does sysfs have a hard requirement for target mode using native TCM/ConfigFS logic.?. Early in the development of TCM/LIO v3.0 I thought that driving creation of configfs struct_groups from kernel code was in fact useful for my own development and for future mainline code, but with the help of foresight of jlbec, gregkh and others with our modern v4.0 code I am no longer convinced we need any direct kernel level interaction between native v4.0 target mode configfs code and existing sysfs code.
So far using interpreted userspace python/shell code has served this purpose really quite well in terms of interaction between target mode configfs and existing sysfs design, and I do not currently see any inherient limitations from a userspace code driven persective for a full native configfs target implementation. I would be happy to be proven wrong on this point, but so far the original decision to drive target mode completely from userspace with native configfs code has in fact proven to be a better decision than a hybrid kernel level configfs + sysfs implementation from the perspective of the userspace developer driving /sys/kernel/config/target/* code.
So on this basis I am currently not interested in moving TCM/LIO code away from a native configfs control plane for the v4.0 release, but I am happy to discuss positive benefits that a hybrid implementation can potentially provide to our existing TCM/LIO userspace ecosystem.
Best,
--nab
Re: [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Joe EykholtQuoted 49 lines · On Mon, 15 Nov 2010 21:04:19 -0800 Joe Eykholt <[email protected]> wrote:
Quoted 46 lines · Greg KH
Quoted 23 lines · Vladislav Bolkhovitin
Quoted 22 lines · Greg KH, on 11/15/2010 09:44 PM wrote:
Quoted 20 lines · Bart Van Assche
Quoted 9 lines · Greg KH
Quoted 6 lines · Vladislav Bolkhovitin
So, I decided to reimplement it to be completely synchronous. SYSFS authors did really great job and thanks to the excellent internal SYSFS design and implementation it is absolutely safe. See:
[root@tgt ~]# modprobe scst
[root@tgt ~]# cd/sys/kernel/scst_tgt/Quoted 6 lines
Sorry, but no, you can't put this in
/sys/kernel/without getting the approval of the sysfs maintainer.I really don't understand why you are using kobjects in the first place, why isn't this in the main device tree in the kernel, using 'struct device'?
We might have missed something, but as far as we know it has not yet been explained in this thread why using 'struct device' would be an advantage over using 'struct kobject'.
Quoted 8 lines
Quoted 6 lines
It's very simple.
You want your device to show up in the global device tree in the kernel, not off to one side, unconnected to anything else.
Please use 'struct device', it is what you want to do here.
But we don't have any device to show up in the global device tree!
Not true at all.
Quoted 1 line
We don't have any devices in the struct device's understanding at all!
Then create them just like you are doing so for your kobject use.
The first device would be the root one, and then everything trickles down from there.
And use configfs for your configuration stuff, that's what it is there for, and if it doesn't somehow work properly for you, please work with the configfs developers to fix that up.
Quoted 8 lines
Quoted 3 lines
thanks,
greg k-h
I don't have any opinion on the above, but I don't see why sysfs can't be used for configuration as well as its other roles. It seems to me wasteful to require configfs to be used in order to change configuration when sysfs works fine for this.
Well, I'm not involved here.. but to me it makes sense. It's just a useful principle in software design. You don't take something that is designed for one purpose and mis-use it. It will grow warts and mutate, stealing flexibility.
it's one of the reasons many software projects become unmaintainable... nobody can change anything anymore because the once simple design has proliferated into a nine headed monster...
Quoted 1 line
Just my two cents.
My two cents too.
Quoted 2 lines
Joe
Flo
Re: [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Joe EykholtQuoted 77 lines · Joe Eykholt, on 11/16/2010 08:04 AM wrote:
Quoted 42 lines · Vladislav Bolkhovitin
Quoted 23 lines
Quoted 22 lines · Greg KH, on 11/15/2010 09:44 PM wrote:
Quoted 20 lines · Bart Van Assche
Quoted 9 lines · Greg KH
Quoted 6 lines · Vladislav Bolkhovitin
So, I decided to reimplement it to be completely synchronous. SYSFS authors did really great job and thanks to the excellent internal SYSFS design and implementation it is absolutely safe. See:
[root@tgt ~]# modprobe scst
[root@tgt ~]# cd/sys/kernel/scst_tgt/Quoted 6 lines
Sorry, but no, you can't put this in
/sys/kernel/without getting the approval of the sysfs maintainer.I really don't understand why you are using kobjects in the first place, why isn't this in the main device tree in the kernel, using 'struct device'?
We might have missed something, but as far as we know it has not yet been explained in this thread why using 'struct device' would be an advantage over using 'struct kobject'.
Quoted 8 lines
Quoted 6 lines
It's very simple.
You want your device to show up in the global device tree in the kernel, not off to one side, unconnected to anything else.
Please use 'struct device', it is what you want to do here.
But we don't have any device to show up in the global device tree!
Not true at all.
Quoted 1 line
We don't have any devices in the struct device's understanding at all!
Then create them just like you are doing so for your kobject use.
The first device would be the root one, and then everything trickles down from there.
Quoted 7 lines
And use configfs for your configuration stuff, that's what it is there for, and if it doesn't somehow work properly for you, please work with the configfs developers to fix that up.
thanks,
greg k-h
I don't have any opinion on the above, but I don't see why sysfs can't be used for configuration as well as its other roles. It seems to me wasteful to require configfs to be used in order to change configuration when sysfs works fine for this.
Here are a couple of existing examples where sysfs is used in a role that would seem similar to SCST's usage:
1)
scsi_transport_fcalready has an sysfs file, fc_host/vport_create, which can be written to create newfc_hostandscsi_hostinstances.2) fcoe.ko uses a write to the sysfs file
/sys/module/fcoe/parameters/createto start the protocol on a particular ethernet interface. There's another file for destroy.I'll bet there are other examples in other subsystems, and I don't think there is anything wrong with the above usages of sysfs.
I agree with Vladislav's point that configfs doesn't work instead of sysfs because configs doesn't make it easy for the kernel side to create nodes for dynamic information like connected initiators and statistics. So, if the above examples are considered a misuse of sysfs,
SCST would need to use both sysfs and configfs. It would use configfs to do configuration, and sysfs to display and access the dynamic information like connected initiators. That seems a minor role for configfs, which is easily handled in sysfs as SCST currently does.
Quoted 1 line
Just my two cents.
Thank you, Joe, for those good examples. I may not know for what SYSFS was _originally_ designed, but the current reality is that SYSFS is _widely_ used to both represent the kernel internal configuration as well as to change it. And SCST is just following that.
After all, if SYSFS supposed to only represent the kernel internal configuration, why wasn't it from the beginning made read-only?
Vlad
Re: [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Greg KHQuoted 4 lines · Greg KH
[ ... ]
And use configfs for your configuration stuff, that's what it is there for, and if it doesn't somehow work properly for you, please work with the configfs developers to fix that up.
Hello Greg,
The reason why we use sysfs instead of configfs is that we do not only want to export kernel objects to user space but because we also want to allow configuration from user space. As far as I can see configfs has been designed to allow configuration from user space only and not for exporting kernel objects. A quote from Documentation/filesystems/configfs/configfs.txt:
12 [What is configfs?]
13
14 configfs is a ram-based filesystem that provides the converse of 15 sysfs's functionality. Where sysfs is a filesystem-based view of 16 kernel objects, configfs is a filesystem-based manager of kernel 17 objects, or config_items.
Bart.
Re: [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Greg KHQuoted 5 lines · Greg KH, on 11/16/2010 01:13 AM wrote:
Quoted 3 lines
Quoted 1 line
Please use 'struct device', it is what you want to do here.
But we don't have any device to show up in the global device tree!
Not true at all.
Why?
Greg, sorry, you keep writing as if we all are idiots, but keep refusing to explain us, idiots, why we can't do what we did. It isn't very constructive, is it?
Quoted 6 lines
Quoted 1 line
We don't have any devices in the struct device's understanding at all!
Then create them just like you are doing so for your kobject use.
The first device would be the root one, and then everything trickles down from there.
Sorry, I can't understand what you mean. What would be the purpose of this configuration and what benefits it would bring?
Anyway, let's forget about SCSI. Do you believe that struct device should be created for all IP addresses on which an NFS server listen and for all exports it exports?
Quoted 3 lines
And use configfs for your configuration stuff, that's what it is there for, and if it doesn't somehow work properly for you, please work with the configfs developers to fix that up.
I explained why it isn't a too good option in another e-mail.
Thanks,
Vlad
Re: [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Greg KHQuoted 10 lines · Greg KH, on 11/14/2010 02:59 AM wrote:
Quoted 6 lines · Vladislav Bolkhovitin
So, I decided to reimplement it to be completely synchronous. SYSFS authors did really great job and thanks to the excellent internal SYSFS design and implementation it is absolutely safe. See:
[root@tgt ~]# modprobe scst
[root@tgt ~]# cd/sys/kernel/scst_tgt/Sorry, but no, you can't put this in
/sys/kernel/without getting the approval of the sysfs maintainer.
Hmm, I thought we had the approvement in the "[RFC]: SCST sysfs layout" thread (http://osdir.com/ml/linux-kernel/2009-04/msg07822.html). Particularly, in the message http://osdir.com/ml/linux-kernel/2009-04/msg08557.html.
But, looks like it isn't so and I should have asked you, the SYSFS maintainer. Sorry.
Could you consider it, please?
You can find detail description why SCST needs such layout below.
Quoted 3 lines
I really don't understand why you are using kobjects in the first place, why isn't this in the main device tree in the kernel, using 'struct device'?
I'll try to explain. It's a bit long story involving deep SCSI target specific knowledge, but I'll try to make it as simple and short as possible.
SCST is a SCSI _target_ side subsystem, i.e. it is a _server_ side sybsystem. It exports SCSI-speaking devices, not using them. You can consider it as an NFS server. What usually meant by "SCSI subsystem" is SCSI _initiator_ subsystem, i.e. client side subsystem (like NFS client), which is using SCSI-speaking devices by sending SCSI commands to them.
Any SCSI-speaking protocol can be used with SCST: parallel (wide) SCSI, Fibre Channel, iSCSI, SAS, SRP, iSER, etc. (Also, non-SCSI speaking protocols, like AoE and NBD can be used, but that's another story.)
Strictly as required by SCSI Architecture Model (SAM [1]), SCST doesn't deal with hardware devices. The closest to hardware things SCST deals with are SCSI target ports and SCSI target devices.
SCSI target port is an abstract concept reflecting path through which SCST exports devices. You can consider it as an IP network (network, not interface!) through which an NFS server's exports can be used. For instance, for iSCSI such ports are iSCSI targets. For Fibre Channel - virtual or hardware Fibre Channel ports.
SCSI target device is an abstract concept, which provides a way to reach real storage (files, block devices, etc.) and contains internal state information (reservations, configuration parameters, etc.). You can consider it as an NFS export. Please don't confuse it with SCSI _initiator_ device, which is a place to generate SCSI commands and send them via one or more SCSI initiator ports (MPIO). On the target side they will be accepted via one or more SCSI target ports, then sent by the corresponding SCSI target device to back storage device (file, block device, etc.).
So, there is no place in SCST to make Linux devices and use struct device. It's up to SCST target drivers to create Linux devices for target hardware, if they need it, which is rare. For instance, scst_local driver make SCST's SCSI target devices be available as SCSI initiator, i.e. regular, devices by creating all the necessary devices and SYSFS infrastructure for them:
Load SCST modules:
[root@tgt ~]# modprobe scst
[root@tgt ~]# modprobe scst_vdisk
Create SCSI target device "blockio" with /dev/sda5 as backstorage:
[root@tgt ~]# echo "add_device blockio filename=/dev/sda5" >/sys/kernel/scst_tgt/handlers/vdisk_blockio/mgmt
Check current SCSI devices:
[root@tgt ~]# lsscsi
[1:0:0:0] disk SEAGATE ST373455LW 0003 /dev/sda [2:0:0:0] disk Linux scsi_debug 0004 /dev/sdb
Check that host3 doesn't exist:
[root@tgt ~]# cd /sys/class/scsi_host/host3
bash: cd: /sys/class/scsi_host/host3: No such file or directory
Load scst_local target driver:
[root@tgt ~]# modprobe scst_local
Create SCSI target port "scst_local_tgt" with SCSI host "scst_local_host" (host3):
[root@tgt ~]# echo "add_target scst_local_tgt session_name=scst_local_host" >/sys/kernel/scst_tgt/targets/scst_local/mgmt
Add "blockio" as LUN 0:
[root@tgt ~]# echo "add blockio 0" >/sys/kernel/scst_tgt/targets/scst_local/scst_local_tgt/luns/mgmt
See new local SCSI device 3:0:0:0 (/dev/sdc):
[root@tgt ~]# lsscsi
[1:0:0:0] disk SEAGATE ST373455LW 0003 /dev/sda [2:0:0:0] disk Linux scsi_debug 0004 /dev/sdb [3:0:0:0] disk SCST_BIO blockio 210 /dev/sdc
[root@tgt ~]# cd /sys/class/scsi_host/host3 [root@tgt host3]# ll
total 0
-rw-r--r-- 1 root root 4096 Nov 16 00:22 active_mode -r--r--r-- 1 root root 4096 Nov 16 00:22 can_queue -r--r--r-- 1 root root 4096 Nov 16 00:22 cmd_per_lun
lrwxrwxrwx 1 root root 0 Nov 16 00:07 device -> ../../../devices/scst_local/scst_local_host/host3
-r--r--r-- 1 root root 4096 Nov 16 00:22 host_busy
drwxr-xr-x 2 root root 0 Nov 16 00:22 power
-r--r--r-- 1 root root 4096 Nov 16 00:22 proc_name -r--r--r-- 1 root root 4096 Nov 16 00:22 prot_capabilities -r--r--r-- 1 root root 4096 Nov 16 00:22 prot_guard_type --w------- 1 root root 4096 Nov 16 00:22 scan -r--r--r-- 1 root root 4096 Nov 16 00:22 sg_tablesize -rw-r--r-- 1 root root 4096 Nov 16 00:22 state
lrwxrwxrwx 1 root root 0 Nov 16 00:22 subsystem -> ../../scsi_host
-rw-r--r-- 1 root root 4096 Nov 16 00:22 supported_mode -rw-r--r-- 1 root root 4096 Nov 16 00:22 uevent -r--r--r-- 1 root root 4096 Nov 16 00:22 unchecked_isa_dma -r--r--r-- 1 root root 4096 Nov 16 00:22 unique_id
Hopefully, it will make a bit clearer, why SCST can't use struct device, but uses struct kobject, and why it needs a special place in the SYSFS tree to attach to.
Thanks,
Vlad
[1] You can download a copy of SAM from http://www.t10.org/drafts.htm. Exact version doesn't matter.
Re: [PATCH 8/19]: SCST SYSFS interface implementation
In reply to Vladislav BolkhovitinQuoted 28 lines · Vladislav Bolkhovitin
Quoted 15 lines · Dmitry Torokhov, on 11/12/2010 04:23 AM wrote:
Quoted 8 lines
Quoted 4 lines
This put might not be the last put on the object, IOs in flight and/or open files might have extra reference on the object. We release our initial ref, and below wait for all operations to complete. (Is there a matter of timeout like files not closing?)
This is the last internal put. All other references are from outsiders. So, we are waiting for all them to put before we go on.
The question is why do you need to wait here? I presume it is module unloading path, but then it is quite bad - you can easily wedge your subsystem if you make something to take a reference to your kobject while module is ytying to be unloaded. Back when sysfs attributes tied kobjects the easiest thing was to do:
Quoted 8 lines
rmmod <module> < / sys/devices/..../attribute
If you are done with the kobject - just proceed with what you were doing and let it die its own peaceful death some time later. You just need to make sure release code sticks around to free it and your subsystem core can be tasked with this. Use module counter to prevent unloading of the subsystem core until all kobjects belonging to the subsystem are destroyed.
This is a very good question. During implementation I spent a lot of time working on it.
Quoted 8 lines
In fact, the first implementation was asynchronous similarly as you proposing, i.e. it just proceed with what you were doing and let it die its own peaceful death some time later. But soon the implementation was becoming so complicated, so it started getting out of control. For instance, some of the tasks to solve with this approach were:
1. What to do if another SCST object is being created with the same name as supposed to be deleted, but not completely dead yet?
The same rules as with files - the object disappears from the "directories" so no new users can get it but is not destroyed till last reference is gone.
Quoted 5 lines
2. What to do if a dieing object is found on some list and reference for is supposed to be taken? If the object deleted from the list before it marked dieing, i.e. the latest internal
put()done, it made additional problems during deleting it after the latest external put done.
You delete the object from the list, then mark it as dead, notify users, drop refcount. No new users will get it (as it is not on the list anymore) and existing ones should notice that it is dead and stop using it.
Quoted 55 lines
...
So, I decided to reimplement it to be completely synchronous. SYSFS authors did really great job and thanks to the excellent internal SYSFS design and implementation it is absolutely safe. See:
[root@tgt ~]# modprobe scst
[root@tgt ~]# cd/sys/kernel/scst_tgt/
[root@tgt scst_tgt]# ls -l
total 0
drwxr-xr-x 4 root root 0 Nov 13 21:31 devices
drwxr-xr-x 2 root root 0 Nov 13 21:31 handlers(quoted diff) +0
-2-r--r--r-- 1 root root 4096 Nov 13 21:30 last_sysfs_mgmt_res -rw-r--r-- 1 root root 4096 Nov 13 21:30 setup_iddrwxr-xr-x 5 root root 0 Nov 13 21:31 sgv
drwxr-xr-x 2 root root 0 Nov 13 21:31 targets(quoted diff) +0
-3-rw-r--r-- 1 root root 4096 Nov 13 21:30 threads -rw-r--r-- 1 root root 4096 Nov 13 21:30 trace_level -r--r--r-- 1 root root 4096 Nov 13 21:30 version[root@tgt scst_tgt]# cat version
2.1.0-pre1
EXTRACHECKS
DEBUG
[root@tgt scst_tgt]# rmmod scst </sys/kernel/scst_tgt/version[root@tgt scst_tgt]# ls -l
total 0
[root@tgt scst_tgt]# pwd/sys/kernel/scst_tgt
[root@tgt scst_tgt]# lsmodModule Size Used by scsi_debug 65188 0 w83627hf 22424 0 hwmon_vid 2207 1 w83627hf adm1021 6189 0 binfmt_misc 6229 1 xfs 673142 1 exportfs 3143 1 xfs dm_mirror 12069 0 dm_region_hash 8703 1 dm_mirror dm_log 8345 2 dm_mirror,dm_region_hash dm_mod 63511 2 dm_mirror,dm_log pci_slot 3378 0 hed 1758 0 floppy 52718 0 uhci_hcd 21459 0 sg 25181 0 e1000 128475 0 i2c_i801 8756 0 pcspkr 1442 0 i2c_core 22319 2 adm1021,i2c_i801 e7xxx_edac 3463 0 parport_pc 25439 0 parport 29682 1 parport_pc
Quoted 6 lines
Everything works fine.
This is because SYSFS doesn't hold references for the corresponding kobjects for every open file handle. It holds references only when
show()andstore()functions called. So, everything is under control and a malicious user can do nothing to hold a reference forever.
Right, Tejun plugged this particular (and very annoying) attributes behavior, but that does not mean that this is the only way kobject's reference might be pinned.
Signature · 1 line
Dmitry
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 13 lines · Dmitry Torokhov, on 11/15/2010 10:04 AM wrote:
Quoted 2 lines
1. What to do if another SCST object is being created with the same name as supposed to be deleted, but not completely dead yet?
The same rules as with files - the object disappears from the "directories" so no new users can get it but is not destroyed till last reference is gone.
Quoted 5 lines
2. What to do if a dieing object is found on some list and reference for is supposed to be taken? If the object deleted from the list before it marked dieing, i.e. the latest internal
put()done, it made additional problems during deleting it after the latest external put done.
Quoted 4 lines
You delete the object from the list, then mark it as dead, notify users, drop refcount. No new users will get it (as it is not on the list anymore) and existing ones should notice that it is dead and stop using it.
Those are good in theory, but on practice, you know, devil is in the details..
Quoted 7 lines
Quoted 4 lines
This is because SYSFS doesn't hold references for the corresponding kobjects for every open file handle. It holds references only when
show()andstore()functions called. So, everything is under control and a malicious user can do nothing to hold a reference forever.Right, Tejun plugged this particular (and very annoying) attributes behavior
This behavior isn't annoying, it's GREAT, because it allows to use SYSFS simply and reliably.
Quoted 2 lines
, but that does not mean that this is the only way kobject's reference might be pinned.
Could you be more specific and point out on exact ways for that? From my quite deep SYSFS source code study I see such cases should not exist.
Thanks,
Vlad
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 7 lines · Vladislav Bolkhovitin
Quoted 5 lines · Dmitry Torokhov, on 11/15/2010 10:04 AM wrote:
Quoted 4 lines
This is because SYSFS doesn't hold references for the corresponding kobjects for every open file handle. It holds references only when
show()andstore()functions called. So, everything is under control and a malicious user can do nothing to hold a reference forever.
Quoted 5 lines
Quoted 2 lines
Right, Tejun plugged this particular (and very annoying) attributes behavior
This behavior isn't annoying, it's GREAT, because it allows to use SYSFS simply and reliably.
Right, I mean that _before_ Tejun plugged that hole the behavior _was_ annoying.
Quoted 6 lines
Quoted 3 lines
, but that does not mean that this is the only way kobject's reference might be pinned.
Could you be more specific and point out on exact ways for that? From my quite deep SYSFS source code study I see such cases should not exist.
While I do not know offhand I am sure there are such scenarios. Isn't there any way for the users that you are waiting on descend back into your module that is waiting for kobject removal and get stuck on some resource?
Even if it isn't possible now the scheme is quite fragile. Kobjects are refcounted so work with them appropriately (rely on refcount, do not wait, etc).
Signature · 1 line
Dmitry
Re: [PATCH 8/19]: SCST SYSFS interface implementation
Quoted 7 lines · Dmitry Torokhov, on 11/16/2010 12:14 AM wrote:
Quoted 2 lines
Could you be more specific and point out on exact ways for that? From my quite deep SYSFS source code study I see such cases should not exist.
While I do not know offhand I am sure there are such scenarios. Isn't there any way for the users that you are waiting on descend back into your module that is waiting for kobject removal and get stuck on some resource?
No, I don't see any, because SYSFS implements atomic "all or nothing" behavior on destroy, which is pretty bulletproof.
Quoted 3 lines
Even if it isn't possible now the scheme is quite fragile. Kobjects are refcounted so work with them appropriately (rely on refcount, do not wait, etc).
The same is true for other SCST objects. For instance, a target can't be destroyed until there are commands from it being processed. So, kobjects are only one of the objects we wait for all their ref counters reach zero, hence addition of kobjects to SCST objects changed nothing in this area.
Vlad
PATCH v4 9/19 : SCST debugging support routines
In reply to Vladislav BolkhovitinThis patch contains SCST debugging support routines.
--- drivers/scst/scst_debug.c | 223 ++++++++++++++++++++++++++++++++++++ include/scst/scst_debug.h | 284 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 507 insertions(+)
include/scst/scst_debug.h renamed from linux-2.6.35/include/scst/scst_debug.h +284 -0
@@ -0,0 +1,284 @@ +/* +* include/scst_debug.h +* +* Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <[email protected]> +* Copyright (C) 2004 - 2005 Leonid Stoljar +* Copyright (C) 2007 - 2010 ID7 Ltd. +* +* Contains macroses for execution tracing and error reporting +* +* 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, version 2 +* of the License. +* +* 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. +*/ + +#ifndef __SCST_DEBUG_H +#define __SCST_DEBUG_H + +#include <generated/autoconf.h> /* for CONFIG_* */ + +#include <linux/bug.h> /* for WARN_ON_ONCE */ + +#ifdef CONFIG_SCST_EXTRACHECKS +#define EXTRACHECKS_BUG_ON (a) BUG_ON(a) +#define EXTRACHECKS_WARN_ON (a) WARN_ON(a) +#define EXTRACHECKS_WARN_ON_ONCE (a) WARN_ON_ONCE(a) +#else +#define EXTRACHECKS_BUG_ON (a) do { } while (0) +#define EXTRACHECKS_WARN_ON (a) do { } while (0) +#define EXTRACHECKS_WARN_ON_ONCE (a) do { } while (0) +#endif + +#define TRACE_NULL 0x00000000 +#define TRACE_DEBUG 0x00000001 +#define TRACE_FUNCTION 0x00000002 +#define TRACE_LINE 0x00000004 +#define TRACE_PID 0x00000008 +#define TRACE_BUFF 0x00000020 +#define TRACE_MEMORY 0x00000040 +#define TRACE_SG_OP 0x00000080 +#define TRACE_OUT_OF_MEM 0x00000100 +#define TRACE_MINOR 0x00000200/* less important events */ +#define TRACE_MGMT 0x00000400 +#define TRACE_MGMT_DEBUG 0x00000800 +#define TRACE_SCSI 0x00001000 +#define TRACE_SPECIAL 0x00002000/* filtering debug, etc */ +#define TRACE_FLOW_CONTROL 0x00004000/* flow control in action */ +#define TRACE_PRES 0x00008000 +#define TRACE_ALL 0xffffffff +/* Flags 0xXXXX0000 are local for users */ + +#define TRACE_MINOR_AND_MGMT_DBG (TRACE_MINOR|TRACE_MGMT_DEBUG) + +#ifndef KERN_CONT +#define KERN_CONT "" +#endif + +/* +* Note: in the next two printk() statements the KERN_CONT macro is only +* present to suppress a checkpatch warning (KERN_CONT is defined as ""). +*/ +#define PRINT(log_flag, format, args...) \ + printk(log_flag format "\n", ## args) +#define PRINTN(log_flag, format, args...) \ + printk(log_flag format, ## args) + +#ifdef LOG_PREFIX +#define __LOG_PREFIX LOG_PREFIX +#else +#define __LOG_PREFIX NULL +#endif + +#if defined(CONFIG_SCST_DEBUG ) || defined(CONFIG_SCST_TRACING ) + +#ifndef CONFIG_SCST_DEBUG +#define ___unlikely (a) (a) +#else +#define ___unlikely (a) unlikely(a) +#endif + +/* +* We don't print prefix for debug traces to not put additional preasure +* on the logging system in case of a lot of logging. +*/ + +int debug_print_prefix (unsigned long trace_flag, +const char *prefix,const char *func,int line); +void debug_print_buffer (const void *data,int len); +const char *debug_transport_id_to_initiator_name (const uint8_t *transport_id); + +#define TRACING_MINOR () (trace_flag & TRACE_MINOR) + +#define TRACE(trace, format, args...) \ +do { \ + if (___unlikely(trace_flag & (trace))) { \ + debug_print_prefix(trace_flag, __LOG_PREFIX, \ + __func__, __LINE__); \ + PRINT(KERN_CONT, format, args); \ + } \ +} while (0) + +#ifdef CONFIG_SCST_DEBUG + +#define PRINT_BUFFER (message, buff, len) \ +do { \ + PRINT(KERN_INFO, "%s:%s:", __func__, message); \ + debug_print_buffer(buff, len); \ +} while (0) + +#else + +#define PRINT_BUFFER (message, buff, len) \ +do { \ + PRINT(KERN_INFO, "%s:", message); \ + debug_print_buffer(buff, len); \ +} while (0) + +#endif + +#define PRINT_BUFF_FLAG (flag, message, buff, len) \ +do { \ + if (___unlikely(trace_flag & (flag))) { \ + debug_print_prefix(trace_flag, NULL, __func__, __LINE__);\ + PRINT(KERN_CONT, "%s:", message); \ + debug_print_buffer(buff, len); \ + } \ +} while (0) + +#else /* CONFIG_SCST_DEBUG || CONFIG_SCST_TRACING */ + +#define TRACING_MINOR () (false) + +#define TRACE(trace, args...) do {} while (0) +#define PRINT_BUFFER (message, buff, len) do {} while (0) +#define PRINT_BUFF_FLAG (flag, message, buff, len) do {} while (0) + +#endif /* CONFIG_SCST_DEBUG || CONFIG_SCST_TRACING */ + +#ifdef CONFIG_SCST_DEBUG + +#define TRACE_DBG_FLAG(trace, format, args...) \ +do { \ + if (trace_flag & (trace)) { \ + debug_print_prefix(trace_flag, NULL, __func__, __LINE__);\ + PRINT(KERN_CONT, format, args); \ + } \ +} while (0) + +#define TRACE_MEM(args...) TRACE_DBG_FLAG(TRACE_MEMORY, args) +#define TRACE_SG(args...) TRACE_DBG_FLAG(TRACE_SG_OP, args) +#define TRACE_DBG(args...) TRACE_DBG_FLAG(TRACE_DEBUG, args) +#define TRACE_DBG_SPECIAL(args...) TRACE_DBG_FLAG(TRACE_DEBUG|TRACE_SPECIAL, args) +#define TRACE_MGMT_DBG(args...) TRACE_DBG_FLAG(TRACE_MGMT_DEBUG, args) +#define TRACE_MGMT_DBG_SPECIAL(args...) \ + TRACE_DBG_FLAG(TRACE_MGMT_DEBUG|TRACE_SPECIAL, args) +#define TRACE_PR(args...) TRACE_DBG_FLAG(TRACE_PRES, args) + +#define TRACE_BUFFER (message, buff, len) \ +do { \ + if (trace_flag & TRACE_BUFF) { \ + debug_print_prefix(trace_flag, NULL, __func__, __LINE__);\ + PRINT(KERN_CONT, "%s:", message); \ + debug_print_buffer(buff, len); \ + } \ +} while (0) + +#define TRACE_BUFF_FLAG (flag, message, buff, len) \ +do { \ + if (trace_flag & (flag)) { \ + debug_print_prefix(trace_flag, NULL, __func__, __LINE__);\ + PRINT(KERN_CONT, "%s:", message); \ + debug_print_buffer(buff, len); \ + } \ +} while (0) + +#define PRINT_LOG_FLAG(log_flag, format, args...) \ +do { \ + debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\ + PRINT(KERN_CONT, format, args); \ +} while (0) + +#define PRINT_WARNING(format, args...) \ +do { \ + debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\ + PRINT(KERN_CONT, "***WARNING***: " format, args); \ +} while (0) + +#define PRINT_ERROR(format, args...) \ +do { \ + debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\ + PRINT(KERN_CONT, "***ERROR***: " format, args); \ +} while (0) + +#define PRINT_CRIT_ERROR(format, args...) \ +do { \ + debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\ + PRINT(KERN_CONT, "***CRITICAL ERROR***: " format, args); \ +} while (0) + +#define PRINT_INFO(format, args...) \ +do { \ + debug_print_prefix(trace_flag, __LOG_PREFIX, __func__, __LINE__);\ + PRINT(KERN_CONT, format, args); \ +} while (0) + +#else /* CONFIG_SCST_DEBUG */ + +#define TRACE_MEM(format, args...) do {} while (0) +#define TRACE_SG(format, args...) do {} while (0) +#define TRACE_DBG(format, args...) do {} while (0) +#define TRACE_DBG_FLAG(format, args...) do {} while (0) +#define TRACE_DBG_SPECIAL(format, args...) do {} while (0) +#define TRACE_MGMT_DBG(format, args...) do {} while (0) +#define TRACE_MGMT_DBG_SPECIAL(format, args...) do {} while (0) +#define TRACE_PR(format, args...) do {} while (0) +#define TRACE_BUFFER (message, buff, len) do {} while (0) +#define TRACE_BUFF_FLAG (flag, message, buff, len) do {} while (0) + +#ifdef LOG_PREFIX + +#define PRINT_INFO(format, args...) \ +do { \ + PRINT(KERN_INFO, "%s: " format, LOG_PREFIX, args); \ +} while (0) + +#define PRINT_WARNING(format, args...) \ +do { \ + PRINT(KERN_INFO, "%s: ***WARNING***: " \ + format, LOG_PREFIX, args); \ +} while (0) + +#define PRINT_ERROR(format, args...) \ +do { \ + PRINT(KERN_INFO, "%s: ***ERROR***: " \ + format, LOG_PREFIX, args); \ +} while (0) + +#define PRINT_CRIT_ERROR(format, args...) \ +do { \ + PRINT(KERN_INFO, "%s: ***CRITICAL ERROR***: " \ + format, LOG_PREFIX, args); \ +} while (0) + +#else + +#define PRINT_INFO(format, args...) \ +do { \ + PRINT(KERN_INFO, format, args); \ +} while (0) + +#define PRINT_WARNING(format, args...) \ +do { \ + PRINT(KERN_INFO, "***WARNING***: " \ + format, args); \ +} while (0) + +#define PRINT_ERROR(format, args...) \ +do { \ + PRINT(KERN_ERR, "***ERROR***: " \ + format, args); \ +} while (0) + +#define PRINT_CRIT_ERROR(format, args...) \ +do { \ + PRINT(KERN_CRIT, "***CRITICAL ERROR***: " \ + format, args); \ +} while (0) + +#endif /* LOG_PREFIX */ + +#endif /* CONFIG_SCST_DEBUG */ + +#if defined(CONFIG_SCST_DEBUG ) && defined(CONFIG_DEBUG_SLAB ) +#define SCST_SLAB_FLAGS (SLAB_RED_ZONE | SLAB_POISON) +#else +#define SCST_SLAB_FLAGS 0L +#endif + +#endif /* __SCST_DEBUG_H */
drivers/scst/scst_debug.c renamed from linux-2.6.35/drivers/scst/scst_debug.c +223 -0
223 lines not on this page · raw message
PATCH v4 10/19 : SCST SGV cache
In reply to Vladislav BolkhovitinThis patch contains SCST SGV cache.
SCST SGV cache is a memory management subsystem in SCST. One can call it a "memory pool", but Linux kernel already have a mempool interface, which serves different purposes. SGV cache provides to SCST core, target drivers and backend dev handlers facilities to allocate, build and cache SG vectors for data buffers. The main advantage of it is the caching facility, when it doesn't free to the system each vector, which is not used anymore, but keeps it for a while (possibly indefinitely) to let it be reused by the next consecutive command. This allows to:
- Reduce commands processing latencies and, hence, improve performance;
- Make commands processing latencies predictable, which is essential for RT applications.
The freed SG vectors are kept by the SGV cache either for some (possibly indefinite) time, or, optionally, until the system needs more memory and asks to free some using the set_shrinker() interface. Also the SGV cache allows to:
- Cluster pages together. "Cluster" means merging adjacent pages in a
single SG entry. It allows to have less SG entries in the resulting SG vector, hence improve performance handling it as well as allow to work with bigger buffers on hardware with limited SG capabilities.
- Set custom page allocator functions. For instance, scst_user device
handler uses this facility to eliminate unneeded mapping/unmapping of user space pages and avoid unneeded IOCTL calls for buffers allocations. In fileio_tgt application, which uses a regular malloc() function to allocate data buffers, this facility allows ~30% less CPU load and considerable performance increase.
- Prevent each initiator or all initiators altogether to allocate too
much memory and DoS the target. Consider 10 initiators, which can have access to 10 devices each. Any of them can queue up to 64 commands, each can transfer up to 1MB of data. So, all of them in a peak can allocate up to 10*10*64 = ~6.5GB of memory for data buffers. This amount must be limited somehow and the SGV cache performs this function.
More info about it you can find in the documentation in this patch.
--- Documentation/scst/sgv_cache.txt | 234 +++++ drivers/scst/scst_mem.c | 1815 +++++++++++++++++++++++++++++++++++++++ drivers/scst/scst_mem.h | 150 +++ include/scst/scst_sgv.h | 97 ++ 4 files changed, 2296 insertions(+)
include/scst/scst_sgv.h renamed from linux-2.6.35/include/scst/scst_sgv.h +97 -0
@@ -0,0 +1,97 @@ +/* +* include/scst_sgv.h +* +* Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <[email protected]> +* Copyright (C) 2007 - 2010 ID7 Ltd. +* +* Include file for SCST SGV cache. +* +* 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, version 2 +* of the License. +* +* 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. +*/ +#ifndef __SCST_SGV_H +#define __SCST_SGV_H + +/** SGV pool routines and flag bits **/ + +/* Set if the allocated object must be not from the cache */ +#define SGV_POOL_ALLOC_NO_CACHED 1 + +/* Set if there should not be any memory allocations on a cache miss */ +#define SGV_POOL_NO_ALLOC_ON_CACHE_MISS 2 + +/* Set an object should be returned even if it doesn't have SG vector built */ +#define SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL 4 + +/* +* Set if the allocated object must be a new one, i.e. from the cache, +* but not cached +*/ +#define SGV_POOL_ALLOC_GET_NEW 8 + +struct sgv_pool_obj ; +struct sgv_pool ; + +/* +* Structure to keep a memory limit for an SCST object +*/ +struct scst_mem_lim { +/* How much memory allocated under this object */ +atomic_t alloced_pages; + +/* +* How much memory allowed to allocated under this object. Put here +* mostly to save a possible cache miss accessing scst_max_dev_cmd_mem. +*/ +int max_allowed_pages; +}; + +/* Types of clustering */ +enum sgv_clustering_types { +/* No clustering performed */ + sgv_no_clustering =0 , + +/* +* A page will only be merged with the latest previously allocated +* page, so the order of pages in the SG will be preserved. +*/ + sgv_tail_clustering, + +/* +* Free merging of pages at any place in the SG is allowed. This mode +* usually provides the best merging rate. +*/ + sgv_full_clustering, +}; + +struct sgv_pool *sgv_pool_create (const char *name, +enum sgv_clustering_types clustered,int single_alloc_pages, +bool shared,int purge_interval); +void sgv_pool_del (struct sgv_pool *pool); + +void sgv_pool_get (struct sgv_pool *pool); +void sgv_pool_put (struct sgv_pool *pool); + +void sgv_pool_flush (struct sgv_pool *pool); + +void sgv_pool_set_allocator (struct sgv_pool *pool, +struct page *(*alloc_pages_fn)(struct scatterlist *,gfp_t ,void *), +void (*free_pages_fn)(struct scatterlist *,int ,void *)); + +struct scatterlist *sgv_pool_alloc (struct sgv_pool *pool,unsigned int size, +gfp_t gfp_mask,int flags,int *count, +struct sgv_pool_obj **sgv,struct scst_mem_lim *mem_lim,void *priv); +void sgv_pool_free (struct sgv_pool_obj *sgv,struct scst_mem_lim *mem_lim); + +void *sgv_get_priv (struct sgv_pool_obj *sgv); + +void scst_init_mem_lim (struct scst_mem_lim *mem_lim); + +#endif /* __SCST_SGV_H */
drivers/scst/scst_mem.h renamed from linux-2.6.35/drivers/scst/scst_mem.h +150 -0
150 lines not on this page · raw message
drivers/scst/scst_mem.c renamed from linux-2.6.35/drivers/scst/scst_mem.c +1815 -0
1,815 lines not on this page · raw message
Documentation/scst/sgv_cache.txt renamed from linux-2.6.35/Documentation/scst/sgv_cache.txt +234 -0
234 lines not on this page · raw message
PATCH v4 11/19 : SCST core's docs
In reply to Vladislav BolkhovitinThis patch contains SCST core's docs.
--- README.scst | 1473 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ SysfsRules | 942 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 2415 insertions(+)
Documentation/scst/README.scst renamed from linux-2.6.35/Documentation/scst/README.scst +1473 -0
@@ -0,0 +1,1473 @@ +Generic SCSI target mid-level for Linux (SCST) +============================================== + +SCST is designed to provide unified, consistent interface between SCSI +target drivers and Linux kernel and simplify target drivers development +as much as possible. Detail description of SCST's features and internals +could be found on its Internet page http://scst.sourceforge.net. + +SCST supports the following I/O modes: + + * Pass-through mode with one to many relationship, i.e. when multiple + initiators can connect to the exported pass-through devices, for + the following SCSI devices types: disks (type 0), tapes (type 1), + processors (type 3), CDROMs (type 5), MO disks (type 7), medium + changers (type 8) and RAID controllers (type 0xC). + + * FILEIO mode, which allows to use files on file systems or block + devices as virtual remotely available SCSI disks or CDROMs with + benefits of the Linux page cache. + + * BLOCKIO mode, which performs direct block IO with a block device, + bypassing page-cache for all operations. This mode works ideally with + high-end storage HBAs and for applications that either do not need + caching between application and disk or need the large block + throughput. + + * "Performance" device handlers, which provide in pseudo pass-through + mode a way for direct performance measurements without overhead of + actual data transferring from/to underlying SCSI device. + +In addition, SCST supports advanced per-initiator access and devices +visibility management, so different initiators could see different set +of devices with different access permissions. See below for details. + +Full list of SCST features and comparison with other Linux targets you +can find on http://scst.sourceforge.net/comparison.html. + + +Installation +------------ + +To see your devices remotely, you need to add a corresponding LUN for +them (see below how). By default, no local devices are seen remotely. +There must be LUN 0 in each LUNs set (security group), i.e. LUs +numeration must not start from, e.g., 1. Otherwise you will see no +devices on remote initiators and SCST core will write into the kernel +log message: "tgt_dev for LUN 0 not found, command to unexisting LU?" + +It is highly recommended to use scstadmin utility for configuring +devices and security groups. + +The flow of SCST inialization should be as the following: + +1. Load of SCST modules with necessary module parameters, if needed. + +2. Configure targets, devices, LUNs, etc. using either scstadmin +(recommended), or the sysfs interface directly as described below. + +If you experience problems during modules load or running, check your +kernel logs (or run dmesg command for the few most recent messages). + +IMPORTANT: Without loading appropriate device handler, corresponding devices +========= will be invisible for remote initiators, which could lead to holes + in the LUN addressing, so automatic device scanning by remote SCSI + mid-level could not notice the devices. Therefore you will have + to add them manually via + 'echo "- - -" >/sys/class/scsi_host/hostX/scan', + where X - is the host number. + +IMPORTANT: Working of target and initiator on the same host is +========= supported, except the following 2 cases: swap over target exported + device and using a writable mmap over a file from target + exported device. The latter means you can't mount a file + system over target exported device. In other words, you can + freely use any sg, sd, st, etc. devices imported from target + on the same host, but you can't mount file systems or put + swap on them. This is a limitation of Linux memory/cache + manager, because in this case an OOM deadlock like: system + needs some memory -> it decides to clear some cache -> cache + needs to write on target exported device -> initiator sends + request to the target -> target needs memory -> system needs + even more memory -> deadlock. + +IMPORTANT: In the current version simultaneous access to local SCSI devices +========= via standard high-level SCSI drivers (sd, st, sg, etc.) and + SCST's target drivers is unsupported. Especially it is + important for execution via sg and st commands that change + the state of devices and their parameters, because that could + lead to data corruption. If any such command is done, at + least related device handler(s) must be restarted. For block + devices READ/WRITE commands using direct disk handler are + generally safe. + + +Usage in failover mode +---------------------- + +It is recommended to use TEST UNIT READY ("tur") command to check if +SCST target is alive in MPIO configurations. + + +Device handlers +--------------- + +Device specific drivers (device handlers) are plugins for SCST, which +help SCST to analyze incoming requests and determine parameters, +specific to various types of devices. If an appropriate device handler +for a SCSI device type isn't loaded, SCST doesn't know how to handle +devices of this type, so they will be invisible for remote initiators +(more precisely, "LUN not supported" sense code will be returned). + +In addition to device handlers for real devices, there are VDISK, user +space and "performance" device handlers. + +VDISK device handler works over files on file systems and makes from +them virtual remotely available SCSI disks or CDROM's. In addition, it +allows to work directly over a block device, e.g. local IDE or SCSI disk +or ever disk partition, where there is no file systems overhead. Using +block devices comparing to sending SCSI commands directly to SCSI +mid-level via scsi_do_req()/scsi_execute_async() has advantage that data +are transferred via system cache, so it is possible to fully benefit from +caching and read ahead performed by Linux's VM subsystem. The only +disadvantage here that in the FILEIO mode there is superfluous data +copying between the cache and SCST's buffers. This issue is going to be +addressed in the next release. Virtual CDROM's are useful for remote +installation. See below for details how to setup and use VDISK device +handler. + +"Performance" device handlers for disks, MO disks and tapes in their +exec() method skip (pretend to execute) all READ and WRITE operations +and thus provide a way for direct link performance measurements without +overhead of actual data transferring from/to underlying SCSI device. + +NOTE: Since "perf" device handlers on READ operations don't touch the +==== commands' data buffer, it is returned to remote initiators as it + was allocated, without even being zeroed. Thus, "perf" device + handlers impose some security risk, so use them with caution. + + +Compilation options +------------------- + +There are the following compilation options, that could be change using +your favorite kernel configuration Makefile target, e.g. "make xconfig": + + - CONFIG_SCST_DEBUG - if defined, turns on some debugging code, + including some logging. Makes the driver considerably bigger and slower, + producing large amount of log data. + + - CONFIG_SCST_TRACING - if defined, turns on ability to log events. Makes the + driver considerably bigger and leads to some performance loss. + + - CONFIG_SCST_EXTRACHECKS - if defined, adds extra validity checks in + the various places. + + - CONFIG_SCST_USE_EXPECTED_VALUES - if not defined (default), initiator + supplied expected data transfer length and direction will be used + only for verification purposes to return error or warn in case if one + of them is invalid. Instead, locally decoded from SCSI command values + will be used. This is necessary for security reasons, because + otherwise a faulty initiator can crash target by supplying invalid + value in one of those parameters. This is especially important in + case of pass-through mode. If CONFIG_SCST_USE_EXPECTED_VALUES is + defined, initiator supplied expected data transfer length and + direction will override the locally decoded values. This might be + necessary if internal SCST commands translation table doesn't contain + SCSI command, which is used in your environment. You can know that if + you enable "minor" trace level and have messages like "Unknown + opcode XX for YY. Should you update scst_scsi_op_table?" in your + kernel log and your initiator returns an error. Also report those + messages in the SCST mailing list [email protected]. + Note, that not all SCSI transports support supplying expected values. + + - CONFIG_SCST_DEBUG_TM - if defined, turns on task management functions + debugging, when on LUN 6 some of the commands will be delayed for + about 60 sec., so making the remote initiator send TM functions, eg + ABORT TASK and TARGET RESET. Also define + CONFIG_SCST_TM_DBG_GO_OFFLINE symbol in the Makefile if you want that + the device eventually become completely unresponsive, or otherwise to + circle around ABORTs and RESETs code. Needs CONFIG_SCST_DEBUG turned + on. + + - CONFIG_SCST_STRICT_SERIALIZING - if defined, makes SCST send all commands to + underlying SCSI device synchronously, one after one. This makes task + management more reliable, with cost of some performance penalty. This + is mostly actual for stateful SCSI devices like tapes, where the + result of command's execution depends from device's settings defined + by previous commands. Disk and RAID devices are stateless in the most + cases. The current SCSI core in Linux doesn't allow to abort all + commands reliably if they sent asynchronously to a stateful device. + Turned off by default, turn it on if you use stateful device(s) and + need as much error recovery reliability as possible. As a side effect + of CONFIG_SCST_STRICT_SERIALIZING, on kernels below 2.6.30 no kernel + patching is necessary for pass-through device handlers (scst_disk, + etc.). + + - CONFIG_SCST_TEST_IO_IN_SIRQ - if defined, allows SCST to submit selected + SCSI commands (TUR and READ/WRITE) from soft-IRQ context (tasklets). + Enabling it will decrease amount of context switches and slightly + improve performance. The goal of this option is to be able to measure + overhead of the context switches. If after enabling this option you + don't see under load in vmstat output on the target significant + decrease of amount of context switches, then your target driver + doesn't submit commands to SCST in IRQ context. For instance, + iSCSI-SCST doesn't do that, but qla2x00t with + CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD disabled - does. This option is + designed to be used with vdisk NULLIO backend. + + WARNING! Using this option enabled with other backend than vdisk + NULLIO is unsafe and can lead you to a kernel crash! + + - CONFIG_SCST_STRICT_SECURITY - if defined, makes SCST zero allocated data + buffers. Undefining it (default) considerably improves performance + and eases CPU load, but could create a security hole (information + leakage), so enable it, if you have strict security requirements. + + - CONFIG_SCST_ABORT_CONSIDER_FINISHED_TASKS_AS_NOT_EXISTING - if defined, + in case when TASK MANAGEMENT function ABORT TASK is trying to abort a + command, which has already finished, remote initiator, which sent the + ABORT TASK request, will receive TASK NOT EXIST (or ABORT FAILED) + response for the ABORT TASK request. This is more logical response, + since, because the command finished, attempt to abort it failed, but + some initiators, particularly VMware iSCSI initiator, consider TASK + NOT EXIST response as if the target got crazy and try to RESET it. + Then sometimes get crazy itself. So, this option is disabled by + default. + + - CONFIG_SCST_MEASURE_LATENCY - if defined, provides in "latency" files + global and per-LUN average commands processing latency statistic. You + can clear already measured results by writing 0 in each file. Note, + you need a non-preemptible kernel to have correct results. + +HIGHMEM kernel configurations are fully supported, but not recommended +for performance reasons. + + +Module parameters +----------------- + +Module scst supports the following parameters: + + - scst_threads - allows to set count of SCST's threads. By default it + is CPU count. + + - scst_max_cmd_mem - sets maximum amount of memory in MB allowed to be + consumed by the SCST commands for data buffers at any given time. By + default it is approximately TotalMem/4. + + +SCST sysfs interface +-------------------- + +Root of SCST sysfs interface is /sys/kernel/scst_tgt. It has the +following entries: + + - devices - this is a root subdirectory for all SCST devices + + - handlers - this is a root subdirectory for all SCST dev handlers + + - sgv - this is a root subdirectory for all SCST SGV caches + + - targets - this is a root subdirectory for all SCST targets + + - setup_id - allows to read and write SCST setup ID. This ID can be + used in cases, when the same SCST configuration should be installed + on several targets, but exported from those targets devices should + have different IDs and SNs. For instance, VDISK dev handler uses this + ID to generate T10 vendor specific identifier and SN of the devices. + + - threads - allows to read and set number of global SCST I/O threads. + Those threads used with async. dev handlers, for instance, vdisk + BLOCKIO or NULLIO. + + - trace_level - allows to enable and disable various tracing + facilities. See content of this file for help how to use it. + + - version - read-only attribute, which allows to see version of + SCST and enabled optional features. + + - last_sysfs_mgmt_res - read-only attribute returning completion status + of the last management command. In the sysfs implementation there are + some problems between internal sysfs and internal SCST locking. To + avoid them in some cases sysfs calls can return error with errno + EAGAIN. This doesn't mean the operation failed. It only means that + the operation queued and not yet completed. To wait for it to + complete, an management tool should poll this file. If the operation + hasn't yet completed, it will also return EAGAIN. But after it's + completed, it will return the result of this operation (0 for success + or -errno for error). + +Each SCST sysfs file (attribute) can contain in the last line mark +"[key]". It is automatically added mark used to allow scstadmin to see +which attributes it should save in the config file. You can ignore it. + +"Devices" subdirectory contains subdirectories for each SCST devices. + +Content of each device's subdirectory is dev handler specific. See +documentation for your dev handlers for more info about it as well as +SysfsRules file for more info about common to all dev handlers rules. +SCST dev handlers can have the following common entries: + + - exported - subdirectory containing links to all LUNs where this + device was exported. + + - handler - if dev handler determined for this device, this link points + to it. The handler can be not set for pass-through devices. + + - threads_num - shows and allows to set number of threads in this device's + threads pool. If 0 - no threads will be created, and global SCST + threads pool will be used. If <0 - creation of the threads pool is + prohibited. + + - threads_pool_type - shows and allows to sets threads pool type. + Possible values: "per_initiator" and "shared". When the value is + "per_initiator" (default), each session from each initiator will use + separate dedicated pool of threads. When the value is "shared", all + sessions from all initiators will share the same per-device pool of + threads. Valid only if threads_num attribute >0. + + - dump_prs - allows to dump persistent reservations information in the + kernel log. + + - type - SCSI type of this device + +See below for more information about other entries of this subdirectory +of the standard SCST dev handlers. + +"Handlers" subdirectory contains subdirectories for each SCST dev +handler. + +Content of each handler's subdirectory is dev handler specific. See +documentation for your dev handlers for more info about it as well as +SysfsRules file for more info about common to all dev handlers rules. +SCST dev handlers can have the following common entries: + + - mgmt - this entry allows to create virtual devices and their + attributes (for virtual devices dev handlers) or assign/unassign real + SCSI devices to/from this dev handler (for pass-through dev + handlers). + + - trace_level - allows to enable and disable various tracing + facilities. See content of this file for help how to use it. + + - type - SCSI type of devices served by this dev handler. + +See below for more information about other entries of this subdirectory +of the standard SCST dev handlers. + +"Sgv" subdirectory contains statistic information of SCST SGV caches. It +has the following entries: + + - None, one or more subdirectories for each existing SGV cache. + + - global_stats - file containing global SGV caches statistics. + +Each SGV cache's subdirectory has the following item: + + - stats - file containing statistics for this SGV caches. + +"Targets" subdirectory contains subdirectories for each SCST target. + +Content of each target's subdirectory is target specific. See +documentation for your target for more info about it as well as +SysfsRules file for more info about common to all targets rules. +Every target should have at least the following entries: + + - ini_groups - subdirectory, which contains and allows to define + initiator-oriented access control information, see below. + + - luns - subdirectory, which contains list of available LUNs in the + target-oriented access control and allows to define it, see below. + + - sessions - subdirectory containing connected to this target sessions. + + - enabled - using this attribute you can enable or disable this target/ + It allows to finish configuring it before it starts accepting new + connections. 0 by default. + + - addr_method - used LUNs addressing method. Possible values: + "Peripheral" and "Flat". Most initiators work well with Peripheral + addressing method (default), but some (HP-UX, for instance) may + require Flat method. This attribute is also available in the + initiators security groups, so you can assign the addressing method + on per-initiator basis. + + - cpu_mask - defines CPU affinity mask for threads serving this target. + For threads serving LUNs it is used only for devices with + threads_pool_type "per_initiator". + + - io_grouping_type - defines how I/O from sessions to this target are + grouped together. This I/O grouping is very important for + performance. By setting this attribute in a right value, you can + considerably increase performance of your setup. This grouping is + performed only if you use CFQ I/O scheduler on the target and for + devices with threads_num >= 0 and, if threads_num > 0, with + threads_pool_type "per_initiator". Possible values: + "this_group_only", "never", "auto", or I/O group number >0. When the + value is "this_group_only" all I/O from all sessions in this target + will be grouped together. When the value is "never", I/O from + different sessions will not be grouped together, i.e. all sessions in + this target will have separate dedicated I/O groups. When the value + is "auto" (default), all I/O from initiators with the same name + (iSCSI initiator name, for instance) in all targets will be grouped + together with a separate dedicated I/O group for each initiator name. + For iSCSI this mode works well, but other transports usually use + different initiator names for different sessions, so using such + transports in MPIO configurations you should either use value + "this_group_only", or an explicit I/O group number. This attribute is + also available in the initiators security groups, so you can assign + the I/O grouping on per-initiator basis. See below for more info how + to use this attribute. + + - rel_tgt_id - allows to read or write SCSI Relative Target Port + Identifier attribute. This identifier is used to identify SCSI Target + Ports by some SCSI commands, mainly by Persistent Reservations + commands. This identifier must be unique among all SCST targets, but + for convenience SCST allows disabled targets to have not unique + rel_tgt_id. In this case SCST will not allow to enable this target + until rel_tgt_id becomes unique. This attribute initialized unique by + SCST by default. + +A target driver may have also the following entries: + + - "hw_target" - if the target driver supports both hardware and virtual + targets (for instance, an FC adapter supporting NPIV, which has + hardware targets for its physical ports as well as virtual NPIV + targets), this read only attribute for all hardware targets will + exist and contain value 1. + +Subdirectory "sessions" contains one subdirectory for each connected +session with name equal to name of the connected initiator. + +Each session subdirectory contains the following entries: + + - initiator_name - contains initiator name + + - force_close - optional write-only attribute, which allows to force + close this session. + + - active_commands - contains number of active, i.e. not yet or being + executed, SCSI commands in this session. + + - commands - contains overall number of SCSI commands in this session. + + - latency - if CONFIG_SCST_MEASURE_LATENCY enabled, contains latency + statistics for this session. + + - luns - a link pointing out to the corresponding LUNs set (security + group) where this session was attached to. + + - One or more "lunX" subdirectories, where 'X' is a number, for each LUN + this session has (see below). + + - other target driver specific attributes and subdirectories. + +See below description of the VDISK's sysfs interface for samples. + + +Access and devices visibility management (LUN masking) +------------------------------------------------------ + +Access and devices visibility management allows for an initiator or +group of initiators to see different devices with different LUNs +with necessary access permissions. + +SCST supports two modes of access control: + +1. Target-oriented. In this mode you define for each target a default +set of LUNs, which are accessible to all initiators, connected to that +target. This is a regular access control mode, which people usually mean +thinking about access control in general. For instance, in IET this is +the only supported mode. + +2. Initiator-oriented. In this mode you define which LUNs are accessible +for each initiator. In this mode you should create for each set of one +or more initiators, which should access to the same set of devices with +the same LUNs, a separate security group, then add to it devices and +names of allowed initiator(s). + +Both modes can be used simultaneously. In this case the +initiator-oriented mode has higher priority, than the target-oriented, +i.e. initiators are at first searched in all defined security groups for +this target and, if none matches, the default target's set of LUNs is +used. This set of LUNs might be empty, then the initiator will not see +any LUNs from the target. + +You can at any time find out which set of LUNs each session is assigned +to by looking where link +/sys/kernel/scst_tgt/targets/target_driver/target_name/sessions/initiator_name/luns +points to. + +To configure the target-oriented access control SCST provides the +following interface. Each target's sysfs subdirectory +(/sys/kernel/scst_tgt/targets/target_driver/target_name) has "luns" +subdirectory. This subdirectory contains the list of already defined +target-oriented access control LUNs for this target as well as file +"mgmt". This file has the following commands, which you can send to it, +for instance, using "echo" shell command. You can always get a small +help about supported commands by looking inside this file. "Parameters" +are one or more param_name=value pairs separated by ';'. + + - "add H:C:I:L lun [parameters]" - adds a pass-through device with + host:channel:id:lun with LUN "lun". Optionally, the device could be + marked as read only by using parameter "read_only". The recommended + way to find out H:C:I:L numbers is use of lsscsi utility. + + - "replace H:C:I:L lun [parameters]" - replaces by pass-through device + with host:channel:id:lun existing with LUN "lun" device with + generation of INQUIRY DATA HAS CHANGED Unit Attention. If the old + device doesn't exist, this command acts as the "add" command. + Optionally, the device could be marked as read only by using + parameter "read_only". The recommended way to find out H:C:I:L + numbers is use of lsscsi utility. + + - "add VNAME lun [parameters]" - adds a virtual device with name VNAME + with LUN "lun". Optionally, the device could be marked as read only + by using parameter "read_only". + + - "replace VNAME lun [parameters]" - replaces by virtual device + with name VNAME existing with LUN "lun" device with generation of + INQUIRY DATA HAS CHANGED Unit Attention. If the old device doesn't + exist, this command acts as the "add" command. Optionally, the device + could be marked as read only by using parameter "read_only". + + - "del lun" - deletes LUN lun + + - "clear" - clears the list of devices + +To configure the initiator-oriented access control SCST provides the +following interface. Each target's sysfs subdirectory +(/sys/kernel/scst_tgt/targets/target_driver/target_name) has "ini_groups" +subdirectory. This subdirectory contains the list of already defined +security groups for this target as well as file "mgmt". This file has +the following commands, which you can send to it, for instance, using +"echo" shell command. You can always get a small help about supported +commands by looking inside this file. + + - "create GROUP_NAME" - creates a new security group. + + - "del GROUP_NAME" - deletes a new security group. + +Each security group's subdirectory contains 2 subdirectories: initiators +and luns as well as the following attributes: addr_method, cpu_mask and +io_grouping_type. See above description of them. + +Each "initiators" subdirectory contains list of added to this groups +initiator as well as as well as file "mgmt". This file has the following +commands, which you can send to it, for instance, using "echo" shell +command. You can always get a small help about supported commands by +looking inside this file. + + - "add INITIATOR_NAME" - adds initiator with name INITIATOR_NAME to the + group. + + - "del INITIATOR_NAME" - deletes initiator with name INITIATOR_NAME + from the group. + + - "move INITIATOR_NAME DEST_GROUP_NAME" moves initiator with name + INITIATOR_NAME from the current group to group with name + DEST_GROUP_NAME. + + - "clear" - deletes all initiators from this group. + +For "add" and "del" commands INITIATOR_NAME can be a simple DOS-type +patterns, containing '*' and '?' symbols. '*' means match all any +symbols, '?' means match only any single symbol. For instance, +"blah.xxx" will match "bl?h.*". Additionally, you can use negative sign +'!' to revert the value of the pattern. For instance, "ah.xxx" will +match "!bl?h.*". + +Each "luns" subdirectory contains the list of already defined LUNs for +this group as well as file "mgmt". Content of this file as well as list +of available in it commands is fully identical to the "luns" +subdirectory of the target-oriented access control. + +Examples: + + - echo "create INI" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/mgmt - + creates security group INI for target iqn.2006-10.net.vlnb:tgt1. + + - echo "add 2:0:1:0 11" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/INI/luns/mgmt - + adds a pass-through device sitting on host 2, channel 0, ID 1, LUN 0 + to group with name INI as LUN 11. + + - echo "add disk1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/INI/luns/mgmt - + adds a virtual disk with name disk1 to group with name INI as LUN 0. + + - echo "add 21:*:e0:?b:83:*" >/sys/kernel/scst_tgt/targets/21:00:00:a0:8c:54:52:12/ini_groups/INI/initiators/mgmt - + adds a pattern to group with name INI to Fibre Channel target with + WWN 21:00:00:a0:8c:54:52:12, which matches WWNs of Fibre Channel + initiator ports. + +Consider you need to have an iSCSI target with name +"iqn.2007-05.com.example:storage.disk1.sys1.xyz", which should export +virtual device "dev1" with LUN 0 and virtual device "dev2" with LUN 1, +but initiator with name +"iqn.2007-05.com.example:storage.disk1.spec_ini.xyz" should see only +virtual device "dev2" read only with LUN 0. To achieve that you should +do the following commands: + +# echo "iqn.2007-05.com.example:storage.disk1.sys1.xyz" >/sys/kernel/scst_tgt/targets/iscsi/mgmt +# echo "add dev1 0" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/luns/mgmt +# echo "add dev2 1" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/luns/mgmt +# echo "create SPEC_INI" >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_groups/mgmt +# echo "add dev2 0 read_only=1" \ + >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_groups/SPEC_INI/luns/mgmt +# echo "iqn.2007-05.com.example:storage.disk1.spec_ini.xyz" \ + >/sys/kernel/scst_tgt/targets/iscsi/iqn.2007-05.com.example:storage.disk1.sys1.xyz/ini_groups/SPEC_INI/initiators/mgmt + +For Fibre Channel or SAS in the above example you should use target's +and initiator ports WWNs instead of iSCSI names. + +It is highly recommended to use scstadmin utility instead of described +in this section low level interface. + +IMPORTANT +========= + +There must be LUN 0 in each set of LUNs, i.e. LUs numeration must not +start from, e.g., 1. Otherwise you will see no devices on remote +initiators and SCST core will write into the kernel log message: "tgt_dev +for LUN 0 not found, command to unexisting LU?" + +IMPORTANT +========= + +All the access control must be fully configured BEFORE the corresponding +target is enabled. When you enable a target, it will immediately start +accepting new connections, hence creating new sessions, and those new +sessions will be assigned to security groups according to the +*currently* configured access control settings. For instance, to +the default target's set of LUNs, instead of "HOST004" group as you may +need, because "HOST004" doesn't exist yet. So, you must configure all +the security groups before new connections from the initiators are +created, i.e. before the target enabled. + + +VDISK device handler +-------------------- + +VDISK has 4 built-in dev handlers: vdisk_fileio, vdisk_blockio, +vdisk_nullio and vcdrom. Roots of their sysfs interface are +/sys/kernel/scst_tgt/handlers/handler_name, e.g. for vdisk_fileio: +/sys/kernel/scst_tgt/handlers/vdisk_fileio. Each root has the following +entries: + + - None, one or more links to devices with name equal to names + of the corresponding devices. + + - trace_level - allows to enable and disable various tracing + facilities. See content of this file for help how to use it. + + - mgmt - main management entry, which allows to add/delete VDISK + devices with the corresponding type. + +The "mgmt" file has the following commands, which you can send to it, +for instance, using "echo" shell command. You can always get a small +help about supported commands by looking inside this file. "Parameters" +are one or more param_name=value pairs separated by ';'. + + - echo "add_device device_name [parameters]" - adds a virtual device + with name device_name and specified parameters (see below) + + - echo "del_device device_name" - deletes a virtual device with name + device_name. + +Handler vdisk_fileio provides FILEIO mode to create virtual devices. +This mode uses as backend files and accesses to them using regular +read()/write() file calls. This allows to use full power of Linux page +cache. The following parameters possible for vdisk_fileio: + + - filename - specifies path and file name of the backend file. The path + must be absolute. + + - blocksize - specifies block size used by this virtual device. The + block size must be power of 2 and >= 512 bytes. Default is 512. + + - write_through - disables write back caching. Note, this option + has sense only if you also *manually* disable write-back cache in + *all* your backstorage devices and make sure it's actually disabled, + since many devices are known to lie about this mode to get better + benchmark results. Default is 0. + + - read_only - read only. Default is 0. + + - o_direct - disables both read and write caching. This mode isn't + currently fully implemented, you should use user space fileio_tgt + program in O_DIRECT mode instead (see below). + + - nv_cache - enables "non-volatile cache" mode. In this mode it is + assumed that the target has a GOOD UPS with ability to cleanly + shutdown target in case of power failure and it is software/hardware + bugs free, i.e. all data from the target's cache are guaranteed + sooner or later to go to the media. Hence all data synchronization + with media operations, like SYNCHRONIZE_CACHE, are ignored in order + to bring more performance. Also in this mode target reports to + initiators that the corresponding device has write-through cache to + disable all write-back cache workarounds used by initiators. Use with + extreme caution, since in this mode after a crash of the target + journaled file systems don't guarantee the consistency after journal + recovery, therefore manual fsck MUST be ran. Note, that since usually + the journal barrier protection (see "IMPORTANT" note below) turned + off, enabling NV_CACHE could change nothing from data protection + point of view, since no data synchronization with media operations + will go from the initiator. This option overrides "write_through" + option. Disabled by default. + + - thin_provisioned - enables thin provisioning facility, when remote + initiators can unmap blocks of storage, if they don't need them + anymore. Backend storage also must support this facility. + + - removable - with this flag set the device is reported to remote + initiators as removable. + +Handler vdisk_blockio provides BLOCKIO mode to create virtual devices. +This mode performs direct block I/O with a block device, bypassing the +page cache for all operations. This mode works ideally with high-end +storage HBAs and for applications that either do not need caching +between application and disk or need the large block throughput. See +below for more info. + +The following parameters possible for vdisk_blockio: filename, +blocksize, nv_cache, read_only, removable, thin_provisioned. See +vdisk_fileio above for description of those parameters. + +Handler vdisk_nullio provides NULLIO mode to create virtual devices. In +this mode no real I/O is done, but success returned to initiators. +Intended to be used for performance measurements at the same way as +"*_perf" handlers. The following parameters possible for vdisk_nullio: +blocksize, read_only, removable. See vdisk_fileio above for description +of those parameters. + +Handler vcdrom allows emulation of a virtual CDROM device using an ISO +file as backend. It doesn't have any parameters. + +For example: + +echo "add_device disk1 filename=/disk1; blocksize=4096; nv_cache=1" >/sys/kernel/scst_tgt/handlers/vdisk_fileio/mgmt + +will create a FILEIO virtual device disk1 with backend file /disk1 +with block size 4K and NV_CACHE enabled. + +Each vdisk_fileio's device has the following attributes in +/sys/kernel/scst_tgt/devices/device_name: + + - filename - contains path and file name of the backend file. + + - blocksize - contains block size used by this virtual device. + + - write_through - contains status of write back caching of this virtual + device. + + - read_only - contains read only status of this virtual device. + + - o_direct - contains O_DIRECT status of this virtual device. + + - nv_cache - contains NV_CACHE status of this virtual device. + + - thin_provisioned - contains thin provisioning status of this virtual + device + + - removable - contains removable status of this virtual device. + + - size_mb - contains size of this virtual device in MB. + + - t10_dev_id - contains and allows to set T10 vendor specific + identifier for Device Identification VPD page (0x83) of INQUIRY data. + By default VDISK handler always generates t10_dev_id for every new + created device at creation time based on the device name and + scst_vdisk_ID scst_vdisk.ko module parameter (see below). + + - usn - contains the virtual device's serial number of INQUIRY data. It + is created at the device creation time based on the device name and + scst_vdisk_ID scst_vdisk.ko module parameter (see below). + + - type - contains SCSI type of this virtual device. + + - resync_size - write only attribute, which makes vdisk_fileio to + rescan size of the backend file. It is useful if you changed it, for + instance, if you resized it. + +For example: + +/sys/kernel/scst_tgt/devices/disk1 +|-- blocksize +|-- exported +| |-- export0 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/luns/0 +| |-- export1 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt/ini_groups/INI/luns/0 +| |-- export2 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/luns/0 +| |-- export3 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/INI1/luns/0 +| |-- export4 -> ../../../targets/iscsi/iqn.2006-10.net.vlnb:tgt1/ini_groups/INI2/luns/0 +|-- filename +|-- handler -> ../../handlers/vdisk_fileio +|-- nv_cache +|-- o_direct +|-- read_only +|-- removable +|-- resync_size +|-- size_mb +|-- t10_dev_id +|-- thin_provisioned +|-- threads_num +|-- threads_pool_type +|-- type +|-- usn +`-- write_through + +Each vdisk_blockio's device has the following attributes in +/sys/kernel/scst_tgt/devices/device_name: blocksize, filename, nv_cache, +read_only, removable, resync_size, size_mb, t10_dev_id, +thin_provisioned, threads_num, threads_pool_type, type, usn. See above +description of those parameters. + +Each vdisk_nullio's device has the following attributes in +/sys/kernel/scst_tgt/devices/device_name: blocksize, read_only, +removable, size_mb, t10_dev_id, threads_num, threads_pool_type, type, +usn. See above description of those parameters. + +Each vcdrom's device has the following attributes in +/sys/kernel/scst_tgt/devices/device_name: filename, size_mb, +t10_dev_id, threads_num, threads_pool_type, type, usn. See above +description of those parameters. Exception is filename attribute. For +vcdrom it is writable. Writing to it allows to virtually insert or +change virtual CD media in the virtual CDROM device. For example: + + - echo "/image.iso" >/sys/kernel/scst_tgt/devices/cdrom/filename - will + insert file /image.iso as virtual media to the virtual CDROM cdrom. + + - echo "" >/sys/kernel/scst_tgt/devices/cdrom/filename - will remove + "media" from the virtual CDROM cdrom. + +Additionally VDISK handler has module parameter "num_threads", which +specifies count of I/O threads for each FILEIO VDISK's or VCDROM device. +If you have a workload, which tends to produce rather random accesses +(e.g. DB-like), you should increase this count to a bigger value, like +32. If you have a rather sequential workload, you should decrease it to +a lower value, like number of CPUs on the target or even 1. Due to some +limitations of Linux I/O subsystem, increasing number of I/O threads too +much leads to sequential performance drop, especially with deadline +scheduler, so decreasing it can improve sequential performance. The +default provides a good compromise between random and sequential +accesses. + +You shouldn't be afraid to have too many VDISK I/O threads if you have +many VDISK devices. Kernel threads consume very little amount of +resources (several KBs) and only necessary threads will be used by SCST, +so the threads will not trash your system. + +CAUTION: If you partitioned/formatted your device with block size X, *NEVER* +======== ever try to export and then mount it (even accidentally) with another + block size. Otherwise you can *instantly* damage it pretty + badly as well as all your data on it. Messages on initiator + like: "attempt to access beyond end of device" is the sign of + such damage. + + Moreover, if you want to compare how well different block sizes + work for you, you **MUST** EVERY TIME AFTER CHANGING BLOCK SIZE + **COMPLETELY** **WIPE OFF** ALL THE DATA FROM THE DEVICE. In + other words, THE **WHOLE** DEVICE **MUST** HAVE ONLY **ZEROS** + AS THE DATA AFTER YOU SWITCH TO NEW BLOCK SIZE. Switching block + sizes isn't like switching between FILEIO and BLOCKIO, after + changing block size all previously written with another block + size data MUST BE ERASED. Otherwise you will have a full set of + very weird behaviors, because blocks addressing will be + changed, but initiators in most cases will not have a + possibility to detect that old addresses written on the device + in, e.g., partition table, don't refer anymore to what they are + intended to refer. + +IMPORTANT: Some disk and partition table management utilities don't support +========= block sizes >512 bytes, therefore make sure that your favorite one + supports it. Currently only cfdisk is known to work only with + 512 bytes blocks, other utilities like fdisk on Linux or + standard disk manager on Windows are proved to work well with + non-512 bytes blocks. Note, if you export a disk file or + device with some block size, different from one, with which + it was already partitioned, you could get various weird + things like utilities hang up or other unexpected behavior. + Hence, to be sure, zero the exported file or device before + the first access to it from the remote initiator with another + block size. On Window initiator make sure you "Set Signature" + in the disk manager on the imported from the target drive + before doing any other partitioning on it. After you + successfully mounted a file system over non-512 bytes block + size device, the block size stops matter, any program will + work with files on such file system. + + +Persistent Reservations +----------------------- + +SCST implements Persistent Reservations with full set of capabilities, +including "Persistence Through Power Loss". + +The "Persistence Through Power Loss" data are saved in /var/lib/scst/pr +with files with names the same as the names of the corresponding +devices. Also this directory contains backup versions of those files +with suffix ".1". Those backup files are used in case of power or other +failure to prevent Persistent Reservation information from corruption +during update. + +The Persistent Reservations available on all transports implementing +get_initiator_port_transport_id() callback. Transports not implementing +this callback will act in one of 2 possible scenarios ("all or +nothing"): + +1. If a device has such transport connected and doesn't have persistent +reservations, it will refuse Persistent Reservations commands as if it +doesn't support them. + +2. If a device has persistent reservations, all initiators newly +connecting via such transports will not see this device. After all +persistent reservations from this device are released, upon reconnect +the initiators will see it. + + +Caching +------- + +By default for performance reasons VDISK FILEIO devices use write back +caching policy. + +Generally, write back caching is safe for use and danger of it is +greatly overestimated, because most modern (especially, Enterprise +level) applications are well prepared to work with write back cached +storage. Particularly, such are all transactions-based applications. +Those applications flush cache to completely avoid ANY data loss on a +crash or power failure. For instance, journaled file systems flush cache +on each meta data update, so they survive power/hardware/software +failures pretty well. + +Since locally on initiators write back caching is always on, if an +application cares about its data consistency, it does flush the cache +when necessary or on any write, if open files with O_SYNC. If it doesn't +care, it doesn't flush the cache. As soon as the cache flushes +propagated to the storage, write back caching on it doesn't make any +difference. If application doesn't flush the cache, it's doomed to loose +data in case of a crash or power failure doesn't matter where this cache +located, locally or on the storage. + +To illustrate that consider, for example, a user who wants to copy /src +directory to /dst directory reliably, i.e. after the copy finished no +power failure or software/hardware crash could lead to a loss of the +data in /dst. There are 2 ways to achieve this. Let's suppose for +simplicity cp opens files for writing with O_SYNC flag, hence bypassing +the local cache. + +1. Slow. Make the device behind /dst working in write through caching +mode and then run "cp -a /src /dst". + +2. Fast. Let the device behind /dst working in write back caching mode +and then run "cp -a /src /dst; sync". The reliability of the result is +the same, but it's much faster than (1). Nobody would care if a crash +happens during the copy, because after recovery simply leftovers from +the not completed attempt would be deleted and the operation would be +restarted from the very beginning. + +So, you can see in (2) there is no danger of ANY data loss from the +write back caching. Moreover, since on practice cp doesn't open files +for writing with O_SYNC flag, to get the copy done reliably, sync +command must be called after cp anyway, so enabling write back caching +wouldn't make any difference for reliability. + +Also you can consider it from another side. Modern HDDs have at least +16MB of cache working in write back mode by default, so for a 10 drives +RAID it is 160MB of a write back cache. How many people are happy with +it and how many disabled write back cache of their HDDs? Almost all and +almost nobody correspondingly? Moreover, many HDDs lie about state of +their cache and report write through while working in write back mode. +They are also successfully used. + +Note, Linux I/O subsystem guarantees to propagated cache flushes to the +storage only using data protection barriers, which usually turned off by +default (see http://lwn.net/Articles/283161). Without barriers enabled +Linux doesn't provide a guarantee that after sync()/fsync() all written +data really hit permanent storage. They can be stored in the cache of +your backstorage devices and, hence, lost on a power failure event. +Thus, ever with write-through cache mode, you still either need to +enable barriers on your backend file system on the target (for direct +/dev/sdX devices this is, indeed, impossible), or need a good UPS to +protect yourself from not committed data loss. Some info about barriers +from the XFS point of view could be found at +http://oss.sgi.com/projects/xfs/faq.html#wcache. On Linux initiators for +Ext3 and ReiserFS file systems the barrier protection could be turned on +using "barrier=1" and "barrier=flush" mount options correspondingly. You +can check if the barriers turn on or off by looking in /proc/mounts. +Windows and, AFAIK, other UNIX'es don't need any special explicit +options and do necessary barrier actions on write-back caching devices +by default. + +To limit this data loss with write back caching you can use files in +/proc/sys/vm to limit amount of unflushed data in the system cache. + +If you for some reason have to use VDISK FILEIO devices in write through +caching mode, don't forget to disable internal caching on their backend +devices or make sure they have additional battery or supercapacitors +power supply on board. Otherwise, you still on a power failure would +loose all the unsaved yet data in the devices internal cache. + +Note, on some real-life workloads write through caching might perform +better, than write back one with the barrier protection turned on. + + +BLOCKIO VDISK mode +------------------ + +This module works best for these types of scenarios: + +1) Data that are not aligned to 4K sector boundaries and <4K block sizes +are used, which is normally found in virtualization environments where +operating systems start partitions on odd sectors (Windows and it's +sector 63). + +2) Large block data transfers normally found in database loads/dumps and +streaming media. + +3) Advanced relational database systems that perform their own caching +which prefer or demand direct IO access and, because of the nature of +their data access, can actually see worse performance with +non-discriminate caching. + +4) Multiple layers of targets were the secondary and above layers need +to have a consistent view of the primary targets in order to preserve +data integrity which a page cache backed IO type might not provide +reliably. + +Also it has an advantage over FILEIO that it doesn't copy data between +the system cache and the commands data buffers, so it saves a +considerable amount of CPU power and memory bandwidth. + +IMPORTANT: Since data in BLOCKIO and FILEIO modes are not consistent between +========= each other, if you try to use a device in both those modes + simultaneously, you will almost instantly corrupt your data + on that device. + +IMPORTANT: If SCST 1.x BLOCKIO worked by default in NV_CACHE mode, when +========= each device reported to remote initiators as having write through + caching. But if your backend block device has internal write + back caching it might create a possibility for data loss of + the cached in the internal cache data in case of a power + failure. Starting from SCST 2.0 BLOCKIO works by default in + non-NV_CACHE mode, when each device reported to remote + initiators as having write back caching, and synchronizes the + internal device's cache on each SYNCHRONIZE_CACHE command + from the initiators. It might lead to some PERFORMANCE LOSS, + so if you are are sure in your power supply and want to + restore 1.x behavior, your should recreate your BLOCKIO + devices in NV_CACHE mode. + + +Pass-through mode +----------------- + +In the pass-through mode (i.e. using the pass-through device handlers +scst_disk, scst_tape, etc) SCSI commands, coming from remote initiators, +are passed to local SCSI devices on target as is, without any +modifications. + +SCST supports 1 to many pass-through, when several initiators can safely +connect a single pass-through device (a tape, for instance). For such +cases SCST emulates all the necessary functionality. + +In the sysfs interface all real SCSI devices are listed in +/sys/kernel/scst_tgt/devices in form host:channel:id:lun numbers, for +instance 1:0:0:0. The recommended way to match those numbers to your +devices is use of lsscsi utility. + +Each pass-through dev handler has in its root subdirectory +/sys/kernel/scst_tgt/handlers/handler_name, e.g. +/sys/kernel/scst_tgt/handlers/dev_disk, "mgmt" file. It allows the +following commands. They can be sent to it using, e.g., echo command. + + - "add_device" - this command assigns SCSI device with +host:channel:id:lun numbers to this dev handler. + +echo "add_device 1:0:0:0" >/sys/kernel/scst_tgt/handlers/dev_disk/mgmt + +will assign SCSI device 1:0:0:0 to this dev handler. + + - "del_device" - this command unassigns SCSI device with +host:channel:id:lun numbers from this dev handler. + +As usually, on read the "mgmt" file returns small help about available +commands. + +You need to manually assign each your real SCSI device to the +corresponding pass-through dev handler using the "add_device" command, +otherwise the real SCSI devices will not be visible remotely. The +assignment isn't done automatically, because it could lead to the +pass-through dev handlers load and initialization problems if any of the +local real SCSI devices are malfunctioning. + +As any other hardware, the local SCSI hardware can not handle commands +with amount of data and/or segments count in scatter-gather array bigger +some values. Therefore, when using the pass-through mode you should note +that values for maximum number of segments and maximum amount of +transferred data for each SCSI command on devices on initiators can not +be bigger, than corresponding values of the corresponding SCSI devices +on the target. Otherwise you will see symptoms like small transfers work +well, but large ones stall and messages like: "Unable to complete +command due to SG IO count limitation" are printed in the kernel logs. + +You can't control from the user space limit of the scatter-gather +segments, but for block devices usually it is sufficient if you set on +the initiators /sys/block/DEVICE_NAME/queue/max_sectors_kb in the same +or lower value as in /sys/block/DEVICE_NAME/queue/max_hw_sectors_kb for +the corresponding devices on the target. + +For not-block devices SCSI commands are usually generated directly by +applications, so, if you experience large transfers stalls, you should +check documentation for your application how to limit the transfer +sizes. + +Another way to solve this issue is to build SG entries with more than 1 +page each. See the following patch as an example: +http://scst.sourceforge.net/sgv_big_order_alloc.diff + + +Performance +----------- + +SCST from the very beginning has been designed and implemented to +provide the best possible performance. Since there is no "one fit all" +the best performance configuration for different setups and loads, SCST +provides extensive set of settings to allow to tune it for the best +performance in each particular case. You don't have to necessary use +those settings. If you don't, SCST will do very good job to autotune for +you, so the resulting performance will, in average, be better +(sometimes, much better) than with other SCSI targets. But in some cases +you can by manual tuning improve it even more. + +Before doing any performance measurements note that performance results +are very much dependent from your type of load, so it is crucial that +you choose access mode (FILEIO, BLOCKIO, O_DIRECT, pass-through), which +suits your needs the best. + +In order to get the maximum performance you should: + +1. For SCST: + + - Disable in Makefile CONFIG_SCST_STRICT_SERIALIZING, CONFIG_SCST_EXTRACHECKS, + CONFIG_SCST_TRACING, CONFIG_SCST_DEBUG*, CONFIG_SCST_STRICT_SECURITY, + CONFIG_SCST_MEASURE_LATENCY + +2. For target drivers: + + - Disable in Makefiles CONFIG_SCST_EXTRACHECKS, CONFIG_SCST_TRACING, + CONFIG_SCST_DEBUG* + +3. For device handlers, including VDISK: + + - Disable in Makefile CONFIG_SCST_TRACING and CONFIG_SCST_DEBUG. + +4. Make sure you have io_grouping_type option set correctly, especially +in the following cases: + + - Several initiators share your target's backstorage. It can be a + shared LU using some cluster FS, like VMFS, as well as can be + different LUs located on the same backstorage (RAID array). For + instance, if you have 3 initiators and each of them using its own + dedicated FILEIO device file from the same RAID-6 array on the + target. + + In this case for the best performance you should have + io_grouping_type option set in value "never" in all the LUNs' targets + and security groups. + + - Your initiator connected to your target in MPIO mode. In this case for + the best performance you should: + + * Either connect all the sessions from the initiator to a single + target or security group and have io_grouping_type option set in + value "this_group_only" in the target or security group, + + * Or, if it isn't possible to connect all the sessions from the + initiator to a single target or security group, assign the same + numeric io_grouping_type value for each target/security group this + initiator connected to. The exact value itself doesn't matter, + important only that all the targets/security groups use the same + value. + +Don't forget, io_grouping_type makes sense only if you use CFQ I/O +scheduler on the target and for devices with threads_num >= 0 and, if +threads_num > 0, with threads_pool_type "per_initiator". + +You can check if in your setup io_grouping_type set correctly as well as +if the "auto" io_grouping_type value works for you by tests like the +following: + + - For not MPIO case you can run single thread sequential reading, e.g. + using buffered dd, from one initiator, then run the same single + thread sequential reading from the second initiator in parallel. If + io_grouping_type is set correctly the aggregate throughput measured + on the target should only slightly decrease as well as all initiators + should have nearly equal share of it. If io_grouping_type is not set + correctly, the aggregate throughput and/or throughput on any + initiator will decrease significantly, in 2 times or even more. For + instance, you have 80MB/s single thread sequential reading from the + target on any initiator. When then both initiators are reading in + parallel you should see on the target aggregate throughput something + like 70-75MB/s with correct io_grouping_type and something like + 35-40MB/s or 8-10MB/s on any initiator with incorrect. + + - For the MPIO case it's quite easier. With incorrect io_grouping_type + you simply won't see performance increase from adding the second + session (assuming your hardware is capable to transfer data through + both sessions in parallel), or can even see a performance decrease. + +5. If you are going to use your target in an VM environment, for +instance as a shared storage with VMware, make sure all your VMs +connected to the target via *separate* sessions. For instance, for iSCSI +it means that each VM has own connection to the target, not all VMs +connected using a single connection. You can check it using SCST sysfs +interface. For other transports you should use available facilities, +like NPIV for Fibre Channel, to make separate sessions for each VM. If +you miss it, you can greatly loose performance of parallel access to +your target from different VMs. This isn't related to the case if your +VMs are using the same shared storage, like with VMFS, for instance. In +this case all your VM hosts will be connected to the target via separate +sessions, which is enough. + +6. For other target and initiator software parts: + + - Make sure you applied on your kernel all available SCST patches. + If for your kernel version this patch doesn't exist, it is strongly + recommended to upgrade your kernel to version, for which this patch + exists. + + - Don't enable debug/hacking features in the kernel, i.e. use them as + they are by default. + + - The default kernel read-ahead and queuing settings are optimized + for locally attached disks, therefore they are not optimal if they + attached remotely (SCSI target case), which sometimes could lead to + unexpectedly low throughput. You should increase read-ahead size to at + least 512KB or even more on all initiators and the target. + + You should also limit on all initiators maximum amount of sectors per + SCSI command. This tuning is also recommended on targets with large + read-ahead values. To do it on Linux, run: + + echo “64” > /sys/block/sdX/queue/max_sectors_kb + + where specify instead of X your imported from target device letter, + like 'b', i.e. sdb. + + To increase read-ahead size on Linux, run: + + blockdev --setra N /dev/sdX + + where N is a read-ahead number in 512-byte sectors and X is a device + letter like above. + + Note: you need to set read-ahead setting for device sdX again after + you changed the maximum amount of sectors per SCSI command for that + device. + + Note2: you need to restart SCST after you changed read-ahead settings + on the target. + + - You may need to increase amount of requests that OS on initiator + sends to the target device. To do it on Linux initiators, run + + echo “64” > /sys/block/sdX/queue/nr_requests + + where X is a device letter like above. + + You may also experiment with other parameters in /sys/block/sdX + directory, they also affect performance. If you find the best values, + please share them with us. + + - On the target use CFQ IO scheduler. In most cases it has performance + advantage over other IO schedulers, sometimes huge (2+ times + aggregate throughput increase). + + - It is recommended to turn the kernel preemption off, i.e. set + the kernel preemption model to "No Forced Preemption (Server)". + + - Looks like XFS is the best filesystem on the target to store device + files, because it allows considerably better linear write throughput, + than ext3. + +7. For hardware on target. + + - Make sure that your target hardware (e.g. target FC or network card) + and underlaying IO hardware (e.g. IO card, like SATA, SCSI or RAID to + which your disks connected) don't share the same PCI bus. You can + check it using lspci utility. They have to work in parallel, so it + will be better if they don't compete for the bus. The problem is not + only in the bandwidth, which they have to share, but also in the + interaction between cards during that competition. This is very + important, because in some cases if target and backend storage + controllers share the same PCI bus, it could lead up to 5-10 times + less performance, than expected. Moreover, some motherboard (by + Supermicro, particularly) have serious stability issues if there are + several high speed devices on the same bus working in parallel. If + you have no choice, but PCI bus sharing, set in the BIOS PCI latency + as low as possible. + +8. If you use VDISK IO module in FILEIO mode, NV_CACHE option will +provide you the best performance. But using it make sure you use a good +UPS with ability to shutdown the target on the power failure. + +Baseline performance numbers you can find in those measurements: +http://lkml.org/lkml/2009/3/30/283. + +IMPORTANT: If you use on initiator some versions of Windows (at least W2K) +========= you can't get good write performance for VDISK FILEIO devices with + default 512 bytes block sizes. You could get about 10% of the + expected one. This is because of the partition alignment, which + is (simplifying) incompatible with how Linux page cache + works, so for each write the corresponding block must be read + first. Use 4096 bytes block sizes for VDISK devices and you + will have the expected write performance. Actually, any OS on + initiators, not only Windows, will benefit from block size + max(PAGE_SIZE, BLOCK_SIZE_ON_UNDERLYING_FS), where PAGE_SIZE + is the page size, BLOCK_SIZE_ON_UNDERLYING_FS is block size + on the underlying FS, on which the device file located, or 0, + if a device node is used. Both values are from the target. + See also important notes about setting block sizes >512 bytes + for VDISK FILEIO devices above. + +9. In some cases, for instance working with SSD devices, which consume +100% of a single CPU load for data transfers in their internal threads, +to maximize IOPS it can be needed to assign for those threads dedicated +CPUs. Consider using cpu_mask attribute for devices with +threads_pool_type "per_initiator" or Linux CPU affinity facilities for +other threads_pool_types. No IRQ processing should be done on those +CPUs. Check that using /proc/interrupts. See taskset command and +Documentation/IRQ-affinity.txt in your kernel's source tree for how to +assign IRQ affinity to tasks and IRQs. + +The reason for that is that processing of coming commands in SIRQ +context might be done on the same CPUs as SSD devices' threads doing data +transfers. As the result, those threads won't receive all the processing +power of those CPUs and perform worse. + + +Work if target's backstorage or link is too slow +------------------------------------------------ + +Under high I/O load, when your target's backstorage gets overloaded, or +working over a slow link between initiator and target, when the link +can't serve all the queued commands on time, you can experience I/O +stalls or see in the kernel log abort or reset messages. + +At first, consider the case of too slow target's backstorage. On some +seek intensive workloads even fast disks or RAIDs, which able to serve +continuous data stream on 500+ MB/s speed, can be as slow as 0.3 MB/s. +Another possible cause for that can be MD/LVM/RAID on your target as in +http://lkml.org/lkml/2008/2/27/96 (check the whole thread as well). + +Thus, in such situations simply processing of one or more commands takes +too long time, hence initiator decides that they are stuck on the target +and tries to recover. Particularly, it is known that the default amount +of simultaneously queued commands (48) is sometimes too high if you do +intensive writes from VMware on a target disk, which uses LVM in the +snapshot mode. In this case value like 16 or even 8-10 depending of your +backstorage speed could be more appropriate. + +Unfortunately, currently SCST lacks dynamic I/O flow control, when the +queue depth on the target is dynamically decreased/increased based on +how slow/fast the backstorage speed comparing to the target link. So, +there are 6 possible actions, which you can do to workaround or fix this +issue in this case: + +1. Ignore incoming task management (TM) commands. It's fine if there are +not too many of them, so average performance isn't hurt and the +corresponding device isn't getting put offline, i.e. if the backstorage +isn't too slow. + +2. Decrease /sys/block/sdX/device/queue_depth on the initiator in case +if it's Linux (see below how) or/and SCST_MAX_TGT_DEV_COMMANDS constant +in scst_priv.h file until you stop seeing incoming TM commands. +ISCSI-SCST driver also has its own iSCSI specific parameter for that, +see its README file. + +To decrease device queue depth on Linux initiators you can run command: + +# echo Y >/sys/block/sdX/device/queue_depth + +where Y is the new number of simultaneously queued commands, X - your +imported device letter, like 'a' for sda device. There are no special +limitations for Y value, it can be any value from 1 to possible maximum +(usually, 32), so start from dividing the current value on 2, i.e. set +16, if /sys/block/sdX/device/queue_depth contains 32. + +3. Increase the corresponding timeout on the initiator. For Linux it is +located in +/sys/devices/platform/host*/session*/target*:0:0/*:0:0:1/timeout. It can +be done automatically by an udev rule. For instance, the following +rule will increase it to 300 seconds: + +SUBSYSTEM=="scsi", KERNEL=="[0-9]*:[0-9]*", ACTION=="add", ATTR{type}=="0|7|14", ATTR{timeout}="300" + +By default, this timeout is 30 or 60 seconds, depending on your distribution. + +4. Try to avoid such seek intensive workloads. + +5. Increase speed of the target's backstorage. + +6. Implement in SCST dynamic I/O flow control. This will be an ultimate +solution. See "Dynamic I/O flow control" section on +http://scst.sourceforge.net/contributing.html page for possible +implementation idea. + +Next, consider the case of too slow link between initiator and target, +when the initiator tries to simultaneously push N commands to the target +over it. In this case time to serve those commands, i.e. send or receive +data for them over the link, can be more, than timeout for any single +command, hence one or more commands in the tail of the queue can not be +served on time less than the timeout, so the initiator will decide that +they are stuck on the target and will try to recover. + +To workaround/fix this issue in this case you can use ways 1, 2, 3, 6 +above or (7): increase speed of the link between target and initiator. +But for some initiators implementations for WRITE commands there might +be cases when target has no way to detect the issue, so dynamic I/O flow +control will not be able to help. In those cases you could also need on +the initiator(s) to either decrease the queue depth (way 2), or increase +the corresponding timeout (way 3). + +Note, that logged messages about QUEUE_FULL status are quite different +by nature. This is a normal work, just SCSI flow control in action. +Simply don't enable "mgmt_minor" logging level, or, alternatively, if +you are confident in the worst case performance of your back-end storage +or initiator-target link, you can increase SCST_MAX_TGT_DEV_COMMANDS in +scst_priv.h to 64. Usually initiators don't try to push more commands on +the target. + + +Credits +------- + +Thanks to: + + * Mark Buechler <[email protected]> for a lot of useful + suggestions, bug reports and help in debugging. + + * Ming Zhang <[email protected]> for fixes and comments. + + * Nathaniel Clark <[email protected]> for fixes and comments. + + * Calvin Morrow <[email protected]> for testing and useful + suggestions. + + * Hu Gang <[email protected]> for the original version of the + LSI target driver. + + * Erik Habbinga <[email protected]> for fixes and support + of the LSI target driver. + + * Ross S. W. Walker <[email protected]> for BLOCKIO inspiration + and Vu Pham <[email protected]> who implemented it for VDISK dev handler. + + * Alessandro Premoli <[email protected]> for fixes + + * Nathan Bullock <[email protected]> for fixes. + + * Terry Greeniaus <[email protected]> for fixes. + + * Krzysztof Blaszkowski <[email protected]> for many fixes and bug reports. + + * Jianxi Chen <[email protected]> for fixing problem with + devices >2TB in size + + * Bart Van Assche <[email protected]> for a lot of help + + * Daniel Debonzi <[email protected]> for a big part of the + initial SCST sysfs tree implementation + + +Vladislav Bolkhovitin <[email protected]>, http://scst.sourceforge.net
Documentation/scst/SysfsRules renamed from linux-2.6.35/Documentation/scst/SysfsRules +942 -0
942 lines not on this page · raw message
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v4 12/19 : SCST dev handlers' Makefile
In reply to Vladislav BolkhovitinThis patch contains SCST dev handlers' Makefile.
--- Makefile | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/scst/dev_handlers/Makefile renamed from linux-2.6.35/drivers/scst/dev_handlers/Makefile +13 -0
@@ -0,0 +1,13 @@ +ccflags-y += -Wno-unused-parameter + +obj-m := scst_cdrom.o scst_changer.o scst_disk.o scst_modisk.o scst_tape.o \ + scst_vdisk.o scst_raid.o scst_processor.o + +obj-$(CONFIG_SCST_DISK) += scst_disk.o +obj-$(CONFIG_SCST_TAPE) += scst_tape.o +obj-$(CONFIG_SCST_CDROM) += scst_cdrom.o +obj-$(CONFIG_SCST_MODISK) += scst_modisk.o +obj-$(CONFIG_SCST_CHANGER) += scst_changer.o +obj-$(CONFIG_SCST_RAID) += scst_raid.o +obj-$(CONFIG_SCST_PROCESSOR) += scst_processor.o +obj-$(CONFIG_SCST_VDISK) += scst_vdisk.o
PATCH v4 13/19 : SCST vdisk dev handler
In reply to Vladislav BolkhovitinThis patch contains SCST vdisk dev handler. This dev handler allows to create virtual disks and CDROMs from files on file system.
It supports the following modes:
- FILEIO mode, which allows to use files on file systems or block devices as virtual remotely available SCSI disks or CDROMs with benefits of the Linux page cache.
- BLOCKIO mode, which performs direct block IO with a block device, bypassing page-cache for all operations. This mode works ideally with high-end storage HBAs and for applications that either do not need caching between application and disk or need the large block throughput.
- NULLIO mode, in which all the commands immediately completed. This mode is intended for performance measurements without overhead of actual data transfers from/to underlying SCSI device.
--- scst_vdisk.c | 4186 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 4186 insertions(+)
drivers/scst/dev_handlers/scst_vdisk.c renamed from linux-2.6.35/drivers/scst/dev_handlers/scst_vdisk.c +4186 -0
@@ -0,0 +1,4186 @@ +/* +* scst_vdisk.c +* +* Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <[email protected]> +* Copyright (C) 2004 - 2005 Leonid Stoljar +* Copyright (C) 2007 Ming Zhang <blackmagic02881 at gmail dot com> +* Copyright (C) 2007 Ross Walker <rswwalker at hotmail dot com> +* Copyright (C) 2007 - 2010 ID7 Ltd. +* +* SCSI disk (type 0) and CDROM (type 5) dev handler using files +* on file systems or block devices (VDISK) +* +* 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, version 2 +* of the License. +* +* 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. +*/ + +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/unistd.h> +#include <linux/smp_lock.h> +#include <linux/spinlock.h> +#include <linux/init.h> +#include <linux/uio.h> +#include <linux/list.h> +#include <linux/ctype.h> +#include <linux/writeback.h> +#include <linux/vmalloc.h> +#include <asm/atomic.h> +#include <linux/kthread.h> +#include <linux/sched.h> +#include <linux/version.h> +#include <asm/div64.h> +#include <asm/unaligned.h> +#include <linux/slab.h> +#include <linux/bio.h> + +#define LOG_PREFIX "dev_vdisk" + +#include <scst/scst.h> + +#if defined(CONFIG_SCST_DEBUG ) || defined(CONFIG_SCST_TRACING ) + +#define TRACE_ORDER 0x80000000 + +static struct scst_trace_log vdisk_local_trace_tbl[] = { + {TRACE_ORDER ,"order" }, + {0 ,NULL } +}; +#define trace_log_tbl vdisk_local_trace_tbl + +#define VDISK_TRACE_TLB_HELP ", order" + +#endif + +#include "scst_dev_handler.h" + +/* 8 byte ASCII Vendor */ +#define SCST_FIO_VENDOR "SCST_FIO" +#define SCST_BIO_VENDOR "SCST_BIO" +/* 4 byte ASCII Product Revision Level - left aligned */ +#define SCST_FIO_REV " 210" + +#define MAX_USN_LEN (20+1)/* For '\0' */ + +#define INQ_BUF_SZ 256 +#define EVPD 0x01 +#define CMDDT 0x02 + +#define MSENSE_BUF_SZ 256 +#define DBD 0x08/* disable block descriptor */ +#define WP 0x80/* write protect */ +#define DPOFUA 0x10/* DPOFUA bit */ +#define WCE 0x04/* write cache enable */ + +#define PF 0x10/* page format */ +#define SP 0x01/* save pages */ +#define PS 0x80/* parameter saveable */ + +#define BYTE 8 +#define DEF_DISK_BLOCKSIZE_SHIFT 9 +#define DEF_DISK_BLOCKSIZE (1 << DEF_DISK_BLOCKSIZE_SHIFT) +#define DEF_CDROM_BLOCKSIZE_SHIFT 11 +#define DEF_CDROM_BLOCKSIZE (1 << DEF_CDROM_BLOCKSIZE_SHIFT) +#define DEF_SECTORS 56 +#define DEF_HEADS 255 +#define LEN_MEM (32 * 1024) +#define DEF_RD_ONLY 0 +#define DEF_WRITE_THROUGH 0 +#define DEF_NV_CACHE 0 +#define DEF_O_DIRECT 0 +#define DEF_REMOVABLE 0 +#define DEF_THIN_PROVISIONED 0 + +#define VDISK_NULLIO_SIZE (3LL*1024*1024*1024*1024/2) + +#define DEF_TST SCST_CONTR_MODE_SEP_TASK_SETS + +/* +* Since we can't control backstorage device's reordering, we have to always +* report unrestricted reordering. +*/ +#define DEF_QUEUE_ALG_WT SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER +#define DEF_QUEUE_ALG SCST_CONTR_MODE_QUEUE_ALG_UNRESTRICTED_REORDER +#define DEF_SWP 0 +#define DEF_TAS 0 + +#define DEF_DSENSE SCST_CONTR_MODE_FIXED_SENSE + +static unsigned int random_values[256 ] = { +9862592UL ,3744545211UL ,2348289082UL ,4036111983UL , +435574201UL ,3110343764UL ,2383055570UL ,1826499182UL , +4076766377UL ,1549935812UL ,3696752161UL ,1200276050UL , +3878162706UL ,1783530428UL ,2291072214UL ,125807985UL , +3407668966UL ,547437109UL ,3961389597UL ,969093968UL , +56006179UL ,2591023451UL ,1849465UL ,1614540336UL , +3699757935UL ,479961779UL ,3768703953UL ,2529621525UL , +4157893312UL ,3673555386UL ,4091110867UL ,2193909423UL , +2800464448UL ,3052113233UL ,450394455UL ,3424338713UL , +2113709130UL ,4082064373UL ,3708640918UL ,3841182218UL , +3141803315UL ,1032476030UL ,1166423150UL ,1169646901UL , +2686611738UL ,575517645UL ,2829331065UL ,1351103339UL , +2856560215UL ,2402488288UL ,867847666UL ,8524618UL , +704790297UL ,2228765657UL ,231508411UL ,1425523814UL , +2146764591UL ,1287631730UL ,4142687914UL ,3879884598UL , +729945311UL ,310596427UL ,2263511876UL ,1983091134UL , +3500916580UL ,1642490324UL ,3858376049UL ,695342182UL , +780528366UL ,1372613640UL ,1100993200UL ,1314818946UL , +572029783UL ,3775573540UL ,776262915UL ,2684520905UL , +1007252738UL ,3505856396UL ,1974886670UL ,3115856627UL , +4194842288UL ,2135793908UL ,3566210707UL ,7929775UL , +1321130213UL ,2627281746UL ,3587067247UL ,2025159890UL , +2587032000UL ,3098513342UL ,3289360258UL ,130594898UL , +2258149812UL ,2275857755UL ,3966929942UL ,1521739999UL , +4191192765UL ,958953550UL ,4153558347UL ,1011030335UL , +524382185UL ,4099757640UL ,498828115UL ,2396978754UL , +328688935UL ,826399828UL ,3174103611UL ,3921966365UL , +2187456284UL ,2631406787UL ,3930669674UL ,4282803915UL , +1776755417UL ,374959755UL ,2483763076UL ,844956392UL , +2209187588UL ,3647277868UL ,291047860UL ,3485867047UL , +2223103546UL ,2526736133UL ,3153407604UL ,3828961796UL , +3355731910UL ,2322269798UL ,2752144379UL ,519897942UL , +3430536488UL ,1801511593UL ,1953975728UL ,3286944283UL , +1511612621UL ,1050133852UL ,409321604UL ,1037601109UL , +3352316843UL ,4198371381UL ,617863284UL ,994672213UL , +1540735436UL ,2337363549UL ,1242368492UL ,665473059UL , +2330728163UL ,3443103219UL ,2291025133UL ,3420108120UL , +2663305280UL ,1608969839UL ,2278959931UL ,1389747794UL , +2226946970UL ,2131266900UL ,3856979144UL ,1894169043UL , +2692697628UL ,3797290626UL ,3248126844UL ,3922786277UL , +343705271UL ,3739749888UL ,2191310783UL ,2962488787UL , +4119364141UL ,1403351302UL ,2984008923UL ,3822407178UL , +1932139782UL ,2323869332UL ,2793574182UL ,1852626483UL , +2722460269UL ,1136097522UL ,1005121083UL ,1805201184UL , +2212824936UL ,2979547931UL ,4133075915UL ,2585731003UL , +2431626071UL ,134370235UL ,3763236829UL ,1171434827UL , +2251806994UL ,1289341038UL ,3616320525UL ,392218563UL , +1544502546UL ,2993937212UL ,1957503701UL ,3579140080UL , +4270846116UL ,2030149142UL ,1792286022UL ,366604999UL , +2625579499UL ,790898158UL ,770833822UL ,815540197UL , +2747711781UL ,3570468835UL ,3976195842UL ,1257621341UL , +1198342980UL ,1860626190UL ,3247856686UL ,351473955UL , +993440563UL ,340807146UL ,1041994520UL ,3573925241UL , +480246395UL ,2104806831UL ,1020782793UL ,3362132583UL , +2272911358UL ,3440096248UL ,2356596804UL ,259492703UL , +3899500740UL ,252071876UL ,2177024041UL ,4284810959UL , +2775999888UL ,2653420445UL ,2876046047UL ,1025771859UL , +1994475651UL ,3564987377UL ,4112956647UL ,1821511719UL , +3113447247UL ,455315102UL ,1585273189UL ,2311494568UL , +774051541UL ,1898115372UL ,2637499516UL ,247231365UL , +1475014417UL ,803585727UL ,3911097303UL ,1714292230UL , +476579326UL ,2496900974UL ,3397613314UL ,341202244UL , +807790202UL ,4221326173UL ,499979741UL ,1301488547UL , +1056807896UL ,3525009458UL ,1174811641UL ,3049738746UL , +}; + +struct scst_vdisk_dev { +uint32_t block_size; +uint64_t nblocks; +int block_shift; +loff_t file_size;/* in bytes */ + +/* +* This lock can be taken on both SIRQ and thread context, but in +* all cases for each particular instance it's taken consistenly either +* on SIRQ or thread context. Mix of them is forbidden. +*/ +spinlock_t flags_lock; + +/* +* Below flags are protected by flags_lock or suspended activity +* with scst_vdisk_mutex. +*/ +unsigned int rd_only:1 ; +unsigned int wt_flag:1 ; +unsigned int nv_cache:1 ; +unsigned int o_direct_flag:1 ; +unsigned int media_changed:1 ; +unsigned int prevent_allow_medium_removal:1 ; +unsigned int nullio:1 ; +unsigned int blockio:1 ; +unsigned int cdrom_empty:1 ; +unsigned int removable:1 ; +unsigned int thin_provisioned:1 ; + +int virt_id; +char name[16 +1 ];/* Name of the virtual device, +must be <= SCSI Model + 1 */ +char *filename;/* File name, protected by +scst_mutex and suspended activities */ +uint16_t command_set_version; +unsigned int t10_dev_id_set:1 ;/* true if t10_dev_id manually set */ +char t10_dev_id[16 +8 +2 ];/* T10 device ID */ +char usn[MAX_USN_LEN ]; +struct scst_device *dev; +struct list_head vdev_list_entry; + +struct scst_dev_type *vdev_devt; +}; + +struct scst_vdisk_thr { +struct scst_thr_data_hdr hdr; +struct file *fd; +struct block_device *bdev; +struct iovec *iv; +int iv_count; +}; + +/* Context RA patch supposed to be applied on the kernel */ +#define DEF_NUM_THREADS 8 +static int num_threads =DEF_NUM_THREADS ; + +module_param_named (num_threads, num_threads, int,S_IRUGO ); +MODULE_PARM_DESC (num_threads,"vdisk threads count" ); + +static int vdisk_attach (struct scst_device *dev); +static void vdisk_detach (struct scst_device *dev); +static int vdisk_attach_tgt (struct scst_tgt_dev *tgt_dev); +static void vdisk_detach_tgt (struct scst_tgt_dev *tgt_dev); +static int vdisk_parse (struct scst_cmd *); +static int vdisk_do_job (struct scst_cmd *cmd); +static int vcdrom_parse (struct scst_cmd *); +static int vcdrom_exec (struct scst_cmd *cmd); +static void vdisk_exec_read (struct scst_cmd *cmd, +struct scst_vdisk_thr *thr,loff_t loff); +static void vdisk_exec_write (struct scst_cmd *cmd, +struct scst_vdisk_thr *thr,loff_t loff); +static void blockio_exec_rw (struct scst_cmd *cmd,struct scst_vdisk_thr *thr, +u64 lba_start,int write); +static int blockio_flush (struct block_device *bdev); +static void vdisk_exec_verify (struct scst_cmd *cmd, +struct scst_vdisk_thr *thr,loff_t loff); +static void vdisk_exec_read_capacity (struct scst_cmd *cmd); +static void vdisk_exec_read_capacity16 (struct scst_cmd *cmd); +static void vdisk_exec_inquiry (struct scst_cmd *cmd); +static void vdisk_exec_request_sense (struct scst_cmd *cmd); +static void vdisk_exec_mode_sense (struct scst_cmd *cmd); +static void vdisk_exec_mode_select (struct scst_cmd *cmd); +static void vdisk_exec_log (struct scst_cmd *cmd); +static void vdisk_exec_read_toc (struct scst_cmd *cmd); +static void vdisk_exec_prevent_allow_medium_removal (struct scst_cmd *cmd); +static void vdisk_exec_unmap (struct scst_cmd *cmd,struct scst_vdisk_thr *thr); +static int vdisk_fsync (struct scst_vdisk_thr *thr,loff_t loff, +loff_t len,struct scst_cmd *cmd,struct scst_device *dev); +static ssize_t vdisk_add_fileio_device (const char *device_name,char *params); +static ssize_t vdisk_add_blockio_device (const char *device_name,char *params); +static ssize_t vdisk_add_nullio_device (const char *device_name,char *params); +static ssize_t vdisk_del_device (const char *device_name); +static ssize_t vcdrom_add_device (const char *device_name,char *params); +static ssize_t vcdrom_del_device (const char *device_name); +static int vdisk_task_mgmt_fn (struct scst_mgmt_cmd *mcmd, +struct scst_tgt_dev *tgt_dev); +static uint64_t vdisk_gen_dev_id_num (const char *virt_dev_name); + +/** SYSFS **/ + +static ssize_t vdev_sysfs_size_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf); +static ssize_t vdisk_sysfs_blocksize_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf); +static ssize_t vdisk_sysfs_rd_only_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf); +static ssize_t vdisk_sysfs_wt_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf); +static ssize_t vdisk_sysfs_tp_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf); +static ssize_t vdisk_sysfs_nv_cache_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf); +static ssize_t vdisk_sysfs_o_direct_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf); +static ssize_t vdisk_sysfs_removable_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf); +static ssize_t vdev_sysfs_filename_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf); +static ssize_t vdisk_sysfs_resync_size_store (struct kobject *kobj, +struct kobj_attribute *attr,const char *buf,size_t count); +static ssize_t vdev_sysfs_t10_dev_id_store (struct kobject *kobj, +struct kobj_attribute *attr,const char *buf,size_t count); +static ssize_t vdev_sysfs_t10_dev_id_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf); +static ssize_t vdev_sysfs_usn_show (struct kobject *kobj, +struct kobj_attribute *attr,char *buf); + +static ssize_t vcdrom_sysfs_filename_store (struct kobject *kobj, +struct kobj_attribute *attr,const char *buf,size_t count); + +static struct kobj_attribute vdev_size_attr = +__ATTR (size_mb,S_IRUGO , vdev_sysfs_size_show,NULL ); +static struct kobj_attribute vdisk_blocksize_attr = +__ATTR (blocksize,S_IRUGO , vdisk_sysfs_blocksize_show,NULL ); +static struct kobj_attribute vdisk_rd_only_attr = +__ATTR (read_only,S_IRUGO , vdisk_sysfs_rd_only_show,NULL ); +static struct kobj_attribute vdisk_wt_attr = +__ATTR (write_through,S_IRUGO , vdisk_sysfs_wt_show,NULL ); +static struct kobj_attribute vdisk_tp_attr = +__ATTR (thin_provisioned,S_IRUGO , vdisk_sysfs_tp_show,NULL ); +static struct kobj_attribute vdisk_nv_cache_attr = +__ATTR (nv_cache,S_IRUGO , vdisk_sysfs_nv_cache_show,NULL ); +static struct kobj_attribute vdisk_o_direct_attr = +__ATTR (o_direct,S_IRUGO , vdisk_sysfs_o_direct_show,NULL ); +static struct kobj_attribute vdisk_removable_attr = +__ATTR (removable,S_IRUGO , vdisk_sysfs_removable_show,NULL ); +static struct kobj_attribute vdisk_filename_attr = +__ATTR (filename,S_IRUGO , vdev_sysfs_filename_show,NULL ); +static struct kobj_attribute vdisk_resync_size_attr = +__ATTR (resync_size,S_IWUSR ,NULL , vdisk_sysfs_resync_size_store); +static struct kobj_attribute vdev_t10_dev_id_attr = +__ATTR (t10_dev_id,S_IWUSR |S_IRUGO , vdev_sysfs_t10_dev_id_show, + vdev_sysfs_t10_dev_id_store); +static struct kobj_attribute vdev_usn_attr = +__ATTR (usn,S_IRUGO , vdev_sysfs_usn_show,NULL ); + +static struct kobj_attribute vcdrom_filename_attr = +__ATTR (filename,S_IRUGO |S_IWUSR , vdev_sysfs_filename_show, + vcdrom_sysfs_filename_store); + +static const struct attribute *vdisk_fileio_attrs[] = { + &vdev_size_attr.attr, + &vdisk_blocksize_attr.attr, + &vdisk_rd_only_attr.attr, + &vdisk_wt_attr.attr, + &vdisk_tp_attr.attr, + &vdisk_nv_cache_attr.attr, + &vdisk_o_direct_attr.attr, + &vdisk_removable_attr.attr, + &vdisk_filename_attr.attr, + &vdisk_resync_size_attr.attr, + &vdev_t10_dev_id_attr.attr, + &vdev_usn_attr.attr, +NULL , +}; + +static const struct attribute *vdisk_blockio_attrs[] = { + &vdev_size_attr.attr, + &vdisk_blocksize_attr.attr, + &vdisk_rd_only_attr.attr, + &vdisk_nv_cache_attr.attr, + &vdisk_removable_attr.attr, + &vdisk_filename_attr.attr, + &vdisk_resync_size_attr.attr, + &vdev_t10_dev_id_attr.attr, + &vdev_usn_attr.attr, + &vdisk_tp_attr.attr, +NULL , +}; + +static const struct attribute *vdisk_nullio_attrs[] = { + &vdev_size_attr.attr, + &vdisk_blocksize_attr.attr, + &vdisk_rd_only_attr.attr, + &vdisk_removable_attr.attr, + &vdev_t10_dev_id_attr.attr, + &vdev_usn_attr.attr, +NULL , +}; + +static const struct attribute *vcdrom_attrs[] = { + &vdev_size_attr.attr, + &vcdrom_filename_attr.attr, + &vdev_t10_dev_id_attr.attr, + &vdev_usn_attr.attr, +NULL , +}; + +/* Protects vdisks addition/deletion and related activities, like search */ +static DEFINE_MUTEX (scst_vdisk_mutex); +static DEFINE_RWLOCK (vdisk_t10_dev_id_rwlock); + +/* Protected by scst_vdisk_mutex */ +static LIST_HEAD (vdev_list); + +static struct kmem_cache *vdisk_thr_cachep; + +/* +* Be careful changing "name" field, since it is the name of the corresponding +* /sys/kernel/scst_tgt entry, hence a part of user space ABI. +*/ + +static struct scst_dev_type vdisk_file_devtype = { + .name ="vdisk_fileio" , + .type =TYPE_DISK , + .exec_sync =1 , + .threads_num =-1 , + .parse_atomic =1 , + .dev_done_atomic =1 , + .attach = vdisk_attach, + .detach = vdisk_detach, + .attach_tgt = vdisk_attach_tgt, + .detach_tgt = vdisk_detach_tgt, + .parse = vdisk_parse, + .exec = vdisk_do_job, + .task_mgmt_fn = vdisk_task_mgmt_fn, + .add_device = vdisk_add_fileio_device, + .del_device = vdisk_del_device, + .dev_attrs = vdisk_fileio_attrs, + .add_device_parameters ="filename, blocksize, write_through, " +"nv_cache, o_direct, read_only, removable, thin_provisioned" , +#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) + .default_trace_flags =SCST_DEFAULT_DEV_LOG_FLAGS , + .trace_flags = &trace_flag, + .trace_tbl = vdisk_local_trace_tbl, + .trace_tbl_help =VDISK_TRACE_TLB_HELP , +#endif +}; + +static struct kmem_cache *blockio_work_cachep; + +static struct scst_dev_type vdisk_blk_devtype = { + .name ="vdisk_blockio" , + .type =TYPE_DISK , + .threads_num =1 , + .parse_atomic =1 , + .dev_done_atomic =1 , + .attach = vdisk_attach, + .detach = vdisk_detach, + .attach_tgt = vdisk_attach_tgt, + .detach_tgt = vdisk_detach_tgt, + .parse = vdisk_parse, + .exec = vdisk_do_job, + .task_mgmt_fn = vdisk_task_mgmt_fn, + .add_device = vdisk_add_blockio_device, + .del_device = vdisk_del_device, + .dev_attrs = vdisk_blockio_attrs, + .add_device_parameters ="filename, blocksize, nv_cache, read_only, " +"removable, thin_provisioned" , +#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) + .default_trace_flags =SCST_DEFAULT_DEV_LOG_FLAGS , + .trace_flags = &trace_flag, + .trace_tbl = vdisk_local_trace_tbl, + .trace_tbl_help =VDISK_TRACE_TLB_HELP , +#endif +}; + +static struct scst_dev_type vdisk_null_devtype = { + .name ="vdisk_nullio" , + .type =TYPE_DISK , + .threads_num =0 , + .parse_atomic =1 , + .dev_done_atomic =1 , + .attach = vdisk_attach, + .detach = vdisk_detach, + .attach_tgt = vdisk_attach_tgt, + .detach_tgt = vdisk_detach_tgt, + .parse = vdisk_parse, + .exec = vdisk_do_job, + .task_mgmt_fn = vdisk_task_mgmt_fn, + .add_device = vdisk_add_nullio_device, + .del_device = vdisk_del_device, + .dev_attrs = vdisk_nullio_attrs, + .add_device_parameters ="blocksize, read_only, removable" , +#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) + .default_trace_flags =SCST_DEFAULT_DEV_LOG_FLAGS , + .trace_flags = &trace_flag, + .trace_tbl = vdisk_local_trace_tbl, + .trace_tbl_help =VDISK_TRACE_TLB_HELP , +#endif +}; + +static struct scst_dev_type vcdrom_devtype = { + .name ="vcdrom" , + .type =TYPE_ROM , + .exec_sync =1 , + .threads_num =-1 , + .parse_atomic =1 , + .dev_done_atomic =1 , + .attach = vdisk_attach, + .detach = vdisk_detach, + .attach_tgt = vdisk_attach_tgt, + .detach_tgt = vdisk_detach_tgt, + .parse = vcdrom_parse, + .exec = vcdrom_exec, + .task_mgmt_fn = vdisk_task_mgmt_fn, + .add_device = vcdrom_add_device, + .del_device = vcdrom_del_device, + .dev_attrs = vcdrom_attrs, + .add_device_parameters =NULL , +#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) + .default_trace_flags =SCST_DEFAULT_DEV_LOG_FLAGS , + .trace_flags = &trace_flag, + .trace_tbl = vdisk_local_trace_tbl, + .trace_tbl_help =VDISK_TRACE_TLB_HELP , +#endif +}; + +static struct scst_vdisk_thr nullio_thr_data; + +static const char *vdev_get_filename (const struct scst_vdisk_dev *virt_dev) +{ +if (virt_dev->filename !=NULL ) +return virt_dev->filename; +else +return "none" ; +} + +/* Returns fd, use IS_ERR(fd) to get error status */ +static struct file *vdev_open_fd (const struct scst_vdisk_dev *virt_dev) +{ +int open_flags =0 ; +struct file *fd; + +if (virt_dev->dev->rd_only) + open_flags |=O_RDONLY ; +else + open_flags |=O_RDWR ; +if (virt_dev->o_direct_flag) + open_flags |=O_DIRECT ; +if (virt_dev->wt_flag && !virt_dev->nv_cache) + open_flags |=O_SYNC ; +TRACE_DBG ("Opening file %s, flags 0x%x" , + virt_dev->filename, open_flags); + fd =filp_open (virt_dev->filename,O_LARGEFILE | open_flags,0600 ); +return fd; +} + +static void vdisk_blockio_check_flush_support (struct scst_vdisk_dev *virt_dev) +{ +struct inode *inode; +struct file *fd; + +if (!virt_dev->blockio || virt_dev->rd_only || virt_dev->nv_cache) + goto out; + + fd =filp_open (virt_dev->filename,O_LARGEFILE ,0600 ); +if (IS_ERR (fd)) { +PRINT_ERROR ("filp_open(%s) returned error %ld" , + virt_dev->filename,PTR_ERR (fd)); + goto out; + } + + inode = fd->f_dentry->d_inode; + +if (!S_ISBLK (inode->i_mode)) { +PRINT_ERROR ("%s is NOT a block device" , virt_dev->filename); + goto out_close; + } + +if (blockio_flush (inode->i_bdev) !=0 ) { +PRINT_WARNING ("Device %s doesn't support barriers, switching " +"to NV_CACHE mode. Read README for more details." , + virt_dev->filename); + virt_dev->nv_cache =1 ; + } + +out_close: +filp_close (fd,NULL ); + +out: +return ; +} + +static void vdisk_check_tp_support (struct scst_vdisk_dev *virt_dev) +{ +struct inode *inode; +struct file *fd; +bool supported = false; + +if (virt_dev->rd_only || !virt_dev->thin_provisioned) + goto out; + + fd =filp_open (virt_dev->filename,O_LARGEFILE ,0600 ); +if (IS_ERR (fd)) { +PRINT_ERROR ("filp_open(%s) returned error %ld" , + virt_dev->filename,PTR_ERR (fd)); + goto out; + } + + inode = fd->f_dentry->d_inode; + +if (virt_dev->blockio) { +if (!S_ISBLK (inode->i_mode)) { +PRINT_ERROR ("%s is NOT a block device" , + virt_dev->filename); + goto out_close; + } + supported =blk_queue_discard (bdev_get_queue (inode->i_bdev)); + + }else { +/* +* truncate_range() was chosen rather as a sample. In future, +* when unmap of range of blocks in file become standard, we +* will just switch to the new call. +*/ + supported = (inode->i_op->truncate_range !=NULL ); + } + +if (!supported) { +PRINT_WARNING ("Device %s doesn't support thin " +"provisioning, disabling it." , + virt_dev->filename); + virt_dev->thin_provisioned =0 ; + } + +out_close: +filp_close (fd,NULL ); + +out: +return ; +} + +/* Returns 0 on success and file size in *file_size, error code otherwise */ +static int vdisk_get_file_size (const char *filename,bool blockio, +loff_t *file_size) +{ +struct inode *inode; +int res =0 ; +struct file *fd; + + *file_size =0 ; + + fd =filp_open (filename,O_LARGEFILE |O_RDONLY ,0600 ); +if (IS_ERR (fd)) { + res =PTR_ERR (fd); +PRINT_ERROR ("filp_open(%s) returned error %d" , filename, res); + goto out; + } + + inode = fd->f_dentry->d_inode; + +if (blockio && !S_ISBLK (inode->i_mode)) { +PRINT_ERROR ("File %s is NOT a block device" , filename); + res = -EINVAL ; + goto out_close; + } + +if (S_ISREG (inode->i_mode)) +/* Nothing to do */ ; +else if (S_ISBLK (inode->i_mode)) + inode = inode->i_bdev->bd_inode; +else { + res = -EINVAL ; + goto out_close; + } + + *file_size = inode->i_size; + +out_close: +filp_close (fd,NULL ); + +out: +return res; +} + +static int vdisk_attach (struct scst_device *dev) +{ +int res =0 ; +loff_t err; +struct scst_vdisk_dev *virt_dev =NULL , *vv; + +TRACE_DBG ("virt_id %d (%s)" , dev->virt_id, dev->virt_name); + +if (dev->virt_id ==0 ) { +PRINT_ERROR ("%s" ,"Not a virtual device" ); + res = -EINVAL ; + goto out; + } + +/* +* scst_vdisk_mutex must be already taken before +* scst_register_virtual_device() +*/ +list_for_each_entry (vv, &vdev_list, vdev_list_entry) { +if (strcmp (vv->name, dev->virt_name) ==0 ) { + virt_dev = vv; +break ; + } + } + +if (virt_dev ==NULL ) { +PRINT_ERROR ("Device %s not found" , dev->virt_name); + res = -EINVAL ; + goto out; + } + + virt_dev->dev = dev; + + dev->rd_only = virt_dev->rd_only; + +if (!virt_dev->cdrom_empty) { +if (virt_dev->nullio) + err =VDISK_NULLIO_SIZE ; +else { + res =vdisk_get_file_size (virt_dev->filename, + virt_dev->blockio, &err); +if (res !=0 ) + goto out; + } + virt_dev->file_size = err; + +TRACE_DBG ("size of file: %lld" , (long long unsigned int )err); + +vdisk_blockio_check_flush_support (virt_dev); +vdisk_check_tp_support (virt_dev); + }else + virt_dev->file_size =0 ; + + virt_dev->nblocks = virt_dev->file_size >> virt_dev->block_shift; + +if (!virt_dev->cdrom_empty) { +PRINT_INFO ("Attached SCSI target virtual %s %s " +"(file=\"%s\", fs=%lldMB, bs=%d, nblocks=%lld," +" cyln=%lld%s)" , + (dev->type ==TYPE_DISK ) ?"disk" :"cdrom" , + virt_dev->name,vdev_get_filename (virt_dev), + virt_dev->file_size >>20 , virt_dev->block_size, + (long long unsigned int )virt_dev->nblocks, + (long long unsigned int )virt_dev->nblocks/64 /32 , + virt_dev->nblocks <64 *32 + ?" !WARNING! cyln less than 1" :"" ); + }else { +PRINT_INFO ("Attached empty SCSI target virtual cdrom %s" , + virt_dev->name); + } + + dev->dh_priv = virt_dev; + + dev->tst =DEF_TST ; + dev->d_sense =DEF_DSENSE ; +if (virt_dev->wt_flag && !virt_dev->nv_cache) + dev->queue_alg =DEF_QUEUE_ALG_WT ; +else + dev->queue_alg =DEF_QUEUE_ALG ; + dev->swp =DEF_SWP ; + dev->tas =DEF_TAS ; + +out: +return res; +} + +/* scst_mutex supposed to be held */ +static void vdisk_detach (struct scst_device *dev) +{ +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)dev->dh_priv; + +TRACE_DBG ("virt_id %d" , dev->virt_id); + +PRINT_INFO ("Detached virtual device %s (\"%s\")" , + virt_dev->name,vdev_get_filename (virt_dev)); + +/* virt_dev will be freed by the caller */ + dev->dh_priv =NULL ; +return ; +} + +static void vdisk_free_thr_data (struct scst_thr_data_hdr *d) +{ +struct scst_vdisk_thr *thr = + container_of(d, struct scst_vdisk_thr, hdr); + +if (thr->fd) +filp_close (thr->fd,NULL ); + +kfree (thr->iv); + +kmem_cache_free (vdisk_thr_cachep, thr); +return ; +} + +static struct scst_vdisk_thr *vdisk_init_thr_data ( +struct scst_tgt_dev *tgt_dev) +{ +struct scst_vdisk_thr *res; +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)tgt_dev->dev->dh_priv; + +EXTRACHECKS_BUG_ON (virt_dev->nullio); + + res =kmem_cache_zalloc (vdisk_thr_cachep,GFP_KERNEL ); +if (res ==NULL ) { +TRACE (TRACE_OUT_OF_MEM ,"%s" ,"Unable to allocate struct " +"scst_vdisk_thr" ); + goto out; + } + +if (!virt_dev->cdrom_empty) { + res->fd =vdev_open_fd (virt_dev); +if (IS_ERR (res->fd)) { +PRINT_ERROR ("filp_open(%s) returned an error %ld" , + virt_dev->filename,PTR_ERR (res->fd)); + goto out_free; + } +if (virt_dev->blockio) + res->bdev = res->fd->f_dentry->d_inode->i_bdev; +else + res->bdev =NULL ; + }else + res->fd =NULL ; + +scst_add_thr_data (tgt_dev, &res->hdr, vdisk_free_thr_data); + +out: +return res; + +out_free: +kmem_cache_free (vdisk_thr_cachep, res); + res =NULL ; + goto out; +} + +static int vdisk_attach_tgt (struct scst_tgt_dev *tgt_dev) +{ +int res =0 ; + +/* Nothing to do */ +return res; +} + +static void vdisk_detach_tgt (struct scst_tgt_dev *tgt_dev) +{ + +scst_del_all_thr_data (tgt_dev); +return ; +} + +static int vdisk_do_job (struct scst_cmd *cmd) +{ +int rc, res; +uint64_t lba_start =0 ; +loff_t data_len =0 ; +uint8_t *cdb = cmd->cdb; +int opcode = cdb[0 ]; +loff_t loff; +struct scst_device *dev = cmd->dev; +struct scst_tgt_dev *tgt_dev = cmd->tgt_dev; +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)dev->dh_priv; +struct scst_thr_data_hdr *d; +struct scst_vdisk_thr *thr =NULL ; +int fua =0 ; + +switch (cmd->queue_type) { +case SCST_CMD_QUEUE_ORDERED : +TRACE (TRACE_ORDER ,"ORDERED cmd %p (op %x)" , cmd, cmd->cdb[0 ]); +break ; +case SCST_CMD_QUEUE_HEAD_OF_QUEUE : +TRACE (TRACE_ORDER ,"HQ cmd %p (op %x)" , cmd, cmd->cdb[0 ]); +break ; +default : +break ; + } + + rc =scst_check_local_events (cmd); +if (unlikely (rc !=0 )) + goto out_done; + + cmd->status =0 ; + cmd->msg_status =0 ; + cmd->host_status =DID_OK ; + cmd->driver_status =0 ; + +if (!virt_dev->nullio) { + d =scst_find_thr_data (tgt_dev); +if (unlikely (d ==NULL )) { + thr =vdisk_init_thr_data (tgt_dev); +if (thr ==NULL ) { +scst_set_busy (cmd); + goto out_compl; + } +scst_thr_data_get (&thr->hdr); + }else + thr = container_of(d, struct scst_vdisk_thr, hdr); + }else { + thr = &nullio_thr_data; +scst_thr_data_get (&thr->hdr); + } + +switch (opcode) { +case READ_6 : +case WRITE_6 : +case VERIFY_6 : + lba_start = (((cdb[1 ] &0x1f ) << (BYTE *2 )) + + (cdb[2 ] << (BYTE *1 )) + + (cdb[3 ] << (BYTE *0 ))); + data_len = cmd->bufflen; +break ; +case READ_10 : +case READ_12 : +case WRITE_10 : +case WRITE_12 : +case VERIFY : +case WRITE_VERIFY : +case WRITE_VERIFY_12 : +case VERIFY_12 : + lba_start |= ((u64 )cdb[2 ]) <<24 ; + lba_start |= ((u64 )cdb[3 ]) <<16 ; + lba_start |= ((u64 )cdb[4 ]) <<8 ; + lba_start |= ((u64 )cdb[5 ]); + data_len = cmd->bufflen; +break ; +case READ_16 : +case WRITE_16 : +case WRITE_VERIFY_16 : +case VERIFY_16 : + lba_start |= ((u64 )cdb[2 ]) <<56 ; + lba_start |= ((u64 )cdb[3 ]) <<48 ; + lba_start |= ((u64 )cdb[4 ]) <<40 ; + lba_start |= ((u64 )cdb[5 ]) <<32 ; + lba_start |= ((u64 )cdb[6 ]) <<24 ; + lba_start |= ((u64 )cdb[7 ]) <<16 ; + lba_start |= ((u64 )cdb[8 ]) <<8 ; + lba_start |= ((u64 )cdb[9 ]); + data_len = cmd->bufflen; +break ; +case SYNCHRONIZE_CACHE : + lba_start |= ((u64 )cdb[2 ]) <<24 ; + lba_start |= ((u64 )cdb[3 ]) <<16 ; + lba_start |= ((u64 )cdb[4 ]) <<8 ; + lba_start |= ((u64 )cdb[5 ]); + data_len = ((cdb[7 ] << (BYTE *1 )) + (cdb[8 ] << (BYTE *0 ))) + << virt_dev->block_shift; +if (data_len ==0 ) + data_len = virt_dev->file_size - + ((loff_t )lba_start << virt_dev->block_shift); +break ; + } + + loff = (loff_t )lba_start << virt_dev->block_shift; +TRACE_DBG ("cmd %p, lba_start %lld, loff %lld, data_len %lld" , cmd, + (long long unsigned int )lba_start, + (long long unsigned int )loff, + (long long unsigned int )data_len); +if (unlikely (loff <0 ) ||unlikely (data_len <0 ) || +unlikely ((loff + data_len) > virt_dev->file_size)) { +PRINT_INFO ("Access beyond the end of the device " +"(%lld of %lld, len %lld)" , + (long long unsigned int )loff, + (long long unsigned int )virt_dev->file_size, + (long long unsigned int )data_len); +scst_set_cmd_error (cmd,SCST_LOAD_SENSE ( + scst_sense_block_out_range_error)); + goto out_compl; + } + +switch (opcode) { +case WRITE_10 : +case WRITE_12 : +case WRITE_16 : + fua = (cdb[1 ] &0x8 ); +if (fua) { +TRACE (TRACE_ORDER ,"FUA: loff=%lld, " +"data_len=%lld" , (long long unsigned int )loff, + (long long unsigned int )data_len); + } +break ; + } + +switch (opcode) { +case READ_6 : +case READ_10 : +case READ_12 : +case READ_16 : +if (virt_dev->blockio) { +blockio_exec_rw (cmd, thr, lba_start,0 ); + goto out_thr; + }else +vdisk_exec_read (cmd, thr, loff); +break ; +case WRITE_6 : +case WRITE_10 : +case WRITE_12 : +case WRITE_16 : + { +if (virt_dev->blockio) { +blockio_exec_rw (cmd, thr, lba_start,1 ); + goto out_thr; + }else +vdisk_exec_write (cmd, thr, loff); +/* O_SYNC flag is used for WT devices */ +if (fua) +vdisk_fsync (thr, loff, data_len, cmd, dev); +break ; + } +case WRITE_VERIFY : +case WRITE_VERIFY_12 : +case WRITE_VERIFY_16 : + { +/* ToDo: BLOCKIO VERIFY */ +vdisk_exec_write (cmd, thr, loff); +/* O_SYNC flag is used for WT devices */ +if (scsi_status_is_good (cmd->status)) +vdisk_exec_verify (cmd, thr, loff); +break ; + } +case SYNCHRONIZE_CACHE : + { +int immed = cdb[1 ] &0x2 ; +TRACE (TRACE_ORDER ,"SYNCHRONIZE_CACHE: " +"loff=%lld, data_len=%lld, immed=%d" , + (long long unsigned int )loff, + (long long unsigned int )data_len, immed); +if (immed) { +scst_cmd_get (cmd);/* to protect dev */ + cmd->completed =1 ; + cmd->scst_cmd_done (cmd,SCST_CMD_STATE_DEFAULT , +SCST_CONTEXT_SAME ); +vdisk_fsync (thr, loff, data_len,NULL , dev); +/* ToDo: vdisk_fsync() error processing */ +scst_cmd_put (cmd); + goto out_thr; + }else { +vdisk_fsync (thr, loff, data_len, cmd, dev); +break ; + } + } +case VERIFY_6 : +case VERIFY : +case VERIFY_12 : +case VERIFY_16 : +vdisk_exec_verify (cmd, thr, loff); +break ; +case MODE_SENSE : +case MODE_SENSE_10 : +vdisk_exec_mode_sense (cmd); +break ; +case MODE_SELECT : +case MODE_SELECT_10 : +vdisk_exec_mode_select (cmd); +break ; +case LOG_SELECT : +case LOG_SENSE : +vdisk_exec_log (cmd); +break ; +case ALLOW_MEDIUM_REMOVAL : +vdisk_exec_prevent_allow_medium_removal (cmd); +break ; +case READ_TOC : +vdisk_exec_read_toc (cmd); +break ; +case START_STOP : +vdisk_fsync (thr,0 , virt_dev->file_size, cmd, dev); +break ; +case RESERVE : +case RESERVE_10 : +case RELEASE : +case RELEASE_10 : +case TEST_UNIT_READY : +break ; +case INQUIRY : +vdisk_exec_inquiry (cmd); +break ; +case REQUEST_SENSE : +vdisk_exec_request_sense (cmd); +break ; +case READ_CAPACITY : +vdisk_exec_read_capacity (cmd); +break ; +case SERVICE_ACTION_IN : +if ((cmd->cdb[1 ] &0x1f ) ==SAI_READ_CAPACITY_16 ) { +vdisk_exec_read_capacity16 (cmd); +break ; + } +case UNMAP : +vdisk_exec_unmap (cmd, thr); +break ; +/* else go through */ +case REPORT_LUNS : +default : +TRACE_DBG ("Invalid opcode %d" , opcode); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_opcode)); + } + +out_compl: + cmd->completed =1 ; + +out_done: + cmd->scst_cmd_done (cmd,SCST_CMD_STATE_DEFAULT ,SCST_CONTEXT_SAME ); + +out_thr: +if (likely (thr !=NULL )) +scst_thr_data_put (&thr->hdr); + + res =SCST_EXEC_COMPLETED ; +return res; +} + +static int vdisk_get_block_shift (struct scst_cmd *cmd) +{ +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)cmd->dev->dh_priv; +return virt_dev->block_shift; +} + +static int vdisk_parse (struct scst_cmd *cmd) +{ +scst_sbc_generic_parse (cmd, vdisk_get_block_shift); +return SCST_CMD_STATE_DEFAULT ; +} + +static int vcdrom_parse (struct scst_cmd *cmd) +{ +scst_cdrom_generic_parse (cmd, vdisk_get_block_shift); +return SCST_CMD_STATE_DEFAULT ; +} + +static int vcdrom_exec (struct scst_cmd *cmd) +{ +int res =SCST_EXEC_COMPLETED ; +int opcode = cmd->cdb[0 ]; +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)cmd->dev->dh_priv; + + cmd->status =0 ; + cmd->msg_status =0 ; + cmd->host_status =DID_OK ; + cmd->driver_status =0 ; + +if (virt_dev->cdrom_empty && (opcode !=INQUIRY )) { +TRACE_DBG ("%s" ,"CDROM empty" ); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_not_ready)); + goto out_done; + } + +if (virt_dev->media_changed &&scst_is_ua_command (cmd)) { +spin_lock (&virt_dev->flags_lock); +if (virt_dev->media_changed) { + virt_dev->media_changed =0 ; +TRACE_DBG ("%s" ,"Reporting media changed" ); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_medium_changed_UA)); +spin_unlock (&virt_dev->flags_lock); + goto out_done; + } +spin_unlock (&virt_dev->flags_lock); + } + + res =vdisk_do_job (cmd); + +out: +return res; + +out_done: + cmd->scst_cmd_done (cmd,SCST_CMD_STATE_DEFAULT ,SCST_CONTEXT_SAME ); + goto out; +} + +static uint64_t vdisk_gen_dev_id_num (const char *virt_dev_name) +{ +unsigned int dev_id_num, i; + +for (dev_id_num =0 , i =0 ; i <strlen (virt_dev_name); i++) { +unsigned int rv = random_values[(int )(virt_dev_name[i])]; +/* Do some rotating of the bits */ + dev_id_num ^= ((rv << i) | (rv >> (32 - i))); + } + +return ((uint64_t )scst_get_setup_id () <<32 ) | dev_id_num; +} + +static void vdisk_exec_unmap (struct scst_cmd *cmd,struct scst_vdisk_thr *thr) +{ +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)cmd->dev->dh_priv; +ssize_t length =0 ; +struct file *fd = thr->fd; +struct inode *inode; +uint8_t *address; +int offset, descriptor_len, total_len; + +if (unlikely (virt_dev->thin_provisioned)) { +TRACE_DBG ("%s" ,"Invalid opcode UNMAP" ); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_opcode)); + goto out; + } + + length =scst_get_full_buf (cmd, &address); +if (unlikely (length <=0 )) { +if (length ==0 ) + goto out_put; +else if (length == -ENOMEM ) +scst_set_busy (cmd); +else +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + goto out; + } + + inode = fd->f_dentry->d_inode; + + total_len = cmd->cdb[7 ] <<8 | cmd->cdb[8 ];/* length */ + offset =8 ; + + descriptor_len = address[2 ] <<8 | address[3 ]; + +TRACE_DBG ("total_len %d, descriptor_len %d" , total_len, descriptor_len); + +if (descriptor_len ==0 ) + goto out_put; + +if (unlikely ((descriptor_len > (total_len -8 )) || + ((descriptor_len %16 ) !=0 ))) { +PRINT_ERROR ("Bad descriptor length: %d < %d - 8" , + descriptor_len, total_len); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_field_in_parm_list)); + goto out_put; + } + +while ((offset -8 ) < descriptor_len) { +int err; +uint64_t start; +uint32_t len; + start =be64_to_cpu (get_unaligned ((__be64 *)&address[offset])); + offset +=8 ; + len =be32_to_cpu (get_unaligned ((__be32 *)&address[offset])); + offset +=8 ; + +if ((start > virt_dev->nblocks) || + ((start + len) > virt_dev->nblocks)) { +PRINT_ERROR ("Device %s: attempt to write beyond max " +"size" , virt_dev->name); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_field_in_cdb)); + goto out_put; + } + +TRACE_DBG ("Unmapping lba %lld (blocks %d)" , + (unsigned long long )start, len); + +if (virt_dev->blockio) { + err =blkdev_issue_discard (inode->i_bdev, start, len, +GFP_KERNEL ,BLKDEV_IFL_WAIT ); +if (unlikely (err !=0 )) { +PRINT_ERROR ("blkdev_issue_discard() for " +"LBA %lld len %d failed with err %d" , + (unsigned long long )start, len, err); + goto out_hw_err; + } + }else { +/* +* We are guaranteed by thin_provisioned flag +* that truncate_range is not NULL. +*/ + inode->i_op->truncate_range (inode, + start, start + len); + } + } + +out_put: +scst_put_full_buf (cmd, address); + +out: +return ; + +out_hw_err: +scst_set_cmd_error (cmd,SCST_LOAD_SENSE (scst_sense_write_error)); + goto out_put; +} + +static void vdisk_exec_inquiry (struct scst_cmd *cmd) +{ +int32_t length, i, resp_len =0 ; +uint8_t *address; +uint8_t *buf; +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)cmd->dev->dh_priv; + +/* ToDo: Performance Boost: +* 1. remove kzalloc, buf +* 2. do all checks before touching *address +* 3. zero *address +* 4. write directly to *address +*/ + + buf =kzalloc (INQ_BUF_SZ ,GFP_KERNEL ); +if (buf ==NULL ) { +scst_set_busy (cmd); + goto out; + } + + length =scst_get_buf_first (cmd, &address); +TRACE_DBG ("length %d" , length); +if (unlikely (length <=0 )) { +if (length <0 ) { +PRINT_ERROR ("scst_get_buf_first() failed: %d" , length); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + } + goto out_free; + } + +if (cmd->cdb[1 ] &CMDDT ) { +TRACE_DBG ("%s" ,"INQUIRY: CMDDT is unsupported" ); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_field_in_cdb)); + goto out_put; + } + + buf[0 ] = cmd->dev->type;/* type dev */ +if (virt_dev->removable) + buf[1 ] =0x80 ;/* removable */ +/* Vital Product */ +if (cmd->cdb[1 ] &EVPD ) { +if (0 == cmd->cdb[2 ]) { +/* supported vital product data pages */ + buf[3 ] =3 ; + buf[4 ] =0x0 ;/* this page */ + buf[5 ] =0x80 ;/* unit serial number */ + buf[6 ] =0x83 ;/* device identification */ +if (virt_dev->dev->type ==TYPE_DISK ) { + buf[3 ] +=1 ; + buf[7 ] =0xB0 ;/* block limits */ +if (virt_dev->thin_provisioned) { + buf[3 ] +=1 ; + buf[8 ] =0xB2 ;/* thin provisioning */ + } + } + resp_len = buf[3 ] +4 ; + }else if (0x80 == cmd->cdb[2 ]) { +/* unit serial number */ +int usn_len =strlen (virt_dev->usn); + buf[1 ] =0x80 ; + buf[3 ] = usn_len; +strncpy (&buf[4 ], virt_dev->usn, usn_len); + resp_len = buf[3 ] +4 ; + }else if (0x83 == cmd->cdb[2 ]) { +/* device identification */ +int num =4 ; + + buf[1 ] =0x83 ; +/* T10 vendor identifier field format (faked) */ + buf[num +0 ] =0x2 ;/* ASCII */ + buf[num +1 ] =0x1 ;/* Vendor ID */ +if (virt_dev->blockio) +memcpy (&buf[num +4 ],SCST_BIO_VENDOR ,8 ); +else +memcpy (&buf[num +4 ],SCST_FIO_VENDOR ,8 ); + +read_lock_bh (&vdisk_t10_dev_id_rwlock); + i =strlen (virt_dev->t10_dev_id); +memcpy (&buf[num +12 ], virt_dev->t10_dev_id, i); +read_unlock_bh (&vdisk_t10_dev_id_rwlock); + + buf[num +3 ] =8 + i; + num += buf[num +3 ]; + + num +=4 ; + +/* +* Relative target port identifier +*/ + buf[num +0 ] =0x01 ;/* binary */ +/* Relative target port id */ + buf[num +1 ] =0x10 |0x04 ; + +put_unaligned (cpu_to_be16 (cmd->tgt->rel_tgt_id), + (__be16 *)&buf[num +4 +2 ]); + + buf[num +3 ] =4 ; + num += buf[num +3 ]; + + num +=4 ; + +/* +* IEEE id +*/ + buf[num +0 ] =0x01 ;/* binary */ + +/* EUI-64 */ + buf[num +1 ] =0x02 ; + buf[num +2 ] =0x00 ; + buf[num +3 ] =0x08 ; + +/* IEEE id */ + buf[num +4 ] = virt_dev->t10_dev_id[0 ]; + buf[num +5 ] = virt_dev->t10_dev_id[1 ]; + buf[num +6 ] = virt_dev->t10_dev_id[2 ]; + +/* IEEE ext id */ + buf[num +7 ] = virt_dev->t10_dev_id[3 ]; + buf[num +8 ] = virt_dev->t10_dev_id[4 ]; + buf[num +9 ] = virt_dev->t10_dev_id[5 ]; + buf[num +10 ] = virt_dev->t10_dev_id[6 ]; + buf[num +11 ] = virt_dev->t10_dev_id[7 ]; + num += buf[num +3 ]; + + resp_len = num; + buf[2 ] = (resp_len >>8 ) &0xFF ; + buf[3 ] = resp_len &0xFF ; + resp_len +=4 ; + }else if ((0xB0 == cmd->cdb[2 ]) && + (virt_dev->dev->type ==TYPE_DISK )) { +/* Block Limits */ +int max_transfer; + buf[1 ] =0xB0 ; + buf[3 ] =0x3C ; +/* Optimal transfer granuality is PAGE_SIZE */ +put_unaligned (cpu_to_be16 (max_t (int, +PAGE_SIZE /virt_dev->block_size,1 )), + (uint16_t *)&buf[6 ]); +/* Max transfer len is min of sg limit and 8M */ + max_transfer =min_t (int, + cmd->tgt_dev->max_sg_cnt <<PAGE_SHIFT , +8 *1024 *1024 ) / virt_dev->block_size; +put_unaligned (cpu_to_be32 (max_transfer), + (uint32_t *)&buf[8 ]); +/* +* Let's have optimal transfer len 1MB. Better to not +* set it at all, because we don't have such limit, +* but some initiators may not understand that (?). +* From other side, too big transfers are not optimal, +* because SGV cache supports only <4M buffers. +*/ +put_unaligned (cpu_to_be32 (min_t (int, + max_transfer, +1 *1024 *1024 / virt_dev->block_size)), + (uint32_t *)&buf[12 ]); +if (virt_dev->thin_provisioned) { +/* MAXIMUM UNMAP LBA COUNT is UNLIMITED */ +put_unaligned (cpu_to_be32 (0xFFFFFFFF ), + (uint16_t *)&buf[20 ]); +/* MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT is UNLIMITED */ +put_unaligned (cpu_to_be32 (0xFFFFFFFF ), + (uint16_t *)&buf[24 ]); + } + resp_len = buf[3 ] +4 ; + }else if ((0xB2 == cmd->cdb[2 ]) && + (virt_dev->dev->type ==TYPE_DISK ) && + virt_dev->thin_provisioned) { +/* Thin Provisioning */ + buf[1 ] =0xB2 ; + buf[3 ] =2 ; + buf[5 ] =0x80 ; + resp_len = buf[3 ] +4 ; + }else { +TRACE_DBG ("INQUIRY: Unsupported EVPD page %x" , + cmd->cdb[2 ]); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_field_in_cdb)); + goto out_put; + } + }else { +int len, num; + +if (cmd->cdb[2 ] !=0 ) { +TRACE_DBG ("INQUIRY: Unsupported page %x" , cmd->cdb[2 ]); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_field_in_cdb)); + goto out_put; + } + + buf[2 ] =5 ;/* Device complies to SPC-3 */ + buf[3 ] =0x12 ;/* HiSup + data in format specified in SPC */ + buf[4 ] =31 ;/* n - 4 = 35 - 4 = 31 for full 36 byte data */ + buf[6 ] =1 ;/* MultiP 1 */ + buf[7 ] =2 ;/* CMDQUE 1, BQue 0 => commands queuing supported */ + +/* +* 8 byte ASCII Vendor Identification of the target +* - left aligned. +*/ +if (virt_dev->blockio) +memcpy (&buf[8 ],SCST_BIO_VENDOR ,8 ); +else +memcpy (&buf[8 ],SCST_FIO_VENDOR ,8 ); + +/* +* 16 byte ASCII Product Identification of the target - left +* aligned. +*/ +memset (&buf[16 ],' ' ,16 ); + len =min (strlen (virt_dev->name), (size_t )16 ); +memcpy (&buf[16 ], virt_dev->name, len); + +/* +* 4 byte ASCII Product Revision Level of the target - left +* aligned. +*/ +memcpy (&buf[32 ],SCST_FIO_REV ,4 ); + +/** Version descriptors **/ + + buf[4 ] +=58 -36 ; + num =0 ; + +/* SAM-3 T10/1561-D revision 14 */ + buf[58 + num] =0x0 ; + buf[58 + num +1 ] =0x76 ; + num +=2 ; + +/* Physical transport */ +if (cmd->tgtt->get_phys_transport_version !=NULL ) { +uint16_t v = cmd->tgtt->get_phys_transport_version (cmd->tgt); +if (v !=0 ) { + *((__be16 *)&buf[58 + num]) =cpu_to_be16 (v); + num +=2 ; + } + } + +/* SCSI transport */ +if (cmd->tgtt->get_scsi_transport_version !=NULL ) { + *((__be16 *)&buf[58 + num]) = +cpu_to_be16 (cmd->tgtt->get_scsi_transport_version (cmd->tgt)); + num +=2 ; + } + +/* SPC-3 T10/1416-D revision 23 */ + buf[58 + num] =0x3 ; + buf[58 + num +1 ] =0x12 ; + num +=2 ; + +/* Device command set */ +if (virt_dev->command_set_version !=0 ) { + *((__be16 *)&buf[58 + num]) = +cpu_to_be16 (virt_dev->command_set_version); + num +=2 ; + } + + buf[4 ] += num; + resp_len = buf[4 ] +5 ; + } + +BUG_ON (resp_len >=INQ_BUF_SZ ); + +if (length > resp_len) + length = resp_len; +memcpy (address, buf, length); + +out_put: +scst_put_buf (cmd, address); +if (length < cmd->resp_data_len) +scst_set_resp_data_len (cmd, length); + +out_free: +kfree (buf); + +out: +return ; +} + +static void vdisk_exec_request_sense (struct scst_cmd *cmd) +{ +int32_t length, sl; +uint8_t *address; +uint8_t b[SCST_STANDARD_SENSE_LEN ]; + + sl =scst_set_sense (b,sizeof (b), cmd->dev->d_sense, +SCST_LOAD_SENSE (scst_sense_no_sense)); + + length =scst_get_buf_first (cmd, &address); +TRACE_DBG ("length %d" , length); +if (length <0 ) { +PRINT_ERROR ("scst_get_buf_first() failed: %d)" , length); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + goto out; + } + + length =min (sl, length); +memcpy (address, b, length); +scst_set_resp_data_len (cmd, length); + +scst_put_buf (cmd, address); + +out: +return ; +} + +/* +* <<Following mode pages info copied from ST318451LW with some corrections>> +* +* ToDo: revise them +*/ +static int vdisk_err_recov_pg (unsigned char *p,int pcontrol, +struct scst_vdisk_dev *virt_dev) +{/* Read-Write Error Recovery page for mode_sense */ +const unsigned char err_recov_pg[] = {0x1 ,0xa ,0xc0 ,11 ,240 ,0 ,0 ,0 , +5 ,0 ,0xff ,0xff }; + +memcpy (p, err_recov_pg,sizeof (err_recov_pg)); +if (1 == pcontrol) +memset (p +2 ,0 ,sizeof (err_recov_pg) -2 ); +return sizeof (err_recov_pg); +} + +static int vdisk_disconnect_pg (unsigned char *p,int pcontrol, +struct scst_vdisk_dev *virt_dev) +{/* Disconnect-Reconnect page for mode_sense */ +const unsigned char disconnect_pg[] = {0x2 ,0xe ,128 ,128 ,0 ,10 ,0 ,0 , +0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 }; + +memcpy (p, disconnect_pg,sizeof (disconnect_pg)); +if (1 == pcontrol) +memset (p +2 ,0 ,sizeof (disconnect_pg) -2 ); +return sizeof (disconnect_pg); +} + +static int vdisk_rigid_geo_pg (unsigned char *p,int pcontrol, +struct scst_vdisk_dev *virt_dev) +{ +unsigned char geo_m_pg[] = {0x04 ,0x16 ,0 ,0 ,0 ,DEF_HEADS ,0 ,0 , +0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , +0x3a ,0x98 /* 15K RPM */ ,0 ,0 }; +int32_t ncyl, n, rem; +uint64_t dividend; + +memcpy (p, geo_m_pg,sizeof (geo_m_pg)); +/* +* Divide virt_dev->nblocks by (DEF_HEADS * DEF_SECTORS) and store +* the quotient in ncyl and the remainder in rem. +*/ + dividend = virt_dev->nblocks; + rem =do_div (dividend,DEF_HEADS *DEF_SECTORS ); + ncyl = dividend; +if (rem !=0 ) + ncyl++; +memcpy (&n, p +2 ,sizeof (u32)); + n = n | ((__force u32 )cpu_to_be32 (ncyl) >>8 ); +memcpy (p +2 , &n,sizeof (u32)); +if (1 == pcontrol) +memset (p +2 ,0 ,sizeof (geo_m_pg) -2 ); +return sizeof (geo_m_pg); +} + +static int vdisk_format_pg (unsigned char *p,int pcontrol, +struct scst_vdisk_dev *virt_dev) +{/* Format device page for mode_sense */ +const unsigned char format_pg[] = {0x3 ,0x16 ,0 ,0 ,0 ,0 ,0 ,0 , +0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , +0 ,0 ,0 ,0 ,0x40 ,0 ,0 ,0 }; + +memcpy (p, format_pg,sizeof (format_pg)); + p[10 ] = (DEF_SECTORS >>8 ) &0xff ; + p[11 ] =DEF_SECTORS &0xff ; + p[12 ] = (virt_dev->block_size >>8 ) &0xff ; + p[13 ] = virt_dev->block_size &0xff ; +if (1 == pcontrol) +memset (p +2 ,0 ,sizeof (format_pg) -2 ); +return sizeof (format_pg); +} + +static int vdisk_caching_pg (unsigned char *p,int pcontrol, +struct scst_vdisk_dev *virt_dev) +{/* Caching page for mode_sense */ +const unsigned char caching_pg[] = {0x8 ,18 ,0x10 ,0 ,0xff ,0xff ,0 ,0 , +0xff ,0xff ,0xff ,0xff ,0x80 ,0x14 ,0 ,0 ,0 ,0 ,0 ,0 }; + +memcpy (p, caching_pg,sizeof (caching_pg)); + p[2 ] |= !(virt_dev->wt_flag || virt_dev->nv_cache) ?WCE :0 ; +if (1 == pcontrol) +memset (p +2 ,0 ,sizeof (caching_pg) -2 ); +return sizeof (caching_pg); +} + +static int vdisk_ctrl_m_pg (unsigned char *p,int pcontrol, +struct scst_vdisk_dev *virt_dev) +{/* Control mode page for mode_sense */ +const unsigned char ctrl_m_pg[] = {0xa ,0xa ,0 ,0 ,0 ,0 ,0 ,0 , +0 ,0 ,0x2 ,0x4b }; + +memcpy (p, ctrl_m_pg,sizeof (ctrl_m_pg)); +switch (pcontrol) { +case 0 : + p[2 ] |= virt_dev->dev->tst <<5 ; + p[2 ] |= virt_dev->dev->d_sense <<2 ; + p[3 ] |= virt_dev->dev->queue_alg <<4 ; + p[4 ] |= virt_dev->dev->swp <<3 ; + p[5 ] |= virt_dev->dev->tas <<6 ; +break ; +case 1 : +memset (p +2 ,0 ,sizeof (ctrl_m_pg) -2 ); +#if 0 /* +* It's too early to implement it, since we can't control the +* backstorage device parameters. ToDo +*/ + p[2 ] |=7 <<5 ;/* TST */ + p[3 ] |=0xF <<4 ;/* QUEUE ALGORITHM MODIFIER */ +#endif + p[2 ] |=1 <<2 ;/* D_SENSE */ + p[4 ] |=1 <<3 ;/* SWP */ + p[5 ] |=1 <<6 ;/* TAS */ +break ; +case 2 : + p[2 ] |=DEF_TST <<5 ; + p[2 ] |=DEF_DSENSE <<2 ; +if (virt_dev->wt_flag || virt_dev->nv_cache) + p[3 ] |=DEF_QUEUE_ALG_WT <<4 ; +else + p[3 ] |=DEF_QUEUE_ALG <<4 ; + p[4 ] |=DEF_SWP <<3 ; + p[5 ] |=DEF_TAS <<6 ; +break ; +default : +BUG (); + } +return sizeof (ctrl_m_pg); +} + +static int vdisk_iec_m_pg (unsigned char *p,int pcontrol, +struct scst_vdisk_dev *virt_dev) +{/* Informational Exceptions control mode page for mode_sense */ +const unsigned char iec_m_pg[] = {0x1c ,0xa ,0x08 ,0 ,0 ,0 ,0 ,0 , +0 ,0 ,0x0 ,0x0 }; +memcpy (p, iec_m_pg,sizeof (iec_m_pg)); +if (1 == pcontrol) +memset (p +2 ,0 ,sizeof (iec_m_pg) -2 ); +return sizeof (iec_m_pg); +} + +static void vdisk_exec_mode_sense (struct scst_cmd *cmd) +{ +int32_t length; +uint8_t *address; +uint8_t *buf; +struct scst_vdisk_dev *virt_dev; +uint32_t blocksize; +uint64_t nblocks; +unsigned char dbd, type; +int pcontrol, pcode, subpcode; +unsigned char dev_spec; +int msense_6, offset =0 , len; +unsigned char *bp; + + buf =kzalloc (MSENSE_BUF_SZ ,GFP_KERNEL ); +if (buf ==NULL ) { +scst_set_busy (cmd); + goto out; + } + + virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv; + blocksize = virt_dev->block_size; + nblocks = virt_dev->nblocks; + + type = cmd->dev->type;/* type dev */ + dbd = cmd->cdb[1 ] &DBD ; + pcontrol = (cmd->cdb[2 ] &0xc0 ) >>6 ; + pcode = cmd->cdb[2 ] &0x3f ; + subpcode = cmd->cdb[3 ]; + msense_6 = (MODE_SENSE == cmd->cdb[0 ]); + dev_spec = (virt_dev->dev->rd_only || + cmd->tgt_dev->acg_dev->rd_only) ?WP :0 ; + +if (!virt_dev->blockio) + dev_spec |=DPOFUA ; + + length =scst_get_buf_first (cmd, &address); +if (unlikely (length <=0 )) { +if (length <0 ) { +PRINT_ERROR ("scst_get_buf_first() failed: %d" , length); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + } + goto out_free; + } + +if (0x3 == pcontrol) { +TRACE_DBG ("%s" ,"MODE SENSE: Saving values not supported" ); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_saving_params_unsup)); + goto out_put; + } + +if (msense_6) { + buf[1 ] = type; + buf[2 ] = dev_spec; + offset =4 ; + }else { + buf[2 ] = type; + buf[3 ] = dev_spec; + offset =8 ; + } + +if (0 != subpcode) { +/* TODO: Control Extension page */ +TRACE_DBG ("%s" ,"MODE SENSE: Only subpage 0 is supported" ); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_field_in_cdb)); + goto out_put; + } + +if (!dbd) { +/* Create block descriptor */ + buf[offset -1 ] =0x08 ;/* block descriptor length */ +if (nblocks >>32 ) { + buf[offset +0 ] =0xFF ; + buf[offset +1 ] =0xFF ; + buf[offset +2 ] =0xFF ; + buf[offset +3 ] =0xFF ; + }else { +/* num blks */ + buf[offset +0 ] = (nblocks >> (BYTE *3 )) &0xFF ; + buf[offset +1 ] = (nblocks >> (BYTE *2 )) &0xFF ; + buf[offset +2 ] = (nblocks >> (BYTE *1 )) &0xFF ; + buf[offset +3 ] = (nblocks >> (BYTE *0 )) &0xFF ; + } + buf[offset +4 ] =0 ;/* density code */ + buf[offset +5 ] = (blocksize >> (BYTE *2 )) &0xFF ;/* blklen */ + buf[offset +6 ] = (blocksize >> (BYTE *1 )) &0xFF ; + buf[offset +7 ] = (blocksize >> (BYTE *0 )) &0xFF ; + + offset +=8 ;/* increment offset */ + } + + bp = buf + offset; + +switch (pcode) { +case 0x1 :/* Read-Write error recovery page, direct access */ + len =vdisk_err_recov_pg (bp, pcontrol, virt_dev); +break ; +case 0x2 :/* Disconnect-Reconnect page, all devices */ + len =vdisk_disconnect_pg (bp, pcontrol, virt_dev); +break ; +case 0x3 :/* Format device page, direct access */ + len =vdisk_format_pg (bp, pcontrol, virt_dev); +break ; +case 0x4 :/* Rigid disk geometry */ + len =vdisk_rigid_geo_pg (bp, pcontrol, virt_dev); +break ; +case 0x8 :/* Caching page, direct access */ + len =vdisk_caching_pg (bp, pcontrol, virt_dev); +break ; +case 0xa :/* Control Mode page, all devices */ + len =vdisk_ctrl_m_pg (bp, pcontrol, virt_dev); +break ; +case 0x1c :/* Informational Exceptions Mode page, all devices */ + len =vdisk_iec_m_pg (bp, pcontrol, virt_dev); +break ; +case 0x3f :/* Read all Mode pages */ + len =vdisk_err_recov_pg (bp, pcontrol, virt_dev); + len +=vdisk_disconnect_pg (bp + len, pcontrol, virt_dev); + len +=vdisk_format_pg (bp + len, pcontrol, virt_dev); + len +=vdisk_caching_pg (bp + len, pcontrol, virt_dev); + len +=vdisk_ctrl_m_pg (bp + len, pcontrol, virt_dev); + len +=vdisk_iec_m_pg (bp + len, pcontrol, virt_dev); + len +=vdisk_rigid_geo_pg (bp + len, pcontrol, virt_dev); +break ; +default : +TRACE_DBG ("MODE SENSE: Unsupported page %x" , pcode); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_field_in_cdb)); + goto out_put; + } + + offset += len; + +if (msense_6) + buf[0 ] = offset -1 ; +else { + buf[0 ] = ((offset -2 ) >>8 ) &0xff ; + buf[1 ] = (offset -2 ) &0xff ; + } + +if (offset > length) + offset = length; +memcpy (address, buf, offset); + +out_put: +scst_put_buf (cmd, address); +if (offset < cmd->resp_data_len) +scst_set_resp_data_len (cmd, offset); + +out_free: +kfree (buf); + +out: +return ; +} + +static int vdisk_set_wt (struct scst_vdisk_dev *virt_dev,int wt) +{ +int res =0 ; + +if ((virt_dev->wt_flag == wt) || virt_dev->nullio || virt_dev->nv_cache) + goto out; + +spin_lock (&virt_dev->flags_lock); + virt_dev->wt_flag = wt; +spin_unlock (&virt_dev->flags_lock); + +scst_dev_del_all_thr_data (virt_dev->dev); + +out: +return res; +} + +static void vdisk_ctrl_m_pg_select (unsigned char *p, +struct scst_vdisk_dev *virt_dev) +{ +struct scst_device *dev = virt_dev->dev; +int old_swp = dev->swp, old_tas = dev->tas, old_dsense = dev->d_sense; + +#if 0 +/* Not implemented yet, see comment in vdisk_ctrl_m_pg() */ + dev->tst = p[2 ] >>5 ; + dev->queue_alg = p[3 ] >>4 ; +#endif + dev->swp = (p[4 ] &0x8 ) >>3 ; + dev->tas = (p[5 ] &0x40 ) >>6 ; + dev->d_sense = (p[2 ] &0x4 ) >>2 ; + +PRINT_INFO ("Device %s: new control mode page parameters: SWP %x " +"(was %x), TAS %x (was %x), D_SENSE %d (was %d)" , + virt_dev->name, dev->swp, old_swp, dev->tas, old_tas, + dev->d_sense, old_dsense); +return ; +} + +static void vdisk_exec_mode_select (struct scst_cmd *cmd) +{ +int32_t length; +uint8_t *address; +struct scst_vdisk_dev *virt_dev; +int mselect_6, offset; + + virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv; + mselect_6 = (MODE_SELECT == cmd->cdb[0 ]); + + length =scst_get_buf_first (cmd, &address); +if (unlikely (length <=0 )) { +if (length <0 ) { +PRINT_ERROR ("scst_get_buf_first() failed: %d" , length); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + } + goto out; + } + +if (!(cmd->cdb[1 ] &PF ) || (cmd->cdb[1 ] &SP )) { +TRACE (TRACE_MINOR |TRACE_SCSI ,"MODE SELECT: Unsupported " +"value(s) of PF and/or SP bits (cdb[1]=%x)" , + cmd->cdb[1 ]); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_field_in_cdb)); + goto out_put; + } + +if (mselect_6) + offset =4 ; +else + offset =8 ; + +if (address[offset -1 ] ==8 ) { + offset +=8 ; + }else if (address[offset -1 ] !=0 ) { +PRINT_ERROR ("%s" ,"MODE SELECT: Wrong parameters list " +"lenght" ); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_field_in_parm_list)); + goto out_put; + } + +while (length > offset +2 ) { +if (address[offset] &PS ) { +PRINT_ERROR ("%s" ,"MODE SELECT: Illegal PS bit" ); +scst_set_cmd_error (cmd,SCST_LOAD_SENSE ( + scst_sense_invalid_field_in_parm_list)); + goto out_put; + } +if ((address[offset] &0x3f ) ==0x8 ) { +/* Caching page */ +if (address[offset +1 ] !=18 ) { +PRINT_ERROR ("%s" ,"MODE SELECT: Invalid " +"caching page request" ); +scst_set_cmd_error (cmd,SCST_LOAD_SENSE ( + scst_sense_invalid_field_in_parm_list)); + goto out_put; + } +if (vdisk_set_wt (virt_dev, + (address[offset +2 ] &WCE ) ?0 :1 ) !=0 ) { +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + goto out_put; + } +break ; + }else if ((address[offset] &0x3f ) ==0xA ) { +/* Control page */ +if (address[offset +1 ] !=0xA ) { +PRINT_ERROR ("%s" ,"MODE SELECT: Invalid " +"control page request" ); +scst_set_cmd_error (cmd,SCST_LOAD_SENSE ( + scst_sense_invalid_field_in_parm_list)); + goto out_put; + } +vdisk_ctrl_m_pg_select (&address[offset], virt_dev); + }else { +PRINT_ERROR ("MODE SELECT: Invalid request %x" , + address[offset] &0x3f ); +scst_set_cmd_error (cmd,SCST_LOAD_SENSE ( + scst_sense_invalid_field_in_parm_list)); + goto out_put; + } + offset += address[offset +1 ]; + } + +out_put: +scst_put_buf (cmd, address); + +out: +return ; +} + +static void vdisk_exec_log (struct scst_cmd *cmd) +{ + +/* No log pages are supported */ +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_field_in_cdb)); +return ; +} + +static void vdisk_exec_read_capacity (struct scst_cmd *cmd) +{ +int32_t length; +uint8_t *address; +struct scst_vdisk_dev *virt_dev; +uint32_t blocksize; +uint64_t nblocks; +uint8_t buffer[8 ]; + + virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv; + blocksize = virt_dev->block_size; + nblocks = virt_dev->nblocks; + +if ((cmd->cdb[8 ] &1 ) ==0 ) { +uint64_t lba =be64_to_cpu (get_unaligned ((__be64 *)&cmd->cdb[2 ])); +if (lba !=0 ) { +TRACE_DBG ("PMI zero and LBA not zero (cmd %p)" , cmd); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_field_in_cdb)); + goto out; + } + } + +/* Last block on the virt_dev is (nblocks-1) */ +memset (buffer,0 ,sizeof (buffer)); + +/* +* If we are thinly provisioned, we must ensure that the initiator +* issues a READ_CAPACITY(16) so we can return the TPE bit. By +* returning 0xFFFFFFFF we do that. +*/ +if (nblocks >>32 || virt_dev->thin_provisioned) { + buffer[0 ] =0xFF ; + buffer[1 ] =0xFF ; + buffer[2 ] =0xFF ; + buffer[3 ] =0xFF ; + }else { + buffer[0 ] = ((nblocks -1 ) >> (BYTE *3 )) &0xFF ; + buffer[1 ] = ((nblocks -1 ) >> (BYTE *2 )) &0xFF ; + buffer[2 ] = ((nblocks -1 ) >> (BYTE *1 )) &0xFF ; + buffer[3 ] = ((nblocks -1 ) >> (BYTE *0 )) &0xFF ; + } + buffer[4 ] = (blocksize >> (BYTE *3 )) &0xFF ; + buffer[5 ] = (blocksize >> (BYTE *2 )) &0xFF ; + buffer[6 ] = (blocksize >> (BYTE *1 )) &0xFF ; + buffer[7 ] = (blocksize >> (BYTE *0 )) &0xFF ; + + length =scst_get_buf_first (cmd, &address); +if (unlikely (length <=0 )) { +if (length <0 ) { +PRINT_ERROR ("scst_get_buf_first() failed: %d" , length); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + } + goto out; + } + + length =min_t (int, length,sizeof (buffer)); + +memcpy (address, buffer, length); + +scst_put_buf (cmd, address); + +if (length < cmd->resp_data_len) +scst_set_resp_data_len (cmd, length); + +out: +return ; +} + +static void vdisk_exec_read_capacity16 (struct scst_cmd *cmd) +{ +int32_t length; +uint8_t *address; +struct scst_vdisk_dev *virt_dev; +uint32_t blocksize; +uint64_t nblocks; +uint8_t buffer[32 ]; + + virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv; + blocksize = virt_dev->block_size; + nblocks = virt_dev->nblocks -1 ; + +if ((cmd->cdb[14 ] &1 ) ==0 ) { +uint64_t lba =be64_to_cpu (get_unaligned ((__be64 *)&cmd->cdb[2 ])); +if (lba !=0 ) { +TRACE_DBG ("PMI zero and LBA not zero (cmd %p)" , cmd); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_field_in_cdb)); + goto out; + } + } + +memset (buffer,0 ,sizeof (buffer)); + + buffer[0 ] = nblocks >>56 ; + buffer[1 ] = (nblocks >>48 ) &0xFF ; + buffer[2 ] = (nblocks >>40 ) &0xFF ; + buffer[3 ] = (nblocks >>32 ) &0xFF ; + buffer[4 ] = (nblocks >>24 ) &0xFF ; + buffer[5 ] = (nblocks >>16 ) &0xFF ; + buffer[6 ] = (nblocks >>8 ) &0xFF ; + buffer[7 ] = nblocks &0xFF ; + + buffer[8 ] = (blocksize >> (BYTE *3 )) &0xFF ; + buffer[9 ] = (blocksize >> (BYTE *2 )) &0xFF ; + buffer[10 ] = (blocksize >> (BYTE *1 )) &0xFF ; + buffer[11 ] = (blocksize >> (BYTE *0 )) &0xFF ; + +switch (blocksize) { +case 512 : + buffer[13 ] =3 ; +break ; +case 1024 : + buffer[13 ] =2 ; +break ; +case 2048 : + buffer[13 ] =1 ; +break ; +case 4096 : +default : + buffer[13 ] =0 ; +break ; + } + +if (virt_dev->thin_provisioned) + buffer[14 ] |=0x80 ;/* Add TPE */ + + length =scst_get_buf_first (cmd, &address); +if (unlikely (length <=0 )) { +if (length <0 ) { +PRINT_ERROR ("scst_get_buf_first() failed: %d" , length); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + } + goto out; + } + + length =min_t (int, length,sizeof (buffer)); + +memcpy (address, buffer, length); + +scst_put_buf (cmd, address); + +if (length < cmd->resp_data_len) +scst_set_resp_data_len (cmd, length); + +out: +return ; +} + +static void vdisk_exec_read_toc (struct scst_cmd *cmd) +{ +int32_t length, off =0 ; +uint8_t *address; +struct scst_vdisk_dev *virt_dev; +uint32_t nblocks; +uint8_t buffer[4 +8 +8 ] = {0x00 ,0x0a ,0x01 ,0x01 ,0x00 ,0x14 , +0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 }; + +if (cmd->dev->type !=TYPE_ROM ) { +PRINT_ERROR ("%s" ,"READ TOC for non-CDROM device" ); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_opcode)); + goto out; + } + +if (cmd->cdb[2 ] &0x0e /*Format*/ ) { +PRINT_ERROR ("%s" ,"READ TOC: invalid requested data format" ); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_field_in_cdb)); + goto out; + } + +if ((cmd->cdb[6 ] !=0 && (cmd->cdb[2 ] &0x01 )) || + (cmd->cdb[6 ] >1 && cmd->cdb[6 ] !=0xAA )) { +PRINT_ERROR ("READ TOC: invalid requested track number %x" , + cmd->cdb[6 ]); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_invalid_field_in_cdb)); + goto out; + } + + length =scst_get_buf_first (cmd, &address); +if (unlikely (length <=0 )) { +if (length <0 ) { +PRINT_ERROR ("scst_get_buf_first() failed: %d" , length); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + } + goto out; + } + + virt_dev = (struct scst_vdisk_dev *)cmd->dev->dh_priv; +/* ToDo when you have > 8TB ROM device. */ + nblocks = (uint32_t )virt_dev->nblocks; + +/* Header */ +memset (buffer,0 ,sizeof (buffer)); + buffer[2 ] =0x01 ;/* First Track/Session */ + buffer[3 ] =0x01 ;/* Last Track/Session */ + off =4 ; +if (cmd->cdb[6 ] <=1 ) { +/* Fistr TOC Track Descriptor */ +/* ADDR 0x10 - Q Sub-channel encodes current position data +CONTROL 0x04 - Data track, recoreded uninterrupted */ + buffer[off+1 ] =0x14 ; +/* Track Number */ + buffer[off+2 ] =0x01 ; + off +=8 ; + } +if (!(cmd->cdb[2 ] &0x01 )) { +/* Lead-out area TOC Track Descriptor */ + buffer[off+1 ] =0x14 ; +/* Track Number */ + buffer[off+2 ] =0xAA ; +/* Track Start Address */ + buffer[off+4 ] = (nblocks >> (BYTE *3 )) &0xFF ; + buffer[off+5 ] = (nblocks >> (BYTE *2 )) &0xFF ; + buffer[off+6 ] = (nblocks >> (BYTE *1 )) &0xFF ; + buffer[off+7 ] = (nblocks >> (BYTE *0 )) &0xFF ; + off +=8 ; + } + + buffer[1 ] = off -2 ;/* Data Length */ + +if (off > length) + off = length; +memcpy (address, buffer, off); + +scst_put_buf (cmd, address); + +if (off < cmd->resp_data_len) +scst_set_resp_data_len (cmd, off); + +out: +return ; +} + +static void vdisk_exec_prevent_allow_medium_removal (struct scst_cmd *cmd) +{ +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)cmd->dev->dh_priv; + +TRACE_DBG ("PERSIST/PREVENT 0x%02x" , cmd->cdb[4 ]); + +spin_lock (&virt_dev->flags_lock); + virt_dev->prevent_allow_medium_removal = cmd->cdb[4 ] &0x01 ?1 :0 ; +spin_unlock (&virt_dev->flags_lock); + +return ; +} + +static int vdisk_fsync (struct scst_vdisk_thr *thr,loff_t loff, +loff_t len,struct scst_cmd *cmd,struct scst_device *dev) +{ +int res =0 ; +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)dev->dh_priv; +struct file *file; + +/* Hopefully, the compiler will generate the single comparison */ +if (virt_dev->nv_cache || virt_dev->wt_flag || + virt_dev->o_direct_flag || virt_dev->nullio) + goto out; + +if (virt_dev->blockio) { + res =blockio_flush (thr->bdev); + goto out; + } + + file = thr->fd; + +#if 0 /* For sparse files we might need to sync metadata as well */ + res =generic_write_sync (file, loff, len); +#else + res =filemap_write_and_wait_range (file->f_mapping, loff, len); +#endif +if (unlikely (res !=0 )) { +PRINT_ERROR ("sync range failed (%d)" , res); +if (cmd !=NULL ) { +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_write_error)); + } + } + +out: +return res; +} + +static struct iovec *vdisk_alloc_iv (struct scst_cmd *cmd, +struct scst_vdisk_thr *thr) +{ +int iv_count; + + iv_count =min_t (int,scst_get_buf_count (cmd),UIO_MAXIOV ); +if (iv_count > thr->iv_count) { +kfree (thr->iv); +/* It can't be called in atomic context */ + thr->iv =kmalloc (sizeof (*thr->iv) * iv_count,GFP_KERNEL ); +if (thr->iv ==NULL ) { +PRINT_ERROR ("Unable to allocate iv (%d)" , iv_count); +scst_set_busy (cmd); + goto out; + } + thr->iv_count = iv_count; + } + +out: +return thr->iv; +} + +static void vdisk_exec_read (struct scst_cmd *cmd, +struct scst_vdisk_thr *thr,loff_t loff) +{ +mm_segment_t old_fs; +loff_t err; +ssize_t length, full_len; +uint8_t __user *address; +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)cmd->dev->dh_priv; +struct file *fd = thr->fd; +struct iovec *iv; +int iv_count, i; +bool finished = false; + +if (virt_dev->nullio) + goto out; + + iv =vdisk_alloc_iv (cmd, thr); +if (iv ==NULL ) + goto out; + + length =scst_get_buf_first (cmd, (uint8_t __force **)&address); +if (unlikely (length <0 )) { +PRINT_ERROR ("scst_get_buf_first() failed: %zd" , length); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + goto out; + } + + old_fs =get_fs (); +set_fs (get_ds ()); + +while (1 ) { + iv_count =0 ; + full_len =0 ; + i =-1 ; +while (length >0 ) { + full_len += length; + i++; + iv_count++; + iv[i].iov_base = address; + iv[i].iov_len = length; +if (iv_count ==UIO_MAXIOV ) +break ; + length =scst_get_buf_next (cmd, + (uint8_t __force **)&address); + } +if (length ==0 ) { + finished = true; +if (unlikely (iv_count ==0 )) +break ; + }else if (unlikely (length <0 )) { +PRINT_ERROR ("scst_get_buf_next() failed: %zd" , length); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + goto out_set_fs; + } + +TRACE_DBG ("(iv_count %d, full_len %zd)" , iv_count, full_len); +/* SEEK */ +if (fd->f_op->llseek) + err = fd->f_op->llseek (fd, loff,0 /*SEEK_SET*/ ); +else + err =default_llseek (fd, loff,0 /*SEEK_SET*/ ); +if (err != loff) { +PRINT_ERROR ("lseek trouble %lld != %lld" , + (long long unsigned int )err, + (long long unsigned int )loff); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + goto out_set_fs; + } + +/* READ */ + err =vfs_readv (fd, (struct iovec __force __user *)iv, iv_count, + &fd->f_pos); + +if ((err <0 ) || (err < full_len)) { +PRINT_ERROR ("readv() returned %lld from %zd" , + (long long unsigned int )err, + full_len); +if (err == -EAGAIN ) +scst_set_busy (cmd); +else { +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_read_error)); + } + goto out_set_fs; + } + +for (i =0 ; i < iv_count; i++) +scst_put_buf (cmd, (void __force *)(iv[i].iov_base)); + +if (finished) +break ; + + loff += full_len; + length =scst_get_buf_next (cmd, (uint8_t __force **)&address); + }; + +set_fs (old_fs); + +out: +return ; + +out_set_fs: +set_fs (old_fs); +for (i =0 ; i < iv_count; i++) +scst_put_buf (cmd, (void __force *)(iv[i].iov_base)); + goto out; +} + +static void vdisk_exec_write (struct scst_cmd *cmd, +struct scst_vdisk_thr *thr,loff_t loff) +{ +mm_segment_t old_fs; +loff_t err; +ssize_t length, full_len, saved_full_len; +uint8_t __user *address; +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)cmd->dev->dh_priv; +struct file *fd = thr->fd; +struct iovec *iv, *eiv; +int i, iv_count, eiv_count; +bool finished = false; + +if (virt_dev->nullio) + goto out; + + iv =vdisk_alloc_iv (cmd, thr); +if (iv ==NULL ) + goto out; + + length =scst_get_buf_first (cmd, (uint8_t __force **)&address); +if (unlikely (length <0 )) { +PRINT_ERROR ("scst_get_buf_first() failed: %zd" , length); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + goto out; + } + + old_fs =get_fs (); +set_fs (get_ds ()); + +while (1 ) { + iv_count =0 ; + full_len =0 ; + i =-1 ; +while (length >0 ) { + full_len += length; + i++; + iv_count++; + iv[i].iov_base = address; + iv[i].iov_len = length; +if (iv_count ==UIO_MAXIOV ) +break ; + length =scst_get_buf_next (cmd, + (uint8_t __force **)&address); + } +if (length ==0 ) { + finished = true; +if (unlikely (iv_count ==0 )) +break ; + }else if (unlikely (length <0 )) { +PRINT_ERROR ("scst_get_buf_next() failed: %zd" , length); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + goto out_set_fs; + } + + saved_full_len = full_len; + eiv = iv; + eiv_count = iv_count; +restart: +TRACE_DBG ("writing(eiv_count %d, full_len %zd)" , eiv_count, full_len); + +/* SEEK */ +if (fd->f_op->llseek) + err = fd->f_op->llseek (fd, loff,0 /*SEEK_SET */ ); +else + err =default_llseek (fd, loff,0 /*SEEK_SET */ ); +if (err != loff) { +PRINT_ERROR ("lseek trouble %lld != %lld" , + (long long unsigned int )err, + (long long unsigned int )loff); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + goto out_set_fs; + } + +/* WRITE */ + err =vfs_writev (fd, (struct iovec __force __user *)eiv, eiv_count, + &fd->f_pos); + +if (err <0 ) { +PRINT_ERROR ("write() returned %lld from %zd" , + (long long unsigned int )err, + full_len); +if (err == -EAGAIN ) +scst_set_busy (cmd); +else { +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_write_error)); + } + goto out_set_fs; + }else if (err < full_len) { +/* +* Probably that's wrong, but sometimes write() returns +* value less, than requested. Let's restart. +*/ +int e = eiv_count; +TRACE_MGMT_DBG ("write() returned %d from %zd " +"(iv_count=%d)" , (int )err, full_len, + eiv_count); +if (err ==0 ) { +PRINT_INFO ("Suspicious: write() returned 0 from " +"%zd (iv_count=%d)" , full_len, eiv_count); + } + full_len -= err; +for (i =0 ; i < e; i++) { +if ((long long )eiv->iov_len < err) { + err -= eiv->iov_len; + eiv++; + eiv_count--; + }else { + eiv->iov_base = + (uint8_t __force __user *)eiv->iov_base + err; + eiv->iov_len -= err; +break ; + } + } + goto restart; + } + +for (i =0 ; i < iv_count; i++) +scst_put_buf (cmd, (void __force *)(iv[i].iov_base)); + +if (finished) +break ; + + loff += saved_full_len; + length =scst_get_buf_next (cmd, (uint8_t __force **)&address); + } + +set_fs (old_fs); + +out: +return ; + +out_set_fs: +set_fs (old_fs); +for (i =0 ; i < iv_count; i++) +scst_put_buf (cmd, (void __force *)(iv[i].iov_base)); + goto out; +} + +struct scst_blockio_work { +atomic_t bios_inflight; +struct scst_cmd *cmd; +}; + +static inline void blockio_check_finish (struct scst_blockio_work *blockio_work) +{ +/* Decrement the bios in processing, and if zero signal completion */ +if (atomic_dec_and_test (&blockio_work->bios_inflight)) { + blockio_work->cmd->completed =1 ; + blockio_work->cmd->scst_cmd_done (blockio_work->cmd, +SCST_CMD_STATE_DEFAULT ,scst_estimate_context ()); +kmem_cache_free (blockio_work_cachep, blockio_work); + } +return ; +} + +static void blockio_endio (struct bio *bio,int error) +{ +struct scst_blockio_work *blockio_work = bio->bi_private; + +if (unlikely (!bio_flagged (bio,BIO_UPTODATE ))) { +if (error ==0 ) { +PRINT_ERROR ("Not up to date bio with error 0 for " +"cmd %p, returning -EIO" , blockio_work->cmd); + error = -EIO ; + } + } + +if (unlikely (error !=0 )) { +static DEFINE_SPINLOCK (blockio_endio_lock); + +PRINT_ERROR ("cmd %p returned error %d" , blockio_work->cmd, + error); + +/* To protect from several bios finishing simultaneously */ +spin_lock_bh (&blockio_endio_lock); + +if (bio->bi_rw & (1 <<BIO_RW )) +scst_set_cmd_error (blockio_work->cmd, +SCST_LOAD_SENSE (scst_sense_write_error)); +else +scst_set_cmd_error (blockio_work->cmd, +SCST_LOAD_SENSE (scst_sense_read_error)); + +spin_unlock_bh (&blockio_endio_lock); + } + +blockio_check_finish (blockio_work); + +bio_put (bio); +return ; +} + +static void blockio_exec_rw (struct scst_cmd *cmd,struct scst_vdisk_thr *thr, +u64 lba_start,int write) +{ +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)cmd->dev->dh_priv; +struct block_device *bdev = thr->bdev; +struct request_queue *q =bdev_get_queue (bdev); +int length, max_nr_vecs =0 , offset; +struct page *page; +struct bio *bio =NULL , *hbio =NULL , *tbio =NULL ; +int need_new_bio; +struct scst_blockio_work *blockio_work; +int bios =0 ; + +if (virt_dev->nullio) + goto out; + +/* Allocate and initialize blockio_work struct */ + blockio_work =kmem_cache_alloc (blockio_work_cachep,GFP_KERNEL ); +if (blockio_work ==NULL ) + goto out_no_mem; + + blockio_work->cmd = cmd; + +if (q) + max_nr_vecs =min (bio_get_nr_vecs (bdev),BIO_MAX_PAGES ); +else + max_nr_vecs =1 ; + + need_new_bio =1 ; + + length =scst_get_sg_page_first (cmd, &page, &offset); +while (length >0 ) { +int len, bytes, off, thislen; +struct page *pg; +u64 lba_start0; + + pg = page; + len = length; + off = offset; + thislen =0 ; + lba_start0 = lba_start; + +while (len >0 ) { +int rc; + +if (need_new_bio) { + bio =bio_kmalloc (GFP_KERNEL , max_nr_vecs); +if (!bio) { +PRINT_ERROR ("Failed to create bio " +"for data segment %d (cmd %p)" , + cmd->get_sg_buf_entry_num, cmd); + goto out_no_bio; + } + + bios++; + need_new_bio =0 ; + bio->bi_end_io = blockio_endio; + bio->bi_sector = lba_start0 << + (virt_dev->block_shift -9 ); + bio->bi_bdev = bdev; + bio->bi_private = blockio_work; +/* +* Better to fail fast w/o any local recovery +* and retries. +*/ +#ifdef BIO_RW_FAILFAST + bio->bi_rw |= (1 <<BIO_RW_FAILFAST ); +#else + bio->bi_rw |= (1 <<BIO_RW_FAILFAST_DEV ) | + (1 <<BIO_RW_FAILFAST_TRANSPORT ) | + (1 <<BIO_RW_FAILFAST_DRIVER ); +#endif +#if 0 /* It could be win, but could be not, so a performance study is needed */ + bio->bi_rw |=1 <<BIO_RW_SYNC ; +#endif +if (!hbio) + hbio = tbio = bio; +else + tbio = tbio->bi_next = bio; + } + + bytes = min_t(unsigned int, len, PAGE_SIZE - off); + + rc =bio_add_page (bio, pg, bytes, off); +if (rc < bytes) { +BUG_ON (rc !=0 ); + need_new_bio =1 ; + lba_start0 += thislen >> virt_dev->block_shift; + thislen =0 ; +continue ; + } + + pg++; + thislen += bytes; + len -= bytes; + off =0 ; + } + + lba_start += length >> virt_dev->block_shift; + +scst_put_sg_page (cmd, page, offset); + length =scst_get_sg_page_next (cmd, &page, &offset); + } + +/* +1 to prevent erroneous too early command completion */ +atomic_set (&blockio_work->bios_inflight, bios+1 ); + +while (hbio) { + bio = hbio; + hbio = hbio->bi_next; + bio->bi_next =NULL ; +submit_bio ((write !=0 ), bio); + } + +if (q && q->unplug_fn) + q->unplug_fn (q); + +blockio_check_finish (blockio_work); + +out: +return ; + +out_no_bio: +while (hbio) { + bio = hbio; + hbio = hbio->bi_next; +bio_put (bio); + } +kmem_cache_free (blockio_work_cachep, blockio_work); + +out_no_mem: +scst_set_busy (cmd); + goto out; +} + +static int blockio_flush (struct block_device *bdev) +{ +int res =0 ; + + res =blkdev_issue_flush (bdev,GFP_KERNEL ,NULL ,BLKDEV_IFL_WAIT ); +if (res !=0 ) +PRINT_ERROR ("blkdev_issue_flush() failed: %d" , res); +return res; +} + +static void vdisk_exec_verify (struct scst_cmd *cmd, +struct scst_vdisk_thr *thr,loff_t loff) +{ +mm_segment_t old_fs; +loff_t err; +ssize_t length, len_mem =0 ; +uint8_t *address_sav, *address; +int compare; +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)cmd->dev->dh_priv; +struct file *fd = thr->fd; +uint8_t *mem_verify =NULL ; + +if (vdisk_fsync (thr, loff, cmd->bufflen, cmd, cmd->dev) !=0 ) + goto out; + +/* +* Until the cache is cleared prior the verifying, there is not +* much point in this code. ToDo. +* +* Nevertherless, this code is valuable if the data have not read +* from the file/disk yet. +*/ + +/* SEEK */ + old_fs =get_fs (); +set_fs (get_ds ()); + +if (!virt_dev->nullio) { +if (fd->f_op->llseek) + err = fd->f_op->llseek (fd, loff,0 /*SEEK_SET*/ ); +else + err =default_llseek (fd, loff,0 /*SEEK_SET*/ ); +if (err != loff) { +PRINT_ERROR ("lseek trouble %lld != %lld" , + (long long unsigned int )err, + (long long unsigned int )loff); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + goto out_set_fs; + } + } + + mem_verify =vmalloc (LEN_MEM ); +if (mem_verify ==NULL ) { +PRINT_ERROR ("Unable to allocate memory %d for verify" , +LEN_MEM ); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + goto out_set_fs; + } + + length =scst_get_buf_first (cmd, &address); + address_sav = address; +if (!length && cmd->data_len) { + length = cmd->data_len; + compare =0 ; + }else + compare =1 ; + +while (length >0 ) { + len_mem = (length >LEN_MEM ) ?LEN_MEM : length; +TRACE_DBG ("Verify: length %zd - len_mem %zd" , length, len_mem); + +if (!virt_dev->nullio) + err =vfs_read (fd, (char __force __user *)mem_verify, + len_mem, &fd->f_pos); +else + err = len_mem; +if ((err <0 ) || (err < len_mem)) { +PRINT_ERROR ("verify() returned %lld from %zd" , + (long long unsigned int )err, len_mem); +if (err == -EAGAIN ) +scst_set_busy (cmd); +else { +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_read_error)); + } +if (compare) +scst_put_buf (cmd, address_sav); + goto out_set_fs; + } +if (compare &&memcmp (address, mem_verify, len_mem) !=0 ) { +TRACE_DBG ("Verify: error memcmp length %zd" , length); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_miscompare_error)); +scst_put_buf (cmd, address_sav); + goto out_set_fs; + } + length -= len_mem; + address += len_mem; +if (compare && length <=0 ) { +scst_put_buf (cmd, address_sav); + length =scst_get_buf_next (cmd, &address); + address_sav = address; + } + } + +if (length <0 ) { +PRINT_ERROR ("scst_get_buf_() failed: %zd" , length); +scst_set_cmd_error (cmd, +SCST_LOAD_SENSE (scst_sense_hardw_error)); + } + +out_set_fs: +set_fs (old_fs); +if (mem_verify) +vfree (mem_verify); + +out: +return ; +} + +static int vdisk_task_mgmt_fn (struct scst_mgmt_cmd *mcmd, +struct scst_tgt_dev *tgt_dev) +{ + +if ((mcmd->fn ==SCST_LUN_RESET ) || (mcmd->fn ==SCST_TARGET_RESET )) { +/* Restore default values */ +struct scst_device *dev = tgt_dev->dev; +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)dev->dh_priv; + + dev->tst =DEF_TST ; + dev->d_sense =DEF_DSENSE ; +if (virt_dev->wt_flag && !virt_dev->nv_cache) + dev->queue_alg =DEF_QUEUE_ALG_WT ; +else + dev->queue_alg =DEF_QUEUE_ALG ; + dev->swp =DEF_SWP ; + dev->tas =DEF_TAS ; + +spin_lock (&virt_dev->flags_lock); + virt_dev->prevent_allow_medium_removal =0 ; +spin_unlock (&virt_dev->flags_lock); + }else if (mcmd->fn ==SCST_PR_ABORT_ALL ) { +struct scst_device *dev = tgt_dev->dev; +struct scst_vdisk_dev *virt_dev = + (struct scst_vdisk_dev *)dev->dh_priv; +spin_lock (&virt_dev->flags_lock); + virt_dev->prevent_allow_medium_removal =0 ; +spin_unlock (&virt_dev->flags_lock); + } +return SCST_DEV_TM_NOT_COMPLETED ; +} + +static void vdisk_report_registering (const struct scst_vdisk_dev *virt_dev) +{ +char buf[128 ]; +int i, j; + + i =snprintf (buf,sizeof (buf),"Registering virtual %s device %s " , + virt_dev->vdev_devt->name, virt_dev->name); + j = i; + +if (virt_dev->wt_flag) + i +=snprintf (&buf[i],sizeof (buf) - i,"(WRITE_THROUGH" ); + +if (virt_dev->nv_cache) + i +=snprintf (&buf[i],sizeof (buf) - i,"%sNV_CACHE" , + (j == i) ?"(" :", " ); + +if (virt_dev->rd_only) + i +=snprintf (&buf[i],sizeof (buf) - i,"%sREAD_ONLY" , + (j == i) ?"(" :", " ); + +if (virt_dev->o_direct_flag) + i +=snprintf (&buf[i],sizeof (buf) - i,"%sO_DIRECT" , + (j == i) ?"(" :", " ); + +if (virt_dev->nullio) + i +=snprintf (&buf[i],sizeof (buf) - i,"%sNULLIO" , + (j == i) ?"(" :", " ); + +if (virt_dev->blockio) + i +=snprintf (&buf[i],sizeof (buf) - i,"%sBLOCKIO" , + (j == i) ?"(" :", " ); + +if (virt_dev->removable) + i +=snprintf (&buf[i],sizeof (buf) - i,"%sREMOVABLE" , + (j == i) ?"(" :", " ); + +if (virt_dev->thin_provisioned) + i +=snprintf (&buf[i],sizeof (buf) - i,"%sTHIN PROVISIONED" , + (j == i) ?"(" :", " ); + +if (j == i) +PRINT_INFO ("%s" , buf); +else +PRINT_INFO ("%s)" , buf); + +return ; +} + +static int vdisk_resync_size (struct scst_vdisk_dev *virt_dev) +{ +loff_t file_size; +int res =0 ; + +BUG_ON (virt_dev->nullio); + + res = vdisk_get_file_size(virt_dev->filename,
Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
PATCH v4 14/19 : SCST pass-through dev handlers
In reply to Vladislav BolkhovitinThis patch contains SCST pass-through dev handlers.
Those handlers allows to export local SCSI-capable devices to remote initiators. 1:many relationship with remote initiators is supported, i.e. many initiators can connect to single exported local SCSI-capable device at the same time.
It is possible, because SCST core emulates necessary functionality of SCSI host adapter. Such emulation is needed, because from remote initiators' point of view a SCSI target acts as a SCSI host with its own devices. You can find more deep elaboration why it is needed in
http://www.mail-archive.com/[email protected]/msg06911.html.
Some of the emulated functions are:
* Generation of necessary UNIT ATTENTIONs, their storage and delivery to all connected remote initiators.
* RESERVE/RELEASE functionality.
* All types of RESETs and other task management functions.
* REPORT LUNS command as well as SCSI address space management in order to have consistent address space on all remote initiators, since local SCSI devices could not know about each other to report via REPORT LUNS command.
--- scst_cdrom.c | 245 ++++++++++++++++++++ scst_changer.c | 167 +++++++++++++ scst_dev_handler.h | 27 ++ scst_disk.c | 647 +++++++++++++++++++++++++++++++++++++++++++++++++++++ scst_modisk.c | 328 ++++++++++++++++++++++++++ scst_processor.c | 167 +++++++++++++ scst_raid.c | 168 +++++++++++++ scst_tape.c | 361 +++++++++++++++++++++++++++++ 8 files changed, 2110 insertions(+)
drivers/scst/dev_handlers/scst_cdrom.c renamed from linux-2.6.35/drivers/scst/dev_handlers/scst_cdrom.c +245 -0
@@ -0,0 +1,245 @@ +/* +* scst_cdrom.c +* +* Copyright (C) 2004 - 2010 Vladislav Bolkhovitin <[email protected]> +* Copyright (C) 2004 - 2005 Leonid Stoljar +* Copyright (C) 2007 - 2010 ID7 Ltd. +* +* SCSI CDROM (type 5) dev handler +* +* 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, version 2 +* of the License. +* +* 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. +*/ + +#include <linux/cdrom.h> +#include <scsi/scsi_host.h> +#include <linux/slab.h> + +#define LOG_PREFIX "dev_cdrom" + +#include <scst/scst.h> +#include "scst_dev_handler.h" + +#define CDROM_NAME "dev_cdrom" + +#define CDROM_DEF_BLOCK_SHIFT 11 + +struct cdrom_params { +int block_shift; +}; + +static int cdrom_attach (struct scst_device *); +static void cdrom_detach (struct scst_device *); +static int cdrom_parse (struct scst_cmd *); +static int cdrom_done (struct scst_cmd *); + +static struct scst_dev_type cdrom_devtype = { + .name =CDROM_NAME , + .type =TYPE_ROM , + .threads_num =1 , + .parse_atomic =1 , + .dev_done_atomic =1 , + .attach = cdrom_attach, + .detach = cdrom_detach, + .parse = cdrom_parse, + .dev_done = cdrom_done, +#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) + .default_trace_flags =SCST_DEFAULT_DEV_LOG_FLAGS , + .trace_flags = &trace_flag, +#endif +}; + +static int cdrom_attach (struct scst_device *dev) +{ +int res, rc; +uint8_t cmd[10 ]; +const int buffer_size =512 ; +uint8_t *buffer =NULL ; +int retries; +unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE ]; +enum dma_data_direction data_dir; +struct cdrom_params *params; + +if (dev->scsi_dev ==NULL || + dev->scsi_dev->type != dev->type) { +PRINT_ERROR ("%s" ,"SCSI device not define or illegal type" ); + res = -ENODEV ; + goto out; + } + + params =kzalloc (sizeof (*params),GFP_KERNEL ); +if (params ==NULL ) { +TRACE (TRACE_OUT_OF_MEM ,"%s" , +"Unable to allocate struct cdrom_params" ); + res = -ENOMEM ; + goto out; + } + + buffer =kmalloc (buffer_size,GFP_KERNEL ); +if (!buffer) { +TRACE (TRACE_OUT_OF_MEM ,"%s" ,"Memory allocation failure" ); + res = -ENOMEM ; + goto out_free_params; + } + +/* Clear any existing UA's and get cdrom capacity (cdrom block size) */ +memset (cmd,0 ,sizeof (cmd)); + cmd[0 ] =READ_CAPACITY ; + cmd[1 ] = (dev->scsi_dev->scsi_level <=SCSI_2 ) ? + ((dev->scsi_dev->lun <<5 ) &0xe0 ) :0 ; + retries =SCST_DEV_UA_RETRIES ; +while (1 ) { +memset (buffer,0 , buffer_size); +memset (sense_buffer,0 ,sizeof (sense_buffer)); + data_dir =SCST_DATA_READ ; + +TRACE_DBG ("%s" ,"Doing READ_CAPACITY" ); + rc =scsi_execute (dev->scsi_dev, cmd, data_dir, buffer, + buffer_size, sense_buffer, +SCST_GENERIC_CDROM_REG_TIMEOUT ,3 ,0 + ,NULL + ); + +TRACE_DBG ("READ_CAPACITY done: %x" , rc); + +if ((rc ==0 ) || + !scst_analyze_sense (sense_buffer, +sizeof (sense_buffer),SCST_SENSE_KEY_VALID , +UNIT_ATTENTION ,0 ,0 )) +break ; + +if (!--retries) { +PRINT_ERROR ("UA not cleared after %d retries" , +SCST_DEV_UA_RETRIES ); + params->block_shift =CDROM_DEF_BLOCK_SHIFT ; + res = -ENODEV ; + goto out_free_buf; + } + } + +if (rc ==0 ) { +int sector_size = ((buffer[4 ] <<24 ) | (buffer[5 ] <<16 ) | + (buffer[6 ] <<8 ) | (buffer[7 ] <<0 )); +if (sector_size ==0 ) + params->block_shift =CDROM_DEF_BLOCK_SHIFT ; +else + params->block_shift = +scst_calc_block_shift (sector_size); +TRACE_DBG ("Sector size is %i scsi_level %d(SCSI_2 %d)" , + sector_size, dev->scsi_dev->scsi_level,SCSI_2 ); + }else { + params->block_shift =CDROM_DEF_BLOCK_SHIFT ; +TRACE (TRACE_MINOR ,"Read capacity failed: %x, using default " +"sector size %d" , rc, params->block_shift); +PRINT_BUFF_FLAG (TRACE_MINOR ,"Returned sense" , sense_buffer, +sizeof (sense_buffer)); + } + + res =scst_obtain_device_parameters (dev); +if (res !=0 ) { +PRINT_ERROR ("Failed to obtain control parameters for device " +"%s" , dev->virt_name); + goto out_free_buf; + } + +out_free_buf: +kfree (buffer); + +out_free_params: +if (res ==0 ) + dev->dh_priv = params; +else +kfree (params); + +out: +return res; +} + +static void cdrom_detach (struct scst_device *dev) +{ +struct cdrom_params *params = + (struct cdrom_params *)dev->dh_priv; + +kfree (params); + dev->dh_priv =NULL ; +return ; +} + +static int cdrom_get_block_shift (struct scst_cmd *cmd) +{ +struct cdrom_params *params = (struct cdrom_params *)cmd->dev->dh_priv; +/* +* No need for locks here, since *_detach() can not be +* called, when there are existing commands. +*/ +return params->block_shift; +} + +static int cdrom_parse (struct scst_cmd *cmd) +{ +int res =SCST_CMD_STATE_DEFAULT ; + +scst_cdrom_generic_parse (cmd, cdrom_get_block_shift); + + cmd->retries =SCST_PASSTHROUGH_RETRIES ; + +return res; +} + +static void cdrom_set_block_shift (struct scst_cmd *cmd,int block_shift) +{ +struct cdrom_params *params = (struct cdrom_params *)cmd->dev->dh_priv; +/* +* No need for locks here, since *_detach() can not be +* called, when there are existing commands. +*/ +if (block_shift !=0 ) + params->block_shift = block_shift; +else + params->block_shift =CDROM_DEF_BLOCK_SHIFT ; +return ; +} + +static int cdrom_done (struct scst_cmd *cmd) +{ +int res =SCST_CMD_STATE_DEFAULT ; + + res =scst_block_generic_dev_done (cmd, cdrom_set_block_shift); +return res; +} + +static int __init cdrom_init (void ) +{ +int res =0 ; + + cdrom_devtype.module =THIS_MODULE ; + + res =scst_register_dev_driver (&cdrom_devtype); +if (res <0 ) + goto out; + +out: +return res; + +} + +static void __exit cdrom_exit(void) +{ +scst_unregister_dev_driver (&cdrom_devtype); +return ; +} + +module_init (cdrom_init); +module_exit (cdrom_exit); + +MODULE_LICENSE ("GPL" ); +MODULE_AUTHOR ("Vladislav Bolkhovitin & Leonid Stoljar" ); +MODULE_DESCRIPTION ("SCSI CDROM (type 5) dev handler for SCST" ); +MODULE_VERSION (SCST_VERSION_STRING );
drivers/scst/dev_handlers/scst_changer.c renamed from linux-2.6.35/drivers/scst/dev_handlers/scst_changer.c +167 -0
167 lines not on this page · raw message
drivers/scst/dev_handlers/scst_dev_handler.h renamed from linux-2.6.35/drivers/scst/dev_handlers/scst_dev_handler.h +27 -0
@@ -0,0 +1,27 @@ +#ifndef __SCST_DEV_HANDLER_H +#define __SCST_DEV_HANDLER_H + +#include <linux/module.h> +#include <scsi/scsi_eh.h> +#include <scst/scst_debug.h> + +#define SCST_DEV_UA_RETRIES 5 +#define SCST_PASSTHROUGH_RETRIES 0 + +#if defined(CONFIG_SCST_DEBUG ) || defined(CONFIG_SCST_TRACING ) + +#ifdef CONFIG_SCST_DEBUG +#define SCST_DEFAULT_DEV_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_PID | \ + TRACE_LINE | TRACE_FUNCTION | TRACE_MGMT | TRACE_MINOR | \ + TRACE_MGMT_DEBUG | TRACE_SPECIAL) +#else +#define SCST_DEFAULT_DEV_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \ + TRACE_SPECIAL) +#endif + +static unsigned long dh_trace_flag =SCST_DEFAULT_DEV_LOG_FLAGS ; +#define trace_flag dh_trace_flag + +#endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */ + +#endif /* __SCST_DEV_HANDLER_H */
drivers/scst/dev_handlers/scst_disk.c renamed from linux-2.6.35/drivers/scst/dev_handlers/scst_disk.c +647 -0
647 lines not on this page · raw message
drivers/scst/dev_handlers/scst_modisk.c renamed from linux-2.6.35/drivers/scst/dev_handlers/scst_modisk.c +328 -0
328 lines not on this page · raw message
drivers/scst/dev_handlers/scst_processor.c renamed from linux-2.6.35/drivers/scst/dev_handlers/scst_processor.c +167 -0
167 lines not on this page · raw message
drivers/scst/dev_handlers/scst_raid.c renamed from linux-2.6.35/drivers/scst/dev_handlers/scst_raid.c +168 -0
168 lines not on this page · raw message
drivers/scst/dev_handlers/scst_tape.c renamed from linux-2.6.35/drivers/scst/dev_handlers/scst_tape.c +361 -0
361 lines not on this page · raw message
PATCH v4 15/19 : Implementation of blk_rq_map_kern_sg()
In reply to Vladislav BolkhovitinThis patch implements function blk_rq_map_kern_sg(), which allows to map a kernel-originated SG vector to a block request. It is necessary to execute SCSI commands with from the kernel going SG buffer. SCST needs this functionality, because its target drivers, which are, basically, SCSI drivers, can deal only with SGs, not with BIOs.
Highlight of this implementations:
- It uses BIOs chaining instead of kmalloc()'ing the whole bio, which is
more reliable.
- It uses SGs chaining instead of kmalloc()'ing one big SG in case if
direct mapping failed (e.g. because of DMA alignment or padding), which is also more reliable.
- When needed, copy_page() is used instead of memcpy() to copy the
whole pages faster.
Also this patch adds and exports function sg_copy(), which copies one SG vector to another.
This patch has already been reviewed in LKML/linux-scsi in
http://lkml.org/lkml/2009/8/12/304. Since then it was only been updated for 2.6.35.
All this functionality can be a part of the internal SCST library, but looks like a better place will be in the common place near similar routines.
--- block/blk-map.c | 334 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/blkdev.h | 3 include/linux/scatterlist.h | 5 lib/scatterlist.c | 129 ++++++++++++++++ 4 files changed, 471 insertions(+)
block/blk-map.c +334 -0
@@ -5,6 +5,8 @@#include <linux/module.h> #include <linux/bio.h> #include <linux/blkdev.h> +#include <linux/scatterlist.h> +#include <linux/slab.h> #include <scsi/sg.h> /* for struct sg_iovec */ #include "blk.h"
@@ -271,6 +273,338 @@ int blk_rq_unmap_user(struct bio *bio) }EXPORT_SYMBOL (blk_rq_unmap_user); +struct blk_kern_sg_work { +atomic_t bios_inflight; +struct sg_table sg_table; +struct scatterlist *src_sgl; +}; + +static void blk_free_kern_sg_work (struct blk_kern_sg_work *bw) +{ +sg_free_table (&bw->sg_table); +kfree (bw); +return ; +} + +static void blk_bio_map_kern_endio (struct bio *bio,int err) +{ +struct blk_kern_sg_work *bw = bio->bi_private; + +if (bw !=NULL ) { +/* Decrement the bios in processing and, if zero, free */ +BUG_ON (atomic_read (&bw->bios_inflight) <=0 ); +if (atomic_dec_and_test (&bw->bios_inflight)) { +if ((bio_data_dir (bio) ==READ ) && (err ==0 )) { +unsigned long flags; + +local_irq_save (flags);/* to protect KMs */ +sg_copy (bw->src_sgl, bw->sg_table.sgl,0 ,0 , +KM_BIO_DST_IRQ ,KM_BIO_SRC_IRQ ); +local_irq_restore (flags); + } +blk_free_kern_sg_work (bw); + } + } + +bio_put (bio); +return ; +} + +static int blk_rq_copy_kern_sg (struct request *rq,struct scatterlist *sgl, +int nents,struct blk_kern_sg_work **pbw, +gfp_t gfp,gfp_t page_gfp) +{ +int res =0 , i; +struct scatterlist *sg; +struct scatterlist *new_sgl; +int new_sgl_nents; +size_t len =0 , to_copy; +struct blk_kern_sg_work *bw; + + bw =kzalloc (sizeof (*bw), gfp); +if (bw ==NULL ) + goto out; + + bw->src_sgl = sgl; + +for_each_sg (sgl, sg, nents, i) + len += sg->length; + to_copy = len; + + new_sgl_nents =PFN_UP (len); + + res =sg_alloc_table (&bw->sg_table, new_sgl_nents, gfp); +if (res !=0 ) + goto out_free_bw; + + new_sgl = bw->sg_table.sgl; + +for_each_sg (new_sgl, sg, new_sgl_nents, i) { +struct page *pg; + + pg =alloc_page (page_gfp); +if (pg ==NULL ) + goto err_free_new_sgl; + +sg_assign_page (sg, pg); + sg->length =min_t (size_t,PAGE_SIZE , len); + + len -=PAGE_SIZE ; + } + +if (rq_data_dir (rq) ==WRITE ) { +/* +* We need to limit amount of copied data to to_copy, because +* sgl might have the last element in sgl not marked as last in +* SG chaining. +*/ +sg_copy (new_sgl, sgl,0 , to_copy, +KM_USER0 ,KM_USER1 ); + } + + *pbw = bw; +/* +* REQ_COPY_USER name is misleading. It should be something like +* REQ_HAS_TAIL_SPACE_FOR_PADDING. +*/ + rq->cmd_flags |=REQ_COPY_USER ; + +out: +return res; + +err_free_new_sgl: +for_each_sg (new_sgl, sg, new_sgl_nents, i) { +struct page *pg =sg_page (sg); +if (pg ==NULL ) +break ; +__free_page (pg); + } +sg_free_table (&bw->sg_table); + +out_free_bw: +kfree (bw); + res = -ENOMEM ; + goto out; +} + +static int __blk_rq_map_kern_sg (struct request *rq,struct scatterlist *sgl, +int nents,struct blk_kern_sg_work *bw,gfp_t gfp) +{ +int res; +struct request_queue *q = rq->q; +int rw =rq_data_dir (rq); +int max_nr_vecs, i; +size_t tot_len; +bool need_new_bio; +struct scatterlist *sg, *prev_sg =NULL ; +struct bio *bio =NULL , *hbio =NULL , *tbio =NULL ; +int bios; + +if (unlikely ((sgl ==NULL ) || (sgl->length ==0 ) || (nents <=0 ))) { +WARN_ON (1 ); + res = -EINVAL ; + goto out; + } + +/* +* Let's keep each bio allocation inside a single page to decrease +* probability of failure. +*/ + max_nr_vecs =min_t (size_t, + ((PAGE_SIZE -sizeof (struct bio )) /sizeof (struct bio_vec )), +BIO_MAX_PAGES ); + + need_new_bio = true; + tot_len =0 ; + bios =0 ; +for_each_sg (sgl, sg, nents, i) { +struct page *page =sg_page (sg); +void *page_addr =page_address (page); +size_t len = sg->length, l; +size_t offset = sg->offset; + + tot_len += len; + prev_sg = sg; + +/* +* Each segment must be aligned on DMA boundary and +* not on stack. The last one may have unaligned +* length as long as the total length is aligned to +* DMA padding alignment. +*/ +if (i == nents -1 ) + l =0 ; +else + l = len; +if (((sg->offset | l) &queue_dma_alignment (q)) || + (page_addr &&object_is_on_stack (page_addr + sg->offset))) { + res = -EINVAL ; + goto out_free_bios; + } + +while (len >0 ) { +size_t bytes; +int rc; + +if (need_new_bio) { + bio =bio_kmalloc (gfp, max_nr_vecs); +if (bio ==NULL ) { + res = -ENOMEM ; + goto out_free_bios; + } + +if (rw ==WRITE ) + bio->bi_rw |=1 <<BIO_RW ; + + bios++; + bio->bi_private = bw; + bio->bi_end_io = blk_bio_map_kern_endio; + +if (hbio ==NULL ) + hbio = tbio = bio; +else + tbio = tbio->bi_next = bio; + } + + bytes =min_t (size_t, len,PAGE_SIZE - offset); + + rc =bio_add_pc_page (q, bio, page, bytes, offset); +if (rc < bytes) { +if (unlikely (need_new_bio || (rc <0 ))) { +if (rc <0 ) + res = rc; +else + res = -EIO ; + goto out_free_bios; + }else { + need_new_bio = true; + len -= rc; + offset += rc; +continue ; + } + } + + need_new_bio = false; + offset =0 ; + len -= bytes; + page =nth_page (page,1 ); + } + } + +if (hbio ==NULL ) { + res = -EINVAL ; + goto out_free_bios; + } + +/* Total length must be aligned on DMA padding alignment */ +if ((tot_len & q->dma_pad_mask) && + !(rq->cmd_flags &REQ_COPY_USER )) { + res = -EINVAL ; + goto out_free_bios; + } + +if (bw !=NULL ) +atomic_set (&bw->bios_inflight, bios); + +while (hbio !=NULL ) { + bio = hbio; + hbio = hbio->bi_next; + bio->bi_next =NULL ; + +blk_queue_bounce (q, &bio); + + res =blk_rq_append_bio (q, rq, bio); +if (unlikely (res !=0 )) { + bio->bi_next = hbio; + hbio = bio; +/* We can have one or more bios bounced */ + goto out_unmap_bios; + } + } + + res =0 ; + + rq->buffer =NULL ; +out: +return res; + +out_free_bios: +while (hbio !=NULL ) { + bio = hbio; + hbio = hbio->bi_next; +bio_put (bio); + } + goto out; + +out_unmap_bios: +blk_rq_unmap_kern_sg (rq, res); + goto out; +} + +/** +* blk_rq_map_kern_sg - map kernel data to a request, for REQ_TYPE_BLOCK_PC +* @rq: request to fill +* @sgl: area to map +* @nents: number of elements in @sgl +* @gfp: memory allocation flags +* +* Description: +* Data will be mapped directly if possible. Otherwise a bounce +* buffer will be used. +*/ +int blk_rq_map_kern_sg (struct request *rq,struct scatterlist *sgl, +int nents,gfp_t gfp) +{ +int res; + + res =__blk_rq_map_kern_sg (rq, sgl, nents,NULL , gfp); +if (unlikely (res !=0 )) { +struct blk_kern_sg_work *bw =NULL ; + + res =blk_rq_copy_kern_sg (rq, sgl, nents, &bw, + gfp, rq->q->bounce_gfp | gfp); +if (unlikely (res !=0 )) + goto out; + + res =__blk_rq_map_kern_sg (rq, bw->sg_table.sgl, + bw->sg_table.nents, bw, gfp); +if (res !=0 ) { +blk_free_kern_sg_work (bw); + goto out; + } + } + + rq->buffer =NULL ; + +out: +return res; +} +EXPORT_SYMBOL (blk_rq_map_kern_sg); + +/** +* blk_rq_unmap_kern_sg - unmap a request with kernel sg +* @rq: request to unmap +* @err: non-zero error code +* +* Description: +* Unmap a rq previously mapped by blk_rq_map_kern_sg(). Must be called +* only in case of an error! +*/ +void blk_rq_unmap_kern_sg (struct request *rq,int err) +{ +struct bio *bio = rq->bio; + +while (bio) { +struct bio *b = bio; + bio = bio->bi_next; + b->bi_end_io (b, err); + } + rq->bio =NULL ; + +return ; +} +EXPORT_SYMBOL (blk_rq_unmap_kern_sg); +/** * blk_rq_map_kern - map kernel data to a request, for REQ_TYPE_BLOCK_PC usage * @q: request queue where request should be inserted
include/linux/blkdev.h +3 -0
@@ -832,6 +834,9 @@ extern int blk_rq_map_kern(struct requesextern int blk_rq_map_user_iov (struct request_queue *,struct request *,struct rq_map_data *,struct sg_iovec *,int ,unsigned int ,gfp_t ); +extern int blk_rq_map_kern_sg (struct request *rq,struct scatterlist *sgl, +int nents,gfp_t gfp); +extern void blk_rq_unmap_kern_sg (struct request *rq,int err);extern int blk_execute_rq (struct request_queue *,struct gendisk *,struct request *,int ); extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *,
include/linux/scatterlist.h +5 -0
@@ -3,6 +3,7 @@#include <asm/types.h> #include <asm/scatterlist.h> +#include <asm/kmap_types.h> #include <linux/mm.h> #include <linux/string.h> #include <asm/io.h>
@@ -218,6 +219,10 @@ size_t sg_copy_from_buffer(struct scattesize_t sg_copy_to_buffer (struct scatterlist *sgl,unsigned int nents,void *buf,size_t buflen); +int sg_copy (struct scatterlist *dst_sg,struct scatterlist *src_sg, +int nents_to_copy,size_t copy_len, +enum km_type d_km_type,enum km_type s_km_type); +/* * Maximum number of entries that will be allocated in one piece, if * a list larger than this is required then chaining will be utilized.
lib/scatterlist.c +129 -0
132 lines not on this page · raw message
PATCH v4 16/19 : scst_local target driver
In reply to Vladislav BolkhovitinThis patchset contains scst_local target driver with documentation.
This driver allows to access devices that are exported via SCST directly on the same Linux system that they are exported from. Some highlights:
1. Fully zero-copy implementation with in-kernel dev handlers
2. Support for BIDI commands and long CDBs
3. Easy way to locate sg/bsg devices (LUNs) for each scst_local's session (Scsi_Host)
4. Allows to create several targets with several sessions (Scsi_Hosts) each
5. Allows for each target to set transport type (SCSI and physical transport version descriptors)
6. Allows for each session set TransportID, used, e.g., to identify the 'I' part of I_T nexus in Persistent Reservation commands
(3) means that each scst_local's session's SYSFS entry contains a link to the corresponding SCSI host. Using it one can find local sg/bsg/sd/etc. devices of this session. For instance, this links points out to host12, so you can find your sg devices by:
$ lsscsi -g|grep "\[12:" [12:0:0:0] disk SCST_FIO rd1 200 /dev/sdc /dev/sg2 [12:0:0:1] disk SCST_FIO nullio 200 /dev/sdd /dev/sg3
They are /dev/sg2 and /dev/sg3.
(4)-(6) allows creation of full features multi-transport/multi-initiator (I_T nexus) SCST target drivers in user space, which can share devices with in-kernel target drivers, i.e. all the reservations, including Persistent Reservations, and other similar per-I_T nexus functionality will be done correctly.
The recommended workflow for a user space target driver:
1. For each SCSI target a user space target driver should create an scst_local's target using "add_target" SYSFS command.
2. Then the user space target driver should, if needed, set its SCSI and physical transport version descriptors (by default it is SAS) using SYSFS attributes scsi_transport_version and phys_transport_version correspondingly in /sys/kernel/scst_tgt/targets/scst_local/target_name directory.
3. For incoming session (I_T nexus) from an initiator the user space target driver should create scst_local's session using "add_session" SYSFS command.
4. Then, if needed, the user space target driver should set TransportID
for this session (I_T nexus) using attribute /sys/kernel/scst_tgt/targets/scst_local/target_name/sessions/session_name/transport_id
5. Then the user space target driver should find out sg/bsg devices for the LUNs the created session has using link /sys/kernel/scst_tgt/targets/scst_local/target_name/sessions/session_name/host as described above.
6. Then the user space target driver can start serving the initiator using found sg/bsg devices.
For other connected initiators steps 3-6 should be repeated.
More info about scst_local driver you can find in the README.scst_local in the patch.
--- Documentation/scst/README.scst_local | 231 +++++ drivers/scst/scst_local/Kconfig | 22 drivers/scst/scst_local/Makefile | 2 drivers/scst/scst_local/scst_local.c | 1452 +++++++++++++++++++++++++++++++++++ 4 files changed, 1707 insertions(+)
drivers/scst/scst_local/Kconfig renamed from linux-2.6.35/drivers/scst/scst_local/Kconfig +22 -0
@@ -0,0 +1,22 @@ +config SCST_LOCAL + tristate "SCST Local driver" + depends on SCST && !HIGHMEM4G && !HIGHMEM64G + ---help--- + This module provides a LLD SCSI driver that connects to + the SCST target mode subsystem in a loop-back manner. + It allows you to test target-mode device-handlers locally. + You will need the SCST subsystem as well. + + If unsure whether you really want or need this, say N. + +config SCST_LOCAL_FORCE_DIRECT_PROCESSING + bool "Force local processing" + depends on SCST_LOCAL + help + This experimental option forces scst_local to make SCST process + SCSI commands in the same context, in which they was submitted. + Otherwise, they will be processed in SCST threads. Setting this + option to "Y" will give some performance increase, but might be + unsafe. + + If unsure, say "N".
drivers/scst/scst_local/Makefile renamed from linux-2.6.35/drivers/scst/scst_local/Makefile +2 -0
@@ -0,0 +1,2 @@ +obj-$(CONFIG_SCST_LOCAL) += scst_local.o +
drivers/scst/scst_local/scst_local.c renamed from linux-2.6.35/drivers/scst/scst_local/scst_local.c +1452 -0
1,452 lines not on this page · raw message
--- README.scst_local | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+)
Documentation/scst/README.scst_local renamed from linux-2.6.35/Documentation/scst/README.scst_local +231 -0
231 lines not on this page · raw message
PATCH v4 17/19 : SCST InfiniBand SRP target driver
In reply to Vladislav BolkhovitinThis patch contains SCST InfiniBand SRP target driver.
This driver works directly on top of InfiniBand stack and SCST.
It is a high performance driver capable of handling 600K+ 4K random write IOPS by a single target as well as 2.5+GB/s sequential throughput from a single QDR IB port.
It was originally developed by Vu Pham/Mellanox, currently Bart Van Assche is maintaining and improving it.
--- Documentation/scst/README.srpt | 112 + drivers/scst/srpt/Kconfig | 12 drivers/scst/srpt/Makefile | 1 drivers/scst/srpt/ib_dm_mad.h | 139 + drivers/scst/srpt/ib_srpt.c | 3809 +++++++++++++++++++++++++++++++++++++++++ drivers/scst/srpt/ib_srpt.h | 370 +++ 6 files changed, 4443 insertions(+)
drivers/scst/srpt/Kconfig renamed from linux-2.6.35/drivers/scst/srpt/Kconfig +12 -0
@@ -0,0 +1,12 @@ +config SCST_SRPT + tristate "InfiniBand SCSI RDMA Protocol target support" + depends on INFINIBAND && SCST + ---help--- + + Support for the SCSI RDMA Protocol (SRP) Target driver. The + SRP protocol is a protocol that allows an initiator to access + a block storage device on another host (target) over a network + that supports the RDMA protocol. Currently the RDMA protocol is + supported by InfiniBand and by iWarp network hardware. More + information about the SRP protocol can be found on the website + of the INCITS T10 technical committee (http://www.t10.org/).
drivers/scst/srpt/Makefile renamed from linux-2.6.35/drivers/scst/srpt/Makefile +1 -0
@@ -0,0 +1,1 @@ +obj-$(CONFIG_SCST_SRPT) += ib_srpt.o
drivers/scst/srpt/ib_dm_mad.h renamed from linux-2.6.35/drivers/scst/srpt/ib_dm_mad.h +139 -0
139 lines not on this page · raw message
drivers/scst/srpt/ib_srpt.c renamed from linux-2.6.35/drivers/scst/srpt/ib_srpt.c +3809 -0
2,848 lines not on this page · raw message
drivers/scst/srpt/ib_srpt.h renamed from linux-2.6.35/drivers/scst/srpt/ib_srpt.h +370 -0
370 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
--- README.srpt | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+)
Documentation/scst/README.srpt renamed from linux-2.6.35/Documentation/scst/README.srpt +112 -0
112 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
PATCH v4 18/19 : ibmvstgt: Port from tgt to SCST
In reply to Vladislav BolkhovitinThe current ibmvstgt and libsrp kernel modules are based on the tgt infrastructure. Both modules need the scsi_tgt kernel module and the tgtd user space process in order to function properly. This patch modifies the ibmvstgt and libsrp kernel modules such that both use the SCST storage target framework instead of tgt.
This patch introduces one backwards-incompatible change, namely that the path of the ibmvstgt sysfs attributes is modified. This change is unavoidable because this patch dissociates ibmvstgt SRP sessions from a SCSI host instance.
Notes:
- ibmvstgt is the only user of libsrp.
- A 2.6.35 kernel tree with this patch applied does compile cleanly on the systems supported by the ibmvstgt kernel module, the patch itself is checkpatch clean and does not introduce any new sparse warnings. This patch has not been tested in any other way however. The primary purpose of this patch is to invite feedback about the chosen approach.
<IMPORTANT>
We are looking for hardware to complete this driver. Any help will be greatly appreciated!
</IMPORTANT>
--- Documentation/powerpc/ibmvstgt.txt | 2 drivers/scsi/ibmvscsi/ibmvstgt.c | 609 +++++++++++++++++++++++++------------ drivers/scsi/libsrp.c | 87 ++--- include/scsi/libsrp.h | 16 4 files changed, 474 insertions(+), 240 deletions(-)
drivers/scsi/ibmvscsi/ibmvstgt.c 15:50:36.616855875 +0400 renamed from linux-2.6.35/drivers/scsi/ibmvscsi/ibmvstgt.c 16:47:55.220115813 +0400 +419 -190
@@ -5,6 +5,7 @@ * Linda Xie ([email protected]) IBM Corp. * * Copyright (C) 2005-2006 FUJITA Tomonori <[email protected]> + * Copyright (C) 2010 Bart Van Assche <[email protected]> * * 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
@@ -24,15 +25,13 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/slab.h> -#include <scsi/scsi.h> -#include <scsi/scsi_host.h> -#include <scsi/scsi_transport_srp.h> -#include <scsi/scsi_tgt.h> +#include <scst/scst.h> +#include <scst/scst_debug.h> #include <scsi/libsrp.h> #include <asm/hvcall.h> #include <asm/iommu.h> #include <asm/prom.h> #include <asm/vio.h> #include "ibmvscsi.h"
@@ -71,11 +87,22 @@ struct vio_port { unsigned long riobn; struct srp_target *target; - struct srp_rport *rport; + struct scst_session *sess; + struct device dev; + bool releasing; + bool enabled; }; +static atomic_t ibmvstgt_device_count; static struct workqueue_struct *vtgtd; -static struct scsi_transport_template *ibmvstgt_transport_template; + +#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) +#define DEFAULT_IBMVSTGT_TRACE_FLAGS \ + (TRACE_OUT_OF_MEM | TRACE_MINOR | TRACE_MGMT | TRACE_SPECIAL) +static unsigned long trace_flag = DEFAULT_IBMVSTGT_TRACE_FLAGS; +module_param(trace_flag, long, 0644); +MODULE_PARM_DESC(trace_flag, "SCST trace flags."); +#endif /* * These are fixed for the system and come from the Open Firmware device tree.
@@ -136,7 +163,7 @@ static int send_iu(struct iu_entry *iue, #define SRP_RSP_SENSE_DATA_LEN 18 -static int send_rsp(struct iu_entry *iue, struct scsi_cmnd *sc, +static int send_rsp(struct iu_entry *iue, struct scst_cmd *sc, unsigned char status, unsigned char asc) { union viosrp_iu *iu = vio_iu(iue);
@@ -165,9 +192,15 @@ static int send_rsp(struct iu_entry *iue uint8_t *sense = iu->srp.rsp.data; if (sc) { + uint8_t *sc_sense; + int sense_data_len; + + sc_sense = scst_cmd_get_sense_buffer(sc); + sense_data_len = min(scst_cmd_get_sense_buffer_len(sc), + SRP_RSP_SENSE_DATA_LEN); iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID; - iu->srp.rsp.sense_data_len = SCSI_SENSE_BUFFERSIZE; - memcpy(sense, sc->sense_buffer, SCSI_SENSE_BUFFERSIZE); + iu->srp.rsp.sense_data_len = sense_data_len; + memcpy(sense, sc_sense, sense_data_len); } else { iu->srp.rsp.status = SAM_STAT_CHECK_CONDITION; iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID;
@@ -192,8 +225,8 @@ static int send_rsp(struct iu_entry *iue static void handle_cmd_queue(struct srp_target *target) { - struct Scsi_Host *shost = target->shost; - struct srp_rport *rport = target_to_port(target)->rport; + struct vio_port *vport = target_to_port(target); + struct scst_session *sess = vport->sess; struct iu_entry *iue; struct srp_cmd *cmd; unsigned long flags;
@@ -206,8 +239,7 @@ retry: if (!test_and_set_bit(V_FLYING, &iue->flags)) { spin_unlock_irqrestore(&target->lock, flags); cmd = iue->sbuf->buf; - err = srp_cmd_queue(shost, cmd, iue, - (unsigned long)rport, 0); + err = srp_cmd_queue(sess, cmd, iue); if (err) { eprintk("cannot queue cmd %p %d\n", cmd, err); srp_iu_put(iue);
@@ -219,11 +251,11 @@ retry: spin_unlock_irqrestore(&target->lock, flags); } -static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg, +static int ibmvstgt_rdma(struct scst_cmd *sc, struct scatterlist *sg, int nsg, struct srp_direct_buf *md, int nmd, enum dma_data_direction dir, unsigned int rest) { - struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; + struct iu_entry *iue = scst_cmd_get_tgt_priv(sc); struct srp_target *target = iue->target; struct vio_port *vport = target_to_port(target); dma_addr_t token;
@@ -282,42 +314,157 @@ static int ibmvstgt_rdma(struct scsi_cmn return 0; } -static int ibmvstgt_cmd_done(struct scsi_cmnd *sc, - void (*done)(struct scsi_cmnd *)) +/** + * ibmvstgt_enable_target() - Allows to enable a target via sysfs. + */ +static int ibmvstgt_enable_target(struct scst_tgt *scst_tgt, bool enable) { + struct srp_target *target = scst_tgt_get_tgt_priv(scst_tgt); + struct vio_port *vport = target_to_port(target); unsigned long flags; - struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; - struct srp_target *target = iue->target; - int err = 0; - dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0], - scsi_sg_count(sc)); + TRACE_DBG("%s target %d", enable ? "Enabling" : "Disabling", + vport->dma_dev->unit_address); + + spin_lock_irqsave(&target->lock, flags); + vport->enabled = enable; + spin_unlock_irqrestore(&target->lock, flags); + + return 0; +} - if (scsi_sg_count(sc)) - err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1); +/** + * ibmvstgt_is_target_enabled() - Allows to query a targets status via sysfs. + */ +static bool ibmvstgt_is_target_enabled(struct scst_tgt *scst_tgt) +{ + struct srp_target *target = scst_tgt_get_tgt_priv(scst_tgt); + struct vio_port *vport = target_to_port(target); + unsigned long flags; + bool res; spin_lock_irqsave(&target->lock, flags); - list_del(&iue->ilist); + res = vport->enabled; spin_unlock_irqrestore(&target->lock, flags); + return res; +} - if (err|| sc->result != SAM_STAT_GOOD) { - eprintk("operation failed %p %d %x\n", - iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]); - send_rsp(iue, sc, HARDWARE_ERROR, 0x00); - } else - send_rsp(iue, sc, NO_SENSE, 0x00); +/** + * ibmvstgt_detect() - Returns the number of target adapters. + * + * Callback function called by the SCST core. + */ +static int ibmvstgt_detect(struct scst_tgt_template *tp) +{ + return atomic_read(&ibmvstgt_device_count); +} + +/** + * ibmvstgt_release() - Free the resources associated with an SCST target. + * + * Callback function called by the SCST core from scst_unregister_target(). + */ +static int ibmvstgt_release(struct scst_tgt *scst_tgt) +{ + unsigned long flags; + struct srp_target *target = scst_tgt_get_tgt_priv(scst_tgt); + struct vio_port *vport = target_to_port(target); + struct scst_session *sess = vport->sess; + + spin_lock_irqsave(&target->lock, flags); + vport->releasing = true; + spin_unlock_irqrestore(&target->lock, flags); + + scst_unregister_session(sess, 0, NULL); - done(sc); - srp_iu_put(iue); return 0; } -int send_adapter_info(struct iu_entry *iue, +/** + * ibmvstgt_xmit_response() - Transmits the response to a SCSI command. + * + * Callback function called by the SCST core. Must not block. Must ensure that + * scst_tgt_cmd_done() will get invoked when returning SCST_TGT_RES_SUCCESS. + */ +static int ibmvstgt_xmit_response(struct scst_cmd *sc) +{ + struct iu_entry *iue = scst_cmd_get_tgt_priv(sc); + int ret; + enum dma_data_direction dir; + + if (unlikely(scst_cmd_aborted(sc))) { + scst_set_delivery_status(sc, SCST_CMD_DELIVERY_ABORTED); + goto out; + } + + dir = srp_cmd_direction(&vio_iu(iue)->srp.cmd); + WARN_ON(dir != DMA_FROM_DEVICE && dir != DMA_TO_DEVICE); + + /* For read commands, transfer the data to the initiator. */ + if (dir == DMA_FROM_DEVICE && scst_cmd_get_adjusted_resp_data_len(sc)) { + ret = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, + ibmvstgt_rdma, 1, 1); + if (ret) + scst_set_delivery_status(sc, SCST_CMD_DELIVERY_FAILED); + } + + send_rsp(iue, sc, scst_cmd_get_status(sc), 0); + +out: + scst_tgt_cmd_done(sc, SCST_CONTEXT_SAME); + + return SCST_TGT_RES_SUCCESS; +} + +/** + * ibmvstgt_rdy_to_xfer() - Transfers data from initiator to target. + * + * Called by the SCST core to transfer data from the initiator to the target + * (SCST_DATA_WRITE / DMA_TO_DEVICE). Must not block. + */ +static int ibmvstgt_rdy_to_xfer(struct scst_cmd *sc) +{ + struct iu_entry *iue = scst_cmd_get_tgt_priv(sc); + int ret = SCST_TGT_RES_SUCCESS; + + WARN_ON(srp_cmd_direction(&vio_iu(iue)->srp.cmd) != DMA_TO_DEVICE); + + /* Transfer the data from the initiator to the target. */ + ret = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1); + if (ret == 0) { + scst_rx_data(sc, SCST_RX_STATUS_SUCCESS, SCST_CONTEXT_SAME); + } else { + PRINT_ERROR("%s: tag= %llu xfer_data failed", __func__, + (long long unsigned)be64_to_cpu(scst_cmd_get_tag(sc))); + scst_rx_data(sc, SCST_RX_STATUS_ERROR, SCST_CONTEXT_SAME); + } + + return SCST_TGT_RES_SUCCESS; +} + +/** + * ibmvstgt_on_free_cmd() - Free command-private data. + * + * Called by the SCST core. May be called in IRQ context. + */ +static void ibmvstgt_on_free_cmd(struct scst_cmd *sc) +{ + unsigned long flags; + struct iu_entry *iue = scst_cmd_get_tgt_priv(sc); + struct srp_target *target = iue->target; + + spin_lock_irqsave(&target->lock, flags); + list_del(&iue->ilist); + spin_unlock_irqrestore(&target->lock, flags); + + srp_iu_put(iue); +} + +static int send_adapter_info(struct iu_entry *iue, dma_addr_t remote_buffer, uint16_t length) { struct srp_target *target = iue->target; struct vio_port *vport = target_to_port(target); - struct Scsi_Host *shost = target->shost; dma_addr_t data_token; struct mad_adapter_info_data *info; int err;
@@ -345,7 +499,7 @@ int send_adapter_info(struct iu_entry *i info->partition_number = partition_number; info->mad_version = 1; info->os_type = 2; - info->port_max_txu[0] = shost->hostt->max_sectors << 9; + info->port_max_txu[0] = DEFAULT_MAX_SECTORS << 9; /* Send our info to remote */ err = h_copy_rdma(sizeof(*info), vport->liobn, data_token,
@@ -365,31 +519,61 @@ static void process_login(struct iu_entr { union viosrp_iu *iu = vio_iu(iue); struct srp_login_rsp *rsp = &iu->srp.login_rsp; + struct srp_login_rej *rej = &iu->srp.login_rej; uint64_t tag = iu->srp.rsp.tag; - struct Scsi_Host *shost = iue->target->shost; - struct srp_target *target = host_to_srp_target(shost); + struct scst_session *sess; + struct srp_target *target = iue->target; struct vio_port *vport = target_to_port(target); - struct srp_rport_identifiers ids; + char name[16]; + + BUG_ON(vport->sess); + + memset(iu, 0, max(sizeof *rsp, sizeof *rej)); - memset(&ids, 0, sizeof(ids)); - sprintf(ids.port_id, "%x", vport->dma_dev->unit_address); - ids.roles = SRP_RPORT_ROLE_INITIATOR; - if (!vport->rport) - vport->rport = srp_rport_add(shost, &ids); + snprintf(name, sizeof(name), "%x", vport->dma_dev->unit_address); + + if (!ibmvstgt_is_target_enabled(target->tgt)) { + rej->reason = + __constant_cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); + PRINT_ERROR("rejected SRP_LOGIN_REQ because the target %s" + " has not yet been enabled", name); + goto reject; + } + + BUG_ON(!target); + sess = scst_register_session(target->tgt, 0, name, target, NULL, NULL); + if (!sess) { + rej->reason = + __constant_cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); + TRACE_DBG("%s", "Failed to create SCST session"); + goto reject; + } + + vport->sess = sess; /* TODO handle case that requested size is wrong and * buffer format is wrong */ - memset(iu, 0, sizeof(struct srp_login_rsp)); rsp->opcode = SRP_LOGIN_RSP; rsp->req_lim_delta = INITIAL_SRP_LIMIT; rsp->tag = tag; rsp->max_it_iu_len = sizeof(union srp_iu); rsp->max_ti_iu_len = sizeof(union srp_iu); /* direct and indirect */ - rsp->buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT; + rsp->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT + | SRP_BUF_FORMAT_INDIRECT); send_iu(iue, sizeof(*rsp), VIOSRP_SRP_FORMAT); + + return; + +reject: + rej->opcode = SRP_LOGIN_REJ; + rej->tag = tag; + rej->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT + | SRP_BUF_FORMAT_INDIRECT); + + send_iu(iue, sizeof *rsp, VIOSRP_SRP_FORMAT); } static inline void queue_cmd(struct iu_entry *iue)
@@ -402,43 +586,134 @@ static inline void queue_cmd(struct iu_e spin_unlock_irqrestore(&target->lock, flags); } +/** + * struct mgmt_ctx - management command context information. + * @iue: VIO SRP information unit associated with the management command. + * @sess: SCST session via which the management command has been received. + * @tag: SCSI tag of the management command. + */ +struct mgmt_ctx { + struct iu_entry *iue; + struct scst_session *sess; +}; + static int process_tsk_mgmt(struct iu_entry *iue) { union viosrp_iu *iu = vio_iu(iue); - int fn; + struct srp_target *target = iue->target; + struct vio_port *vport = target_to_port(target); + struct scst_session *sess = vport->sess; + struct srp_tsk_mgmt *srp_tsk; + struct mgmt_ctx *mgmt_ctx; + int ret = 0; + + srp_tsk = &iu->srp.tsk_mgmt; + + dprintk("%p %u\n", iue, srp_tsk->tsk_mgmt_func); + + ret = SCST_MGMT_STATUS_FAILED; + mgmt_ctx = kmalloc(sizeof *mgmt_ctx, GFP_ATOMIC); + if (!mgmt_ctx) + goto err; - dprintk("%p %u\n", iue, iu->srp.tsk_mgmt.tsk_mgmt_func); + mgmt_ctx->iue = iue; + mgmt_ctx->sess = sess; + iu->srp.rsp.tag = srp_tsk->tag; - switch (iu->srp.tsk_mgmt.tsk_mgmt_func) { + switch (srp_tsk->tsk_mgmt_func) { case SRP_TSK_ABORT_TASK: - fn = ABORT_TASK; + ret = scst_rx_mgmt_fn_tag(sess, SCST_ABORT_TASK, + srp_tsk->task_tag, + SCST_ATOMIC, mgmt_ctx); break; case SRP_TSK_ABORT_TASK_SET: - fn = ABORT_TASK_SET; + ret = scst_rx_mgmt_fn_lun(sess, SCST_ABORT_TASK_SET, + (u8 *) &srp_tsk->lun, + sizeof srp_tsk->lun, + SCST_ATOMIC, mgmt_ctx); break; case SRP_TSK_CLEAR_TASK_SET: - fn = CLEAR_TASK_SET; + ret = scst_rx_mgmt_fn_lun(sess, SCST_CLEAR_TASK_SET, + (u8 *) &srp_tsk->lun, + sizeof srp_tsk->lun, + SCST_ATOMIC, mgmt_ctx); break; case SRP_TSK_LUN_RESET: - fn = LOGICAL_UNIT_RESET; + ret = scst_rx_mgmt_fn_lun(sess, SCST_LUN_RESET, + (u8 *) &srp_tsk->lun, + sizeof srp_tsk->lun, + SCST_ATOMIC, mgmt_ctx); break; case SRP_TSK_CLEAR_ACA: - fn = CLEAR_ACA; + ret = scst_rx_mgmt_fn_lun(sess, SCST_CLEAR_ACA, + (u8 *) &srp_tsk->lun, + sizeof srp_tsk->lun, + SCST_ATOMIC, mgmt_ctx); break; default: - fn = 0; + ret = SCST_MGMT_STATUS_FN_NOT_SUPPORTED; } - if (fn) - scsi_tgt_tsk_mgmt_request(iue->target->shost, - (unsigned long)iue->target->shost, - fn, - iu->srp.tsk_mgmt.task_tag, - (struct scsi_lun *) &iu->srp.tsk_mgmt.lun, - iue); - else - send_rsp(iue, NULL, ILLEGAL_REQUEST, 0x20); - return !fn; + if (ret != SCST_MGMT_STATUS_SUCCESS) + goto err; + return ret; + +err: + kfree(mgmt_ctx); + return ret; +} + +enum { + /* See also table 24 in the T10 r16a document. */ + SRP_TSK_MGMT_SUCCESS = 0x00, + SRP_TSK_MGMT_FUNC_NOT_SUPP = 0x04, + SRP_TSK_MGMT_FAILED = 0x05, +}; + +static u8 scst_to_srp_tsk_mgmt_status(const int scst_mgmt_status) +{ + switch (scst_mgmt_status) { + case SCST_MGMT_STATUS_SUCCESS: + return SRP_TSK_MGMT_SUCCESS; + case SCST_MGMT_STATUS_FN_NOT_SUPPORTED: + return SRP_TSK_MGMT_FUNC_NOT_SUPP; + case SCST_MGMT_STATUS_TASK_NOT_EXIST: + case SCST_MGMT_STATUS_LUN_NOT_EXIST: + case SCST_MGMT_STATUS_REJECTED: + case SCST_MGMT_STATUS_FAILED: + default: + break; + } + return SRP_TSK_MGMT_FAILED; +} + +static void ibmvstgt_tsk_mgmt_done(struct scst_mgmt_cmd *mcmnd) +{ + struct mgmt_ctx *mgmt_ctx; + struct scst_session *sess; + struct iu_entry *iue; + union viosrp_iu *iu; + + mgmt_ctx = scst_mgmt_cmd_get_tgt_priv(mcmnd); + BUG_ON(!mgmt_ctx); + + sess = mgmt_ctx->sess; + BUG_ON(!sess); + + iue = mgmt_ctx->iue; + BUG_ON(!iue); + + iu = vio_iu(iue); + + TRACE_DBG("%s: tag %lld status %d", + __func__, (long long unsigned)be64_to_cpu(iu->srp.rsp.tag), + scst_mgmt_cmd_get_status(mcmnd)); + + send_rsp(iue, NULL, + scst_to_srp_tsk_mgmt_status(scst_mgmt_cmd_get_status(mcmnd)), + 0/*asc*/); + + kfree(mgmt_ctx); } static int process_mad_iu(struct iu_entry *iue)
@@ -476,16 +751,26 @@ static int process_mad_iu(struct iu_entr static int process_srp_iu(struct iu_entry *iue) { + unsigned long flags; union viosrp_iu *iu = vio_iu(iue); + struct srp_target *target = iue->target; + struct vio_port *vport = target_to_port(target); int done = 1; u8 opcode = iu->srp.rsp.opcode; + spin_lock_irqsave(&target->lock, flags); + if (vport->releasing) { + spin_unlock_irqrestore(&target->lock, flags); + return done; + } + spin_unlock_irqrestore(&target->lock, flags); + switch (opcode) { case SRP_LOGIN_REQ: process_login(iue); break; case SRP_TSK_MGMT: - done = process_tsk_mgmt(iue); + done = process_tsk_mgmt(iue) != SCST_MGMT_STATUS_SUCCESS; break; case SRP_CMD: queue_cmd(iue);
@@ -722,65 +1007,6 @@ static void handle_crq(struct work_struc handle_cmd_queue(target); } - -static int ibmvstgt_eh_abort_handler(struct scsi_cmnd *sc) -{ - unsigned long flags; - struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; - struct srp_target *target = iue->target; - - dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]); - - spin_lock_irqsave(&target->lock, flags); - list_del(&iue->ilist); - spin_unlock_irqrestore(&target->lock, flags); - - srp_iu_put(iue); - - return 0; -} - -static int ibmvstgt_tsk_mgmt_response(struct Scsi_Host *shost, - u64 itn_id, u64 mid, int result) -{ - struct iu_entry *iue = (struct iu_entry *) ((void *) mid); - union viosrp_iu *iu = vio_iu(iue); - unsigned char status, asc; - - eprintk("%p %d\n", iue, result); - status = NO_SENSE; - asc = 0; - - switch (iu->srp.tsk_mgmt.tsk_mgmt_func) { - case SRP_TSK_ABORT_TASK: - asc = 0x14; - if (result) - status = ABORTED_COMMAND; - break; - default: - break; - } - - send_rsp(iue, NULL, status, asc); - srp_iu_put(iue); - - return 0; -} - -static int ibmvstgt_it_nexus_response(struct Scsi_Host *shost, u64 itn_id, - int result) -{ - struct srp_target *target = host_to_srp_target(shost); - struct vio_port *vport = target_to_port(target); - - if (result) { - eprintk("%p %d\n", shost, result); - srp_rport_del(vport->rport); - vport->rport = NULL; - } - return 0; -} - static ssize_t system_id_show(struct device *dev, struct device_attribute *attr, char *buf) {
@@ -796,40 +1022,51 @@ static ssize_t partition_number_show(str static ssize_t unit_address_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct Scsi_Host *shost = class_to_shost(dev); - struct srp_target *target = host_to_srp_target(shost); - struct vio_port *vport = target_to_port(target); + struct vio_port *vport = container_of(dev, struct vio_port, dev); return snprintf(buf, PAGE_SIZE, "%x\n", vport->dma_dev->unit_address); } -static DEVICE_ATTR(system_id, S_IRUGO, system_id_show, NULL); -static DEVICE_ATTR(partition_number, S_IRUGO, partition_number_show, NULL); -static DEVICE_ATTR(unit_address, S_IRUGO, unit_address_show, NULL); - -static struct device_attribute *ibmvstgt_attrs[] = { - &dev_attr_system_id, - &dev_attr_partition_number, - &dev_attr_unit_address, - NULL, +static struct class_attribute ibmvstgt_class_attrs[] = { + __ATTR_NULL, +}; + +static struct device_attribute ibmvstgt_attrs[] = { + __ATTR(system_id, S_IRUGO, system_id_show, NULL), + __ATTR(partition_number, S_IRUGO, partition_number_show, NULL), + __ATTR(unit_address, S_IRUGO, unit_address_show, NULL), + __ATTR_NULL, +}; + +static void ibmvstgt_dev_release(struct device *dev) +{ } + +static struct class ibmvstgt_class = { + .name = "ibmvstgt", + .dev_release = ibmvstgt_dev_release, + .class_attrs = ibmvstgt_class_attrs, + .dev_attrs = ibmvstgt_attrs, }; -static struct scsi_host_template ibmvstgt_sht = { +static struct scst_tgt_template ibmvstgt_template = { .name = TGT_NAME, - .module = THIS_MODULE, - .can_queue = INITIAL_SRP_LIMIT, - .sg_tablesize = SG_ALL, - .use_clustering = DISABLE_CLUSTERING, - .max_sectors = DEFAULT_MAX_SECTORS, - .transfer_response = ibmvstgt_cmd_done, - .eh_abort_handler = ibmvstgt_eh_abort_handler, - .shost_attrs = ibmvstgt_attrs, - .proc_name = TGT_NAME, - .supported_mode = MODE_TARGET, + .sg_tablesize = SCSI_MAX_SG_SEGMENTS, +#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) + .default_trace_flags = DEFAULT_IBMVSTGT_TRACE_FLAGS, + .trace_flags = &trace_flag, +#endif + .enable_target = ibmvstgt_enable_target, + .is_target_enabled = ibmvstgt_is_target_enabled, + .detect = ibmvstgt_detect, + .release = ibmvstgt_release, + .xmit_response = ibmvstgt_xmit_response, + .rdy_to_xfer = ibmvstgt_rdy_to_xfer, + .on_free_cmd = ibmvstgt_on_free_cmd, + .task_mgmt_fn_done = ibmvstgt_tsk_mgmt_done, }; static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) { - struct Scsi_Host *shost; + struct scst_tgt *scst_tgt; struct srp_target *target; struct vio_port *vport; unsigned int *dma, dma_size;
@@ -838,20 +1077,24 @@ static int ibmvstgt_probe(struct vio_dev vport = kzalloc(sizeof(struct vio_port), GFP_KERNEL); if (!vport) return err; - shost = scsi_host_alloc(&ibmvstgt_sht, sizeof(struct srp_target)); - if (!shost) + + target = kzalloc(sizeof(struct srp_target), GFP_KERNEL); + if (!target) goto free_vport; - shost->transportt = ibmvstgt_transport_template; - target = host_to_srp_target(shost); - target->shost = shost; + scst_tgt = scst_register_target(&ibmvstgt_template, NULL); + if (!scst_tgt) + goto free_target; + + scst_tgt_set_tgt_priv(scst_tgt, target); + target->tgt = scst_tgt; vport->dma_dev = dev; target->ldata = vport; vport->target = target; err = srp_target_alloc(target, &dev->dev, INITIAL_SRP_LIMIT, SRP_MAX_IU_LEN); if (err) - goto put_host; + goto unregister_target; dma = (unsigned int *) vio_get_attribute(dev, "ibm,my-dma-window", &dma_size);
@@ -865,27 +1108,29 @@ static int ibmvstgt_probe(struct vio_dev INIT_WORK(&vport->crq_work, handle_crq); - err = scsi_add_host(shost, target->dev); + err = crq_queue_create(&vport->crq_queue, target); if (err) goto free_srp_target; - err = scsi_tgt_alloc_queue(shost); - if (err) - goto remove_host; + vport->dev.class = &ibmvstgt_class; + vport->dev.parent = &dev->dev; + dev_set_name(&vport->dev, "ibmvstgt-%d", + vport->dma_dev->unit_address); + if (device_register(&vport->dev)) + goto destroy_crq_queue; - err = crq_queue_create(&vport->crq_queue, target); - if (err) - goto free_queue; + atomic_inc(&ibmvstgt_device_count); return 0; -free_queue: - scsi_tgt_free_queue(shost); -remove_host: - scsi_remove_host(shost); + +destroy_crq_queue: + crq_queue_destroy(target); free_srp_target: srp_target_free(target); -put_host: - scsi_host_put(shost); +unregister_target: + scst_unregister_target(scst_tgt); +free_target: + kfree(target); free_vport: kfree(vport); return err;
@@ -894,16 +1139,15 @@ free_vport: static int ibmvstgt_remove(struct vio_dev *dev) { struct srp_target *target = dev_get_drvdata(&dev->dev); - struct Scsi_Host *shost = target->shost; struct vio_port *vport = target->ldata; + atomic_dec(&ibmvstgt_device_count); + crq_queue_destroy(target); - srp_remove_host(shost); - scsi_remove_host(shost); - scsi_tgt_free_queue(shost); srp_target_free(target); + scst_unregister_target(target->tgt); + kfree(target); kfree(vport); - scsi_host_put(shost); return 0; }
@@ -915,9 +1159,9 @@ static struct vio_device_id ibmvstgt_dev MODULE_DEVICE_TABLE(vio, ibmvstgt_device_table); static struct vio_driver ibmvstgt_driver = { - .id_table = ibmvstgt_device_table, - .probe = ibmvstgt_probe, - .remove = ibmvstgt_remove, + .id_table = ibmvstgt_device_table, + .probe = ibmvstgt_probe, + .remove = ibmvstgt_remove, .driver = { .name = "ibmvscsis", .owner = THIS_MODULE,
@@ -951,25 +1195,31 @@ static int get_system_info(void) return 0; } -static struct srp_function_template ibmvstgt_transport_functions = { - .tsk_mgmt_response = ibmvstgt_tsk_mgmt_response, - .it_nexus_response = ibmvstgt_it_nexus_response, -}; - +/** + * ibmvstgt_init() - Kernel module initialization. + * + * Note: Since vio_register_driver() registers callback functions, and since + * at least one of these callback functions (ibmvstgt_probe()) calls SCST + * functions, the SCST target template must be registered before + * vio_register_driver() is called. + */ static int ibmvstgt_init(void) { int err = -ENOMEM; printk("IBM eServer i/pSeries Virtual SCSI Target Driver\n"); - ibmvstgt_transport_template = - srp_attach_transport(&ibmvstgt_transport_functions); - if (!ibmvstgt_transport_template) - return err; + err = class_register(&ibmvstgt_class); + if (err) + goto out; + + err = scst_register_target_template(&ibmvstgt_template); + if (err) + goto unregister_class; vtgtd = create_workqueue("ibmvtgtd"); if (!vtgtd) - goto release_transport; + goto unregister_tgt; err = get_system_info(); if (err)
@@ -980,10 +1230,14 @@ static int ibmvstgt_init(void) goto destroy_wq; return 0; + destroy_wq: destroy_workqueue(vtgtd); -release_transport: - srp_release_transport(ibmvstgt_transport_template); +unregister_tgt: + scst_unregister_target_template(&ibmvstgt_template); +unregister_class: + class_unregister(&ibmvstgt_class); +out: return err; }
@@ -991,9 +1245,10 @@ static void ibmvstgt_exit(void) { printk("Unregister IBM virtual SCSI driver\n"); - destroy_workqueue(vtgtd); vio_unregister_driver(&ibmvstgt_driver); - srp_release_transport(ibmvstgt_transport_template); + destroy_workqueue(vtgtd); + scst_unregister_target_template(&ibmvstgt_template); + class_unregister(&ibmvstgt_class); } MODULE_DESCRIPTION("IBM Virtual SCSI Target");
drivers/scsi/libsrp.c 22:43:50.105800350 +0400 renamed from linux-2.6.35/drivers/scsi/libsrp.c 16:47:55.220115813 +0400 +48 -39
180 lines not on this page · raw message
include/scsi/libsrp.h 16:47:55.240117096 +0400 renamed from linux-2.6.35/include/scsi/libsrp.h 16:47:55.220115813 +0400 +5 -11
@@ -3,8 +3,7 @@ #include <linux/list.h> #include <linux/kfifo.h> -#include <scsi/scsi_cmnd.h> -#include <scsi/scsi_host.h> +#include <scst/scst.h> #include <scsi/srp.h> enum iue_flags {
@@ -27,7 +30,7 @@ struct srp_queue { }; struct srp_target { - struct Scsi_Host *shost; + struct scst_tgt *tgt; struct device *dev; spinlock_t lock;
@@ -51,7 +54,7 @@ struct iu_entry { struct srp_buf *sbuf; }; -typedef int (srp_rdma_t)(struct scsi_cmnd *, struct scatterlist *, int, +typedef int (srp_rdma_t)(struct scst_cmd *, struct scatterlist *, int, struct srp_direct_buf *, int, enum dma_data_direction, unsigned int); extern int srp_target_alloc(struct srp_target *, struct device *, size_t, size_t);
@@ -60,16 +63,11 @@ extern void srp_target_free(struct srp_t extern struct iu_entry *srp_iu_get(struct srp_target *); extern void srp_iu_put(struct iu_entry *); -extern int srp_cmd_queue(struct Scsi_Host *, struct srp_cmd *, void *, u64, u64); -extern int srp_transfer_data(struct scsi_cmnd *, struct srp_cmd *, +extern int srp_cmd_queue(struct scst_session *, struct srp_cmd *, void *); +extern int srp_transfer_data(struct scst_cmd *, struct srp_cmd *, srp_rdma_t, int, int); -static inline struct srp_target *host_to_srp_target(struct Scsi_Host *host) -{ - return (struct srp_target *) host->hostdata; -} - static inline int srp_cmd_direction(struct srp_cmd *cmd) { return (cmd->buf_fmt >> 4) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
Documentation/powerpc/ibmvstgt.txt renamed from linux-2.6.35/Documentation/powerpc/ibmvstgt.txt +2 -0
@@ -0,0 +1,2 @@ +Documentation about IBM System p Virtual I/O (VIO) can be found here: +http://www.ibm.com/developerworks/wikis/display/virtualization/VIO
PATCH v4 19/19 : tgt: Removal
In reply to Vladislav BolkhovitinBecause of the conversion of the ibmvstgt driver from tgt to SCST, and because the ibmvstgt driver was the only user of scsi_tgt, the scsi_tgt kernel module, the CONFIG_SCSI_TGT, CONFIG_SCSI_SRP_TGT_ATTRS and CONFIG_SCSI_FC_TGT_ATTRS kbuild variable, the scsi_host_template member variables transfer_response, supportedmode and active_mode and the constants MODE_UNKNOWN, MODE_INITIATOR and MODE_TARGET are no longer needed.
Note: this patch applies cleanly on a 2.6.35 kernel tree. The patch tool however complains about the defconfig changes when trying to apply this patch on a 2.6.36 kernel tree.
--- arch/arm/configs/at572d940hfek_defconfig | 1 arch/arm/configs/cam60_defconfig | 1 arch/arm/configs/s3c2410_defconfig | 1 arch/m68k/configs/amiga_defconfig | 2 arch/m68k/configs/apollo_defconfig | 2 arch/m68k/configs/atari_defconfig | 2 arch/m68k/configs/bvme6000_defconfig | 2 arch/m68k/configs/hp300_defconfig | 2 arch/m68k/configs/mac_defconfig | 2 arch/m68k/configs/multi_defconfig | 2 arch/m68k/configs/mvme147_defconfig | 2 arch/m68k/configs/mvme16x_defconfig | 2 arch/m68k/configs/q40_defconfig | 2 arch/m68k/configs/sun3_defconfig | 2 arch/m68k/configs/sun3x_defconfig | 2 arch/mips/configs/bcm47xx_defconfig | 1 arch/mips/configs/decstation_defconfig | 1 arch/mips/configs/ip22_defconfig | 1 arch/mips/configs/ip27_defconfig | 1 arch/mips/configs/ip32_defconfig | 1 arch/mips/configs/jazz_defconfig | 1 arch/mips/configs/malta_defconfig | 1 arch/mips/configs/markeins_defconfig | 1 arch/mips/configs/pnx8550-jbs_defconfig | 1 arch/mips/configs/pnx8550-stb810_defconfig | 1 arch/mips/configs/rm200_defconfig | 1 arch/mips/configs/tb0226_defconfig | 1 arch/mips/configs/tb0287_defconfig | 1 arch/powerpc/configs/52xx/motionpro_defconfig | 1 arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig | 1 arch/powerpc/configs/mpc5200_defconfig | 1 drivers/scsi/Makefile | 3 drivers/scsi/hosts.c | 6 drivers/scsi/scsi_sysfs.c | 32 - drivers/scsi/scsi_tgt_if.c | 399 ------------- drivers/scsi/scsi_tgt_lib.c | 661 ----------------------- drivers/scsi/scsi_tgt_priv.h | 32 - drivers/scsi/scsi_transport_fc.c | 12 drivers/scsi/scsi_transport_fc_internal.h | 26 drivers/scsi/scsi_transport_srp.c | 18 drivers/scsi/scsi_transport_srp_internal.h | 25 include/scsi/scsi_host.h | 31 - include/scsi/scsi_tgt.h | 21 include/scsi/scsi_tgt_if.h | 108 --- 44 files changed, 2 insertions(+), 1415 deletions(-)
arch/arm/configs/at572d940hfek_defconfig 14:43:16.209585626 +0400 renamed from linux-2.6.35/arch/arm/configs/at572d940hfek_defconfig 14:43:13.033585149 +0400 +0 -1
@@ -107,7 +107,6 @@ CONFIG_SENSORS_TSL2550=m CONFIG_DS1682=m CONFIG_RAID_ATTRS=m CONFIG_SCSI=m -CONFIG_SCSI_TGT=m # CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=m CONFIG_BLK_DEV_SR=m
arch/arm/configs/cam60_defconfig 14:43:16.181586006 +0400 renamed from linux-2.6.35/arch/arm/configs/cam60_defconfig 14:43:13.009586086 +0400 +0 -1
@@ -55,7 +55,6 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y # CONFIG_MISC_DEVICES is not set CONFIG_SCSI=y -CONFIG_SCSI_TGT=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y CONFIG_CHR_DEV_SCH=y
arch/arm/configs/s3c2410_defconfig 14:43:16.189586873 +0400 renamed from linux-2.6.35/arch/arm/configs/s3c2410_defconfig 14:43:13.017586533 +0400 +0 -1
@@ -229,7 +229,6 @@ CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_IDETAPE=m CONFIG_BLK_DEV_PLATFORM=y CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=m
arch/m68k/configs/amiga_defconfig 14:43:16.181586006 +0400 renamed from linux-2.6.35/arch/m68k/configs/amiga_defconfig 14:43:13.013586335 +0400 +0 -2
@@ -506,7 +506,6 @@ CONFIG_BLK_DEV_BUDDHA=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
@@ -541,7 +540,6 @@ CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SAS_HOST_SMP=y # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_SCSI_AHA152X is not set
arch/m68k/configs/apollo_defconfig 14:43:16.166085929 +0400 renamed from linux-2.6.35/arch/m68k/configs/apollo_defconfig 14:43:12.993587185 +0400 +0 -2
@@ -469,7 +469,6 @@ CONFIG_HAVE_IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
@@ -504,7 +503,6 @@ CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SAS_HOST_SMP=y # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_LIBFC is not set
arch/m68k/configs/atari_defconfig 14:43:16.221586248 +0400 renamed from linux-2.6.35/arch/m68k/configs/atari_defconfig 14:43:13.054085875 +0400 +0 -2
@@ -497,7 +497,6 @@ CONFIG_BLK_DEV_FALCON_IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
@@ -532,7 +531,6 @@ CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SAS_HOST_SMP=y # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_LIBFC is not set
arch/m68k/configs/bvme6000_defconfig 14:43:16.205586184 +0400 renamed from linux-2.6.35/arch/m68k/configs/bvme6000_defconfig 14:43:13.033585149 +0400 +0 -2
@@ -471,7 +471,6 @@ CONFIG_HAVE_IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
@@ -506,7 +505,6 @@ CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SAS_HOST_SMP=y # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_LIBFC is not set
arch/m68k/configs/hp300_defconfig 14:43:16.233586430 +0400 renamed from linux-2.6.35/arch/m68k/configs/hp300_defconfig 14:43:13.065586532 +0400 +0 -2
@@ -470,7 +470,6 @@ CONFIG_HAVE_IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
@@ -505,7 +504,6 @@ CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SAS_HOST_SMP=y # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_LIBFC is not set
arch/m68k/configs/mac_defconfig 14:43:16.221586248 +0400 renamed from linux-2.6.35/arch/m68k/configs/mac_defconfig 14:43:13.054085875 +0400 +0 -2
@@ -493,7 +493,6 @@ CONFIG_BLK_DEV_MAC_IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
@@ -528,7 +527,6 @@ CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SAS_HOST_SMP=y # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_LIBFC is not set
arch/m68k/configs/multi_defconfig 14:43:16.221586248 +0400 renamed from linux-2.6.35/arch/m68k/configs/multi_defconfig 14:43:13.054085875 +0400 +0 -2
@@ -523,7 +523,6 @@ CONFIG_BLK_DEV_Q40IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
@@ -558,7 +557,6 @@ CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SAS_HOST_SMP=y # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_SCSI_AHA152X is not set
arch/m68k/configs/mvme147_defconfig 14:43:16.181586006 +0400 renamed from linux-2.6.35/arch/m68k/configs/mvme147_defconfig 14:43:13.009586086 +0400 +0 -2
@@ -471,7 +471,6 @@ CONFIG_HAVE_IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
@@ -506,7 +505,6 @@ CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SAS_HOST_SMP=y # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_LIBFC is not set
arch/m68k/configs/mvme16x_defconfig 14:43:16.197586106 +0400 renamed from linux-2.6.35/arch/m68k/configs/mvme16x_defconfig 14:43:13.029586280 +0400 +0 -2
@@ -471,7 +471,6 @@ CONFIG_HAVE_IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
@@ -506,7 +505,6 @@ CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SAS_HOST_SMP=y # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_LIBFC is not set
arch/m68k/configs/q40_defconfig 14:43:16.225586829 +0400 renamed from linux-2.6.35/arch/m68k/configs/q40_defconfig 14:43:13.058085429 +0400 +0 -2
@@ -490,7 +490,6 @@ CONFIG_BLK_DEV_Q40IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
@@ -525,7 +524,6 @@ CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SAS_HOST_SMP=y # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_SCSI_AHA152X is not set
arch/m68k/configs/sun3_defconfig 14:43:16.233586430 +0400 renamed from linux-2.6.35/arch/m68k/configs/sun3_defconfig 14:43:13.065586532 +0400 +0 -2
@@ -466,7 +466,6 @@ CONFIG_HAVE_IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y # CONFIG_SCSI_DMA is not set -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
@@ -501,7 +500,6 @@ CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SAS_HOST_SMP=y # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_LIBFC is not set
arch/m68k/configs/sun3x_defconfig 14:43:16.201587395 +0400 renamed from linux-2.6.35/arch/m68k/configs/sun3x_defconfig 14:43:13.033585149 +0400 +0 -2
@@ -468,7 +468,6 @@ CONFIG_HAVE_IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
@@ -503,7 +502,6 @@ CONFIG_SCSI_SAS_LIBSAS=m CONFIG_SCSI_SAS_HOST_SMP=y # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_LIBFC is not set
arch/mips/configs/bcm47xx_defconfig 14:43:16.233586430 +0400 renamed from linux-2.6.35/arch/mips/configs/bcm47xx_defconfig 14:43:13.065586532 +0400 +0 -1
@@ -931,7 +931,6 @@ CONFIG_SCSI_MOD=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
arch/mips/configs/decstation_defconfig 14:43:16.213585862 +0400 renamed from linux-2.6.35/arch/mips/configs/decstation_defconfig 14:43:13.046086036 +0400 +0 -1
@@ -413,7 +413,6 @@ CONFIG_BLK_DEV_LOOP=m # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
arch/mips/configs/ip22_defconfig 14:43:16.170085979 +0400 renamed from linux-2.6.35/arch/mips/configs/ip22_defconfig 14:43:13.001586197 +0400 +0 -1
@@ -644,7 +644,6 @@ CONFIG_HAVE_IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
arch/mips/configs/ip27_defconfig 14:43:16.193586687 +0400 renamed from linux-2.6.35/arch/mips/configs/ip27_defconfig 14:43:13.021586545 +0400 +0 -1
@@ -585,7 +585,6 @@ CONFIG_HAVE_IDE=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y
arch/mips/configs/ip32_defconfig 14:43:16.201587395 +0400 renamed from linux-2.6.35/arch/mips/configs/ip32_defconfig 14:43:13.029586280 +0400 +0 -1
@@ -439,7 +439,6 @@ CONFIG_HAVE_IDE=y CONFIG_RAID_ATTRS=y CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=y # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
arch/mips/configs/jazz_defconfig 14:43:16.217586134 +0400 renamed from linux-2.6.35/arch/mips/configs/jazz_defconfig 14:43:13.050085967 +0400 +0 -1
@@ -696,7 +696,6 @@ CONFIG_ATA_OVER_ETH=m # CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y
arch/mips/configs/malta_defconfig 14:43:16.181586006 +0400 renamed from linux-2.6.35/arch/mips/configs/malta_defconfig 14:43:13.009586086 +0400 +0 -1
@@ -883,7 +883,6 @@ CONFIG_BLK_DEV_IDEDMA=y CONFIG_RAID_ATTRS=m CONFIG_SCSI=m CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y
arch/mips/configs/markeins_defconfig 14:43:16.209585626 +0400 renamed from linux-2.6.35/arch/mips/configs/markeins_defconfig 14:43:13.038085920 +0400 +0 -1
@@ -646,7 +646,6 @@ CONFIG_SGI_IOC4=m # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=m -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set # CONFIG_SCSI_PROC_FS is not set
arch/mips/configs/pnx8550-jbs_defconfig 14:43:16.221586248 +0400 renamed from linux-2.6.35/arch/mips/configs/pnx8550-jbs_defconfig 14:43:13.058085429 +0400 +0 -1
@@ -470,7 +470,6 @@ CONFIG_BLK_DEV_IDEDMA=y # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y
arch/mips/configs/pnx8550-stb810_defconfig 14:43:16.170085979 +0400 renamed from linux-2.6.35/arch/mips/configs/pnx8550-stb810_defconfig 14:43:12.993587185 +0400 +0 -1
@@ -467,7 +467,6 @@ CONFIG_BLK_DEV_IDEDMA=y # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
arch/mips/configs/rm200_defconfig 14:43:16.170085979 +0400 renamed from linux-2.6.35/arch/mips/configs/rm200_defconfig 14:43:12.993587185 +0400 +0 -1
@@ -719,7 +719,6 @@ CONFIG_SGI_IOC4=m # CONFIG_RAID_ATTRS=m CONFIG_SCSI=y -CONFIG_SCSI_TGT=m CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y
arch/mips/configs/tb0226_defconfig 14:43:16.229587170 +0400 renamed from linux-2.6.35/arch/mips/configs/tb0226_defconfig 14:43:13.062085069 +0400 +0 -1
@@ -393,7 +393,6 @@ CONFIG_HAVE_IDE=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
arch/mips/configs/tb0287_defconfig 14:43:16.197586106 +0400 renamed from linux-2.6.35/arch/mips/configs/tb0287_defconfig 14:43:13.025585564 +0400 +0 -1
@@ -410,7 +410,6 @@ CONFIG_HAVE_IDE=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
arch/powerpc/configs/52xx/motionpro_defconfig 14:43:16.197586106 +0400 renamed from linux-2.6.35/arch/powerpc/configs/52xx/motionpro_defconfig 14:43:13.025585564 +0400 +0 -1
@@ -559,7 +559,6 @@ CONFIG_HAVE_IDE=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=y # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig 14:43:16.197586106 +0400 renamed from linux-2.6.35/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig 14:43:13.025585564 +0400 +0 -1
@@ -671,7 +671,6 @@ CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=y # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
arch/powerpc/configs/mpc5200_defconfig 14:43:16.197586106 +0400 renamed from linux-2.6.35/arch/powerpc/configs/mpc5200_defconfig 14:43:13.025585564 +0400 +0 -1
@@ -624,7 +624,6 @@ CONFIG_HAVE_IDE=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=y # CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y
drivers/scsi/Makefile 14:30:45.817271498 +0400 renamed from linux-2.6.35/drivers/scsi/Makefile 00:33:17.745901144 +0400 +0 -3
@@ -20,7 +20,6 @@ CFLAGS_gdth.o = # -DDEBUG_GDTH=2 -D__ obj-$(CONFIG_PCMCIA) += pcmcia/ obj-$(CONFIG_SCSI) += scsi_mod.o -obj-$(CONFIG_SCSI_TGT) += scsi_tgt.o obj-$(CONFIG_RAID_ATTRS) += raid_class.o
@@ -164,8 +163,6 @@ scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o scsi_mod-y += scsi_trace.o -scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o - sd_mod-objs := sd.o sd_mod-$(CONFIG_BLK_DEV_INTEGRITY) += sd_dif.o
drivers/scsi/hosts.c 17:35:38.853585850 +0400 renamed from linux-2.6.35/drivers/scsi/hosts.c 17:35:38.837586708 +0400 +0 -6
@@ -376,12 +376,6 @@ struct Scsi_Host *scsi_host_alloc(struct shost->use_clustering = sht->use_clustering; shost->ordered_tag = sht->ordered_tag; - if (sht->supported_mode == MODE_UNKNOWN) - /* means we didn't set it ... default to INITIATOR */ - shost->active_mode = MODE_INITIATOR; - else - shost->active_mode = sht->supported_mode; - if (sht->max_host_blocked) shost->max_host_blocked = sht->max_host_blocked; else
drivers/scsi/scsi_sysfs.c 22:00:10.726089770 +0400 renamed from linux-2.6.35/drivers/scsi/scsi_sysfs.c 00:33:17.745901144 +0400 +2 -30
@@ -200,33 +200,10 @@ struct device_attribute dev_attr_hstate __ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state); static ssize_t -show_shost_mode(unsigned int mode, char *buf) -{ - ssize_t len = 0; - - if (mode & MODE_INITIATOR) - len = sprintf(buf, "%s", "Initiator"); - - if (mode & MODE_TARGET) - len += sprintf(buf + len, "%s%s", len ? ", " : "", "Target"); - - len += sprintf(buf + len, "\n"); - - return len; -} - -static ssize_t show_shost_supported_mode(struct device *dev, struct device_attribute *attr, char *buf) { - struct Scsi_Host *shost = class_to_shost(dev); - unsigned int supported_mode = shost->hostt->supported_mode; - - if (supported_mode == MODE_UNKNOWN) - /* by default this should be initiator */ - supported_mode = MODE_INITIATOR; - - return show_shost_mode(supported_mode, buf); + return sprintf(buf, "Initiator\n"); } static DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL);
@@ -235,12 +212,7 @@ static ssize_t show_shost_active_mode(struct device *dev, struct device_attribute *attr, char *buf) { - struct Scsi_Host *shost = class_to_shost(dev); - - if (shost->active_mode == MODE_UNKNOWN) - return snprintf(buf, 20, "unknown\n"); - else - return show_shost_mode(shost->active_mode, buf); + return sprintf(buf, "Initiator\n"); } static DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL);
drivers/scsi/scsi_tgt_if.c 00:33:18.173901783 +0400 renamed from linux-2.6.35/drivers/scsi/scsi_tgt_if.c 21:27:39.757901065 +0400 +0 -399
399 lines not on this page · raw message
drivers/scsi/scsi_tgt_lib.c 00:33:18.173901783 +0400 renamed from linux-2.6.35/drivers/scsi/scsi_tgt_lib.c 21:27:39.757901065 +0400 +0 -661
661 lines not on this page · raw message
drivers/scsi/scsi_tgt_priv.h 00:33:18.173901783 +0400 renamed from linux-2.6.35/drivers/scsi/scsi_tgt_priv.h 21:27:39.757901065 +0400 +0 -32
@@ -1,32 +0,0 @@ -struct scsi_cmnd; -struct scsi_lun; -struct Scsi_Host; -struct task_struct; - -/* tmp - will replace with SCSI logging stuff */ -#define eprintk(fmt, args...) \ -do { \ - printk("%s(%d) " fmt, __func__, __LINE__, ##args); \ -} while (0) - -#define dprintk(fmt, args...) -/* #define dprintk eprintk */ - -extern void scsi_tgt_if_exit(void); -extern int scsi_tgt_if_init(void); - -extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 it_nexus_id, - struct scsi_lun *lun, u64 tag); -extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 it_nexus_id, - u64 tag); -extern int scsi_tgt_kspace_exec(int host_no, u64 it_nexus_id, int result, u64 tag, - unsigned long uaddr, u32 len, - unsigned long sense_uaddr, u32 sense_len, u8 rw); -extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 it_nexus_id, - int function, u64 tag, - struct scsi_lun *scsilun, void *data); -extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 it_nexus_id, - u64 mid, int result); -extern int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 it_nexus_id, - int function, char *initiator); -extern int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 it_nexus_id, int result);
drivers/scsi/scsi_transport_fc.c 14:43:16.170085979 +0400 renamed from linux-2.6.35/drivers/scsi/scsi_transport_fc.c 00:33:17.745901144 +0400 +0 -12
@@ -39,7 +39,6 @@ #include <scsi/scsi_netlink_fc.h> #include <scsi/scsi_bsg_fc.h> #include "scsi_priv.h" -#include "scsi_transport_fc_internal.h" static int fc_queue_work(struct Scsi_Host *, struct work_struct *); static void fc_vport_sched_delete(struct work_struct *work);
@@ -2908,10 +2907,6 @@ fc_remote_port_delete(struct fc_rport * spin_unlock_irqrestore(shost->host_lock, flags); - if (rport->roles & FC_PORT_ROLE_FCP_INITIATOR && - shost->active_mode & MODE_TARGET) - fc_tgt_it_nexus_destroy(shost, (unsigned long)rport); - scsi_target_block(&rport->dev); /* see if we need to kill io faster than waiting for device loss */
@@ -2952,7 +2947,6 @@ fc_remote_port_rolechg(struct fc_rport struct fc_host_attrs *fc_host = shost_to_fc_host(shost); unsigned long flags; int create = 0; - int ret; spin_lock_irqsave(shost->host_lock, flags); if (roles & FC_PORT_ROLE_FCP_TARGET) {
@@ -2961,12 +2955,6 @@ fc_remote_port_rolechg(struct fc_rport create = 1; } else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET)) create = 1; - } else if (shost->active_mode & MODE_TARGET) { - ret = fc_tgt_it_nexus_create(shost, (unsigned long)rport, - (char *)&rport->node_name); - if (ret) - printk(KERN_ERR "FC Remore Port tgt nexus failed %d\n", - ret); } rport->roles = roles;
drivers/scsi/scsi_transport_fc_internal.h 00:33:18.173901783 +0400 renamed from linux-2.6.35/drivers/scsi/scsi_transport_fc_internal.h 21:27:39.757901065 +0400 +0 -26
@@ -1,26 +0,0 @@ -#include <scsi/scsi_tgt.h> - -#ifdef CONFIG_SCSI_FC_TGT_ATTRS -static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, - char *initiator) -{ - return scsi_tgt_it_nexus_create(shost, itn_id, initiator); -} - -static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) -{ - return scsi_tgt_it_nexus_destroy(shost, itn_id); -} -#else -static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, - char *initiator) -{ - return 0; -} - -static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) -{ - return 0; -} - -#endif
drivers/scsi/scsi_transport_srp.c 14:43:16.201587395 +0400 renamed from linux-2.6.35/drivers/scsi/scsi_transport_srp.c 00:33:17.745901144 +0400 +0 -18
@@ -30,7 +30,6 @@ #include <scsi/scsi_host.h> #include <scsi/scsi_transport.h> #include <scsi/scsi_transport_srp.h> -#include "scsi_transport_srp_internal.h" struct srp_host_attrs { atomic_t next_port_id;
@@ -223,18 +222,6 @@ struct srp_rport *srp_rport_add(struct S return ERR_PTR(ret); } - if (shost->active_mode & MODE_TARGET && - ids->roles == SRP_RPORT_ROLE_INITIATOR) { - ret = srp_tgt_it_nexus_create(shost, (unsigned long)rport, - rport->port_id); - if (ret) { - device_del(&rport->dev); - transport_destroy_device(&rport->dev); - put_device(&rport->dev); - return ERR_PTR(ret); - } - } - transport_add_device(&rport->dev); transport_configure_device(&rport->dev);
@@ -251,11 +238,6 @@ EXPORT_SYMBOL_GPL(srp_rport_add); void srp_rport_del(struct srp_rport *rport) { struct device *dev = &rport->dev; - struct Scsi_Host *shost = dev_to_shost(dev->parent); - - if (shost->active_mode & MODE_TARGET && - rport->roles == SRP_RPORT_ROLE_INITIATOR) - srp_tgt_it_nexus_destroy(shost, (unsigned long)rport); transport_remove_device(dev); device_del(dev);
drivers/scsi/scsi_transport_srp_internal.h 00:33:18.169901710 +0400 renamed from linux-2.6.35/drivers/scsi/scsi_transport_srp_internal.h 21:27:39.753900649 +0400 +0 -25
@@ -1,25 +0,0 @@ -#include <scsi/scsi_tgt.h> - -#ifdef CONFIG_SCSI_SRP_TGT_ATTRS -static inline int srp_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, - char *initiator) -{ - return scsi_tgt_it_nexus_create(shost, itn_id, initiator); -} - -static inline int srp_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) -{ - return scsi_tgt_it_nexus_destroy(shost, itn_id); -} - -#else -static inline int srp_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, - char *initiator) -{ - return 0; -} -static inline int srp_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) -{ - return 0; -} -#endif
include/scsi/scsi_host.h 22:00:10.726089770 +0400 renamed from linux-2.6.35/include/scsi/scsi_host.h 21:27:39.753900649 +0400 +0 -31
@@ -36,10 +36,6 @@ struct blk_queue_tags; #define SG_NONE 0 #define SG_ALL SCSI_MAX_SG_SEGMENTS -#define MODE_UNKNOWN 0x00 -#define MODE_INITIATOR 0x01 -#define MODE_TARGET 0x02 - #define DISABLE_CLUSTERING 0 #define ENABLE_CLUSTERING 1
@@ -131,27 +127,6 @@ struct scsi_host_template { void (*done)(struct scsi_cmnd *)); /* - * The transfer functions are used to queue a scsi command to - * the LLD. When the driver is finished processing the command - * the done callback is invoked. - * - * This is called to inform the LLD to transfer - * scsi_bufflen(cmd) bytes. scsi_sg_count(cmd) speciefies the - * number of scatterlist entried in the command and - * scsi_sglist(cmd) returns the scatterlist. - * - * return values: see queuecommand - * - * If the LLD accepts the cmd, it should set the result to an - * appropriate value when completed before calling the done function. - * - * STATUS: REQUIRED FOR TARGET DRIVERS - */ - /* TODO: rename */ - int (* transfer_response)(struct scsi_cmnd *, - void (*done)(struct scsi_cmnd *)); - - /* * This is an error handling strategy routine. You don't need to * define one of these if you don't want to - there is a default * routine that is present that should work in most cases. For those
@@ -426,11 +401,6 @@ struct scsi_host_template { unsigned char present; /* - * This specifies the mode that a LLD supports. - */ - unsigned supported_mode:2; - - /* * True if this host adapter uses unchecked DMA onto an ISA bus. */ unsigned unchecked_isa_dma:1;
@@ -607,7 +577,6 @@ struct Scsi_Host { */ unsigned long cmd_serial_number; - unsigned active_mode:2; unsigned unchecked_isa_dma:1; unsigned use_clustering:1; unsigned use_blk_tcq:1;
include/scsi/scsi_tgt.h 00:33:18.173901783 +0400 renamed from linux-2.6.35/include/scsi/scsi_tgt.h 21:27:39.753900649 +0400 +0 -21
@@ -1,21 +0,0 @@ -/* - * SCSI target definitions - */ - -#include <linux/dma-mapping.h> - -struct Scsi_Host; -struct scsi_cmnd; -struct scsi_lun; - -extern struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *); -extern int scsi_tgt_alloc_queue(struct Scsi_Host *); -extern void scsi_tgt_free_queue(struct Scsi_Host *); -extern int scsi_tgt_queue_command(struct scsi_cmnd *, u64, struct scsi_lun *, u64); -extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, u64, int, u64, - struct scsi_lun *, void *); -extern struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *, - enum dma_data_direction, gfp_t); -extern void scsi_host_put_command(struct Scsi_Host *, struct scsi_cmnd *); -extern int scsi_tgt_it_nexus_create(struct Scsi_Host *, u64, char *); -extern int scsi_tgt_it_nexus_destroy(struct Scsi_Host *, u64);
include/scsi/scsi_tgt_if.h 00:33:18.169901710 +0400 renamed from linux-2.6.35/include/scsi/scsi_tgt_if.h 21:27:39.741900784 +0400 +0 -108
108 lines not on this page · raw message
Quoted 9 lines · Vladislav Bolkhovitin
Hi All,
Please review the next iteration of the patch set of the new (although, in fact, the oldest) SCSI target framework for Linux SCST with a set of dev handlers and 3 target drivers: for local access (
scst_local), for Infiniband SRP (srpt) and IBM POWER Virtual SCSI .[ ... ]
Note: as far as I know currently SCST is the first and only in-kernel target storage framework that satisfies both criteria (1) and (2) as defined during the LSF 2010 summit storage track (see also
http://lwn.net/Articles/400589/):
1. Being a drop in replacement for STGT (the current in-kernel target mode driver).
2. Using a modern sysfs based control and configuration plane.
Regarding criterion (3), that the code was reviewed as clean enough for inclusion: any feedback is welcome.
Bart.
Hi All,
Small Tree would very much like to see the SCST framework included in the mainline kernel. It's used in one of the products we've been working on as well as in some products we sell. It seems reliable and the performance seems good. Having it in the mainline kernel would save us a great deal of headache.
Steve
Quoted 178 lines · Vladislav Bolkhovitin
Hi All,
Please review the next iteration of the patch set of the new (although, in fact, the oldest) SCSI target framework for Linux SCST with a set of dev handlers and 3 target drivers: for local access (
scst_local), for Infiniband SRP (srpt) and IBM POWER Virtual SCSI .SCST is the most advanced and features rich SCSI target subsystem for Linux. It allows to build the fastest devices and clusters delivering millions of IOPS. Many companies are using it as a foundation for their storage products and solutions. List of some of them you can find on
http://scst.sourceforge.net/users.html. There are also many other who not yet added there or prefer for some reasons to not be listed on this page.The previous iterations of the SCST patch set you can find on
http://lkml.org/lkml/2008 and http://lkml.org/lkml/2010/4/13/146.We believe that code is fully mainline ready (considering that ibmvstgt driver for SCST not yet tested on hardware).
This iteration for simplicity contains only 2 target drivers: for local access (
scst_local) and SRP (ib_srpt). If SCST accepted, we will prepare and submit patches for other target drivers: for iSCSI, FCoE, QLogic Fibre Channel QLA 2xxx, Emulex Fibre Channel/FCoE and Marvell 88SE63xx/64xx/68xx/94xx SAS hardware.Also this patchset contains port of ibmvstgt driver for SCST, many thanks to Bart Van Assche for performing it!
This patchset is for kernel 2.6.35. On request we will rebase it for any other kernel tree. Since SCST is quite self-contained and almost doesn't touch outside kernel code, there are no problems in it.
As Dmitry Torokhov requested (thanks for the review!), in this iteration we added more detail descriptions of each patch. Since the space for description is too limited, we can't describe full SCST internals (it's worth a book). But we hope that those description will be a good starting point.
More detail description of SCST, its drivers and utilities you can find on SCST home page http://scst.sourceforge.net. Detail features list and comparison with other Linux target subsystems you can find on
http://scst.sourceforge.net/comparison.html. Description of the SCST processing flow you can find in http://scst.sourceforge.net/scst_pg.html
(especially see picture "The commands processing flow").SCST is complete self-contained subsystem. It shares only few with the Linux SCSI (initiator) subsystem: constants and some low level utility functions. This is a deliberate decision, because the task of implementing a SCSI target (i.e. server) is orthogonal to the task of implementing a SCSI initiator (i.e. client). Such orthogonality between client and server implementations is quite common. In fact, I can't recall anything, where client and server are coupled together. You can see how few NFS client and server are sharing in the Linux kernel (<300 LOC). For me to build SCSI target around initiator is similar as to build Sendmail around Mutt, or Apache around Firefox.
I'm writing about it so much, because STGT's in-kernel interface and data fields embedded into the Linux SCSI (initiator) subsystem, i.e. STGT is built around the Linux SCSI (initiator) subsystem, and this approach considered the best by many kernel developers. But, in fact, this approach is wrong, because of orthogonality between initiator and target subsystems. A good design is to keep orthogonal things separately, not coupled together.
Consequences of this bad move is predictable and common for cases when separate things coupled together:
1. Internal: sometimes it isn't obvious if a function or data type is for target or initiator mode. Hence, it is easy fixing initiator mode break target and vice versa.
2. User visible. At the moment, supposed to be initiator-side scsi_transport_* modules for FC and SRP depends from the target side module module
scsi_tgt, like:# lsmod Module Size Used by qla2xxx 130844 0 firmware_class 8064 1 qla2xxx scsi_transport_fc 40900 1 qla2xxx scsi_tgt 12196 1 scsi_transport_fc ...This means that all FC and SRP users must have
scsi_tgtloaded although they never going to run a SCSI target and have never heard about the only module in the kernel which actually needs scsi_tgt.ko: ibmvstgt.ko.SCSI target and initiator devices generally live under different lifetime rules starting from initialization: initiator devices created by target scanning, while target devices created by external action on the target side.
SCSI target and initiator devices doing opposite processing: initiator is initiating SCSI commands, while target is processing them. The target side initiating notifications, the initiator side - processing them, for instance, by rescanning the corresponding target port after REPORT LUNS DATA HAS CHANGED Unit Attention. Even DMA transfer direction for the same commands is opposite. For instance for a READ command:
TO_DEVICEfor target device andFROM_DEVICEfor initiator device.SCSI target and initiator subsystems need completely different user interface, because the initiator subsystem creates devices internally, but for the target subsystem devices created by external actions via the user interface.
Yes, sure, there are cases when a HBA can serve both target and initiator modes, but this is rather a special case. For instance, SCST has 9 target drivers, from which 7 are target mode only drivers. For such cases, the best is (and this approach is used by
mvsas_tgtand qla2x00t drivers):- To make the target mode part a separate add-on to the main initiator mode driver. The initiator mode driver will be responsible for initializing hardware and managing ports for both modes.
- To add to the initiator module a set of hooks to allow it to interact with target mode add-on as soon as it is loaded and send to it target commands from initiators.
As an illustration, consider STGT ibmvstgt driver and see how many it actually shares with the initiator mode. It is defined as:
static struct
scsi_host_templateibmvstgt_sht= {
.name =TGT_NAME,
.module =THIS_MODULE,
.can_queue =INITIAL_SRP_LIMIT,
.sg_tablesize =SG_ALL,
.use_clustering =DISABLE_CLUSTERING,
.max_sectors =DEFAULT_MAX_SECTORS,
.transfer_response =ibmvstgt_cmd_done,
.eh_abort_handler =ibmvstgt_eh_abort_handler,
.shost_attrs =ibmvstgt_attrs,
.proc_name =TGT_NAME,
.supported_mode =MODE_TARGET,
};1. For "
can_queue" we see inscsi_tgt_alloc_queue()commented code:/*
* this is a silly hack. We should probably just queue as many
* command as is recvd to userspace. uspace can then make
* sure we do not overload the HBA
*/q->nr_requests=shost->can_queue;The comment is correct,
can_queueis nonsense on the target side, because initiator is queuing commands and a target driver generally can't do anything with it, socan_queueisn't property of a target driver, but property of common flow control managed by the target mid-layer.2. Similarly, "
max_sectors" is also nonsense for a target driver, because it doesn't queuing commands. In SCSI such limit is negotiated by Block Limits VPD page on per LUN, not per target driver basis.3.
eh_abort_handler(). Such callback in the way how it is used by STGT can only be used with a single threaded processing, because abort can happen fully asynchronously to the processing of the affected command, so the processing would need complicated locking to allow such async abort. On practice with multithreaded processing it is much simpler to have all commands processing fully synchronous and check for aborts only in specially defined places. In this approach, such callback isn't needed.4.
transfer_response()- fully target mode callback5.
shost_attrsandproc_name- it's better to have target mode user interface in different place with initiator mode.Thus, we have shared between target and initiator modes only "name", "module", "
sg_tablesize", "use_clustering" fields. Not many, yes?In the descriptions for specific patches I'll evaluate more about SCST architecture.
Thanks,
Vlad
Quoted 10 lines
------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances and start using them to simplify application deployment and accelerate your shift to cloud computing.
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
Scst-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/scst-devel
--
Steve Modica
CTO - Small Tree Communications
www.small-tree.com
phone: 651-209-6509 ext 301
mobile: 651-261-3201