* that the slab was corrupted
*/
unsigned frozen:1;
+#ifdef CONFIG_64BIT
+ /*
+ * Some optimizations use free bits in 'counters' field
+ * to save memory. In case ->stride field is not available,
+ * such optimizations are disabled.
+ */
+ unsigned short stride;
+#endif
};
};
};
return obj_exts & ~OBJEXTS_FLAGS_MASK;
}
+#ifdef CONFIG_64BIT
+static inline void slab_set_stride(struct slab *slab, unsigned short stride)
+{
+ slab->stride = stride;
+}
+static inline unsigned short slab_get_stride(struct slab *slab)
+{
+ return slab->stride;
+}
+#else
+static inline void slab_set_stride(struct slab *slab, unsigned short stride)
+{
+ VM_WARN_ON_ONCE(stride != sizeof(struct slabobj_ext));
+}
+static inline unsigned short slab_get_stride(struct slab *slab)
+{
+ return sizeof(struct slabobj_ext);
+}
+#endif
+
/*
* slab_obj_ext - get the pointer to the slab object extension metadata
* associated with an object in a slab.
unsigned long obj_exts,
unsigned int index)
{
- struct slabobj_ext *obj_ext;
-
VM_WARN_ON_ONCE(obj_exts != slab_obj_exts(slab));
- obj_ext = (struct slabobj_ext *)obj_exts;
- return &obj_ext[index];
+ return (struct slabobj_ext *)(obj_exts + slab_get_stride(slab) * index);
}
int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s,
return NULL;
}
+static inline void slab_set_stride(struct slab *slab, unsigned int stride) { }
+static inline unsigned int slab_get_stride(struct slab *slab) { return 0; }
+
+
#endif /* CONFIG_SLAB_OBJ_EXT */
static inline enum node_stat_item cache_vmstat_idx(struct kmem_cache *s)
retry:
old_exts = READ_ONCE(slab->obj_exts);
handle_failed_objexts_alloc(old_exts, vec, objects);
+ slab_set_stride(slab, sizeof(struct slabobj_ext));
+
if (new_slab) {
/*
* If the slab is brand new and nobody can yet access its