Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4e11180 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  vfs: new helper - d_make_root()
  dcache: use a dispose list in select_parent
  ceph: d_alloc_root() may fail
  ext4: fix failure exits
  isofs: inode leak on mount failure
parents 37cfc3f6 adc0e91a
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -636,19 +636,26 @@ static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
	req->r_num_caps = 2;
	err = ceph_mdsc_do_request(mdsc, NULL, req);
	if (err == 0) {
		struct inode *inode = req->r_target_inode;
		req->r_target_inode = NULL;
		dout("open_root_inode success\n");
		if (ceph_ino(req->r_target_inode) == CEPH_INO_ROOT &&
		if (ceph_ino(inode) == CEPH_INO_ROOT &&
		    fsc->sb->s_root == NULL) {
			root = d_alloc_root(req->r_target_inode);
			root = d_alloc_root(inode);
			if (!root) {
				iput(inode);
				root = ERR_PTR(-ENOMEM);
				goto out;
			}
			ceph_init_dentry(root);
		} else {
			root = d_obtain_alias(req->r_target_inode);
			root = d_obtain_alias(inode);
		}
		req->r_target_inode = NULL;
		dout("open_root_inode success, root dentry is %p\n", root);
	} else {
		root = ERR_PTR(err);
	}
out:
	ceph_mdsc_put_request(req);
	return root;
}
+38 −42
Original line number Diff line number Diff line
@@ -276,15 +276,15 @@ static void dentry_lru_prune(struct dentry *dentry)
	}
}

static void dentry_lru_move_tail(struct dentry *dentry)
static void dentry_lru_move_list(struct dentry *dentry, struct list_head *list)
{
	spin_lock(&dcache_lru_lock);
	if (list_empty(&dentry->d_lru)) {
		list_add_tail(&dentry->d_lru, &dentry->d_sb->s_dentry_lru);
		list_add_tail(&dentry->d_lru, list);
		dentry->d_sb->s_nr_dentry_unused++;
		dentry_stat.nr_unused++;
	} else {
		list_move_tail(&dentry->d_lru, &dentry->d_sb->s_dentry_lru);
		list_move_tail(&dentry->d_lru, list);
	}
	spin_unlock(&dcache_lru_lock);
}
@@ -770,14 +770,18 @@ static void shrink_dentry_list(struct list_head *list)
}

/**
 * __shrink_dcache_sb - shrink the dentry LRU on a given superblock
 * @sb:		superblock to shrink dentry LRU.
 * @count:	number of entries to prune
 * @flags:	flags to control the dentry processing
 * prune_dcache_sb - shrink the dcache
 * @sb: superblock
 * @count: number of entries to try to free
 *
 * Attempt to shrink the superblock dcache LRU by @count entries. This is
 * done when we need more memory an called from the superblock shrinker
 * function.
 *
 * If flags contains DCACHE_REFERENCED reference dentries will not be pruned.
 * This function may fail to free any resources if all the dentries are in
 * use.
 */
static void __shrink_dcache_sb(struct super_block *sb, int count, int flags)
void prune_dcache_sb(struct super_block *sb, int count)
{
	struct dentry *dentry;
	LIST_HEAD(referenced);
@@ -796,13 +800,7 @@ relock:
			goto relock;
		}

		/*
		 * If we are honouring the DCACHE_REFERENCED flag and the
		 * dentry has this flag set, don't free it.  Clear the flag
		 * and put it back on the LRU.
		 */
		if (flags & DCACHE_REFERENCED &&
				dentry->d_flags & DCACHE_REFERENCED) {
		if (dentry->d_flags & DCACHE_REFERENCED) {
			dentry->d_flags &= ~DCACHE_REFERENCED;
			list_move(&dentry->d_lru, &referenced);
			spin_unlock(&dentry->d_lock);
@@ -821,23 +819,6 @@ relock:
	shrink_dentry_list(&tmp);
}

/**
 * prune_dcache_sb - shrink the dcache
 * @sb: superblock
 * @nr_to_scan: number of entries to try to free
 *
 * Attempt to shrink the superblock dcache LRU by @nr_to_scan entries. This is
 * done when we need more memory an called from the superblock shrinker
 * function.
 *
 * This function may fail to free any resources if all the dentries are in
 * use.
 */
void prune_dcache_sb(struct super_block *sb, int nr_to_scan)
{
	__shrink_dcache_sb(sb, nr_to_scan, DCACHE_REFERENCED);
}

/**
 * shrink_dcache_sb - shrink dcache for a superblock
 * @sb: superblock
@@ -1092,7 +1073,7 @@ EXPORT_SYMBOL(have_submounts);
 * drop the lock and return early due to latency
 * constraints.
 */
static int select_parent(struct dentry * parent)
static int select_parent(struct dentry *parent, struct list_head *dispose)
{
	struct dentry *this_parent;
	struct list_head *next;
@@ -1115,11 +1096,10 @@ resume:
		spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);

		/*
		 * move only zero ref count dentries to the end 
		 * of the unused list for prune_dcache
		 * move only zero ref count dentries to the dispose list.
		 */
		if (!dentry->d_count) {
			dentry_lru_move_tail(dentry);
			dentry_lru_move_list(dentry, dispose);
			found++;
		} else {
			dentry_lru_del(dentry);
@@ -1181,14 +1161,13 @@ rename_retry:
 *
 * Prune the dcache to remove unused children of the parent dentry.
 */
 
void shrink_dcache_parent(struct dentry * parent)
{
	struct super_block *sb = parent->d_sb;
	LIST_HEAD(dispose);
	int found;

	while ((found = select_parent(parent)) != 0)
		__shrink_dcache_sb(sb, found, 0);
	while ((found = select_parent(parent, &dispose)) != 0)
		shrink_dentry_list(&dispose);
}
EXPORT_SYMBOL(shrink_dcache_parent);

@@ -1461,6 +1440,23 @@ struct dentry * d_alloc_root(struct inode * root_inode)
}
EXPORT_SYMBOL(d_alloc_root);

struct dentry *d_make_root(struct inode *root_inode)
{
	struct dentry *res = NULL;

	if (root_inode) {
		static const struct qstr name = { .name = "/", .len = 1 };

		res = __d_alloc(root_inode->i_sb, &name);
		if (res)
			d_instantiate(res, root_inode);
		else
			iput(root_inode);
	}
	return res;
}
EXPORT_SYMBOL(d_make_root);

static struct dentry * __d_find_any_alias(struct inode *inode)
{
	struct dentry *alias;
+8 −5
Original line number Diff line number Diff line
@@ -3733,10 +3733,12 @@ no_journal:
	}
	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
		ext4_msg(sb, KERN_ERR, "corrupt root inode, run e2fsck");
		iput(root);
		goto failed_mount4;
	}
	sb->s_root = d_alloc_root(root);
	if (!sb->s_root) {
		iput(root);
		ext4_msg(sb, KERN_ERR, "get root dentry failed");
		ret = -ENOMEM;
		goto failed_mount4;
@@ -3773,7 +3775,7 @@ no_journal:
	if (err) {
		ext4_msg(sb, KERN_ERR, "failed to initialize system "
			 "zone (%d)", err);
		goto failed_mount4;
		goto failed_mount4a;
	}

	ext4_ext_init(sb);
@@ -3830,13 +3832,14 @@ cantfind_ext4:
failed_mount7:
	ext4_unregister_li_request(sb);
failed_mount6:
	ext4_ext_release(sb);
failed_mount5:
	ext4_mb_release(sb);
failed_mount5:
	ext4_ext_release(sb);
	ext4_release_system_zone(sb);
failed_mount4:
	iput(root);
failed_mount4a:
	dput(sb->s_root);
	sb->s_root = NULL;
failed_mount4:
	ext4_msg(sb, KERN_ERR, "mount failed");
	destroy_workqueue(EXT4_SB(sb)->dio_unwritten_wq);
failed_mount_wq:
+5 −2
Original line number Diff line number Diff line
@@ -948,8 +948,11 @@ root_found:

	/* get the root dentry */
	s->s_root = d_alloc_root(inode);
	if (!(s->s_root))
		goto out_no_root;
	if (!(s->s_root)) {
		iput(inode);
		error = -ENOMEM;
		goto out_no_inode;
	}

	kfree(opt.iocharset);

+1 −0
Original line number Diff line number Diff line
@@ -249,6 +249,7 @@ extern int d_invalidate(struct dentry *);

/* only used at mount-time */
extern struct dentry * d_alloc_root(struct inode *);
extern struct dentry * d_make_root(struct inode *);

/* <clickety>-<click> the ramfs-type tree */
extern void d_genocide(struct dentry *);