Define container_of which cast from member to struct with some type checking.
This is much like list_entry but is cearly for things other than lists.
List_entry now uses container_of.
struct pci_driver *drv;
struct pci_dev *pci_dev;
- drv = list_entry(dev->driver, struct pci_driver, driver);
- pci_dev = list_entry(dev, struct pci_dev, dev);
+ drv = to_pci_driver(dev->driver);
+ pci_dev = to_pci_dev(dev);
if (drv->probe) {
const struct pci_device_id *id;
static int pci_device_remove(struct device * dev)
{
- struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev);
+ struct pci_dev * pci_dev = to_pci_dev(dev);
struct pci_driver * drv = pci_dev->driver;
if (drv) {
static int pci_device_suspend(struct device * dev, u32 state, u32 level)
{
- struct pci_dev * pci_dev = (struct pci_dev *)list_entry(dev,struct pci_dev,dev);
+ struct pci_dev * pci_dev = to_pci_dev(dev);
int error = 0;
if (pci_dev->driver) {
static int pci_device_resume(struct device * dev, u32 level)
{
- struct pci_dev * pci_dev = (struct pci_dev *)list_entry(dev,struct pci_dev,dev);
+ struct pci_dev * pci_dev = to_pci_dev(dev);
if (pci_dev->driver) {
if (level == RESUME_POWER_ON && pci_dev->driver->resume)
*/
static int pci_bus_match(struct device * dev, struct device_driver * drv)
{
- struct pci_dev * pci_dev = list_entry(dev, struct pci_dev, dev);
- struct pci_driver * pci_drv = list_entry(drv,struct pci_driver,driver);
+ struct pci_dev * pci_dev = to_pci_dev(dev);
+ struct pci_driver * pci_drv = to_pci_driver(drv);
const struct pci_device_id * ids = pci_drv->id_table;
if (!ids)
/* driverfs files */
static ssize_t pci_show_irq(struct device * dev, char * buf, size_t count, loff_t off)
{
- struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev);
+ struct pci_dev * pci_dev = to_pci_dev(dev);
return off ? 0 : sprintf(buf,"%u\n",pci_dev->irq);
}
static ssize_t pci_show_resources(struct device * dev, char * buf, size_t count, loff_t off)
{
- struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev);
+ struct pci_dev * pci_dev = to_pci_dev(dev);
char * str = buf;
int i;
int allow_revalidate;
struct device sdev_driverfs_dev;
};
+#define to_scsi_device(d) \
+ container_of(d, struct scsi_device, sdev_driverfs_dev)
/*
static ssize_t scsi_device_type_read(struct device *driverfs_dev, char *page,
size_t count, loff_t off)
{
- struct scsi_device *SDpnt = list_entry(driverfs_dev,
- struct scsi_device, sdev_driverfs_dev);
+ struct scsi_device *SDpnt = to_scsi_device(driverfs_dev);
if ((SDpnt->type <= MAX_SCSI_DEVICE_CODE) &&
(scsi_device_types[(int)SDpnt->type] != NULL))
if (off)
return 0;
- udev = list_entry (dev, struct usb_device, dev);
+ udev = to_usb_device (dev);
return sprintf (buf, "%u\n", udev->actconfig->bConfigurationValue);
}
static struct driver_file_entry usb_config_entry = {
if (off)
return 0;
- interface = list_entry (dev, struct usb_interface, dev);
+ interface = to_usb_interface (dev);
return sprintf (buf, "%u\n", interface->altsetting->bAlternateSetting);
}
static struct driver_file_entry usb_altsetting_entry = {
if (off)
return 0;
- udev = list_entry (dev, struct usb_device, dev);
+ udev = to_usb_device (dev);
len = usb_string(udev, udev->descriptor.iProduct, buf, PAGE_SIZE);
buf[len] = '\n';
if (off)
return 0;
- udev = list_entry (dev, struct usb_device, dev);
+ udev = to_usb_device (dev);
len = usb_string(udev, udev->descriptor.iManufacturer, buf, PAGE_SIZE);
buf[len] = '\n';
if (off)
return 0;
- udev = list_entry (dev, struct usb_device, dev);
+ udev = to_usb_device (dev);
len = usb_string(udev, udev->descriptor.iSerialNumber, buf, PAGE_SIZE);
buf[len] = '\n';
if (count > PAGE_SIZE)
count = PAGE_SIZE;
- dev = list_entry(entry->parent,struct device, dir);
+ dev = to_device(entry->parent);
page = (unsigned char*)__get_free_page(GFP_KERNEL);
if (!page)
if (!entry->store)
return 0;
- dev = list_entry(entry->parent,struct device, dir);
+ dev = to_device(entry->parent);
page = (char *)__get_free_page(GFP_KERNEL);
if (!page)
entry = (struct driver_file_entry *)inode->u.generic_ip;
if (!entry)
return -EFAULT;
- dev = (struct device *)list_entry(entry->parent,struct device,dir);
+ dev = to_device(entry->parent);
get_device(dev);
filp->private_data = entry;
return 0;
entry = (struct driver_file_entry *)filp->private_data;
if (!entry)
return -EFAULT;
- dev = (struct device *)list_entry(entry->parent,struct device,dir);
+ dev = to_device(entry->parent);
put_device(dev);
return 0;
}
static inline struct ext2_inode_info *EXT2_I(struct inode *inode)
{
- return list_entry(inode, struct ext2_inode_info, vfs_inode);
+ return container_of(inode, struct ext2_inode_info, vfs_inode);
}
/* balloc.c */
static inline struct adfs_inode_info *ADFS_I(struct inode *inode)
{
- return list_entry(inode, struct adfs_inode_info, vfs_inode);
+ return container_of(inode, struct adfs_inode_info, vfs_inode);
}
#endif
void (*release)(struct device * dev);
};
+#define to_device(d) container_of(d, struct device, dir)
+
static inline struct device *
list_to_dev(struct list_head *node)
{
static inline struct efs_inode_info *INODE_INFO(struct inode *inode)
{
- return list_entry(inode, struct efs_inode_info, vfs_inode);
+ return container_of(inode, struct efs_inode_info, vfs_inode);
}
static inline struct efs_sb_info *SUPER_INFO(struct super_block *sb)
#define EXT3_SB(sb) (&((sb)->u.ext3_sb))
static inline struct ext3_inode_info *EXT3_I(struct inode *inode)
{
- return list_entry(inode, struct ext3_inode_info, vfs_inode);
+ return container_of(inode, struct ext3_inode_info, vfs_inode);
}
#else
/* Assume that user mode programs are passing in an ext3fs superblock, not
static inline struct socket *SOCKET_I(struct inode *inode)
{
- return &list_entry(inode, struct socket_alloc, vfs_inode)->socket;
+ return &container_of(inode, struct socket_alloc, vfs_inode)->socket;
}
static inline struct inode *SOCK_INODE(struct socket *socket)
{
- return &list_entry(socket, struct socket_alloc, socket)->vfs_inode;
+ return &container_of(socket, struct socket_alloc, socket)->vfs_inode;
}
/* will die */
static inline struct hfs_inode_info *HFS_I(struct inode *inode)
{
- return list_entry(inode, struct hfs_inode_info, vfs_inode);
+ return container_of(inode, struct hfs_inode_info, vfs_inode);
}
static inline struct hfs_sb_info *HFS_SB(struct super_block *sb)
static inline struct iso_inode_info *ISOFS_I(struct inode *inode)
{
- return list_entry(inode, struct iso_inode_info, vfs_inode);
+ return container_of(inode, struct iso_inode_info, vfs_inode);
}
static inline int isonum_711(char *p)
#define max_t(type,x,y) \
({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ *
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
#endif /* __KERNEL__ */
#define SI_LOAD_SHIFT 16
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
- ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+ container_of(ptr, type, member)
/**
* list_for_each - iterate over a list
static inline struct msdos_inode_info *MSDOS_I(struct inode *inode)
{
- return list_entry(inode, struct msdos_inode_info, vfs_inode);
+ return container_of(inode, struct msdos_inode_info, vfs_inode);
}
struct fat_cache {
#define NCP_SERVER(inode) NCP_SBP((inode)->i_sb)
static inline struct ncp_inode_info *NCP_FINFO(struct inode *inode)
{
- return list_entry(inode, struct ncp_inode_info, vfs_inode);
+ return container_of(inode, struct ncp_inode_info, vfs_inode);
}
#ifdef DEBUG_NCP_MALLOC
static inline struct nfs_inode *NFS_I(struct inode *inode)
{
- return list_entry(inode, struct nfs_inode, vfs_inode);
+ return container_of(inode, struct nfs_inode, vfs_inode);
}
#define NFS_SB(s) ((struct nfs_server *)(s->u.generic_sbp))
#define pci_dev_g(n) list_entry(n, struct pci_dev, global_list)
#define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list)
+#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
/*
* For PCI devices, the region numbers are assigned this way:
struct device_driver driver;
};
+#define to_pci_driver(drv) container_of(drv,struct pci_driver, driver)
+
/* these external functions are only available when PCI support is enabled */
#ifdef CONFIG_PCI
static inline struct proc_inode *PROC_I(const struct inode *inode)
{
- return list_entry(inode, struct proc_inode, vfs_inode);
+ return container_of(inode, struct proc_inode, vfs_inode);
}
static inline struct proc_dir_entry *PDE(const struct inode *inode)
static inline struct qnx4_inode_info *qnx4_i(struct inode *inode)
{
- return list_entry(inode, struct qnx4_inode_info, vfs_inode);
+ return container_of(inode, struct qnx4_inode_info, vfs_inode);
}
static inline struct qnx4_inode_entry *qnx4_raw_inode(struct inode *inode)
static inline struct reiserfs_inode_info *REISERFS_I(struct inode *inode)
{
- return list_entry(inode, struct reiserfs_inode_info, vfs_inode);
+ return container_of(inode, struct reiserfs_inode_info, vfs_inode);
}
static inline struct reiserfs_sb_info *REISERFS_SB(const struct super_block *sb)
static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
{
- return list_entry(inode, struct shmem_inode_info, vfs_inode);
+ return container_of(inode, struct shmem_inode_info, vfs_inode);
}
#endif
static inline struct smb_inode_info *SMB_I(struct inode *inode)
{
- return list_entry(inode, struct smb_inode_info, vfs_inode);
+ return container_of(inode, struct smb_inode_info, vfs_inode);
}
/* macro names are short for word, double-word, long value (?) */
static inline struct ufs_inode_info *UFS_I(struct inode *inode)
{
- return list_entry(inode, struct ufs_inode_info, vfs_inode);
+ return container_of(inode, struct ufs_inode_info, vfs_inode);
}
#endif /* __KERNEL__ */
struct device dev; /* interface specific device info */
void *private_data;
};
+#define to_usb_interface(d) container_of(d, struct usb_interface, dev)
/* USB_DT_CONFIG: Configuration descriptor information.
*
int maxchild; /* Number of ports if hub */
struct usb_device *children[USB_MAXCHILDREN];
};
+#define to_usb_device(d) container_of(d, struct usb_device, dev)
extern struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *);
extern struct usb_device *usb_get_dev(struct usb_device *dev);
static void sock_destroy_inode(struct inode *inode)
{
kmem_cache_free(sock_inode_cachep,
- list_entry(inode, struct socket_alloc, vfs_inode));
+ container_of(inode, struct socket_alloc, vfs_inode));
}
static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)