From: Alexander Zarochentsev Date: Fri, 20 Dec 2019 23:19:44 +0000 (+0300) Subject: LU-13228 clio: mmap write when overquota X-Git-Tag: 2.12.5-RC1~27 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;ds=sidebyside;h=refs%2Fchanges%2F92%2F38292%2F2;p=fs%2Flustre-release.git LU-13228 clio: mmap write when overquota Flagging client by overquota flag should not cause mmap write access to sigbus the app. Lustre-change: https://review.whamcloud.com/37495 Lustre-commit: b651089f859e8269af7272b91f5e60aa25f24226 Cray-bug-id: LUS-8221 Signed-off-by: Alexander Zarochentsev Change-Id: I29d5901fa5078b5cfca40391a02531cf27efce93 Reviewed-on: https://review.whamcloud.com/38292 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Wang Shilong Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/cl_object.h b/lustre/include/cl_object.h index 1011226..4192161 100644 --- a/lustre/include/cl_object.h +++ b/lustre/include/cl_object.h @@ -1906,6 +1906,10 @@ struct cl_io { */ ci_tried_all_mirrors:1; /** + * Bypass quota check + */ + unsigned ci_noquota:1; + /** * How many times the read has retried before this one. * Set by the top level and consumed by the LOV. */ diff --git a/lustre/llite/vvp_internal.h b/lustre/llite/vvp_internal.h index 128e5ac..0fb9b51 100644 --- a/lustre/llite/vvp_internal.h +++ b/lustre/llite/vvp_internal.h @@ -93,6 +93,7 @@ struct vvp_io { * check that flags are from filemap_fault */ bool ft_flags_valid; + struct cl_page_list ft_queue; } fault; struct { struct pipe_inode_info *vui_pipe; diff --git a/lustre/llite/vvp_io.c b/lustre/llite/vvp_io.c index 5a08d5d..7dba79e 100644 --- a/lustre/llite/vvp_io.c +++ b/lustre/llite/vvp_io.c @@ -1314,7 +1314,7 @@ static int vvp_io_fault_start(const struct lu_env *env, if (fio->ft_mkwrite) { wait_on_page_writeback(vmpage); if (!PageDirty(vmpage)) { - struct cl_page_list *plist = &io->ci_queue.c2_qin; + struct cl_page_list *plist = &vio->u.fault.ft_queue; struct vvp_page *vpg = cl_object_page_slice(obj, page); int to = PAGE_SIZE; @@ -1326,13 +1326,34 @@ static int vvp_io_fault_start(const struct lu_env *env, /* size fixup */ if (last_index == vvp_index(vpg)) - to = size & ~PAGE_MASK; + to = ((size - 1) & ~PAGE_MASK) + 1; /* Do not set Dirty bit here so that in case IO is * started before the page is really made dirty, we * still have chance to detect it. */ result = cl_io_commit_async(env, io, plist, 0, to, mkwrite_commit_callback); + /* Have overquota flag, trying sync write to check + * whether indeed out of quota */ + if (result == -EDQUOT) { + cl_page_get(page); + result = vvp_io_commit_sync(env, io, + plist, 0, to); + if (result >= 0) { + io->ci_noquota = 1; + cl_page_own(env, io, page); + cl_page_list_add(plist, page); + lu_ref_add(&page->cp_reference, + "cl_io", io); + result = cl_io_commit_async(env, io, + plist, 0, to, + mkwrite_commit_callback); + io->ci_noquota = 0; + } else { + cl_page_put(env, page); + } + } + LASSERT(cl_page_is_owned(page, io)); cl_page_list_fini(env, plist); @@ -1347,8 +1368,9 @@ static int vvp_io_fault_start(const struct lu_env *env, if (result == -EDQUOT) result = -ENOSPC; GOTO(out, result); - } else + } else { cl_page_disown(env, io, page); + } } } diff --git a/lustre/lov/lov_io.c b/lustre/lov/lov_io.c index dbb627a..8900e79 100644 --- a/lustre/lov/lov_io.c +++ b/lustre/lov/lov_io.c @@ -183,6 +183,8 @@ struct lov_io_sub *lov_sub_get(const struct lu_env *env, out: if (rc < 0) sub = ERR_PTR(rc); + else + sub->sub_io.ci_noquota = lio->lis_cl.cis_io->ci_noquota; RETURN(sub); } diff --git a/lustre/obdclass/cl_io.c b/lustre/obdclass/cl_io.c index d261a3f..181ef89 100644 --- a/lustre/obdclass/cl_io.c +++ b/lustre/obdclass/cl_io.c @@ -681,6 +681,7 @@ int cl_io_submit_sync(const struct lu_env *env, struct cl_io *io, struct cl_sync_io *anchor = &cl_env_info(env)->clt_anchor; struct cl_page *pg; int rc; + ENTRY; cl_page_list_for_each(pg, &queue->c2_qin) { LASSERT(pg->cp_sync_io == NULL); @@ -709,7 +710,7 @@ int cl_io_submit_sync(const struct lu_env *env, struct cl_io *io, cl_page_list_for_each(pg, &queue->c2_qin) pg->cp_sync_io = NULL; } - return rc; + RETURN(rc); } EXPORT_SYMBOL(cl_io_submit_sync); diff --git a/lustre/osc/osc_cache.c b/lustre/osc/osc_cache.c index 0e89a26..a4bb3c8 100644 --- a/lustre/osc/osc_cache.c +++ b/lustre/osc/osc_cache.c @@ -2405,7 +2405,7 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, /* Set the OBD_BRW_SRVLOCK before the page is queued. */ brw_flags |= ops->ops_srvlock ? OBD_BRW_SRVLOCK : 0; - if (oio->oi_cap_sys_resource) { + if (oio->oi_cap_sys_resource || io->ci_noquota) { brw_flags |= OBD_BRW_NOQUOTA; cmd |= OBD_BRW_NOQUOTA; } diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index 0b0e4ad..4e9f7f1 100755 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -797,6 +797,11 @@ test_block_soft() { OFFSET=$((OFFSET + 1024)) # make sure we don't write to same block cancel_lru_locks osc + echo "mmap write when over soft limit" + $RUNAS $MULTIOP $TESTFILE.mmap OT40960SMW || + quota_error a $TSTUSR "mmap write failure, but expect success" + cancel_lru_locks osc + $SHOW_QUOTA_USER $SHOW_QUOTA_GROUP $SHOW_QUOTA_PROJID