hi all, while googling i found similar question but in detail the same problem i had faced i'm cut and pasting this ,sorry i can't get the answer while googling so let me know? In list.h, we have: #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) >From what I understand, this is supposed to be a hack that gives C++ inheritence support in C. The idea is that the compiler thinks that ptr is a pointer to type list_head but in reality it is a pointer to a larger struct that shares the same first bytes as list_head. Like this: struct list_head { struct list_head *next, *prev; }; typedef struct page { struct list_head list; struct address_space *mapping; unsigned long index; struct page *next_hash; atomic_t count; unsigned long flags; /* atomic flags, some possibly updated asynchronously */ struct list_head lru; wait_queue_head_t wait; struct page **pprev_hash; struct buffer_head * buffers; unsigned long virtual; /* nonzero if kmapped */ struct zone_struct *zone; } mem_map_t; Notice how list_head is the first element in mem_map_t. What I don't understand about list_entry is why there is a minus symbol instead of a plus symbol. Assume to call list_entry with these parameters: struct list_head *curr; struct page *page; page = memlist_entry(curr, struct page, list); According to the macro, we treat curr as a char pointer. "(unsigned long)(&((type *)0)->member)" is equal to the offset within "struct page" of member "list", which happens to be zero. so "(char *)(ptr) - 0) is just (char *)(ptr), which is then typecast to (struct page *). I think the minus is a bug. It should be plus. Let's take a case where the third parameter is NOT "list": struct pci_driver { struct list_head node; char *name; const struct pci_device_id *id_table; /* NULL if wants all devices */ int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ void (*suspend)(struct pci_dev *dev); /* Device suspended */ void (*resume)(struct pci_dev *dev); /* Device woken up */ }; struct list_head *ln; struct pci_driver *drv = list_entry(ln, struct pci_driver, node); "(unsigned long)(&((type *)0)->member)" gives you the offset of name, which is basically sizeof(struct list_head), or 8. In this case, list_entry is equal to the address of ln MINUS 8, which points outside of the structure! I know the kernel would crash instantly if this macro didn't work, but I can't see how it could! __________________________________ Do you Yahoo!? Yahoo! Finance: Get your refund fast by filing online. http://taxes.yahoo.com/filing.html -- Kernelnewbies: Help each other learn about the Linux kernel. Archive: http://mail.nl.linux.org/kernelnewbies/ FAQ: http://kernelnewbies.org/faq/