If an osp_object is created by multiple threads at the same time,
lu_object_find_at() could allocate an osp_object without calling
osp_object_init(). Before hash inserting of the object, it finds another
object has been created and inserted by another thread, it will free
the uninitialized osp_object, and osp_object_free() will access
an uninitialized list_head (opo_xattr_list).
Initializes osp_object fields in osp_object_alloc() to avoid this.
Call trace:
lu_object_free.isra.30+0xf2/0x170 [obdclass]
lu_object_find_at+0x496/0x930 [obdclass]
lod_initialize_objects+0x3e4/0xba0 [lod]
lod_parse_striping+0x693/0xc20 [lod]
lod_striping_load+0x2b2/0x660 [lod]
lod_declare_destroy+0x12b/0x600 [lod]
mdd_declare_finish_unlink+0x91/0x210 [mdd]
mdd_unlink+0x48f/0xab0 [mdd]
mdt_reint_unlink+0xc32/0x1550 [mdt]
mdt_reint_rec+0x83/0x210 [mdt]
mdt_reint_internal+0x6e1/0xb00 [mdt]
mdt_reint+0x67/0x140 [mdt]
tgt_request_handle+0xaee/0x15f0 [ptlrpc]
ptlrpc_server_handle_request+0x24b/0xab0 [ptlrpc]
ptlrpc_main+0xb34/0x1470 [ptlrpc]
kthread+0xd1/0xe0
Lustre-commit: TBD (from
20dde5a8d428b3f9bf2d0421b333a09545be1c65)
Lustre-change: https://review.whamcloud.com/45442
Fixes:
226fd401f9d ("LU-7660 dne: support fs default stripe")
Signed-off-by: Bobi Jam <bobijam@whamcloud.com>
Change-Id: Ib86aca5b41e94a1758f177655ea3a0f680335e0f
Reviewed-on: https://review.whamcloud.com/46094
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Bobi Jam <bobijam@hotmail.com>
Reviewed-by: John L. Hammond <jhammond@whamcloud.com>
const struct lu_object_header *hdr,
struct lu_device *d)
{
- struct lu_object_header *h = NULL;
- struct osp_object *o;
- struct lu_object *l;
+ struct osp_object *o;
OBD_SLAB_ALLOC_PTR_GFP(o, osp_object_kmem, GFP_NOFS);
if (o != NULL) {
- l = &o->opo_obj.do_lu;
+ struct lu_object *l = &o->opo_obj.do_lu;
/* If hdr is NULL, it means the object is not built
* from the top dev(MDT/OST), usually it happens when
* building striped object, like data object on MDT or
* striped object for directory */
if (hdr == NULL) {
- h = &o->opo_header;
+ struct lu_object_header *h = &o->opo_header;
+
lu_object_header_init(h);
dt_object_init(&o->opo_obj, h, d);
lu_object_add_top(h, l);
} else {
- dt_object_init(&o->opo_obj, h, d);
+ dt_object_init(&o->opo_obj, NULL, d);
}
l->lo_ops = &osp_lu_obj_ops;
+ init_rwsem(&o->opo_sem);
+ INIT_LIST_HEAD(&o->opo_xattr_list);
+ INIT_LIST_HEAD(&o->opo_invalidate_cb_list);
+ spin_lock_init(&o->opo_lock);
+ init_rwsem(&o->opo_invalidate_sem);
+
return l;
- } else {
- return NULL;
}
+
+ return NULL;
}
/**
int rc = 0;
ENTRY;
- spin_lock_init(&po->opo_lock);
o->lo_header->loh_attr |= LOHA_REMOTE;
- INIT_LIST_HEAD(&po->opo_xattr_list);
- INIT_LIST_HEAD(&po->opo_invalidate_cb_list);
- init_rwsem(&po->opo_invalidate_sem);
if (is_ost_obj(o)) {
po->opo_obj.do_ops = &osp_obj_ops;
rc = 0;
}
}
- init_rwsem(&po->opo_sem);
}
RETURN(rc);
}