Skip to content

Commit 93ce935

Browse files
committed
Merge branch 'davidh' (fixes from David Howells)
Merge misc fixes from David Howells: "A set of patches for watch_queue filter issues noted by Jann. I've added in a cleanup patch from Christophe Jaillet to convert to using formal bitmap specifiers for the note allocation bitmap. Also two filesystem fixes (afs and cachefiles)" * emailed patches from David Howells <dhowells@redhat.com>: cachefiles: Fix volume coherency attribute afs: Fix potential thrashing in afs writeback watch_queue: Make comment about setting ->defunct more accurate watch_queue: Fix lack of barrier/sync/lock between post and read watch_queue: Free the alloc bitmap when the watch_queue is torn down watch_queue: Fix the alloc bitmap size to reflect notes allocated watch_queue: Use the bitmap API when applicable watch_queue: Fix to always request a pow-of-2 pipe ring size watch_queue: Fix to release page in ->release() watch_queue, pipe: Free watchqueue state after clearing pipe ring watch_queue: Fix filter limit check
2 parents 79b0003 + 413a4a6 commit 93ce935

6 files changed

Lines changed: 50 additions & 20 deletions

File tree

fs/afs/write.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ static int afs_writepages_region(struct address_space *mapping,
703703
struct folio *folio;
704704
struct page *head_page;
705705
ssize_t ret;
706-
int n;
706+
int n, skips = 0;
707707

708708
_enter("%llx,%llx,", start, end);
709709

@@ -754,8 +754,15 @@ static int afs_writepages_region(struct address_space *mapping,
754754
#ifdef CONFIG_AFS_FSCACHE
755755
folio_wait_fscache(folio);
756756
#endif
757+
} else {
758+
start += folio_size(folio);
757759
}
758760
folio_put(folio);
761+
if (wbc->sync_mode == WB_SYNC_NONE) {
762+
if (skips >= 5 || need_resched())
763+
break;
764+
skips++;
765+
}
759766
continue;
760767
}
761768

fs/cachefiles/xattr.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ struct cachefiles_xattr {
2828
static const char cachefiles_xattr_cache[] =
2929
XATTR_USER_PREFIX "CacheFiles.cache";
3030

31+
struct cachefiles_vol_xattr {
32+
__be32 reserved; /* Reserved, should be 0 */
33+
__u8 data[]; /* netfs volume coherency data */
34+
} __packed;
35+
3136
/*
3237
* set the state xattr on a cache file
3338
*/
@@ -185,17 +190,25 @@ void cachefiles_prepare_to_write(struct fscache_cookie *cookie)
185190
*/
186191
bool cachefiles_set_volume_xattr(struct cachefiles_volume *volume)
187192
{
193+
struct cachefiles_vol_xattr *buf;
188194
unsigned int len = volume->vcookie->coherency_len;
189195
const void *p = volume->vcookie->coherency;
190196
struct dentry *dentry = volume->dentry;
191197
int ret;
192198

193199
_enter("%x,#%d", volume->vcookie->debug_id, len);
194200

201+
len += sizeof(*buf);
202+
buf = kmalloc(len, GFP_KERNEL);
203+
if (!buf)
204+
return false;
205+
buf->reserved = cpu_to_be32(0);
206+
memcpy(buf->data, p, len);
207+
195208
ret = cachefiles_inject_write_error();
196209
if (ret == 0)
197210
ret = vfs_setxattr(&init_user_ns, dentry, cachefiles_xattr_cache,
198-
p, len, 0);
211+
buf, len, 0);
199212
if (ret < 0) {
200213
trace_cachefiles_vfs_error(NULL, d_inode(dentry), ret,
201214
cachefiles_trace_setxattr_error);
@@ -209,6 +222,7 @@ bool cachefiles_set_volume_xattr(struct cachefiles_volume *volume)
209222
cachefiles_coherency_vol_set_ok);
210223
}
211224

225+
kfree(buf);
212226
_leave(" = %d", ret);
213227
return ret == 0;
214228
}
@@ -218,7 +232,7 @@ bool cachefiles_set_volume_xattr(struct cachefiles_volume *volume)
218232
*/
219233
int cachefiles_check_volume_xattr(struct cachefiles_volume *volume)
220234
{
221-
struct cachefiles_xattr *buf;
235+
struct cachefiles_vol_xattr *buf;
222236
struct dentry *dentry = volume->dentry;
223237
unsigned int len = volume->vcookie->coherency_len;
224238
const void *p = volume->vcookie->coherency;
@@ -228,6 +242,7 @@ int cachefiles_check_volume_xattr(struct cachefiles_volume *volume)
228242

229243
_enter("");
230244

245+
len += sizeof(*buf);
231246
buf = kmalloc(len, GFP_KERNEL);
232247
if (!buf)
233248
return -ENOMEM;
@@ -245,7 +260,9 @@ int cachefiles_check_volume_xattr(struct cachefiles_volume *volume)
245260
"Failed to read xattr with error %zd", xlen);
246261
}
247262
why = cachefiles_coherency_vol_check_xattr;
248-
} else if (memcmp(buf->data, p, len) != 0) {
263+
} else if (buf->reserved != cpu_to_be32(0)) {
264+
why = cachefiles_coherency_vol_check_resv;
265+
} else if (memcmp(buf->data, p, len - sizeof(*buf)) != 0) {
249266
why = cachefiles_coherency_vol_check_cmp;
250267
} else {
251268
why = cachefiles_coherency_vol_check_ok;

fs/pipe.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,8 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
253253
*/
254254
was_full = pipe_full(pipe->head, pipe->tail, pipe->max_usage);
255255
for (;;) {
256-
unsigned int head = pipe->head;
256+
/* Read ->head with a barrier vs post_one_notification() */
257+
unsigned int head = smp_load_acquire(&pipe->head);
257258
unsigned int tail = pipe->tail;
258259
unsigned int mask = pipe->ring_size - 1;
259260

@@ -831,10 +832,8 @@ void free_pipe_info(struct pipe_inode_info *pipe)
831832
int i;
832833

833834
#ifdef CONFIG_WATCH_QUEUE
834-
if (pipe->watch_queue) {
835+
if (pipe->watch_queue)
835836
watch_queue_clear(pipe->watch_queue);
836-
put_watch_queue(pipe->watch_queue);
837-
}
838837
#endif
839838

840839
(void) account_pipe_buffers(pipe->user, pipe->nr_accounted, 0);
@@ -844,6 +843,10 @@ void free_pipe_info(struct pipe_inode_info *pipe)
844843
if (buf->ops)
845844
pipe_buf_release(pipe, buf);
846845
}
846+
#ifdef CONFIG_WATCH_QUEUE
847+
if (pipe->watch_queue)
848+
put_watch_queue(pipe->watch_queue);
849+
#endif
847850
if (pipe->tmp_page)
848851
__free_page(pipe->tmp_page);
849852
kfree(pipe->bufs);

include/linux/watch_queue.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ struct watch_type_filter {
2828
struct watch_filter {
2929
union {
3030
struct rcu_head rcu;
31-
unsigned long type_filter[2]; /* Bitmask of accepted types */
31+
/* Bitmask of accepted types */
32+
DECLARE_BITMAP(type_filter, WATCH_TYPE__NR);
3233
};
3334
u32 nr_filters; /* Number of filters */
3435
struct watch_type_filter filters[];

include/trace/events/cachefiles.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ enum cachefiles_coherency_trace {
5656
cachefiles_coherency_set_ok,
5757
cachefiles_coherency_vol_check_cmp,
5858
cachefiles_coherency_vol_check_ok,
59+
cachefiles_coherency_vol_check_resv,
5960
cachefiles_coherency_vol_check_xattr,
6061
cachefiles_coherency_vol_set_fail,
6162
cachefiles_coherency_vol_set_ok,
@@ -139,6 +140,7 @@ enum cachefiles_error_trace {
139140
EM(cachefiles_coherency_set_ok, "SET ok ") \
140141
EM(cachefiles_coherency_vol_check_cmp, "VOL BAD cmp ") \
141142
EM(cachefiles_coherency_vol_check_ok, "VOL OK ") \
143+
EM(cachefiles_coherency_vol_check_resv, "VOL BAD resv") \
142144
EM(cachefiles_coherency_vol_check_xattr,"VOL BAD xatt") \
143145
EM(cachefiles_coherency_vol_set_fail, "VOL SET fail") \
144146
E_(cachefiles_coherency_vol_set_ok, "VOL SET ok ")

kernel/watch_queue.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ static void watch_queue_pipe_buf_release(struct pipe_inode_info *pipe,
5454
bit += page->index;
5555

5656
set_bit(bit, wqueue->notes_bitmap);
57+
generic_pipe_buf_release(pipe, buf);
5758
}
5859

5960
// No try_steal function => no stealing
@@ -112,7 +113,7 @@ static bool post_one_notification(struct watch_queue *wqueue,
112113
buf->offset = offset;
113114
buf->len = len;
114115
buf->flags = PIPE_BUF_FLAG_WHOLE;
115-
pipe->head = head + 1;
116+
smp_store_release(&pipe->head, head + 1); /* vs pipe_read() */
116117

117118
if (!test_and_clear_bit(note, wqueue->notes_bitmap)) {
118119
spin_unlock_irq(&pipe->rd_wait.lock);
@@ -219,7 +220,6 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes)
219220
struct page **pages;
220221
unsigned long *bitmap;
221222
unsigned long user_bufs;
222-
unsigned int bmsize;
223223
int ret, i, nr_pages;
224224

225225
if (!wqueue)
@@ -243,7 +243,8 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes)
243243
goto error;
244244
}
245245

246-
ret = pipe_resize_ring(pipe, nr_notes);
246+
nr_notes = nr_pages * WATCH_QUEUE_NOTES_PER_PAGE;
247+
ret = pipe_resize_ring(pipe, roundup_pow_of_two(nr_notes));
247248
if (ret < 0)
248249
goto error;
249250

@@ -258,17 +259,15 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes)
258259
pages[i]->index = i * WATCH_QUEUE_NOTES_PER_PAGE;
259260
}
260261

261-
bmsize = (nr_notes + BITS_PER_LONG - 1) / BITS_PER_LONG;
262-
bmsize *= sizeof(unsigned long);
263-
bitmap = kmalloc(bmsize, GFP_KERNEL);
262+
bitmap = bitmap_alloc(nr_notes, GFP_KERNEL);
264263
if (!bitmap)
265264
goto error_p;
266265

267-
memset(bitmap, 0xff, bmsize);
266+
bitmap_fill(bitmap, nr_notes);
268267
wqueue->notes = pages;
269268
wqueue->notes_bitmap = bitmap;
270269
wqueue->nr_pages = nr_pages;
271-
wqueue->nr_notes = nr_pages * WATCH_QUEUE_NOTES_PER_PAGE;
270+
wqueue->nr_notes = nr_notes;
272271
return 0;
273272

274273
error_p:
@@ -320,7 +319,7 @@ long watch_queue_set_filter(struct pipe_inode_info *pipe,
320319
tf[i].info_mask & WATCH_INFO_LENGTH)
321320
goto err_filter;
322321
/* Ignore any unknown types */
323-
if (tf[i].type >= sizeof(wfilter->type_filter) * 8)
322+
if (tf[i].type >= WATCH_TYPE__NR)
324323
continue;
325324
nr_filter++;
326325
}
@@ -336,7 +335,7 @@ long watch_queue_set_filter(struct pipe_inode_info *pipe,
336335

337336
q = wfilter->filters;
338337
for (i = 0; i < filter.nr_filters; i++) {
339-
if (tf[i].type >= sizeof(wfilter->type_filter) * BITS_PER_LONG)
338+
if (tf[i].type >= WATCH_TYPE__NR)
340339
continue;
341340

342341
q->type = tf[i].type;
@@ -371,6 +370,7 @@ static void __put_watch_queue(struct kref *kref)
371370

372371
for (i = 0; i < wqueue->nr_pages; i++)
373372
__free_page(wqueue->notes[i]);
373+
bitmap_free(wqueue->notes_bitmap);
374374

375375
wfilter = rcu_access_pointer(wqueue->filter);
376376
if (wfilter)
@@ -566,7 +566,7 @@ void watch_queue_clear(struct watch_queue *wqueue)
566566
rcu_read_lock();
567567
spin_lock_bh(&wqueue->lock);
568568

569-
/* Prevent new additions and prevent notifications from happening */
569+
/* Prevent new notifications from being stored. */
570570
wqueue->defunct = true;
571571

572572
while (!hlist_empty(&wqueue->watches)) {

0 commit comments

Comments
 (0)