int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data);
int libcfs_ioctl(unsigned long cmd, void __user *arg);
-/* container_of depends on "likely" which is defined in libcfs_private.h */
-static inline void *__container_of(void *ptr, unsigned long shift)
-{
- if (IS_ERR_OR_NULL(ptr))
- return ptr;
- return (char *)ptr - shift;
-}
-
-#define container_of0(ptr, type, member) \
- ((type *)__container_of((void *)(ptr), offsetof(type, member)))
-
#define _LIBCFS_H
extern struct miscdevice libcfs_dev;
static inline struct cl_device *lu2cl_dev(const struct lu_device *d)
{
LASSERT(!d || IS_ERR(d) || lu_device_is_cl(d));
- return container_of0(d, struct cl_device, cd_lu_dev);
+ return container_of_safe(d, struct cl_device, cd_lu_dev);
}
static inline struct lu_device *cl2lu_dev(struct cl_device *d)
static inline struct cl_object *lu2cl(const struct lu_object *o)
{
LASSERT(!o || IS_ERR(o) || lu_device_is_cl(o->lo_dev));
- return container_of0(o, struct cl_object, co_lu);
+ return container_of_safe(o, struct cl_object, co_lu);
}
static inline const struct cl_object_conf *
lu2cl_conf(const struct lu_object_conf *conf)
{
- return container_of0(conf, struct cl_object_conf, coc_lu);
+ return container_of_safe(conf, struct cl_object_conf, coc_lu);
}
static inline struct cl_object *cl_object_next(const struct cl_object *obj)
static inline struct cl_device *cl_object_device(const struct cl_object *o)
{
LASSERT(!o || IS_ERR(o) || lu_device_is_cl(o->co_lu.lo_dev));
- return container_of0(o->co_lu.lo_dev, struct cl_device, cd_lu_dev);
+ return container_of_safe(o->co_lu.lo_dev, struct cl_device, cd_lu_dev);
}
static inline struct cl_object_header *luh2coh(const struct lu_object_header *h)
{
- return container_of0(h, struct cl_object_header, coh_lu);
+ return container_of_safe(h, struct cl_object_header, coh_lu);
}
static inline struct cl_site *cl_object_site(const struct cl_object *obj)
static inline struct lu_object *lu_object_top(struct lu_object_header *h)
{
LASSERT(!list_empty(&h->loh_layers));
- return container_of0(h->loh_layers.next, struct lu_object, lo_linkage);
+ return list_first_entry(&h->loh_layers, struct lu_object, lo_linkage);
}
/**
* Next sub-object in the layering
*/
-static inline struct lu_object *lu_object_next(const struct lu_object *o)
+static inline const struct lu_object *lu_object_next(const struct lu_object *o)
{
- return container_of0(o->lo_linkage.next, struct lu_object, lo_linkage);
+ return list_next_entry(o, lo_linkage);
}
/**
/* It is hack to access lde_fid for comparison with lgd_fid.
* So the input 'name' must be part of the 'lu_dirent'.
*/
- struct lu_dirent *lde = container_of0(name, struct lu_dirent, lde_name);
+ struct lu_dirent *lde = container_of((void*)name, struct lu_dirent, lde_name);
struct ll_getname_data *lgd =
container_of(ctx, struct ll_getname_data, ctx);
struct lu_fid fid;
static inline struct vvp_device *lu2vvp_dev(const struct lu_device *d)
{
- return container_of0(d, struct vvp_device, vdv_cl.cd_lu_dev);
+ return container_of_safe(d, struct vvp_device, vdv_cl.cd_lu_dev);
}
static inline struct vvp_device *cl2vvp_dev(const struct cl_device *d)
{
- return container_of0(d, struct vvp_device, vdv_cl);
+ return container_of_safe(d, struct vvp_device, vdv_cl);
}
static inline struct vvp_object *cl2vvp(const struct cl_object *obj)
{
- return container_of0(obj, struct vvp_object, vob_cl);
+ return container_of_safe(obj, struct vvp_object, vob_cl);
}
static inline struct vvp_object *lu2vvp(const struct lu_object *obj)
{
- return container_of0(obj, struct vvp_object, vob_cl.co_lu);
+ return container_of_safe(obj, struct vvp_object, vob_cl.co_lu);
}
static inline struct inode *vvp_object_inode(const struct cl_object *obj)
static inline struct obd_device *lmv2obd_dev(struct lmv_obd *lmv)
{
- return container_of0(lmv, struct obd_device, u.lmv);
+ return container_of_safe(lmv, struct obd_device, u.lmv);
}
static inline struct lmv_tgt_desc *
static inline struct lov_device *lu2lov_dev(const struct lu_device *d)
{
LINVRNT(d->ld_type == &lov_device_type);
- return container_of0(d, struct lov_device, ld_cl.cd_lu_dev);
+ return container_of(d, struct lov_device, ld_cl.cd_lu_dev);
}
static inline struct cl_device *lovsub2cl_dev(struct lovsub_device *lovsub)
static inline struct lovsub_device *lu2lovsub_dev(const struct lu_device *d)
{
LINVRNT(d->ld_type == &lovsub_device_type);
- return container_of0(d, struct lovsub_device, acid_cl.cd_lu_dev);
+ return container_of(d, struct lovsub_device, acid_cl.cd_lu_dev);
}
static inline struct lovsub_device *cl2lovsub_dev(const struct cl_device *d)
{
LINVRNT(d->cd_lu_dev.ld_type == &lovsub_device_type);
- return container_of0(d, struct lovsub_device, acid_cl);
+ return container_of(d, struct lovsub_device, acid_cl);
}
static inline struct lu_object *lov2lu(struct lov_object *lov)
static inline struct lov_object *lu2lov(const struct lu_object *obj)
{
LINVRNT(lov_is_object(obj));
- return container_of0(obj, struct lov_object, lo_cl.co_lu);
+ return container_of(obj, struct lov_object, lo_cl.co_lu);
}
static inline struct lov_object *cl2lov(const struct cl_object *obj)
{
LINVRNT(lov_is_object(&obj->co_lu));
- return container_of0(obj, struct lov_object, lo_cl);
+ return container_of(obj, struct lov_object, lo_cl);
}
static inline struct lu_object *lovsub2lu(struct lovsub_object *los)
static inline struct lovsub_object *cl2lovsub(const struct cl_object *obj)
{
LINVRNT(lovsub_is_object(&obj->co_lu));
- return container_of0(obj, struct lovsub_object, lso_cl);
+ return container_of(obj, struct lovsub_object, lso_cl);
}
static inline struct lovsub_object *lu2lovsub(const struct lu_object *obj)
{
LINVRNT(lovsub_is_object(obj));
- return container_of0(obj, struct lovsub_object, lso_cl.co_lu);
+ return container_of(obj, struct lovsub_object, lso_cl.co_lu);
}
static inline struct lovsub_lock *
static inline struct lov_page *cl2lov_page(const struct cl_page_slice *slice)
{
LINVRNT(lov_is_object(&slice->cpl_obj->co_lu));
- return container_of0(slice, struct lov_page, lps_cl);
+ return container_of(slice, struct lov_page, lps_cl);
}
static inline struct lovsub_page *
cl2lovsub_page(const struct cl_page_slice *slice)
{
LINVRNT(lovsub_is_object(&slice->cpl_obj->co_lu));
- return container_of0(slice, struct lovsub_page, lsb_cl);
+ return container_of(slice, struct lovsub_page, lsb_cl);
}
static inline struct lov_io *cl2lov_io(const struct lu_env *env,
static inline struct obd_device *lov2obd(const struct lov_obd *lov)
{
- return container_of0(lov, struct obd_device, u.lov);
+ return container_of_safe(lov, struct obd_device, u.lov);
}
#endif
* lives as long as possible and ->loo_object_free() methods
* can look at its contents.
*/
- o = container_of0(splice.prev, struct lu_object, lo_linkage);
+ o = container_of(splice.prev, struct lu_object, lo_linkage);
list_del_init(&o->lo_linkage);
o->lo_ops->loo_object_free(env, o);
}
* races due to the reasons described in lu_object_put().
*/
while (!list_empty(&dispose)) {
- h = container_of0(dispose.next,
- struct lu_object_header, loh_lru);
+ h = container_of(dispose.next,
+ struct lu_object_header, loh_lru);
list_del_init(&h->loh_lru);
lu_object_free(env, lu_object_top(h));
lprocfs_counter_incr(s->ls_stats, LU_SS_LRU_PURGED);
return ERR_PTR(-ENOENT);
}
- h = container_of0(hnode, struct lu_object_header, loh_hash);
+ h = container_of(hnode, struct lu_object_header, loh_hash);
if (likely(!lu_object_is_dying(h))) {
cfs_hash_get(s->ls_obj_hash, hnode);
lprocfs_counter_incr(s->ls_stats, LU_SS_CACHE_HIT);
*/
static inline struct echo_device *cl2echo_dev(const struct cl_device *dev)
{
- return container_of0(dev, struct echo_device, ed_cl);
+ return container_of_safe(dev, struct echo_device, ed_cl);
}
static inline struct cl_device *echo_dev2cl(struct echo_device *d)
static inline struct osc_device *lu2osc_dev(const struct lu_device *d)
{
LINVRNT(d->ld_type == &osc_device_type);
- return container_of0(d, struct osc_device, od_cl.cd_lu_dev);
+ return container_of(d, struct osc_device, od_cl.cd_lu_dev);
}
static inline struct obd_export *osc_export(const struct osc_object *obj)
static inline struct osc_object *cl2osc(const struct cl_object *obj)
{
LINVRNT(osc_is_object(&obj->co_lu));
- return container_of0(obj, struct osc_object, oo_cl);
+ return container_of(obj, struct osc_object, oo_cl);
}
static inline struct cl_object *osc2cl(const struct osc_object *obj)
static inline struct osc_page *cl2osc_page(const struct cl_page_slice *slice)
{
LINVRNT(osc_is_object(&slice->cpl_obj->co_lu));
- return container_of0(slice, struct osc_page, ops_cl);
+ return container_of(slice, struct osc_page, ops_cl);
}
static inline struct osc_page *oap2osc(struct osc_async_page *oap)
{
- return container_of0(oap, struct osc_page, ops_oap);
+ return container_of_safe(oap, struct osc_page, ops_oap);
}
static inline pgoff_t osc_index(struct osc_page *opg)
static inline struct osc_lock *cl2osc_lock(const struct cl_lock_slice *slice)
{
LINVRNT(osc_is_object(&slice->cls_obj->co_lu));
- return container_of0(slice, struct osc_lock, ols_cl);
+ return container_of(slice, struct osc_lock, ols_cl);
}
static inline struct osc_lock *osc_lock_at(const struct cl_lock *lock)
static inline struct osc_device *obd2osc_dev(const struct obd_device *d)
{
- return container_of0(d->obd_lu_dev, struct osc_device, od_cl.cd_lu_dev);
+ return container_of_safe(d->obd_lu_dev, struct osc_device, od_cl.cd_lu_dev);
}
extern struct lu_kmem_descr osc_caches[];
static struct osc_io *cl2osc_io(const struct lu_env *env,
const struct cl_io_slice *slice)
{
- struct osc_io *oio = container_of0(slice, struct osc_io, oi_cl);
+ struct osc_io *oio = container_of_safe(slice, struct osc_io, oi_cl);
LINVRNT(oio == osc_env_io(env));
return oio;
static struct osc_object *lu2osc(const struct lu_object *obj)
{
LINVRNT(osc_is_object(obj));
- return container_of0(obj, struct osc_object, oo_cl.co_lu);
+ return container_of(obj, struct osc_object, oo_cl.co_lu);
}
/*****************************************************************************
"pointer type mismatch in container_of()"); \
((type *)(__mptr - offsetof(type, member))); })
+/**
+ * container_of_safe - 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.
+ *
+ * If IS_ERR_OR_NULL(ptr), ptr is returned unchanged.
+ */
+#define container_of_safe(ptr, type, member) ({ \
+ void *__mptr = (void *)(ptr); \
+ BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
+ !__same_type(*(ptr), void), \
+ "pointer type mismatch in container_of()"); \
+ IS_ERR_OR_NULL(ptr) ? ERR_CAST(ptr) : \
+ ((type *)(__mptr - offsetof(type, member))); })
+
/* Rebuild everything on CONFIG_FTRACE_MCOUNT_RECORD */
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
# define REBUILD_DUE_TO_FTRACE_MCOUNT_RECORD