Skip to content

Commit 5fe85a5

Browse files
committed
Merge patch series "netfs, ceph, nfs, cachefiles: Miscellaneous fixes/changes"
David Howells <dhowells@redhat.com> says: Here are some miscellaneous fixes and changes for netfslib and the ceph and nfs filesystems: (1) Ignore silly-rename files from afs and nfs when building the header archive in a kernel build. (2) netfs: Fix the way read result collection applies results to folios when each folio is being read by multiple subrequests and the results come out of order. (3) netfs: Fix ENOMEM handling in buffered reads. (4) nfs: Fix an oops in nfs_netfs_init_request() when copying to the cache. (5) cachefiles: Parse the "secctx" command immediately to get the correct error rather than leaving it to the "bind" command. (6) netfs: Remove a redundant smp_rmb(). This isn't a bug per se and could be deferred. (7) netfs: Fix missing barriers by using clear_and_wake_up_bit(). (8) netfs: Work around recursion in read retry by failing and abandoning the retried subrequest if no I/O is performed. [!] NOTE: This only works around the recursion problem if the recursion keeps returning no data. If the server manages, say, to repeatedly return a single byte of data faster than the retry algorithm can complete, it will still recurse and the stack overrun may still occur. Actually fixing this requires quite an intrusive change which will hopefully make the next merge window. (9) netfs: Fix the clearance of a folio_queue when unlocking the page if we're going to want to subsequently send the queue for copying to the cache (if, for example, we're using ceph). (10) netfs: Fix the lack of cancellation of copy-to-cache when the cache for a file is temporarily disabled (for example when a DIO write is done to the file). This patch and (9) fix hangs with ceph. With these patches, I can run xfstest -g quick to completion on ceph with a local cache. The patches can also be found here with a bonus cifs patch: https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=netfs-fixes * patches from https://lore.kernel.org/r/20241213135013.2964079-1-dhowells@redhat.com: netfs: Fix is-caching check in read-retry netfs: Fix the (non-)cancellation of copy when cache is temporarily disabled netfs: Fix ceph copy to cache on write-begin netfs: Work around recursion by abandoning retry if nothing read netfs: Fix missing barriers by using clear_and_wake_up_bit() netfs: Remove redundant use of smp_rmb() cachefiles: Parse the "secctx" immediately nfs: Fix oops in nfs_netfs_init_request() when copying to cache netfs: Fix enomem handling in buffered reads netfs: Fix non-contiguous donation between completed reads kheaders: Ignore silly-rename files Link: https://lore.kernel.org/r/20241213135013.2964079-1-dhowells@redhat.com Signed-off-by: Christian Brauner <brauner@kernel.org>
2 parents 974e3fe + d4e338d commit 5fe85a5

File tree

17 files changed

+99
-64
lines changed

17 files changed

+99
-64
lines changed

fs/9p/vfs_addr.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ static void v9fs_issue_write(struct netfs_io_subrequest *subreq)
5757
int err, len;
5858

5959
len = p9_client_write(fid, subreq->start, &subreq->io_iter, &err);
60+
if (len > 0)
61+
__set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
6062
netfs_write_subrequest_terminated(subreq, len ?: err, false);
6163
}
6264

@@ -80,8 +82,10 @@ static void v9fs_issue_read(struct netfs_io_subrequest *subreq)
8082
if (pos + total >= i_size_read(rreq->inode))
8183
__set_bit(NETFS_SREQ_HIT_EOF, &subreq->flags);
8284

83-
if (!err)
85+
if (!err) {
8486
subreq->transferred += total;
87+
__set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
88+
}
8589

8690
netfs_read_subreq_terminated(subreq, err, false);
8791
}

fs/afs/write.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ static void afs_issue_write_worker(struct work_struct *work)
122122
if (subreq->debug_index == 3)
123123
return netfs_write_subrequest_terminated(subreq, -ENOANO, false);
124124

125-
if (!test_bit(NETFS_SREQ_RETRYING, &subreq->flags)) {
125+
if (!subreq->retry_count) {
126126
set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
127127
return netfs_write_subrequest_terminated(subreq, -EAGAIN, false);
128128
}
@@ -149,6 +149,9 @@ static void afs_issue_write_worker(struct work_struct *work)
149149
afs_wait_for_operation(op);
150150
ret = afs_put_operation(op);
151151
switch (ret) {
152+
case 0:
153+
__set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
154+
break;
152155
case -EACCES:
153156
case -EPERM:
154157
case -ENOKEY:

fs/cachefiles/daemon.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/namei.h>
1616
#include <linux/poll.h>
1717
#include <linux/mount.h>
18+
#include <linux/security.h>
1819
#include <linux/statfs.h>
1920
#include <linux/ctype.h>
2021
#include <linux/string.h>
@@ -576,7 +577,7 @@ static int cachefiles_daemon_dir(struct cachefiles_cache *cache, char *args)
576577
*/
577578
static int cachefiles_daemon_secctx(struct cachefiles_cache *cache, char *args)
578579
{
579-
char *secctx;
580+
int err;
580581

581582
_enter(",%s", args);
582583

@@ -585,16 +586,16 @@ static int cachefiles_daemon_secctx(struct cachefiles_cache *cache, char *args)
585586
return -EINVAL;
586587
}
587588

588-
if (cache->secctx) {
589+
if (cache->have_secid) {
589590
pr_err("Second security context specified\n");
590591
return -EINVAL;
591592
}
592593

593-
secctx = kstrdup(args, GFP_KERNEL);
594-
if (!secctx)
595-
return -ENOMEM;
594+
err = security_secctx_to_secid(args, strlen(args), &cache->secid);
595+
if (err)
596+
return err;
596597

597-
cache->secctx = secctx;
598+
cache->have_secid = true;
598599
return 0;
599600
}
600601

@@ -820,7 +821,6 @@ static void cachefiles_daemon_unbind(struct cachefiles_cache *cache)
820821
put_cred(cache->cache_cred);
821822

822823
kfree(cache->rootdirname);
823-
kfree(cache->secctx);
824824
kfree(cache->tag);
825825

826826
_leave("");

fs/cachefiles/internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,14 +122,15 @@ struct cachefiles_cache {
122122
#define CACHEFILES_STATE_CHANGED 3 /* T if state changed (poll trigger) */
123123
#define CACHEFILES_ONDEMAND_MODE 4 /* T if in on-demand read mode */
124124
char *rootdirname; /* name of cache root directory */
125-
char *secctx; /* LSM security context */
126125
char *tag; /* cache binding tag */
127126
refcount_t unbind_pincount;/* refcount to do daemon unbind */
128127
struct xarray reqs; /* xarray of pending on-demand requests */
129128
unsigned long req_id_next;
130129
struct xarray ondemand_ids; /* xarray for ondemand_id allocation */
131130
u32 ondemand_id_next;
132131
u32 msg_id_next;
132+
u32 secid; /* LSM security id */
133+
bool have_secid; /* whether "secid" was set */
133134
};
134135

135136
static inline bool cachefiles_in_ondemand_mode(struct cachefiles_cache *cache)

fs/cachefiles/security.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@ int cachefiles_get_security_ID(struct cachefiles_cache *cache)
1818
struct cred *new;
1919
int ret;
2020

21-
_enter("{%s}", cache->secctx);
21+
_enter("{%u}", cache->have_secid ? cache->secid : 0);
2222

2323
new = prepare_kernel_cred(current);
2424
if (!new) {
2525
ret = -ENOMEM;
2626
goto error;
2727
}
2828

29-
if (cache->secctx) {
30-
ret = set_security_override_from_ctx(new, cache->secctx);
29+
if (cache->have_secid) {
30+
ret = set_security_override(new, cache->secid);
3131
if (ret < 0) {
3232
put_cred(new);
3333
pr_err("Security denies permission to nominate security context: error %d\n",

fs/netfs/buffered_read.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -275,22 +275,14 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
275275
netfs_stat(&netfs_n_rh_download);
276276
if (rreq->netfs_ops->prepare_read) {
277277
ret = rreq->netfs_ops->prepare_read(subreq);
278-
if (ret < 0) {
279-
atomic_dec(&rreq->nr_outstanding);
280-
netfs_put_subrequest(subreq, false,
281-
netfs_sreq_trace_put_cancel);
282-
break;
283-
}
278+
if (ret < 0)
279+
goto prep_failed;
284280
trace_netfs_sreq(subreq, netfs_sreq_trace_prepare);
285281
}
286282

287283
slice = netfs_prepare_read_iterator(subreq);
288-
if (slice < 0) {
289-
atomic_dec(&rreq->nr_outstanding);
290-
netfs_put_subrequest(subreq, false, netfs_sreq_trace_put_cancel);
291-
ret = slice;
292-
break;
293-
}
284+
if (slice < 0)
285+
goto prep_iter_failed;
294286

295287
rreq->netfs_ops->issue_read(subreq);
296288
goto done;
@@ -302,6 +294,8 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
302294
trace_netfs_sreq(subreq, netfs_sreq_trace_submit);
303295
netfs_stat(&netfs_n_rh_zero);
304296
slice = netfs_prepare_read_iterator(subreq);
297+
if (slice < 0)
298+
goto prep_iter_failed;
305299
__set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags);
306300
netfs_read_subreq_terminated(subreq, 0, false);
307301
goto done;
@@ -310,6 +304,8 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
310304
if (source == NETFS_READ_FROM_CACHE) {
311305
trace_netfs_sreq(subreq, netfs_sreq_trace_submit);
312306
slice = netfs_prepare_read_iterator(subreq);
307+
if (slice < 0)
308+
goto prep_iter_failed;
313309
netfs_read_cache_to_pagecache(rreq, subreq);
314310
goto done;
315311
}
@@ -318,6 +314,14 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
318314
WARN_ON_ONCE(1);
319315
break;
320316

317+
prep_iter_failed:
318+
ret = slice;
319+
prep_failed:
320+
subreq->error = ret;
321+
atomic_dec(&rreq->nr_outstanding);
322+
netfs_put_subrequest(subreq, false, netfs_sreq_trace_put_cancel);
323+
break;
324+
321325
done:
322326
size -= slice;
323327
start += slice;

fs/netfs/direct_write.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ ssize_t netfs_unbuffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *
104104
trace_netfs_rreq(wreq, netfs_rreq_trace_wait_ip);
105105
wait_on_bit(&wreq->flags, NETFS_RREQ_IN_PROGRESS,
106106
TASK_UNINTERRUPTIBLE);
107-
smp_rmb(); /* Read error/transferred after RIP flag */
108107
ret = wreq->error;
109108
if (ret == 0) {
110109
ret = wreq->transferred;

fs/netfs/read_collect.c

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,14 @@ static void netfs_unlock_read_folio(struct netfs_io_subrequest *subreq,
6262
} else {
6363
trace_netfs_folio(folio, netfs_folio_trace_read_done);
6464
}
65+
66+
folioq_clear(folioq, slot);
6567
} else {
6668
// TODO: Use of PG_private_2 is deprecated.
6769
if (test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags))
6870
netfs_pgpriv2_mark_copy_to_cache(subreq, rreq, folioq, slot);
71+
else
72+
folioq_clear(folioq, slot);
6973
}
7074

7175
if (!test_bit(NETFS_RREQ_DONT_UNLOCK_FOLIOS, &rreq->flags)) {
@@ -77,8 +81,6 @@ static void netfs_unlock_read_folio(struct netfs_io_subrequest *subreq,
7781
folio_unlock(folio);
7882
}
7983
}
80-
81-
folioq_clear(folioq, slot);
8284
}
8385

8486
/*
@@ -247,16 +249,17 @@ static bool netfs_consume_read_data(struct netfs_io_subrequest *subreq, bool was
247249

248250
/* Deal with the trickiest case: that this subreq is in the middle of a
249251
* folio, not touching either edge, but finishes first. In such a
250-
* case, we donate to the previous subreq, if there is one, so that the
251-
* donation is only handled when that completes - and remove this
252-
* subreq from the list.
252+
* case, we donate to the previous subreq, if there is one and if it is
253+
* contiguous, so that the donation is only handled when that completes
254+
* - and remove this subreq from the list.
253255
*
254256
* If the previous subreq finished first, we will have acquired their
255257
* donation and should be able to unlock folios and/or donate nextwards.
256258
*/
257259
if (!subreq->consumed &&
258260
!prev_donated &&
259-
!list_is_first(&subreq->rreq_link, &rreq->subrequests)) {
261+
!list_is_first(&subreq->rreq_link, &rreq->subrequests) &&
262+
subreq->start == prev->start + prev->len) {
260263
prev = list_prev_entry(subreq, rreq_link);
261264
WRITE_ONCE(prev->next_donated, prev->next_donated + subreq->len);
262265
subreq->start += subreq->len;
@@ -378,8 +381,7 @@ static void netfs_rreq_assess(struct netfs_io_request *rreq)
378381
task_io_account_read(rreq->transferred);
379382

380383
trace_netfs_rreq(rreq, netfs_rreq_trace_wake_ip);
381-
clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &rreq->flags);
382-
wake_up_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS);
384+
clear_and_wake_up_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags);
383385

384386
trace_netfs_rreq(rreq, netfs_rreq_trace_done);
385387
netfs_clear_subrequests(rreq, false);
@@ -438,7 +440,7 @@ void netfs_read_subreq_progress(struct netfs_io_subrequest *subreq,
438440
rreq->origin == NETFS_READPAGE ||
439441
rreq->origin == NETFS_READ_FOR_WRITE)) {
440442
netfs_consume_read_data(subreq, was_async);
441-
__clear_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags);
443+
__set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
442444
}
443445
}
444446
EXPORT_SYMBOL(netfs_read_subreq_progress);
@@ -497,7 +499,7 @@ void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq,
497499
rreq->origin == NETFS_READPAGE ||
498500
rreq->origin == NETFS_READ_FOR_WRITE)) {
499501
netfs_consume_read_data(subreq, was_async);
500-
__clear_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags);
502+
__set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
501503
}
502504
rreq->transferred += subreq->transferred;
503505
}
@@ -511,10 +513,13 @@ void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq,
511513
} else {
512514
trace_netfs_sreq(subreq, netfs_sreq_trace_short);
513515
if (subreq->transferred > subreq->consumed) {
514-
__set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
515-
__clear_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags);
516-
set_bit(NETFS_RREQ_NEED_RETRY, &rreq->flags);
517-
} else if (!__test_and_set_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags)) {
516+
/* If we didn't read new data, abandon retry. */
517+
if (subreq->retry_count &&
518+
test_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags)) {
519+
__set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
520+
set_bit(NETFS_RREQ_NEED_RETRY, &rreq->flags);
521+
}
522+
} else if (test_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags)) {
518523
__set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
519524
set_bit(NETFS_RREQ_NEED_RETRY, &rreq->flags);
520525
} else {

fs/netfs/read_pgpriv2.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ void netfs_pgpriv2_write_to_the_cache(struct netfs_io_request *rreq)
170170

171171
trace_netfs_write(wreq, netfs_write_trace_copy_to_cache);
172172
netfs_stat(&netfs_n_wh_copy_to_cache);
173+
if (!wreq->io_streams[1].avail) {
174+
netfs_put_request(wreq, false, netfs_rreq_trace_put_return);
175+
goto couldnt_start;
176+
}
173177

174178
for (;;) {
175179
error = netfs_pgpriv2_copy_folio(wreq, folio);

fs/netfs/read_retry.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,15 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq)
4949
* up to the first permanently failed one.
5050
*/
5151
if (!rreq->netfs_ops->prepare_read &&
52-
!test_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags)) {
52+
!rreq->cache_resources.ops) {
5353
struct netfs_io_subrequest *subreq;
5454

5555
list_for_each_entry(subreq, &rreq->subrequests, rreq_link) {
5656
if (test_bit(NETFS_SREQ_FAILED, &subreq->flags))
5757
break;
5858
if (__test_and_clear_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags)) {
59+
__clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
60+
subreq->retry_count++;
5961
netfs_reset_iter(subreq);
6062
netfs_reissue_read(rreq, subreq);
6163
}
@@ -137,7 +139,8 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq)
137139
stream0->sreq_max_len = subreq->len;
138140

139141
__clear_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
140-
__set_bit(NETFS_SREQ_RETRYING, &subreq->flags);
142+
__clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
143+
subreq->retry_count++;
141144

142145
spin_lock_bh(&rreq->lock);
143146
list_add_tail(&subreq->rreq_link, &rreq->subrequests);
@@ -213,7 +216,6 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq)
213216
subreq->error = -ENOMEM;
214217
__clear_bit(NETFS_SREQ_FAILED, &subreq->flags);
215218
__clear_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
216-
__clear_bit(NETFS_SREQ_RETRYING, &subreq->flags);
217219
}
218220
spin_lock_bh(&rreq->lock);
219221
list_splice_tail_init(&queue, &rreq->subrequests);

0 commit comments

Comments
 (0)