Whamcloud - gitweb
LU-13228 clio: mmap write when overquota 92/38292/2
authorAlexander Zarochentsev <c17826@cray.com>
Fri, 20 Dec 2019 23:19:44 +0000 (02:19 +0300)
committerOleg Drokin <green@whamcloud.com>
Mon, 11 May 2020 23:00:41 +0000 (23:00 +0000)
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 <c17826@cray.com>
Change-Id: I29d5901fa5078b5cfca40391a02531cf27efce93
Reviewed-on: https://review.whamcloud.com/38292
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Wang Shilong <wshilong@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/cl_object.h
lustre/llite/vvp_internal.h
lustre/llite/vvp_io.c
lustre/lov/lov_io.c
lustre/obdclass/cl_io.c
lustre/osc/osc_cache.c
lustre/tests/sanity-quota.sh

index 1011226..4192161 100644 (file)
@@ -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.
         */
index 128e5ac..0fb9b51 100644 (file)
@@ -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;
index 5a08d5d..7dba79e 100644 (file)
@@ -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);
+                       }
                }
        }
 
index dbb627a..8900e79 100644 (file)
@@ -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);
 }
 
index d261a3f..181ef89 100644 (file)
@@ -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);
 
index 0e89a26..a4bb3c8 100644 (file)
@@ -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;
        }
index 0b0e4ad..4e9f7f1 100755 (executable)
@@ -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