Skip to content

Commit 7cd122b

Browse files
committed
Merge tag 'pull-persistency' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull persistent dentry infrastructure and conversion from Al Viro: "Some filesystems use a kinda-sorta controlled dentry refcount leak to pin dentries of created objects in dcache (and undo it when removing those). A reference is grabbed and not released, but it's not actually _stored_ anywhere. That works, but it's hard to follow and verify; among other things, we have no way to tell _which_ of the increments is intended to be an unpaired one. Worse, on removal we need to decide whether the reference had already been dropped, which can be non-trivial if that removal is on umount and we need to figure out if this dentry is pinned due to e.g. unlink() not done. Usually that is handled by using kill_litter_super() as ->kill_sb(), but there are open-coded special cases of the same (consider e.g. /proc/self). Things get simpler if we introduce a new dentry flag (DCACHE_PERSISTENT) marking those "leaked" dentries. Having it set claims responsibility for +1 in refcount. The end result this series is aiming for: - get these unbalanced dget() and dput() replaced with new primitives that would, in addition to adjusting refcount, set and clear persistency flag. - instead of having kill_litter_super() mess with removing the remaining "leaked" references (e.g. for all tmpfs files that hadn't been removed prior to umount), have the regular shrink_dcache_for_umount() strip DCACHE_PERSISTENT of all dentries, dropping the corresponding reference if it had been set. After that kill_litter_super() becomes an equivalent of kill_anon_super(). Doing that in a single step is not feasible - it would affect too many places in too many filesystems. It has to be split into a series. This work has really started early in 2024; quite a few preliminary pieces have already gone into mainline. This chunk is finally getting to the meat of that stuff - infrastructure and most of the conversions to it. Some pieces are still sitting in the local branches, but the bulk of that stuff is here" * tag 'pull-persistency' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (54 commits) d_make_discardable(): warn if given a non-persistent dentry kill securityfs_recursive_remove() convert securityfs get rid of kill_litter_super() convert rust_binderfs convert nfsctl convert rpc_pipefs convert hypfs hypfs: swich hypfs_create_u64() to returning int hypfs: switch hypfs_create_str() to returning int hypfs: don't pin dentries twice convert gadgetfs gadgetfs: switch to simple_remove_by_name() convert functionfs functionfs: switch to simple_remove_by_name() functionfs: fix the open/removal races functionfs: need to cancel ->reset_work in ->kill_sb() functionfs: don't bother with ffs->ref in ffs_data_{opened,closed}() functionfs: don't abuse ffs_data_closed() on fs shutdown convert selinuxfs ...
2 parents 7203ca4 + eb028c3 commit 7cd122b

53 files changed

Lines changed: 649 additions & 834 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Documentation/filesystems/porting.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,3 +1327,10 @@ When vfs_mkdir() returns an error, and so both dputs() the original
13271327
dentry and doesn't provide a replacement, it also unlocks the parent.
13281328
Consequently the return value from vfs_mkdir() can be passed to
13291329
end_creating() and the parent will be unlocked precisely when necessary.
1330+
1331+
---
1332+
1333+
**mandatory**
1334+
1335+
kill_litter_super() is gone; convert to DCACHE_PERSISTENT use (as all
1336+
in-tree filesystems have done).

arch/powerpc/platforms/cell/spufs/inode.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ spufs_new_file(struct super_block *sb, struct dentry *dentry,
127127
inode->i_fop = fops;
128128
inode->i_size = size;
129129
inode->i_private = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
130-
d_add(dentry, inode);
130+
d_make_persistent(dentry, inode);
131131
out:
132132
return ret;
133133
}
@@ -163,10 +163,9 @@ static int spufs_fill_dir(struct dentry *dir,
163163
return -ENOMEM;
164164
ret = spufs_new_file(dir->d_sb, dentry, files->ops,
165165
files->mode & mode, files->size, ctx);
166-
if (ret) {
167-
dput(dentry);
166+
dput(dentry);
167+
if (ret)
168168
return ret;
169-
}
170169
files++;
171170
}
172171
return 0;
@@ -241,11 +240,10 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
241240

242241
inode_lock(inode);
243242

244-
dget(dentry);
245243
inc_nlink(dir);
246244
inc_nlink(inode);
247245

248-
d_instantiate(dentry, inode);
246+
d_make_persistent(dentry, inode);
249247

250248
if (flags & SPU_CREATE_NOSCHED)
251249
ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents,
@@ -468,10 +466,9 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, umode_t mode)
468466
inode->i_op = &simple_dir_inode_operations;
469467
inode->i_fop = &simple_dir_operations;
470468

471-
d_instantiate(dentry, inode);
472-
dget(dentry);
473469
inc_nlink(dir);
474-
inc_nlink(d_inode(dentry));
470+
inc_nlink(inode);
471+
d_make_persistent(dentry, inode);
475472
return ret;
476473

477474
out_iput:
@@ -758,7 +755,7 @@ static struct file_system_type spufs_type = {
758755
.name = "spufs",
759756
.init_fs_context = spufs_init_fs_context,
760757
.parameters = spufs_fs_parameters,
761-
.kill_sb = kill_litter_super,
758+
.kill_sb = kill_anon_super,
762759
};
763760
MODULE_ALIAS_FS("spufs");
764761

arch/s390/hypfs/hypfs.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,9 @@
2222

2323
extern struct dentry *hypfs_mkdir(struct dentry *parent, const char *name);
2424

25-
extern struct dentry *hypfs_create_u64(struct dentry *dir, const char *name,
26-
__u64 value);
25+
extern int hypfs_create_u64(struct dentry *dir, const char *name, __u64 value);
2726

28-
extern struct dentry *hypfs_create_str(struct dentry *dir, const char *name,
29-
char *string);
27+
extern int hypfs_create_str(struct dentry *dir, const char *name, char *string);
3028

3129
/* LPAR Hypervisor */
3230
extern int hypfs_diag_init(void);

arch/s390/hypfs/hypfs_diag_fs.c

Lines changed: 21 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ static int hypfs_create_cpu_files(struct dentry *cpus_dir, void *cpu_info)
203203
{
204204
struct dentry *cpu_dir;
205205
char buffer[TMP_SIZE];
206-
void *rc;
206+
int rc;
207207

208208
snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_get_info_type(),
209209
cpu_info));
@@ -213,22 +213,21 @@ static int hypfs_create_cpu_files(struct dentry *cpus_dir, void *cpu_info)
213213
rc = hypfs_create_u64(cpu_dir, "mgmtime",
214214
cpu_info__acc_time(diag204_get_info_type(), cpu_info) -
215215
cpu_info__lp_time(diag204_get_info_type(), cpu_info));
216-
if (IS_ERR(rc))
217-
return PTR_ERR(rc);
216+
if (rc)
217+
return rc;
218218
rc = hypfs_create_u64(cpu_dir, "cputime",
219219
cpu_info__lp_time(diag204_get_info_type(), cpu_info));
220-
if (IS_ERR(rc))
221-
return PTR_ERR(rc);
220+
if (rc)
221+
return rc;
222222
if (diag204_get_info_type() == DIAG204_INFO_EXT) {
223223
rc = hypfs_create_u64(cpu_dir, "onlinetime",
224224
cpu_info__online_time(diag204_get_info_type(),
225225
cpu_info));
226-
if (IS_ERR(rc))
227-
return PTR_ERR(rc);
226+
if (rc)
227+
return rc;
228228
}
229229
diag224_idx2name(cpu_info__ctidx(diag204_get_info_type(), cpu_info), buffer);
230-
rc = hypfs_create_str(cpu_dir, "type", buffer);
231-
return PTR_ERR_OR_ZERO(rc);
230+
return hypfs_create_str(cpu_dir, "type", buffer);
232231
}
233232

234233
static void *hypfs_create_lpar_files(struct dentry *systems_dir, void *part_hdr)
@@ -263,7 +262,7 @@ static int hypfs_create_phys_cpu_files(struct dentry *cpus_dir, void *cpu_info)
263262
{
264263
struct dentry *cpu_dir;
265264
char buffer[TMP_SIZE];
266-
void *rc;
265+
int rc;
267266

268267
snprintf(buffer, TMP_SIZE, "%i", phys_cpu__cpu_addr(diag204_get_info_type(),
269268
cpu_info));
@@ -272,11 +271,10 @@ static int hypfs_create_phys_cpu_files(struct dentry *cpus_dir, void *cpu_info)
272271
return PTR_ERR(cpu_dir);
273272
rc = hypfs_create_u64(cpu_dir, "mgmtime",
274273
phys_cpu__mgm_time(diag204_get_info_type(), cpu_info));
275-
if (IS_ERR(rc))
276-
return PTR_ERR(rc);
274+
if (rc)
275+
return rc;
277276
diag224_idx2name(phys_cpu__ctidx(diag204_get_info_type(), cpu_info), buffer);
278-
rc = hypfs_create_str(cpu_dir, "type", buffer);
279-
return PTR_ERR_OR_ZERO(rc);
277+
return hypfs_create_str(cpu_dir, "type", buffer);
280278
}
281279

282280
static void *hypfs_create_phys_files(struct dentry *parent_dir, void *phys_hdr)
@@ -315,41 +313,25 @@ int hypfs_diag_create_files(struct dentry *root)
315313
return rc;
316314

317315
systems_dir = hypfs_mkdir(root, "systems");
318-
if (IS_ERR(systems_dir)) {
319-
rc = PTR_ERR(systems_dir);
320-
goto err_out;
321-
}
316+
if (IS_ERR(systems_dir))
317+
return PTR_ERR(systems_dir);
322318
time_hdr = (struct x_info_blk_hdr *)buffer;
323319
part_hdr = time_hdr + info_blk_hdr__size(diag204_get_info_type());
324320
for (i = 0; i < info_blk_hdr__npar(diag204_get_info_type(), time_hdr); i++) {
325321
part_hdr = hypfs_create_lpar_files(systems_dir, part_hdr);
326-
if (IS_ERR(part_hdr)) {
327-
rc = PTR_ERR(part_hdr);
328-
goto err_out;
329-
}
322+
if (IS_ERR(part_hdr))
323+
return PTR_ERR(part_hdr);
330324
}
331325
if (info_blk_hdr__flags(diag204_get_info_type(), time_hdr) &
332326
DIAG204_LPAR_PHYS_FLG) {
333327
ptr = hypfs_create_phys_files(root, part_hdr);
334-
if (IS_ERR(ptr)) {
335-
rc = PTR_ERR(ptr);
336-
goto err_out;
337-
}
328+
if (IS_ERR(ptr))
329+
return PTR_ERR(ptr);
338330
}
339331
hyp_dir = hypfs_mkdir(root, "hyp");
340-
if (IS_ERR(hyp_dir)) {
341-
rc = PTR_ERR(hyp_dir);
342-
goto err_out;
343-
}
344-
ptr = hypfs_create_str(hyp_dir, "type", "LPAR Hypervisor");
345-
if (IS_ERR(ptr)) {
346-
rc = PTR_ERR(ptr);
347-
goto err_out;
348-
}
349-
rc = 0;
350-
351-
err_out:
352-
return rc;
332+
if (IS_ERR(hyp_dir))
333+
return PTR_ERR(hyp_dir);
334+
return hypfs_create_str(hyp_dir, "type", "LPAR Hypervisor");
353335
}
354336

355337
/* Diagnose 224 functions */

arch/s390/hypfs/hypfs_vm_fs.c

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@
1919

2020
#define ATTRIBUTE(dir, name, member) \
2121
do { \
22-
void *rc; \
23-
rc = hypfs_create_u64(dir, name, member); \
24-
if (IS_ERR(rc)) \
25-
return PTR_ERR(rc); \
22+
int rc = hypfs_create_u64(dir, name, member); \
23+
if (rc) \
24+
return rc; \
2625
} while (0)
2726

2827
static int hypfs_vm_create_guest(struct dentry *systems_dir,
@@ -85,7 +84,7 @@ static int hypfs_vm_create_guest(struct dentry *systems_dir,
8584

8685
int hypfs_vm_create_files(struct dentry *root)
8786
{
88-
struct dentry *dir, *file;
87+
struct dentry *dir;
8988
struct diag2fc_data *data;
9089
unsigned int count = 0;
9190
int rc, i;
@@ -100,23 +99,19 @@ int hypfs_vm_create_files(struct dentry *root)
10099
rc = PTR_ERR(dir);
101100
goto failed;
102101
}
103-
file = hypfs_create_str(dir, "type", "z/VM Hypervisor");
104-
if (IS_ERR(file)) {
105-
rc = PTR_ERR(file);
102+
rc = hypfs_create_str(dir, "type", "z/VM Hypervisor");
103+
if (rc)
106104
goto failed;
107-
}
108105

109106
/* physical cpus */
110107
dir = hypfs_mkdir(root, "cpus");
111108
if (IS_ERR(dir)) {
112109
rc = PTR_ERR(dir);
113110
goto failed;
114111
}
115-
file = hypfs_create_u64(dir, "count", data->lcpus);
116-
if (IS_ERR(file)) {
117-
rc = PTR_ERR(file);
112+
rc = hypfs_create_u64(dir, "count", data->lcpus);
113+
if (rc)
118114
goto failed;
119-
}
120115

121116
/* guests */
122117
dir = hypfs_mkdir(root, "systems");

0 commit comments

Comments
 (0)