Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull more vfs stuff from Al Viro: "O_TMPFILE ABI changes, Oleg's fput() series, misc cleanups, including making simple_lookup() usable for filesystems with non-NULL s_d_op, which allows us to get rid of quite a bit of ugliness" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: sunrpc: now we can just set ->s_d_op cgroup: we can use simple_lookup() now efivarfs: we can use simple_lookup() now make simple_lookup() usable for filesystems that set ->s_d_op configfs: don't open-code d_alloc_name() __rpc_lookup_create_exclusive: pass string instead of qstr rpc_create_*_dir: don't bother with qstr llist: llist_add() can use llist_add_batch() llist: fix/simplify llist_add() and llist_add_batch() fput: turn "list_head delayed_fput_list" into llist_head fs/file_table.c:fput(): add comment Safer ABI for O_TMPFILE
This commit is contained in:
		
				commit
				
					
						41d9884c44
					
				
			
		
					 18 changed files with 73 additions and 137 deletions
				
			
		| 
						 | 
					@ -32,7 +32,7 @@
 | 
				
			||||||
#define O_SYNC		(__O_SYNC|O_DSYNC)
 | 
					#define O_SYNC		(__O_SYNC|O_DSYNC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define O_PATH		040000000
 | 
					#define O_PATH		040000000
 | 
				
			||||||
#define O_TMPFILE	0100000000
 | 
					#define __O_TMPFILE	0100000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define F_GETLK		7
 | 
					#define F_GETLK		7
 | 
				
			||||||
#define F_SETLK		8
 | 
					#define F_SETLK		8
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@
 | 
				
			||||||
#define O_INVISIBLE	004000000 /* invisible I/O, for DMAPI/XDSM */
 | 
					#define O_INVISIBLE	004000000 /* invisible I/O, for DMAPI/XDSM */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define O_PATH		020000000
 | 
					#define O_PATH		020000000
 | 
				
			||||||
#define O_TMPFILE	040000000
 | 
					#define __O_TMPFILE	040000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define F_GETLK64	8
 | 
					#define F_GETLK64	8
 | 
				
			||||||
#define F_SETLK64	9
 | 
					#define F_SETLK64	9
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,7 @@
 | 
				
			||||||
#define O_SYNC		(__O_SYNC|O_DSYNC)
 | 
					#define O_SYNC		(__O_SYNC|O_DSYNC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define O_PATH		0x1000000
 | 
					#define O_PATH		0x1000000
 | 
				
			||||||
#define O_TMPFILE	0x2000000
 | 
					#define __O_TMPFILE	0x2000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define F_GETOWN	5	/*  for sockets. */
 | 
					#define F_GETOWN	5	/*  for sockets. */
 | 
				
			||||||
#define F_SETOWN	6	/*  for sockets. */
 | 
					#define F_SETOWN	6	/*  for sockets. */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -660,19 +660,15 @@ static int create_default_group(struct config_group *parent_group,
 | 
				
			||||||
				struct config_group *group)
 | 
									struct config_group *group)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	struct qstr name;
 | 
					 | 
				
			||||||
	struct configfs_dirent *sd;
 | 
						struct configfs_dirent *sd;
 | 
				
			||||||
	/* We trust the caller holds a reference to parent */
 | 
						/* We trust the caller holds a reference to parent */
 | 
				
			||||||
	struct dentry *child, *parent = parent_group->cg_item.ci_dentry;
 | 
						struct dentry *child, *parent = parent_group->cg_item.ci_dentry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!group->cg_item.ci_name)
 | 
						if (!group->cg_item.ci_name)
 | 
				
			||||||
		group->cg_item.ci_name = group->cg_item.ci_namebuf;
 | 
							group->cg_item.ci_name = group->cg_item.ci_namebuf;
 | 
				
			||||||
	name.name = group->cg_item.ci_name;
 | 
					 | 
				
			||||||
	name.len = strlen(name.name);
 | 
					 | 
				
			||||||
	name.hash = full_name_hash(name.name, name.len);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = -ENOMEM;
 | 
						ret = -ENOMEM;
 | 
				
			||||||
	child = d_alloc(parent, &name);
 | 
						child = d_alloc_name(parent, group->cg_item.ci_name);
 | 
				
			||||||
	if (child) {
 | 
						if (child) {
 | 
				
			||||||
		d_add(child, NULL);
 | 
							d_add(child, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1650,7 +1646,6 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
	struct config_group *group = &subsys->su_group;
 | 
						struct config_group *group = &subsys->su_group;
 | 
				
			||||||
	struct qstr name;
 | 
					 | 
				
			||||||
	struct dentry *dentry;
 | 
						struct dentry *dentry;
 | 
				
			||||||
	struct dentry *root;
 | 
						struct dentry *root;
 | 
				
			||||||
	struct configfs_dirent *sd;
 | 
						struct configfs_dirent *sd;
 | 
				
			||||||
| 
						 | 
					@ -1667,12 +1662,8 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_PARENT);
 | 
						mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_PARENT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	name.name = group->cg_item.ci_name;
 | 
					 | 
				
			||||||
	name.len = strlen(name.name);
 | 
					 | 
				
			||||||
	name.hash = full_name_hash(name.name, name.len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = -ENOMEM;
 | 
						err = -ENOMEM;
 | 
				
			||||||
	dentry = d_alloc(root, &name);
 | 
						dentry = d_alloc_name(root, group->cg_item.ci_name);
 | 
				
			||||||
	if (dentry) {
 | 
						if (dentry) {
 | 
				
			||||||
		d_add(dentry, NULL);
 | 
							d_add(dentry, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,20 +155,8 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Handle negative dentry.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static struct dentry *efivarfs_lookup(struct inode *dir, struct dentry *dentry,
 | 
					 | 
				
			||||||
				      unsigned int flags)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (dentry->d_name.len > NAME_MAX)
 | 
					 | 
				
			||||||
		return ERR_PTR(-ENAMETOOLONG);
 | 
					 | 
				
			||||||
	d_add(dentry, NULL);
 | 
					 | 
				
			||||||
	return NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const struct inode_operations efivarfs_dir_inode_operations = {
 | 
					const struct inode_operations efivarfs_dir_inode_operations = {
 | 
				
			||||||
	.lookup = efivarfs_lookup,
 | 
						.lookup = simple_lookup,
 | 
				
			||||||
	.unlink = efivarfs_unlink,
 | 
						.unlink = efivarfs_unlink,
 | 
				
			||||||
	.create = efivarfs_create,
 | 
						.create = efivarfs_create,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -265,18 +265,15 @@ static void __fput(struct file *file)
 | 
				
			||||||
	mntput(mnt);
 | 
						mntput(mnt);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static DEFINE_SPINLOCK(delayed_fput_lock);
 | 
					static LLIST_HEAD(delayed_fput_list);
 | 
				
			||||||
static LIST_HEAD(delayed_fput_list);
 | 
					 | 
				
			||||||
static void delayed_fput(struct work_struct *unused)
 | 
					static void delayed_fput(struct work_struct *unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	LIST_HEAD(head);
 | 
						struct llist_node *node = llist_del_all(&delayed_fput_list);
 | 
				
			||||||
	spin_lock_irq(&delayed_fput_lock);
 | 
						struct llist_node *next;
 | 
				
			||||||
	list_splice_init(&delayed_fput_list, &head);
 | 
					
 | 
				
			||||||
	spin_unlock_irq(&delayed_fput_lock);
 | 
						for (; node; node = next) {
 | 
				
			||||||
	while (!list_empty(&head)) {
 | 
							next = llist_next(node);
 | 
				
			||||||
		struct file *f = list_first_entry(&head, struct file, f_u.fu_list);
 | 
							__fput(llist_entry(node, struct file, f_u.fu_llist));
 | 
				
			||||||
		list_del_init(&f->f_u.fu_list);
 | 
					 | 
				
			||||||
		__fput(f);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -306,18 +303,22 @@ void fput(struct file *file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (atomic_long_dec_and_test(&file->f_count)) {
 | 
						if (atomic_long_dec_and_test(&file->f_count)) {
 | 
				
			||||||
		struct task_struct *task = current;
 | 
							struct task_struct *task = current;
 | 
				
			||||||
		unsigned long flags;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		file_sb_list_del(file);
 | 
							file_sb_list_del(file);
 | 
				
			||||||
		if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) {
 | 
							if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) {
 | 
				
			||||||
			init_task_work(&file->f_u.fu_rcuhead, ____fput);
 | 
								init_task_work(&file->f_u.fu_rcuhead, ____fput);
 | 
				
			||||||
			if (!task_work_add(task, &file->f_u.fu_rcuhead, true))
 | 
								if (!task_work_add(task, &file->f_u.fu_rcuhead, true))
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * After this task has run exit_task_work(),
 | 
				
			||||||
 | 
								 * task_work_add() will fail.  free_ipc_ns()->
 | 
				
			||||||
 | 
								 * shm_destroy() can do this.  Fall through to delayed
 | 
				
			||||||
 | 
								 * fput to avoid leaking *file.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		spin_lock_irqsave(&delayed_fput_lock, flags);
 | 
					
 | 
				
			||||||
		list_add(&file->f_u.fu_list, &delayed_fput_list);
 | 
							if (llist_add(&file->f_u.fu_llist, &delayed_fput_list))
 | 
				
			||||||
		schedule_work(&delayed_fput_work);
 | 
								schedule_work(&delayed_fput_work);
 | 
				
			||||||
		spin_unlock_irqrestore(&delayed_fput_lock, flags);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,7 +61,8 @@ struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, unsigned
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dentry->d_name.len > NAME_MAX)
 | 
						if (dentry->d_name.len > NAME_MAX)
 | 
				
			||||||
		return ERR_PTR(-ENAMETOOLONG);
 | 
							return ERR_PTR(-ENAMETOOLONG);
 | 
				
			||||||
	d_set_d_op(dentry, &simple_dentry_operations);
 | 
						if (!dentry->d_sb->s_d_op)
 | 
				
			||||||
 | 
							d_set_d_op(dentry, &simple_dentry_operations);
 | 
				
			||||||
	d_add(dentry, NULL);
 | 
						d_add(dentry, NULL);
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2977,7 +2977,7 @@ static struct file *path_openat(int dfd, struct filename *pathname,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	file->f_flags = op->open_flag;
 | 
						file->f_flags = op->open_flag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (unlikely(file->f_flags & O_TMPFILE)) {
 | 
						if (unlikely(file->f_flags & __O_TMPFILE)) {
 | 
				
			||||||
		error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened);
 | 
							error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened);
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -840,8 +840,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
 | 
				
			||||||
	if (flags & __O_SYNC)
 | 
						if (flags & __O_SYNC)
 | 
				
			||||||
		flags |= O_DSYNC;
 | 
							flags |= O_DSYNC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (flags & O_TMPFILE) {
 | 
						if (flags & __O_TMPFILE) {
 | 
				
			||||||
		if (!(flags & O_CREAT))
 | 
							if ((flags & O_TMPFILE_MASK) != O_TMPFILE)
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
		acc_mode = MAY_OPEN | ACC_MODE(flags);
 | 
							acc_mode = MAY_OPEN | ACC_MODE(flags);
 | 
				
			||||||
	} else if (flags & O_PATH) {
 | 
						} else if (flags & O_PATH) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,7 @@
 | 
				
			||||||
#include <linux/stat.h>
 | 
					#include <linux/stat.h>
 | 
				
			||||||
#include <linux/cache.h>
 | 
					#include <linux/cache.h>
 | 
				
			||||||
#include <linux/list.h>
 | 
					#include <linux/list.h>
 | 
				
			||||||
 | 
					#include <linux/llist.h>
 | 
				
			||||||
#include <linux/radix-tree.h>
 | 
					#include <linux/radix-tree.h>
 | 
				
			||||||
#include <linux/rbtree.h>
 | 
					#include <linux/rbtree.h>
 | 
				
			||||||
#include <linux/init.h>
 | 
					#include <linux/init.h>
 | 
				
			||||||
| 
						 | 
					@ -768,6 +769,7 @@ struct file {
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	union {
 | 
						union {
 | 
				
			||||||
		struct list_head	fu_list;
 | 
							struct list_head	fu_list;
 | 
				
			||||||
 | 
							struct llist_node	fu_llist;
 | 
				
			||||||
		struct rcu_head 	fu_rcuhead;
 | 
							struct rcu_head 	fu_rcuhead;
 | 
				
			||||||
	} f_u;
 | 
						} f_u;
 | 
				
			||||||
	struct path		f_path;
 | 
						struct path		f_path;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -142,6 +142,9 @@ static inline struct llist_node *llist_next(struct llist_node *node)
 | 
				
			||||||
	return node->next;
 | 
						return node->next;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern bool llist_add_batch(struct llist_node *new_first,
 | 
				
			||||||
 | 
								    struct llist_node *new_last,
 | 
				
			||||||
 | 
								    struct llist_head *head);
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * llist_add - add a new entry
 | 
					 * llist_add - add a new entry
 | 
				
			||||||
 * @new:	new entry to be added
 | 
					 * @new:	new entry to be added
 | 
				
			||||||
| 
						 | 
					@ -151,18 +154,7 @@ static inline struct llist_node *llist_next(struct llist_node *node)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static inline bool llist_add(struct llist_node *new, struct llist_head *head)
 | 
					static inline bool llist_add(struct llist_node *new, struct llist_head *head)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct llist_node *entry, *old_entry;
 | 
						return llist_add_batch(new, new, head);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	entry = head->first;
 | 
					 | 
				
			||||||
	for (;;) {
 | 
					 | 
				
			||||||
		old_entry = entry;
 | 
					 | 
				
			||||||
		new->next = entry;
 | 
					 | 
				
			||||||
		entry = cmpxchg(&head->first, old_entry, new);
 | 
					 | 
				
			||||||
		if (entry == old_entry)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return old_entry == NULL;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -178,9 +170,6 @@ static inline struct llist_node *llist_del_all(struct llist_head *head)
 | 
				
			||||||
	return xchg(&head->first, NULL);
 | 
						return xchg(&head->first, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern bool llist_add_batch(struct llist_node *new_first,
 | 
					 | 
				
			||||||
			    struct llist_node *new_last,
 | 
					 | 
				
			||||||
			    struct llist_head *head);
 | 
					 | 
				
			||||||
extern struct llist_node *llist_del_first(struct llist_head *head);
 | 
					extern struct llist_node *llist_del_first(struct llist_head *head);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* LLIST_H */
 | 
					#endif /* LLIST_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,12 +73,12 @@ extern ssize_t rpc_pipe_generic_upcall(struct file *, struct rpc_pipe_msg *,
 | 
				
			||||||
extern int rpc_queue_upcall(struct rpc_pipe *, struct rpc_pipe_msg *);
 | 
					extern int rpc_queue_upcall(struct rpc_pipe *, struct rpc_pipe_msg *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct rpc_clnt;
 | 
					struct rpc_clnt;
 | 
				
			||||||
extern struct dentry *rpc_create_client_dir(struct dentry *, struct qstr *, struct rpc_clnt *);
 | 
					extern struct dentry *rpc_create_client_dir(struct dentry *, const char *, struct rpc_clnt *);
 | 
				
			||||||
extern int rpc_remove_client_dir(struct dentry *);
 | 
					extern int rpc_remove_client_dir(struct dentry *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct cache_detail;
 | 
					struct cache_detail;
 | 
				
			||||||
extern struct dentry *rpc_create_cache_dir(struct dentry *,
 | 
					extern struct dentry *rpc_create_cache_dir(struct dentry *,
 | 
				
			||||||
					   struct qstr *,
 | 
										   const char *,
 | 
				
			||||||
					   umode_t umode,
 | 
										   umode_t umode,
 | 
				
			||||||
					   struct cache_detail *);
 | 
										   struct cache_detail *);
 | 
				
			||||||
extern void rpc_remove_cache_dir(struct dentry *);
 | 
					extern void rpc_remove_cache_dir(struct dentry *);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -84,10 +84,14 @@
 | 
				
			||||||
#define O_PATH		010000000
 | 
					#define O_PATH		010000000
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef O_TMPFILE
 | 
					#ifndef __O_TMPFILE
 | 
				
			||||||
#define O_TMPFILE	020000000
 | 
					#define __O_TMPFILE	020000000
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* a horrid kludge trying to make sure that this will fail on old kernels */
 | 
				
			||||||
 | 
					#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY | O_RDWR)
 | 
				
			||||||
 | 
					#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT | O_ACCMODE)      
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef O_NDELAY
 | 
					#ifndef O_NDELAY
 | 
				
			||||||
#define O_NDELAY	O_NONBLOCK
 | 
					#define O_NDELAY	O_NONBLOCK
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -802,7 +802,6 @@ static struct cgroup *task_cgroup_from_root(struct task_struct *task,
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
 | 
					static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
 | 
				
			||||||
static struct dentry *cgroup_lookup(struct inode *, struct dentry *, unsigned int);
 | 
					 | 
				
			||||||
static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry);
 | 
					static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry);
 | 
				
			||||||
static int cgroup_populate_dir(struct cgroup *cgrp, bool base_files,
 | 
					static int cgroup_populate_dir(struct cgroup *cgrp, bool base_files,
 | 
				
			||||||
			       unsigned long subsys_mask);
 | 
								       unsigned long subsys_mask);
 | 
				
			||||||
| 
						 | 
					@ -2642,7 +2641,7 @@ static const struct inode_operations cgroup_file_inode_operations = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct inode_operations cgroup_dir_inode_operations = {
 | 
					static const struct inode_operations cgroup_dir_inode_operations = {
 | 
				
			||||||
	.lookup = cgroup_lookup,
 | 
						.lookup = simple_lookup,
 | 
				
			||||||
	.mkdir = cgroup_mkdir,
 | 
						.mkdir = cgroup_mkdir,
 | 
				
			||||||
	.rmdir = cgroup_rmdir,
 | 
						.rmdir = cgroup_rmdir,
 | 
				
			||||||
	.rename = cgroup_rename,
 | 
						.rename = cgroup_rename,
 | 
				
			||||||
| 
						 | 
					@ -2652,14 +2651,6 @@ static const struct inode_operations cgroup_dir_inode_operations = {
 | 
				
			||||||
	.removexattr = cgroup_removexattr,
 | 
						.removexattr = cgroup_removexattr,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct dentry *cgroup_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (dentry->d_name.len > NAME_MAX)
 | 
					 | 
				
			||||||
		return ERR_PTR(-ENAMETOOLONG);
 | 
					 | 
				
			||||||
	d_add(dentry, NULL);
 | 
					 | 
				
			||||||
	return NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Check if a file is a control file
 | 
					 * Check if a file is a control file
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								lib/llist.c
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								lib/llist.c
									
										
									
									
									
								
							| 
						 | 
					@ -39,18 +39,13 @@
 | 
				
			||||||
bool llist_add_batch(struct llist_node *new_first, struct llist_node *new_last,
 | 
					bool llist_add_batch(struct llist_node *new_first, struct llist_node *new_last,
 | 
				
			||||||
		     struct llist_head *head)
 | 
							     struct llist_head *head)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct llist_node *entry, *old_entry;
 | 
						struct llist_node *first;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	entry = head->first;
 | 
						do {
 | 
				
			||||||
	for (;;) {
 | 
							new_last->next = first = ACCESS_ONCE(head->first);
 | 
				
			||||||
		old_entry = entry;
 | 
						} while (cmpxchg(&head->first, first, new_first) != first);
 | 
				
			||||||
		new_last->next = entry;
 | 
					 | 
				
			||||||
		entry = cmpxchg(&head->first, old_entry, new_first);
 | 
					 | 
				
			||||||
		if (entry == old_entry)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return old_entry == NULL;
 | 
						return !first;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(llist_add_batch);
 | 
					EXPORT_SYMBOL_GPL(llist_add_batch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1823,19 +1823,11 @@ int sunrpc_cache_register_pipefs(struct dentry *parent,
 | 
				
			||||||
				 const char *name, umode_t umode,
 | 
									 const char *name, umode_t umode,
 | 
				
			||||||
				 struct cache_detail *cd)
 | 
									 struct cache_detail *cd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct qstr q;
 | 
						struct dentry *dir = rpc_create_cache_dir(parent, name, umode, cd);
 | 
				
			||||||
	struct dentry *dir;
 | 
						if (IS_ERR(dir))
 | 
				
			||||||
	int ret = 0;
 | 
							return PTR_ERR(dir);
 | 
				
			||||||
 | 
						cd->u.pipefs.dir = dir;
 | 
				
			||||||
	q.name = name;
 | 
						return 0;
 | 
				
			||||||
	q.len = strlen(name);
 | 
					 | 
				
			||||||
	q.hash = full_name_hash(q.name, q.len);
 | 
					 | 
				
			||||||
	dir = rpc_create_cache_dir(parent, &q, umode, cd);
 | 
					 | 
				
			||||||
	if (!IS_ERR(dir))
 | 
					 | 
				
			||||||
		cd->u.pipefs.dir = dir;
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		ret = PTR_ERR(dir);
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(sunrpc_cache_register_pipefs);
 | 
					EXPORT_SYMBOL_GPL(sunrpc_cache_register_pipefs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -128,9 +128,7 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static uint32_t clntid;
 | 
						static uint32_t clntid;
 | 
				
			||||||
	char name[15];
 | 
						char name[15];
 | 
				
			||||||
	struct qstr q = { .name = name };
 | 
					 | 
				
			||||||
	struct dentry *dir, *dentry;
 | 
						struct dentry *dir, *dentry;
 | 
				
			||||||
	int error;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dir = rpc_d_lookup_sb(sb, dir_name);
 | 
						dir = rpc_d_lookup_sb(sb, dir_name);
 | 
				
			||||||
	if (dir == NULL) {
 | 
						if (dir == NULL) {
 | 
				
			||||||
| 
						 | 
					@ -138,19 +136,17 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
 | 
				
			||||||
		return dir;
 | 
							return dir;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for (;;) {
 | 
						for (;;) {
 | 
				
			||||||
		q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++);
 | 
							snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++);
 | 
				
			||||||
		name[sizeof(name) - 1] = '\0';
 | 
							name[sizeof(name) - 1] = '\0';
 | 
				
			||||||
		q.hash = full_name_hash(q.name, q.len);
 | 
							dentry = rpc_create_client_dir(dir, name, clnt);
 | 
				
			||||||
		dentry = rpc_create_client_dir(dir, &q, clnt);
 | 
					 | 
				
			||||||
		if (!IS_ERR(dentry))
 | 
							if (!IS_ERR(dentry))
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		error = PTR_ERR(dentry);
 | 
							if (dentry == ERR_PTR(-EEXIST))
 | 
				
			||||||
		if (error != -EEXIST) {
 | 
								continue;
 | 
				
			||||||
			printk(KERN_INFO "RPC: Couldn't create pipefs entry"
 | 
							printk(KERN_INFO "RPC: Couldn't create pipefs entry"
 | 
				
			||||||
					" %s/%s, error %d\n",
 | 
									" %s/%s, error %ld\n",
 | 
				
			||||||
					dir_name, name, error);
 | 
									dir_name, name, PTR_ERR(dentry));
 | 
				
			||||||
			break;
 | 
							break;
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dput(dir);
 | 
						dput(dir);
 | 
				
			||||||
	return dentry;
 | 
						return dentry;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -673,13 +673,12 @@ static int __rpc_rmpipe(struct inode *dir, struct dentry *dentry)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent,
 | 
					static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent,
 | 
				
			||||||
					  struct qstr *name)
 | 
										  const char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dentry *dentry;
 | 
						struct qstr q = QSTR_INIT(name, strlen(name));
 | 
				
			||||||
 | 
						struct dentry *dentry = d_hash_and_lookup(parent, &q);
 | 
				
			||||||
	dentry = d_lookup(parent, name);
 | 
					 | 
				
			||||||
	if (!dentry) {
 | 
						if (!dentry) {
 | 
				
			||||||
		dentry = d_alloc(parent, name);
 | 
							dentry = d_alloc(parent, &q);
 | 
				
			||||||
		if (!dentry)
 | 
							if (!dentry)
 | 
				
			||||||
			return ERR_PTR(-ENOMEM);
 | 
								return ERR_PTR(-ENOMEM);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -704,8 +703,7 @@ static void __rpc_depopulate(struct dentry *parent,
 | 
				
			||||||
	for (i = start; i < eof; i++) {
 | 
						for (i = start; i < eof; i++) {
 | 
				
			||||||
		name.name = files[i].name;
 | 
							name.name = files[i].name;
 | 
				
			||||||
		name.len = strlen(files[i].name);
 | 
							name.len = strlen(files[i].name);
 | 
				
			||||||
		name.hash = full_name_hash(name.name, name.len);
 | 
							dentry = d_hash_and_lookup(parent, &name);
 | 
				
			||||||
		dentry = d_lookup(parent, &name);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (dentry == NULL)
 | 
							if (dentry == NULL)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
| 
						 | 
					@ -747,12 +745,7 @@ static int rpc_populate(struct dentry *parent,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&dir->i_mutex);
 | 
						mutex_lock(&dir->i_mutex);
 | 
				
			||||||
	for (i = start; i < eof; i++) {
 | 
						for (i = start; i < eof; i++) {
 | 
				
			||||||
		struct qstr q;
 | 
							dentry = __rpc_lookup_create_exclusive(parent, files[i].name);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		q.name = files[i].name;
 | 
					 | 
				
			||||||
		q.len = strlen(files[i].name);
 | 
					 | 
				
			||||||
		q.hash = full_name_hash(q.name, q.len);
 | 
					 | 
				
			||||||
		dentry = __rpc_lookup_create_exclusive(parent, &q);
 | 
					 | 
				
			||||||
		err = PTR_ERR(dentry);
 | 
							err = PTR_ERR(dentry);
 | 
				
			||||||
		if (IS_ERR(dentry))
 | 
							if (IS_ERR(dentry))
 | 
				
			||||||
			goto out_bad;
 | 
								goto out_bad;
 | 
				
			||||||
| 
						 | 
					@ -785,7 +778,7 @@ out_bad:
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct dentry *rpc_mkdir_populate(struct dentry *parent,
 | 
					static struct dentry *rpc_mkdir_populate(struct dentry *parent,
 | 
				
			||||||
		struct qstr *name, umode_t mode, void *private,
 | 
							const char *name, umode_t mode, void *private,
 | 
				
			||||||
		int (*populate)(struct dentry *, void *), void *args_populate)
 | 
							int (*populate)(struct dentry *, void *), void *args_populate)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dentry *dentry;
 | 
						struct dentry *dentry;
 | 
				
			||||||
| 
						 | 
					@ -856,7 +849,6 @@ struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name,
 | 
				
			||||||
	struct dentry *dentry;
 | 
						struct dentry *dentry;
 | 
				
			||||||
	struct inode *dir = parent->d_inode;
 | 
						struct inode *dir = parent->d_inode;
 | 
				
			||||||
	umode_t umode = S_IFIFO | S_IRUSR | S_IWUSR;
 | 
						umode_t umode = S_IFIFO | S_IRUSR | S_IWUSR;
 | 
				
			||||||
	struct qstr q;
 | 
					 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pipe->ops->upcall == NULL)
 | 
						if (pipe->ops->upcall == NULL)
 | 
				
			||||||
| 
						 | 
					@ -864,12 +856,8 @@ struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name,
 | 
				
			||||||
	if (pipe->ops->downcall == NULL)
 | 
						if (pipe->ops->downcall == NULL)
 | 
				
			||||||
		umode &= ~S_IWUGO;
 | 
							umode &= ~S_IWUGO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	q.name = name;
 | 
					 | 
				
			||||||
	q.len = strlen(name);
 | 
					 | 
				
			||||||
	q.hash = full_name_hash(q.name, q.len),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
 | 
						mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
 | 
				
			||||||
	dentry = __rpc_lookup_create_exclusive(parent, &q);
 | 
						dentry = __rpc_lookup_create_exclusive(parent, name);
 | 
				
			||||||
	if (IS_ERR(dentry))
 | 
						if (IS_ERR(dentry))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops,
 | 
						err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops,
 | 
				
			||||||
| 
						 | 
					@ -940,8 +928,8 @@ static void rpc_clntdir_depopulate(struct dentry *dentry)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * rpc_create_client_dir - Create a new rpc_client directory in rpc_pipefs
 | 
					 * rpc_create_client_dir - Create a new rpc_client directory in rpc_pipefs
 | 
				
			||||||
 * @dentry: dentry from the rpc_pipefs root to the new directory
 | 
					 * @dentry: the parent of new directory
 | 
				
			||||||
 * @name: &struct qstr for the name
 | 
					 * @name: the name of new directory
 | 
				
			||||||
 * @rpc_client: rpc client to associate with this directory
 | 
					 * @rpc_client: rpc client to associate with this directory
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This creates a directory at the given @path associated with
 | 
					 * This creates a directory at the given @path associated with
 | 
				
			||||||
| 
						 | 
					@ -950,7 +938,7 @@ static void rpc_clntdir_depopulate(struct dentry *dentry)
 | 
				
			||||||
 * later be created using rpc_mkpipe().
 | 
					 * later be created using rpc_mkpipe().
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct dentry *rpc_create_client_dir(struct dentry *dentry,
 | 
					struct dentry *rpc_create_client_dir(struct dentry *dentry,
 | 
				
			||||||
				   struct qstr *name,
 | 
									   const char *name,
 | 
				
			||||||
				   struct rpc_clnt *rpc_client)
 | 
									   struct rpc_clnt *rpc_client)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return rpc_mkdir_populate(dentry, name, S_IRUGO | S_IXUGO, NULL,
 | 
						return rpc_mkdir_populate(dentry, name, S_IRUGO | S_IXUGO, NULL,
 | 
				
			||||||
| 
						 | 
					@ -996,7 +984,7 @@ static void rpc_cachedir_depopulate(struct dentry *dentry)
 | 
				
			||||||
	rpc_depopulate(dentry, cache_pipefs_files, 0, 3);
 | 
						rpc_depopulate(dentry, cache_pipefs_files, 0, 3);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct dentry *rpc_create_cache_dir(struct dentry *parent, struct qstr *name,
 | 
					struct dentry *rpc_create_cache_dir(struct dentry *parent, const char *name,
 | 
				
			||||||
				    umode_t umode, struct cache_detail *cd)
 | 
									    umode_t umode, struct cache_detail *cd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return rpc_mkdir_populate(parent, name, umode, NULL,
 | 
						return rpc_mkdir_populate(parent, name, umode, NULL,
 | 
				
			||||||
| 
						 | 
					@ -1076,9 +1064,7 @@ struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
 | 
				
			||||||
			       const unsigned char *dir_name)
 | 
								       const unsigned char *dir_name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct qstr dir = QSTR_INIT(dir_name, strlen(dir_name));
 | 
						struct qstr dir = QSTR_INIT(dir_name, strlen(dir_name));
 | 
				
			||||||
 | 
						return d_hash_and_lookup(sb->s_root, &dir);
 | 
				
			||||||
	dir.hash = full_name_hash(dir.name, dir.len);
 | 
					 | 
				
			||||||
	return d_lookup(sb->s_root, &dir);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
 | 
					EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue