Skip to content

Commit 3e9bff3

Browse files
committed
Merge tag 'vfs-6.11-rc6.fixes' of gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs
Pull vfs fixes from Christian Brauner: "VFS: - Ensure that backing files uses file->f_ops->splice_write() for splice netfs: - Revert the removal of PG_private_2 from netfs_release_folio() as cephfs still relies on this - When AS_RELEASE_ALWAYS is set on a mapping the folio needs to always be invalidated during truncation - Fix losing untruncated data in a folio by making letting netfs_release_folio() return false if the folio is dirty - Fix trimming of streaming-write folios in netfs_inval_folio() - Reset iterator before retrying a short read - Fix interaction of streaming writes with zero-point tracker afs: - During truncation afs currently calls truncate_setsize() which sets i_size, expands the pagecache and truncates it. The first two operations aren't needed because they will have already been done. So call truncate_pagecache() instead and skip the redundant parts overlayfs: - Fix checking of the number of allowed lower layers so 500 layers can actually be used instead of just 499 - Add missing '\n' to pr_err() output - Pass string to ovl_parse_layer() and thus allow it to be used for Opt_lowerdir as well pidfd: - Revert blocking the creation of pidfds for kthread as apparently userspace relies on this. Specifically, it breaks systemd during shutdown romfs: - Fix romfs_read_folio() to use the correct offset with folio_zero_tail()" * tag 'vfs-6.11-rc6.fixes' of gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs: netfs: Fix interaction of streaming writes with zero-point tracker netfs: Fix missing iterator reset on retry of short read netfs: Fix trimming of streaming-write folios in netfs_inval_folio() netfs: Fix netfs_release_folio() to say no if folio dirty afs: Fix post-setattr file edit to do truncation correctly mm: Fix missing folio invalidation calls during truncation ovl: ovl_parse_param_lowerdir: Add missed '\n' for pr_err ovl: fix wrong lowerdir number check for parameter Opt_lowerdir ovl: pass string to ovl_parse_layer() backing-file: convert to using fops->splice_write Revert "pidfd: prevent creation of pidfds for kthreads" romfs: fix romfs_read_folio() netfs, ceph: Partially revert "netfs: Replace PG_fscache by setting folio->private and marking dirty"
2 parents 5be63fc + e00e99b commit 3e9bff3

File tree

10 files changed

+84
-83
lines changed

10 files changed

+84
-83
lines changed

fs/afs/inode.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -695,13 +695,18 @@ static void afs_setattr_edit_file(struct afs_operation *op)
695695
{
696696
struct afs_vnode_param *vp = &op->file[0];
697697
struct afs_vnode *vnode = vp->vnode;
698+
struct inode *inode = &vnode->netfs.inode;
698699

699700
if (op->setattr.attr->ia_valid & ATTR_SIZE) {
700701
loff_t size = op->setattr.attr->ia_size;
701-
loff_t i_size = op->setattr.old_i_size;
702+
loff_t old = op->setattr.old_i_size;
703+
704+
/* Note: inode->i_size was updated by afs_apply_status() inside
705+
* the I/O and callback locks.
706+
*/
702707

703-
if (size != i_size) {
704-
truncate_setsize(&vnode->netfs.inode, size);
708+
if (size != old) {
709+
truncate_pagecache(inode, size);
705710
netfs_resize_file(&vnode->netfs, size, true);
706711
fscache_resize_cookie(afs_vnode_cache(vnode), size);
707712
}

fs/backing-file.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,13 +303,16 @@ ssize_t backing_file_splice_write(struct pipe_inode_info *pipe,
303303
if (WARN_ON_ONCE(!(out->f_mode & FMODE_BACKING)))
304304
return -EIO;
305305

306+
if (!out->f_op->splice_write)
307+
return -EINVAL;
308+
306309
ret = file_remove_privs(ctx->user_file);
307310
if (ret)
308311
return ret;
309312

310313
old_cred = override_creds(ctx->cred);
311314
file_start_write(out);
312-
ret = iter_file_splice_write(pipe, out, ppos, len, flags);
315+
ret = out->f_op->splice_write(pipe, out, ppos, len, flags);
313316
file_end_write(out);
314317
revert_creds(old_cred);
315318

fs/ceph/inode.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,7 @@ void ceph_evict_inode(struct inode *inode)
695695

696696
percpu_counter_dec(&mdsc->metric.total_inodes);
697697

698+
netfs_wait_for_outstanding_io(inode);
698699
truncate_inode_pages_final(&inode->i_data);
699700
if (inode->i_state & I_PINNING_NETFS_WB)
700701
ceph_fscache_unuse_cookie(inode, true);

fs/netfs/io.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ static bool netfs_rreq_perform_resubmissions(struct netfs_io_request *rreq)
313313
netfs_reset_subreq_iter(rreq, subreq);
314314
netfs_read_from_server(rreq, subreq);
315315
} else if (test_bit(NETFS_SREQ_SHORT_IO, &subreq->flags)) {
316+
netfs_reset_subreq_iter(rreq, subreq);
316317
netfs_rreq_short_read(rreq, subreq);
317318
}
318319
}

fs/netfs/misc.c

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,22 @@ EXPORT_SYMBOL(netfs_clear_inode_writeback);
9797
void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t length)
9898
{
9999
struct netfs_folio *finfo;
100+
struct netfs_inode *ctx = netfs_inode(folio_inode(folio));
100101
size_t flen = folio_size(folio);
101102

102103
_enter("{%lx},%zx,%zx", folio->index, offset, length);
103104

105+
if (offset == 0 && length == flen) {
106+
unsigned long long i_size = i_size_read(&ctx->inode);
107+
unsigned long long fpos = folio_pos(folio), end;
108+
109+
end = umin(fpos + flen, i_size);
110+
if (fpos < i_size && end > ctx->zero_point)
111+
ctx->zero_point = end;
112+
}
113+
114+
folio_wait_private_2(folio); /* [DEPRECATED] */
115+
104116
if (!folio_test_private(folio))
105117
return;
106118

@@ -113,18 +125,34 @@ void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t length)
113125
/* We have a partially uptodate page from a streaming write. */
114126
unsigned int fstart = finfo->dirty_offset;
115127
unsigned int fend = fstart + finfo->dirty_len;
116-
unsigned int end = offset + length;
128+
unsigned int iend = offset + length;
117129

118130
if (offset >= fend)
119131
return;
120-
if (end <= fstart)
132+
if (iend <= fstart)
133+
return;
134+
135+
/* The invalidation region overlaps the data. If the region
136+
* covers the start of the data, we either move along the start
137+
* or just erase the data entirely.
138+
*/
139+
if (offset <= fstart) {
140+
if (iend >= fend)
141+
goto erase_completely;
142+
/* Move the start of the data. */
143+
finfo->dirty_len = fend - iend;
144+
finfo->dirty_offset = offset;
145+
return;
146+
}
147+
148+
/* Reduce the length of the data if the invalidation region
149+
* covers the tail part.
150+
*/
151+
if (iend >= fend) {
152+
finfo->dirty_len = offset - fstart;
121153
return;
122-
if (offset <= fstart && end >= fend)
123-
goto erase_completely;
124-
if (offset <= fstart && end > fstart)
125-
goto reduce_len;
126-
if (offset > fstart && end >= fend)
127-
goto move_start;
154+
}
155+
128156
/* A partial write was split. The caller has already zeroed
129157
* it, so just absorb the hole.
130158
*/
@@ -137,12 +165,6 @@ void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t length)
137165
folio_clear_uptodate(folio);
138166
kfree(finfo);
139167
return;
140-
reduce_len:
141-
finfo->dirty_len = offset + length - finfo->dirty_offset;
142-
return;
143-
move_start:
144-
finfo->dirty_len -= offset - finfo->dirty_offset;
145-
finfo->dirty_offset = offset;
146168
}
147169
EXPORT_SYMBOL(netfs_invalidate_folio);
148170

@@ -159,12 +181,20 @@ bool netfs_release_folio(struct folio *folio, gfp_t gfp)
159181
struct netfs_inode *ctx = netfs_inode(folio_inode(folio));
160182
unsigned long long end;
161183

162-
end = folio_pos(folio) + folio_size(folio);
184+
if (folio_test_dirty(folio))
185+
return false;
186+
187+
end = umin(folio_pos(folio) + folio_size(folio), i_size_read(&ctx->inode));
163188
if (end > ctx->zero_point)
164189
ctx->zero_point = end;
165190

166191
if (folio_test_private(folio))
167192
return false;
193+
if (unlikely(folio_test_private_2(folio))) { /* [DEPRECATED] */
194+
if (current_is_kswapd() || !(gfp & __GFP_FS))
195+
return false;
196+
folio_wait_private_2(folio);
197+
}
168198
fscache_note_page_release(netfs_i_cookie(ctx));
169199
return true;
170200
}

fs/netfs/write_collect.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
int netfs_folio_written_back(struct folio *folio)
3434
{
3535
enum netfs_folio_trace why = netfs_folio_trace_clear;
36+
struct netfs_inode *ictx = netfs_inode(folio->mapping->host);
3637
struct netfs_folio *finfo;
3738
struct netfs_group *group = NULL;
3839
int gcount = 0;
@@ -41,6 +42,12 @@ int netfs_folio_written_back(struct folio *folio)
4142
/* Streaming writes cannot be redirtied whilst under writeback,
4243
* so discard the streaming record.
4344
*/
45+
unsigned long long fend;
46+
47+
fend = folio_pos(folio) + finfo->dirty_offset + finfo->dirty_len;
48+
if (fend > ictx->zero_point)
49+
ictx->zero_point = fend;
50+
4451
folio_detach_private(folio);
4552
group = finfo->netfs_group;
4653
gcount++;

fs/overlayfs/params.c

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,8 @@ static void ovl_add_layer(struct fs_context *fc, enum ovl_opt layer,
353353
case Opt_datadir_add:
354354
ctx->nr_data++;
355355
fallthrough;
356+
case Opt_lowerdir:
357+
fallthrough;
356358
case Opt_lowerdir_add:
357359
WARN_ON(ctx->nr >= ctx->capacity);
358360
l = &ctx->lower[ctx->nr++];
@@ -365,18 +367,17 @@ static void ovl_add_layer(struct fs_context *fc, enum ovl_opt layer,
365367
}
366368
}
367369

368-
static int ovl_parse_layer(struct fs_context *fc, struct fs_parameter *param,
369-
enum ovl_opt layer)
370+
static int ovl_parse_layer(struct fs_context *fc, const char *layer_name, enum ovl_opt layer)
370371
{
371-
char *name = kstrdup(param->string, GFP_KERNEL);
372+
char *name = kstrdup(layer_name, GFP_KERNEL);
372373
bool upper = (layer == Opt_upperdir || layer == Opt_workdir);
373374
struct path path;
374375
int err;
375376

376377
if (!name)
377378
return -ENOMEM;
378379

379-
if (upper)
380+
if (upper || layer == Opt_lowerdir)
380381
err = ovl_mount_dir(name, &path);
381382
else
382383
err = ovl_mount_dir_noesc(name, &path);
@@ -432,7 +433,6 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
432433
{
433434
int err;
434435
struct ovl_fs_context *ctx = fc->fs_private;
435-
struct ovl_fs_context_layer *l;
436436
char *dup = NULL, *iter;
437437
ssize_t nr_lower, nr;
438438
bool data_layer = false;
@@ -449,7 +449,7 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
449449
return 0;
450450

451451
if (*name == ':') {
452-
pr_err("cannot append lower layer");
452+
pr_err("cannot append lower layer\n");
453453
return -EINVAL;
454454
}
455455

@@ -472,35 +472,11 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
472472
goto out_err;
473473
}
474474

475-
if (nr_lower > ctx->capacity) {
476-
err = -ENOMEM;
477-
l = krealloc_array(ctx->lower, nr_lower, sizeof(*ctx->lower),
478-
GFP_KERNEL_ACCOUNT);
479-
if (!l)
480-
goto out_err;
481-
482-
ctx->lower = l;
483-
ctx->capacity = nr_lower;
484-
}
485-
486475
iter = dup;
487-
l = ctx->lower;
488-
for (nr = 0; nr < nr_lower; nr++, l++) {
489-
ctx->nr++;
490-
memset(l, 0, sizeof(*l));
491-
492-
err = ovl_mount_dir(iter, &l->path);
476+
for (nr = 0; nr < nr_lower; nr++) {
477+
err = ovl_parse_layer(fc, iter, Opt_lowerdir);
493478
if (err)
494-
goto out_put;
495-
496-
err = ovl_mount_dir_check(fc, &l->path, Opt_lowerdir, iter, false);
497-
if (err)
498-
goto out_put;
499-
500-
err = -ENOMEM;
501-
l->name = kstrdup(iter, GFP_KERNEL_ACCOUNT);
502-
if (!l->name)
503-
goto out_put;
479+
goto out_err;
504480

505481
if (data_layer)
506482
ctx->nr_data++;
@@ -517,8 +493,8 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
517493
* there are no data layers.
518494
*/
519495
if (ctx->nr_data > 0) {
520-
pr_err("regular lower layers cannot follow data lower layers");
521-
goto out_put;
496+
pr_err("regular lower layers cannot follow data lower layers\n");
497+
goto out_err;
522498
}
523499

524500
data_layer = false;
@@ -532,9 +508,6 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
532508
kfree(dup);
533509
return 0;
534510

535-
out_put:
536-
ovl_reset_lowerdirs(ctx);
537-
538511
out_err:
539512
kfree(dup);
540513

@@ -582,7 +555,7 @@ static int ovl_parse_param(struct fs_context *fc, struct fs_parameter *param)
582555
case Opt_datadir_add:
583556
case Opt_upperdir:
584557
case Opt_workdir:
585-
err = ovl_parse_layer(fc, param, opt);
558+
err = ovl_parse_layer(fc, param->string, opt);
586559
break;
587560
case Opt_default_permissions:
588561
config->default_permissions = true;

fs/romfs/super.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ static int romfs_read_folio(struct file *file, struct folio *folio)
126126
}
127127
}
128128

129-
buf = folio_zero_tail(folio, fillsize, buf);
129+
buf = folio_zero_tail(folio, fillsize, buf + fillsize);
130130
kunmap_local(buf);
131131
folio_end_read(folio, ret == 0);
132132
return ret;

kernel/fork.c

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2053,23 +2053,10 @@ static int __pidfd_prepare(struct pid *pid, unsigned int flags, struct file **re
20532053
*/
20542054
int pidfd_prepare(struct pid *pid, unsigned int flags, struct file **ret)
20552055
{
2056-
if (!pid)
2057-
return -EINVAL;
2058-
2059-
scoped_guard(rcu) {
2060-
struct task_struct *tsk;
2061-
2062-
if (flags & PIDFD_THREAD)
2063-
tsk = pid_task(pid, PIDTYPE_PID);
2064-
else
2065-
tsk = pid_task(pid, PIDTYPE_TGID);
2066-
if (!tsk)
2067-
return -EINVAL;
2056+
bool thread = flags & PIDFD_THREAD;
20682057

2069-
/* Don't create pidfds for kernel threads for now. */
2070-
if (tsk->flags & PF_KTHREAD)
2071-
return -EINVAL;
2072-
}
2058+
if (!pid || !pid_has_task(pid, thread ? PIDTYPE_PID : PIDTYPE_TGID))
2059+
return -EINVAL;
20732060

20742061
return __pidfd_prepare(pid, flags, ret);
20752062
}
@@ -2416,12 +2403,6 @@ __latent_entropy struct task_struct *copy_process(
24162403
if (clone_flags & CLONE_PIDFD) {
24172404
int flags = (clone_flags & CLONE_THREAD) ? PIDFD_THREAD : 0;
24182405

2419-
/* Don't create pidfds for kernel threads for now. */
2420-
if (args->kthread) {
2421-
retval = -EINVAL;
2422-
goto bad_fork_free_pid;
2423-
}
2424-
24252406
/* Note that no task has been attached to @pid yet. */
24262407
retval = __pidfd_prepare(pid, flags, &pidfile);
24272408
if (retval < 0)

mm/truncate.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ static void truncate_cleanup_folio(struct folio *folio)
157157
if (folio_mapped(folio))
158158
unmap_mapping_folio(folio);
159159

160-
if (folio_has_private(folio))
160+
if (folio_needs_release(folio))
161161
folio_invalidate(folio, 0, folio_size(folio));
162162

163163
/*
@@ -219,7 +219,7 @@ bool truncate_inode_partial_folio(struct folio *folio, loff_t start, loff_t end)
219219
if (!mapping_inaccessible(folio->mapping))
220220
folio_zero_range(folio, offset, length);
221221

222-
if (folio_has_private(folio))
222+
if (folio_needs_release(folio))
223223
folio_invalidate(folio, offset, length);
224224
if (!folio_test_large(folio))
225225
return true;

0 commit comments

Comments
 (0)