Skip to content

Commit d453cc5

Browse files
committed
Merge tag 'fsverity-for-linus' of git://git.kernel.org/pub/scm/fs/fsverity/linux
Pull fsverity update from Eric Biggers: "Slightly improve data verification performance by eliminating an unnecessary lock" * tag 'fsverity-for-linus' of git://git.kernel.org/pub/scm/fs/fsverity/linux: fsverity: remove hash page spin lock
2 parents 3bf95d5 + 8e43fb0 commit d453cc5

File tree

3 files changed

+24
-26
lines changed

3 files changed

+24
-26
lines changed

fs/verity/fsverity_private.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ struct fsverity_info {
6969
u8 file_digest[FS_VERITY_MAX_DIGEST_SIZE];
7070
const struct inode *inode;
7171
unsigned long *hash_block_verified;
72-
spinlock_t hash_page_init_lock;
7372
};
7473

7574
#define FS_VERITY_MAX_SIGNATURE_SIZE (FS_VERITY_MAX_DESCRIPTOR_SIZE - \

fs/verity/open.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,6 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode,
239239
err = -ENOMEM;
240240
goto fail;
241241
}
242-
spin_lock_init(&vi->hash_page_init_lock);
243242
}
244243

245244
return vi;

fs/verity/verify.c

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ static struct workqueue_struct *fsverity_read_workqueue;
1919
static bool is_hash_block_verified(struct fsverity_info *vi, struct page *hpage,
2020
unsigned long hblock_idx)
2121
{
22-
bool verified;
2322
unsigned int blocks_per_page;
2423
unsigned int i;
2524

@@ -43,12 +42,20 @@ static bool is_hash_block_verified(struct fsverity_info *vi, struct page *hpage,
4342
* re-instantiated from the backing storage are re-verified. To do
4443
* this, we use PG_checked again, but now it doesn't really mean
4544
* "checked". Instead, now it just serves as an indicator for whether
46-
* the hash page is newly instantiated or not.
45+
* the hash page is newly instantiated or not. If the page is new, as
46+
* indicated by PG_checked=0, we clear the bitmap bits for the page's
47+
* blocks since they are untrustworthy, then set PG_checked=1.
48+
* Otherwise we return the bitmap bit for the requested block.
4749
*
48-
* The first thread that sees PG_checked=0 must clear the corresponding
49-
* bitmap bits, then set PG_checked=1. This requires a spinlock. To
50-
* avoid having to take this spinlock in the common case of
51-
* PG_checked=1, we start with an opportunistic lockless read.
50+
* Multiple threads may execute this code concurrently on the same page.
51+
* This is safe because we use memory barriers to ensure that if a
52+
* thread sees PG_checked=1, then it also sees the associated bitmap
53+
* clearing to have occurred. Also, all writes and their corresponding
54+
* reads are atomic, and all writes are safe to repeat in the event that
55+
* multiple threads get into the PG_checked=0 section. (Clearing a
56+
* bitmap bit again at worst causes a hash block to be verified
57+
* redundantly. That event should be very rare, so it's not worth using
58+
* a lock to avoid. Setting PG_checked again has no effect.)
5259
*/
5360
if (PageChecked(hpage)) {
5461
/*
@@ -58,24 +65,17 @@ static bool is_hash_block_verified(struct fsverity_info *vi, struct page *hpage,
5865
smp_rmb();
5966
return test_bit(hblock_idx, vi->hash_block_verified);
6067
}
61-
spin_lock(&vi->hash_page_init_lock);
62-
if (PageChecked(hpage)) {
63-
verified = test_bit(hblock_idx, vi->hash_block_verified);
64-
} else {
65-
blocks_per_page = vi->tree_params.blocks_per_page;
66-
hblock_idx = round_down(hblock_idx, blocks_per_page);
67-
for (i = 0; i < blocks_per_page; i++)
68-
clear_bit(hblock_idx + i, vi->hash_block_verified);
69-
/*
70-
* A write memory barrier is needed here to give RELEASE
71-
* semantics to the below SetPageChecked() operation.
72-
*/
73-
smp_wmb();
74-
SetPageChecked(hpage);
75-
verified = false;
76-
}
77-
spin_unlock(&vi->hash_page_init_lock);
78-
return verified;
68+
blocks_per_page = vi->tree_params.blocks_per_page;
69+
hblock_idx = round_down(hblock_idx, blocks_per_page);
70+
for (i = 0; i < blocks_per_page; i++)
71+
clear_bit(hblock_idx + i, vi->hash_block_verified);
72+
/*
73+
* A write memory barrier is needed here to give RELEASE semantics to
74+
* the below SetPageChecked() operation.
75+
*/
76+
smp_wmb();
77+
SetPageChecked(hpage);
78+
return false;
7979
}
8080

8181
/*

0 commit comments

Comments
 (0)