From: Dan Carpenter <dan.carpenter@oracle.com>
To: tiantao6@hisilicon.com
Cc: linux-mm@kvack.org
Subject: [bug report] mm/zswap: add the flag can_sleep_mapped
Date: Fri, 22 Jan 2021 03:08:54 -0800 (PST) [thread overview]
Message-ID: <YAqyRoMNog+6syTS@mwanda> (raw)
Hello Tian Tao,
The patch 6753c561f653: "mm/zswap: add the flag can_sleep_mapped"
from Jan 20, 2021, leads to the following static checker warning:
mm/zswap.c:947 zswap_writeback_entry()
error: potentially dereferencing uninitialized 'entry'.
mm/zswap.c
927 static int zswap_writeback_entry(struct zpool *pool, unsigned long handle)
928 {
929 struct zswap_header *zhdr;
930 swp_entry_t swpentry;
931 struct zswap_tree *tree;
932 pgoff_t offset;
933 struct zswap_entry *entry;
934 struct page *page;
935 struct scatterlist input, output;
936 struct crypto_acomp_ctx *acomp_ctx;
937
938 u8 *src, *tmp;
939 unsigned int dlen;
940 int ret;
941 struct writeback_control wbc = {
942 .sync_mode = WB_SYNC_NONE,
943 };
944
945 if (!zpool_can_sleep_mapped(pool)) {
946
947 tmp = kmalloc(entry->length, GFP_ATOMIC);
^^^^^^^^^^^^^
"entry" uninitialized.
948 if (!tmp)
949 return -ENOMEM;
950 }
951
952 /* extract swpentry from data */
953 zhdr = zpool_map_handle(pool, handle, ZPOOL_MM_RO);
954 swpentry = zhdr->swpentry; /* here */
955 tree = zswap_trees[swp_type(swpentry)];
956 offset = swp_offset(swpentry);
957
958 /* find and ref zswap entry */
959 spin_lock(&tree->lock);
960 entry = zswap_entry_find_get(&tree->rbroot, offset);
961 if (!entry) {
962 /* entry was invalidated */
963 spin_unlock(&tree->lock);
964 zpool_unmap_handle(pool, handle);
965 return 0;
memory leak.
966 }
967 spin_unlock(&tree->lock);
968 BUG_ON(offset != entry->offset);
969
970 /* try to allocate swap cache page */
971 switch (zswap_get_swap_cache_page(swpentry, &page)) {
972 case ZSWAP_SWAPCACHE_FAIL: /* no memory or invalidate happened */
973 ret = -ENOMEM;
974 goto fail;
975
976 case ZSWAP_SWAPCACHE_EXIST:
977 /* page is already in the swap cache, ignore for now */
978 put_page(page);
979 ret = -EEXIST;
980 goto fail;
981
982 case ZSWAP_SWAPCACHE_NEW: /* page is locked */
983 /* decompress */
984 acomp_ctx = raw_cpu_ptr(entry->pool->acomp_ctx);
985
986 dlen = PAGE_SIZE;
987 src = (u8 *)zhdr + sizeof(struct zswap_header);
988
989 if (!zpool_can_sleep_mapped(pool)) {
990
991 memcpy(tmp, src, entry->length);
992 src = tmp;
993
994 zpool_unmap_handle(pool, handle);
Why not just do a "src = tmp = kmemdup(src, entry->length, GFP_ATOMIC);
right, here? That would avoid unnecessary allocations for the other
cases.
This path calls zpool_unmap_handle() and it frees the "tmp" buffer. The
other fail paths only free the "tmp" buffer but don't call
zpool_unmap_handle() so is that a leak?
995 }
996
997 mutex_lock(acomp_ctx->mutex);
998 sg_init_one(&input, src, entry->length);
999 sg_init_table(&output, 1);
1000 sg_set_page(&output, page, PAGE_SIZE, 0);
1001 acomp_request_set_params(acomp_ctx->req, &input, &output, entry->length, dlen);
1002 ret = crypto_wait_req(crypto_acomp_decompress(acomp_ctx->req), &acomp_ctx->wait);
1003 dlen = acomp_ctx->req->dlen;
1004 mutex_unlock(acomp_ctx->mutex);
1005
1006 BUG_ON(ret);
1007 BUG_ON(dlen != PAGE_SIZE);
1008
1009 /* page is up to date */
1010 SetPageUptodate(page);
1011 }
1012
1013 /* move it to the tail of the inactive list after end_writeback */
1014 SetPageReclaim(page);
1015
1016 /* start writeback */
1017 __swap_writepage(page, &wbc, end_swap_bio_write);
1018 put_page(page);
1019 zswap_written_back_pages++;
1020
1021 spin_lock(&tree->lock);
1022 /* drop local reference */
1023 zswap_entry_put(tree, entry);
1024
1025 /*
1026 * There are two possible situations for entry here:
1027 * (1) refcount is 1(normal case), entry is valid and on the tree
1028 * (2) refcount is 0, entry is freed and not on the tree
1029 * because invalidate happened during writeback
1030 * search the tree and free the entry if find entry
1031 */
1032 if (entry == zswap_rb_search(&tree->rbroot, offset))
1033 zswap_entry_put(tree, entry);
1034 spin_unlock(&tree->lock);
1035
1036 goto end;
1037
1038 /*
1039 * if we get here due to ZSWAP_SWAPCACHE_EXIST
1040 * a load may be happening concurrently.
1041 * it is safe and okay to not free the entry.
1042 * if we free the entry in the following put
1043 * it is also okay to return !0
1044 */
1045 fail:
1046 spin_lock(&tree->lock);
1047 zswap_entry_put(tree, entry);
1048 spin_unlock(&tree->lock);
1049
1050 end:
1051 if (zpool_can_sleep_mapped(pool))
1052 zpool_unmap_handle(pool, handle);
1053 else
1054 kfree(tmp);
1055
1056 return ret;
1057 }
regards,
dan carpenter
next reply other threads:[~2021-01-22 11:09 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-22 11:08 Dan Carpenter [this message]
-- strict thread matches above, loose matches on Subject: below --
2021-01-22 11:11 [bug report] mm/zswap: add the flag can_sleep_mapped Dan Carpenter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YAqyRoMNog+6syTS@mwanda \
--to=dan.carpenter@oracle.com \
--cc=linux-mm@kvack.org \
--cc=tiantao6@hisilicon.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.