On Mon, Aug 31, 2015 at 12:14:16PM -0400, Konrad Rzeszutek Wilk wrote:
> > >And the 'container_of' macro looks to require only one level of
> > >nesting.
> > 
> > I'm pretty sure the macro can deal with both.
> 
> OK, let me experiement with it as at the first blush it does not work for me.

I can't get it to work.

My understanding (and the test case - see attached) seem to agree that
the 'container_of' is to be used when you have the pointer to the nested
member (oid) and want the pointer to the structure in which it is
embedded in (op). We have the opposite case - we have the pointer to the
structure in which it was embedded (op):

 struct tmem_op *op;
  
 oidp = (struct tmem_oid *)&op.u.gen.oid[0];

Hence using the container_of macro won't work.
#include <stdio.h>

struct tmem_oid {
        unsigned long oid[3];
};

struct internal {
        unsigned int cmd;
        struct tmem_oid oid;
};
struct tmem_op {
        unsigned int x;
        union {
                struct {
                        unsigned int cmd;
                } g;
                struct internal c;
        } u;
};

#define container_of(ptr, type, member) ({                      \
        typeof( ((type *)0)->member ) *__mptr = (ptr);          \
        (type *)( (char *)__mptr - offsetof(type,member) );})

#define offsetof(a,b) __builtin_offsetof(a,b)

void main(void) {

        struct tmem_op op;
        struct tmem_oid *_oid;
        struct tmem_oid *_src;
        struct internal *_i;
        struct internal *_q;
        printf("%d \n", offsetof(struct tmem_op, u.c.oid)); // 16
        printf("%d \n", offsetof(struct tmem_op, u.c.oid.oid)); // 16
        printf("%d \n", offsetof(struct internal, oid)); // 8

        _i = &op.u.c;
        printf("%d\n", (void *)_i - (void *)&op); // 8
        _oid = &op.u.c.oid;
        printf("%d\n", (void *)_oid - (void *)&op); // 16

    /* Pointer to struct tmem_oid (_oid), getting the pointer to 'struct 
internal' */
        _q = container_of(_oid, struct internal, oid);

        printf("%d\n", (void *)_q - (void *)&op); // 8

    /* Having the pointer to outer ('*op') we can get the pointer to the 
internal. */
        _src = (struct tmem_oid *)((void *)&op + offsetof(struct tmem_op, 
u.c.Xoid.oid));
        printf("%d\n", (void *)_src - (void *)&op); // 16
};
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

Reply via email to