Skip to content

Commit 1959e18

Browse files
committed
Merge tag 'pull-simple_recursive_removal' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull simple_recursive_removal() update from Al Viro: "Removing subtrees of kernel filesystems is done in quite a few places; unfortunately, it's easy to get wrong. A number of open-coded attempts are out there, with varying amount of bogosities. simple_recursive_removal() had been introduced for doing that with all precautions needed; it does an equivalent of rm -rf, with sufficient locking, eviction of anything mounted on top of the subtree, etc. This series converts a bunch of open-coded instances to using that" * tag 'pull-simple_recursive_removal' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: functionfs, gadgetfs: use simple_recursive_removal() kill binderfs_remove_file() fuse_ctl: use simple_recursive_removal() pstore: switch to locked_recursive_removal() binfmt_misc: switch to locked_recursive_removal() spufs: switch to locked_recursive_removal() add locked_recursive_removal() better lockdep annotations for simple_recursive_removal() simple_recursive_removal(): saner interaction with fsnotify
2 parents 11fe69f + bad356b commit 1959e18

12 files changed

Lines changed: 55 additions & 142 deletions

File tree

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

Lines changed: 9 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -143,42 +143,13 @@ spufs_evict_inode(struct inode *inode)
143143
put_spu_gang(ei->i_gang);
144144
}
145145

146-
static void spufs_prune_dir(struct dentry *dir)
147-
{
148-
struct dentry *dentry;
149-
struct hlist_node *n;
150-
151-
inode_lock(d_inode(dir));
152-
hlist_for_each_entry_safe(dentry, n, &dir->d_children, d_sib) {
153-
spin_lock(&dentry->d_lock);
154-
if (simple_positive(dentry)) {
155-
dget_dlock(dentry);
156-
__d_drop(dentry);
157-
spin_unlock(&dentry->d_lock);
158-
simple_unlink(d_inode(dir), dentry);
159-
/* XXX: what was dcache_lock protecting here? Other
160-
* filesystems (IB, configfs) release dcache_lock
161-
* before unlink */
162-
dput(dentry);
163-
} else {
164-
spin_unlock(&dentry->d_lock);
165-
}
166-
}
167-
shrink_dcache_parent(dir);
168-
inode_unlock(d_inode(dir));
169-
}
170-
171146
/* Caller must hold parent->i_mutex */
172-
static int spufs_rmdir(struct inode *parent, struct dentry *dir)
147+
static void spufs_rmdir(struct inode *parent, struct dentry *dir)
173148
{
174-
/* remove all entries */
175-
int res;
176-
spufs_prune_dir(dir);
177-
d_drop(dir);
178-
res = simple_rmdir(parent, dir);
179-
/* We have to give up the mm_struct */
180-
spu_forget(SPUFS_I(d_inode(dir))->i_ctx);
181-
return res;
149+
struct spu_context *ctx = SPUFS_I(d_inode(dir))->i_ctx;
150+
151+
locked_recursive_removal(dir, NULL);
152+
spu_forget(ctx);
182153
}
183154

184155
static int spufs_fill_dir(struct dentry *dir,
@@ -222,15 +193,13 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
222193
{
223194
struct inode *parent;
224195
struct dentry *dir;
225-
int ret;
226196

227197
dir = file->f_path.dentry;
228198
parent = d_inode(dir->d_parent);
229199

230200
inode_lock_nested(parent, I_MUTEX_PARENT);
231-
ret = spufs_rmdir(parent, dir);
201+
spufs_rmdir(parent, dir);
232202
inode_unlock(parent);
233-
WARN_ON(ret);
234203

235204
unuse_gang(dir->d_parent);
236205
return dcache_dir_close(inode, file);
@@ -288,11 +257,11 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
288257
ret = spufs_fill_dir(dentry, spufs_dir_debug_contents,
289258
mode, ctx);
290259

260+
inode_unlock(inode);
261+
291262
if (ret)
292263
spufs_rmdir(dir, dentry);
293264

294-
inode_unlock(inode);
295-
296265
return ret;
297266
}
298267

@@ -475,7 +444,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
475444

476445
ret = spufs_context_open(&path);
477446
if (ret < 0)
478-
WARN_ON(spufs_rmdir(inode, dentry));
447+
spufs_rmdir(inode, dentry);
479448

480449
out_aff_unlock:
481450
if (affinity)

drivers/android/binder.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6128,7 +6128,7 @@ static int binder_release(struct inode *nodp, struct file *filp)
61286128
debugfs_remove(proc->debugfs_entry);
61296129

61306130
if (proc->binderfs_entry) {
6131-
binderfs_remove_file(proc->binderfs_entry);
6131+
simple_recursive_removal(proc->binderfs_entry, NULL);
61326132
proc->binderfs_entry = NULL;
61336133
}
61346134

drivers/android/binder_internal.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ extern bool is_binderfs_device(const struct inode *inode);
8181
extern struct dentry *binderfs_create_file(struct dentry *dir, const char *name,
8282
const struct file_operations *fops,
8383
void *data);
84-
extern void binderfs_remove_file(struct dentry *dentry);
8584
#else
8685
static inline bool is_binderfs_device(const struct inode *inode)
8786
{
@@ -94,7 +93,6 @@ static inline struct dentry *binderfs_create_file(struct dentry *dir,
9493
{
9594
return NULL;
9695
}
97-
static inline void binderfs_remove_file(struct dentry *dentry) {}
9896
#endif
9997

10098
#ifdef CONFIG_ANDROID_BINDERFS

drivers/android/binderfs.c

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -500,21 +500,6 @@ static struct dentry *binderfs_create_dentry(struct dentry *parent,
500500
return dentry;
501501
}
502502

503-
void binderfs_remove_file(struct dentry *dentry)
504-
{
505-
struct inode *parent_inode;
506-
507-
parent_inode = d_inode(dentry->d_parent);
508-
inode_lock(parent_inode);
509-
if (simple_positive(dentry)) {
510-
dget(dentry);
511-
simple_unlink(parent_inode, dentry);
512-
d_delete(dentry);
513-
dput(dentry);
514-
}
515-
inode_unlock(parent_inode);
516-
}
517-
518503
struct dentry *binderfs_create_file(struct dentry *parent, const char *name,
519504
const struct file_operations *fops,
520505
void *data)

drivers/usb/gadget/function/f_fs.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2369,8 +2369,7 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
23692369
for (; count; --count, ++epfile) {
23702370
BUG_ON(mutex_is_locked(&epfile->mutex));
23712371
if (epfile->dentry) {
2372-
d_delete(epfile->dentry);
2373-
dput(epfile->dentry);
2372+
simple_recursive_removal(epfile->dentry, NULL);
23742373
epfile->dentry = NULL;
23752374
}
23762375
}

drivers/usb/gadget/legacy/inode.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,7 +1561,6 @@ static void destroy_ep_files (struct dev_data *dev)
15611561
spin_lock_irq (&dev->lock);
15621562
while (!list_empty(&dev->epfiles)) {
15631563
struct ep_data *ep;
1564-
struct inode *parent;
15651564
struct dentry *dentry;
15661565

15671566
/* break link to FS */
@@ -1571,7 +1570,6 @@ static void destroy_ep_files (struct dev_data *dev)
15711570

15721571
dentry = ep->dentry;
15731572
ep->dentry = NULL;
1574-
parent = d_inode(dentry->d_parent);
15751573

15761574
/* break link to controller */
15771575
mutex_lock(&ep->lock);
@@ -1586,10 +1584,7 @@ static void destroy_ep_files (struct dev_data *dev)
15861584
put_ep (ep);
15871585

15881586
/* break link to dcache */
1589-
inode_lock(parent);
1590-
d_delete (dentry);
1591-
dput (dentry);
1592-
inode_unlock(parent);
1587+
simple_recursive_removal(dentry, NULL);
15931588

15941589
spin_lock_irq (&dev->lock);
15951590
}

fs/binfmt_misc.c

Lines changed: 3 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -674,44 +674,6 @@ static void bm_evict_inode(struct inode *inode)
674674
}
675675
}
676676

677-
/**
678-
* unlink_binfmt_dentry - remove the dentry for the binary type handler
679-
* @dentry: dentry associated with the binary type handler
680-
*
681-
* Do the actual filesystem work to remove a dentry for a registered binary
682-
* type handler. Since binfmt_misc only allows simple files to be created
683-
* directly under the root dentry of the filesystem we ensure that we are
684-
* indeed passed a dentry directly beneath the root dentry, that the inode
685-
* associated with the root dentry is locked, and that it is a regular file we
686-
* are asked to remove.
687-
*/
688-
static void unlink_binfmt_dentry(struct dentry *dentry)
689-
{
690-
struct dentry *parent = dentry->d_parent;
691-
struct inode *inode, *parent_inode;
692-
693-
/* All entries are immediate descendants of the root dentry. */
694-
if (WARN_ON_ONCE(dentry->d_sb->s_root != parent))
695-
return;
696-
697-
/* We only expect to be called on regular files. */
698-
inode = d_inode(dentry);
699-
if (WARN_ON_ONCE(!S_ISREG(inode->i_mode)))
700-
return;
701-
702-
/* The parent inode must be locked. */
703-
parent_inode = d_inode(parent);
704-
if (WARN_ON_ONCE(!inode_is_locked(parent_inode)))
705-
return;
706-
707-
if (simple_positive(dentry)) {
708-
dget(dentry);
709-
simple_unlink(parent_inode, dentry);
710-
d_delete(dentry);
711-
dput(dentry);
712-
}
713-
}
714-
715677
/**
716678
* remove_binfmt_handler - remove a binary type handler
717679
* @misc: handle to binfmt_misc instance
@@ -729,7 +691,7 @@ static void remove_binfmt_handler(struct binfmt_misc *misc, Node *e)
729691
write_lock(&misc->entries_lock);
730692
list_del_init(&e->list);
731693
write_unlock(&misc->entries_lock);
732-
unlink_binfmt_dentry(e->dentry);
694+
locked_recursive_removal(e->dentry, NULL);
733695
}
734696

735697
/* /<entry> */
@@ -772,7 +734,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
772734
case 3:
773735
/* Delete this handler. */
774736
inode = d_inode(inode->i_sb->s_root);
775-
inode_lock(inode);
737+
inode_lock_nested(inode, I_MUTEX_PARENT);
776738

777739
/*
778740
* In order to add new element or remove elements from the list
@@ -922,7 +884,7 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer,
922884
case 3:
923885
/* Delete all handlers. */
924886
inode = d_inode(file_inode(file)->i_sb->s_root);
925-
inode_lock(inode);
887+
inode_lock_nested(inode, I_MUTEX_PARENT);
926888

927889
/*
928890
* In order to add new element or remove elements from the list

fs/fuse/control.c

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/init.h>
1212
#include <linux/module.h>
1313
#include <linux/fs_context.h>
14+
#include <linux/namei.h>
1415

1516
#define FUSE_CTL_SUPER_MAGIC 0x65735543
1617

@@ -212,7 +213,6 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
212213
struct dentry *dentry;
213214
struct inode *inode;
214215

215-
BUG_ON(fc->ctl_ndents >= FUSE_CTL_NUM_DENTRIES);
216216
dentry = d_alloc_name(parent, name);
217217
if (!dentry)
218218
return NULL;
@@ -236,8 +236,6 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
236236
inode->i_private = fc;
237237
d_add(dentry, inode);
238238

239-
fc->ctl_dentry[fc->ctl_ndents++] = dentry;
240-
241239
return dentry;
242240
}
243241

@@ -280,27 +278,29 @@ int fuse_ctl_add_conn(struct fuse_conn *fc)
280278
return -ENOMEM;
281279
}
282280

281+
static void remove_one(struct dentry *dentry)
282+
{
283+
d_inode(dentry)->i_private = NULL;
284+
}
285+
283286
/*
284287
* Remove a connection from the control filesystem (if it exists).
285288
* Caller must hold fuse_mutex
286289
*/
287290
void fuse_ctl_remove_conn(struct fuse_conn *fc)
288291
{
289-
int i;
292+
struct dentry *dentry;
293+
char name[32];
290294

291295
if (!fuse_control_sb || fc->no_control)
292296
return;
293297

294-
for (i = fc->ctl_ndents - 1; i >= 0; i--) {
295-
struct dentry *dentry = fc->ctl_dentry[i];
296-
d_inode(dentry)->i_private = NULL;
297-
if (!i) {
298-
/* Get rid of submounts: */
299-
d_invalidate(dentry);
300-
}
301-
dput(dentry);
298+
sprintf(name, "%u", fc->dev);
299+
dentry = lookup_noperm_positive_unlocked(&QSTR(name), fuse_control_sb->s_root);
300+
if (!IS_ERR(dentry)) {
301+
simple_recursive_removal(dentry, remove_one);
302+
dput(dentry); // paired with lookup_noperm_positive_unlocked()
302303
}
303-
drop_nlink(d_inode(fuse_control_sb->s_root));
304304
}
305305

306306
static int fuse_ctl_fill_super(struct super_block *sb, struct fs_context *fsc)
@@ -346,12 +346,8 @@ static int fuse_ctl_init_fs_context(struct fs_context *fsc)
346346

347347
static void fuse_ctl_kill_sb(struct super_block *sb)
348348
{
349-
struct fuse_conn *fc;
350-
351349
mutex_lock(&fuse_mutex);
352350
fuse_control_sb = NULL;
353-
list_for_each_entry(fc, &fuse_conn_list, entry)
354-
fc->ctl_ndents = 0;
355351
mutex_unlock(&fuse_mutex);
356352

357353
kill_litter_super(sb);

fs/fuse/fuse_i.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -913,12 +913,6 @@ struct fuse_conn {
913913
/** Device ID from the root super block */
914914
dev_t dev;
915915

916-
/** Dentries in the control filesystem */
917-
struct dentry *ctl_dentry[FUSE_CTL_NUM_DENTRIES];
918-
919-
/** number of dentries used in the above array */
920-
int ctl_ndents;
921-
922916
/** Key for lock owner ID scrambling */
923917
u32 scramble_key[4];
924918

0 commit comments

Comments
 (0)