From: James Simmons Date: Wed, 2 Jan 2019 17:13:50 +0000 (-0500) Subject: LU-11828 clio: fix incorrect invariant in cl_io_iter_fini() X-Git-Tag: 2.12.51~12 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=8160b9bdf16cc8ed887216b0a9a83932b86d5705 LU-11828 clio: fix incorrect invariant in cl_io_iter_fini() It was discovered during PFL testing that if LINVRNT() is enabled that cl_io_iter_fini() will crash with the following backtrace: kernel: LustreError: 16009:0:(cl_io.c:439:cl_io_iter_fini()) ASSERTION( io->ci_state == CIS_UNLOCKED ) failed kernel: cl_io_iter_fini+0x10c/0x110 [obdclass] kernel: cl_io_loop+0x46/0x220 [obdclass] kernel: cl_setattr_ost+0x1ed/0x2a0 [lustre] kernel: ll_setattr_raw+0x7b0/0x9a0 [lustre] kernel: notify_change+0x1dc/0x430 kernel: do_truncate+0x72/0xc0 kernel: do_sys_ftruncate+0xf5/0x160 This is due to the incorrect assumption that the ci_state will always be CIS_UNLOCKED, but by looking at the behavior of cl_io_loop() it can be seen that is not the case with PFL. We do want to make sure the IO state is not in the middle of some other action (up to CIS_IT_STARTED or CIS_IO_FINISHED or later) when cl_io_iter_fini() is called. Change-Id: I41c4d3ae5618d0e138f850e63edfd2dc6d4df19a Signed-off-by: James Simmons Reviewed-on: https://review.whamcloud.com/33915 Reviewed-by: Andreas Dilger Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Bobi Jam Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin --- diff --git a/lustre/obdclass/cl_io.c b/lustre/obdclass/cl_io.c index d261a3f..9d777dc 100644 --- a/lustre/obdclass/cl_io.c +++ b/lustre/obdclass/cl_io.c @@ -443,19 +443,20 @@ EXPORT_SYMBOL(cl_io_iter_init); */ void cl_io_iter_fini(const struct lu_env *env, struct cl_io *io) { - const struct cl_io_slice *scan; + const struct cl_io_slice *scan; - LINVRNT(cl_io_is_loopable(io)); - LINVRNT(io->ci_state == CIS_UNLOCKED); - LINVRNT(cl_io_invariant(io)); + LINVRNT(cl_io_is_loopable(io)); + LINVRNT(io->ci_state <= CIS_IT_STARTED || + io->ci_state > CIS_IO_FINISHED); + LINVRNT(cl_io_invariant(io)); - ENTRY; + ENTRY; list_for_each_entry_reverse(scan, &io->ci_layers, cis_linkage) { if (scan->cis_iop->op[io->ci_type].cio_iter_fini != NULL) scan->cis_iop->op[io->ci_type].cio_iter_fini(env, scan); } - io->ci_state = CIS_IT_ENDED; - EXIT; + io->ci_state = CIS_IT_ENDED; + EXIT; } EXPORT_SYMBOL(cl_io_iter_fini);