]> git.hungrycats.org Git - linux/commitdiff
[PATCH] type safe(r) list_entry repacement: container_of
authorNeil Brown <neilb@cse.unsw.edu.au>
Wed, 24 Jul 2002 03:40:09 +0000 (20:40 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Wed, 24 Jul 2002 03:40:09 +0000 (20:40 -0700)
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.

28 files changed:
drivers/pci/pci-driver.c
drivers/pci/proc.c
drivers/scsi/scsi.h
drivers/scsi/scsi_scan.c
drivers/usb/core/usb.c
fs/driverfs/inode.c
fs/ext2/ext2.h
include/linux/adfs_fs.h
include/linux/device.h
include/linux/efs_fs.h
include/linux/ext3_fs.h
include/linux/fs.h
include/linux/hfs_fs.h
include/linux/iso_fs.h
include/linux/kernel.h
include/linux/list.h
include/linux/msdos_fs.h
include/linux/ncp_fs.h
include/linux/nfs_fs.h
include/linux/pci.h
include/linux/proc_fs.h
include/linux/qnx4_fs.h
include/linux/reiserfs_fs.h
include/linux/shmem_fs.h
include/linux/smb_fs.h
include/linux/ufs_fs.h
include/linux/usb.h
net/socket.c

index db4cdb8e3ad4b708b7a5edd89cddf13486de409a..3ad23175d6a51633b40b3a18a806904df810044d 100644 (file)
@@ -41,8 +41,8 @@ static int pci_device_probe(struct device * dev)
        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;
@@ -60,7 +60,7 @@ static int pci_device_probe(struct device * dev)
 
 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) {
@@ -73,7 +73,7 @@ static int pci_device_remove(struct device * dev)
 
 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) {
@@ -87,7 +87,7 @@ static int pci_device_suspend(struct device * dev, u32 state, u32 level)
 
 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)
@@ -175,8 +175,8 @@ pci_dev_driver(const struct pci_dev *dev)
  */
 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) 
index 35b28e319384ea823504bbab6040952eced1f760..0359172c3d3751873acd947e7bae193e8def8740 100644 (file)
@@ -374,7 +374,7 @@ static struct proc_dir_entry *proc_bus_pci_dir;
 /* 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);
 }
 
@@ -386,7 +386,7 @@ static struct driver_file_entry pci_irq_entry = {
 
 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;
 
index 6170d763e2aae0202ce2091a6fc7d5f5fa9d0033..1981e23e7ea4d511776dbd5417a2aa63582948f7 100644 (file)
@@ -627,6 +627,8 @@ struct scsi_device {
        int allow_revalidate;
        struct device sdev_driverfs_dev;
 };
+#define        to_scsi_device(d)       \
+       container_of(d, struct scsi_device, sdev_driverfs_dev)
 
 
 /*
index 3a2b1fcbf760f3c8f9cb07b971e60899436765bc..40beb9ad51ff5b518c2061c5a1ddae432fb25391 100644 (file)
@@ -293,8 +293,7 @@ static int scsilun_to_int(ScsiLun *scsilun_pnt)
 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))
index ed2e03089e5713e3a9e7efc8336c6c22974ec341..914abb2f3c3ee43314bdcee13e76b28675044e84 100644 (file)
@@ -832,7 +832,7 @@ show_config (struct device *dev, char *buf, size_t count, loff_t off)
 
        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 = {
@@ -851,7 +851,7 @@ show_altsetting (struct device *dev, char *buf, size_t count, loff_t off)
 
        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 = {
@@ -868,7 +868,7 @@ static ssize_t show_product (struct device *dev, char *buf, size_t count, loff_t
 
        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';
@@ -890,7 +890,7 @@ show_manufacturer (struct device *dev, char *buf, size_t count, loff_t off)
 
        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';
@@ -912,7 +912,7 @@ show_serial (struct device *dev, char *buf, size_t count, loff_t off)
 
        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';
index e6a098cdd04be4372e9645a8b973eef0ff1099c2..99778778634452c1ffca95d6e0ace56b05c69cb8 100644 (file)
@@ -267,7 +267,7 @@ driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
        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)
@@ -328,7 +328,7 @@ driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *pp
        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)
@@ -394,7 +394,7 @@ static int driverfs_open_file(struct inode * inode, struct file * filp)
        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;
@@ -408,7 +408,7 @@ static int driverfs_release(struct inode * inode, struct file * filp)
        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;
 }
index 04fead0831eb639d74f5d876bbdae947124a391b..3d2431e6b91a4875e7e66332d723052376e42233 100644 (file)
@@ -34,7 +34,7 @@ struct ext2_inode_info {
 
 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 */
index bebb2a0c525485a8eb4496207ec5b16f6f02f78a..8241dab73109695778b6d405706fd851abbc4201 100644 (file)
@@ -68,7 +68,7 @@ static inline struct adfs_sb_info *ADFS_SB(struct super_block *sb)
 
 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
index 053572009fa16c1254fbabe2cf840ff6501ff6ef..a6d10931ae7f43ce76cf1da2ed81f074ca2afae2 100644 (file)
@@ -160,6 +160,8 @@ struct device {
        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)
 {
index 2ad894c6893dff613e05325487775978995140d4..8121f57b49477ad878ebacaa751984209ff4f659 100644 (file)
@@ -41,7 +41,7 @@ static const char cprt[] = "EFS: "EFS_VERSION" - (c) 1999 Al Smith <Al.Smith@aes
 
 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)
index 5847e06c102088c5a4ff95c86c3fa9448f51e2fd..e05c9d984080a98e9bfdc110a1fe1708e07f89e1 100644 (file)
@@ -447,7 +447,7 @@ struct ext3_super_block {
 #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
index b58c1b43f734c8b04a0e1a5571beacb9c7357f3f..618bbd8efbd50107f802e7b939b3cc10e205655f 100644 (file)
@@ -412,12 +412,12 @@ struct socket_alloc {
 
 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 */
index c0acee5f5f4b71a943de5e75767fc8ce8026a8ee..308d27b2017a55907961901aa492c1ad0f605d3f 100644 (file)
@@ -322,7 +322,7 @@ extern void hfs_tolower(unsigned char *, int);
 
 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)
index 3520e22a2af884382800d5156b7900ba32b58840..17e9d20b7edbcb4161d1493c66d18618d664b776 100644 (file)
@@ -179,7 +179,7 @@ static inline struct isofs_sb_info *ISOFS_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)
index 2204760615d8059ee7ed08e572dafcb6500a6ce3..9fe11d9b6dc44f7f88a5fd2f781dd3a42fbaab63 100644 (file)
@@ -150,6 +150,19 @@ extern const char *print_tainted(void);
 #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
index 3e70aa03ac112829cc96f322e5ac17663cdd6fb6..80e2739cedc831844bf82e6b7ee91aa65ad5e752 100644 (file)
@@ -184,7 +184,7 @@ static inline void list_splice_init(list_t *list, list_t *head)
  * @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
index 5868e91b16ecc12d3b891cd5e91430fa0d10cbfb..75d86d869771a0898a8af14eb7ee1870dc84d761 100644 (file)
@@ -198,7 +198,7 @@ static inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb)
 
 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 {
index 6597dd71259b4f05e8d9f67608df32d346277506..74206155eb42a1af42c9136cadf12b1104243d83 100644 (file)
@@ -199,7 +199,7 @@ static inline struct ncp_server *NCP_SBP(struct super_block *sb)
 #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
index 64c3b5ef2d8808c722473a96f831fe531217dda6..f45c35f298e66e2cf2ce2eec7aa72c6acadee767 100644 (file)
@@ -176,7 +176,7 @@ struct nfs_inode {
 
 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))
 
index 7cbc68fdb743bbceb942913229877d5d8778f15a..5099b9f382e09c4bd6fb213d2da59d2d3500fbe9 100644 (file)
@@ -392,6 +392,7 @@ struct pci_dev {
 
 #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:
@@ -491,6 +492,8 @@ struct pci_driver {
        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
index 4490c4d3a5deadb7cb18105d88929d2743bb01a7..aa67525a617d949f87db67f10ee37a6d5c13f26d 100644 (file)
@@ -219,7 +219,7 @@ struct proc_inode {
 
 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)
index a84aa2091c2b5adf7671a634b604b7b47db954cf..14a8c6ff743ce09bc159fc5d4e3e9e0c90a5a127 100644 (file)
@@ -140,7 +140,7 @@ static inline struct qnx4_sb_info *qnx4_sb(struct super_block *sb)
 
 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)
index 4d33fabe04a6cec16c9aa681c260fe95f48e3fd2..9ddf1e2f0a20405e7d4691829cb561cbfafc793d 100644 (file)
@@ -288,7 +288,7 @@ struct unfm_nodeinfo {
 
 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)
index 46b6b67b0906be55cea0ab49d81b7c905521e7d3..d4e0ab279388248441bc196f92e1148a3c58cd62 100644 (file)
@@ -31,7 +31,7 @@ struct shmem_sb_info {
 
 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
index e049feae8dea46d10bd707fc93dc730722535ad6..be0f419928bcbe34e75cb14f6e7d08047542af98 100644 (file)
@@ -38,7 +38,7 @@ static inline struct smb_sb_info *SMB_SB(struct super_block *sb)
 
 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 (?) */
index faccf5ad22d5ab43e17cd62166af6e1dbc8a8a7a..7ba4e3e66e4ee178cd1e709cea68ecec4aa81cbe 100644 (file)
@@ -784,7 +784,7 @@ extern void ufs_truncate (struct inode *);
 
 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__ */
index 92496658baf5d0ceccc53826536a2e2d7a1a6e0c..7d89cfa455921b6d08f64bcda88ea41488dd0d0a 100644 (file)
@@ -257,6 +257,7 @@ struct usb_interface {
        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.
  *
@@ -422,6 +423,7 @@ struct usb_device {
        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);
index 798eeab2f47c0139416cfe6408911bede0f6a4a9..680b617772f34c8592139dd7731c2f9045604db9 100644 (file)
@@ -288,7 +288,7 @@ static struct inode *sock_alloc_inode(struct super_block *sb)
 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)