Struct Inheritance in drivers/ata/

Ankit Jain mail at ankitjain.org
Fri May 27 00:49:43 EDT 2011


On Fri, May 27, 2011 at 7:50 AM, Peter Hamilton
<peterghamilton at gmail.com> wrote:
> I see that it works, but I'm not exactly following how.  Maybe I just don't
> have enough C experience.  But I can't seem to duplicate that functionality.
>
> I understand the way I've normally seen inheritance, where:
> struct Child {
>   struct Parent p;
>   int somethingOnlyForChildren;
> }
>
> Or something similar.  Then the Child struct can be casted as a Parent, and
> since there is no padding before the first piece of data in a struct, every
> parent attribute is accessed as though the struct were a Parent.
> I see how it all lines up in memory, but in the case of the kernel code I
> can't quite follow it.  Wouldn't everything assigned to 'inherits' be so
> much farther down in memory?  I feel like I'm missing something.  Is there a
> special way they all need to be accessed?

I think an example should clear this.

//class type
struct klass {
  void (*foo)();
  void (*bar)(int x);

  struct parent *inherits;
};

//object 1, parent
struct klass klass_a {
   //no .inherits
   .foo = a_foo,
   .bar = a_bar,
};

//object 2, child, inherits klass_a
struct klass klass_b {
   .inherits = &klass_a,
   .foo = b_foo,
};

klass_b inherits klass_a. klass_b "overrides" only foo "member", so klass_b
will have the new overriden foo (b_foo), and will "inherit" bar from its parent,
a_bar. The relationship is setup as shown above, by using the .inherits field,
and final pointers are setup by ata_finalize_port_ops in
drivers/ata/libata-core.c .

Once the pointers of the various objects have been set to their final values,
while honoring the inheritance relationship, the 'inherits' field is
no longer required,
and the pointers can be used directly.

This function is called whenever an ata host is started.
See the comments on that function and read the code, should make things
clearer.

I also just read that code and then replying here, so I could have missed or
misunderstood something.

-Ankit

> - Peter
> On Thu, May 26, 2011 at 7:23 PM, Greg KH <greg at kroah.com> wrote:
>>
>> On Thu, May 26, 2011 at 02:46:08PM -0600, Peter Hamilton wrote:
>> > The code in drivers/ata/ uses an implementation of inheritance that I
>> > have not
>> > seen before.  It's only briefly explained in the header file (
>> > include/linux/
>> > libata.h:885):
>> >
>> > /*
>> >  * ->inherits must be the last field and all the preceding
>> >  * fields must be pointers.
>> >  */
>> >
>> > The structs are then initialized with .inherits assigned first:
>> >
>> > drivers/ata/sata_nv.c:475
>> >
>> > static struct ata_port_operations nv_nf2_ops = {
>> >
>> >         .inherits               = &nv_generic_ops,
>> >         .freeze                 = nv_nf2_freeze,
>> >
>> >         .thaw                   = nv_nf2_thaw,
>> >
>> > };
>> >
>> >
>> > Is this actually implementing inheritance?  Why do all preceding fields
>> > need to
>> > be pointers?
>> >
>> > As far as I can tell, this style is only found in the ata drivers.
>>
>> I think you are right, but more subsystems need to emulate it, it is
>> very powerful and works very well.  I have been wanting to convert the
>> usb-serial layer to use the same thing one of these days.
>>
>> > Could anyone explain how this works?
>>
>> The code is all there that shows it, but basically the driver is telling
>> the core to "use this type of functions, but if I set any others, use
>> them instead."  It's a nicer way of doing inheritance in C than we do in
>> other places in the kernel where we are a bit more "verbose" in making
>> it happen.
>>
>> hope this helps,
>>
>> greg k-h
>
>
> _______________________________________________
> Kernelnewbies mailing list
> Kernelnewbies at kernelnewbies.org
> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>
>



More information about the Kernelnewbies mailing list