diff options
Diffstat (limited to 'fs/kernfs/dir.c')
| -rw-r--r-- | fs/kernfs/dir.c | 34 | 
1 files changed, 18 insertions, 16 deletions
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index ef00b5fe8cee..45b6919903e6 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -17,7 +17,7 @@  #include "kernfs-internal.h" -static DEFINE_SPINLOCK(kernfs_rename_lock);	/* kn->parent and ->name */ +static DEFINE_RWLOCK(kernfs_rename_lock);	/* kn->parent and ->name */  /*   * Don't use rename_lock to piggy back on pr_cont_buf. We don't want to   * call pr_cont() while holding rename_lock. Because sometimes pr_cont() @@ -196,9 +196,9 @@ int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen)  	unsigned long flags;  	int ret; -	spin_lock_irqsave(&kernfs_rename_lock, flags); +	read_lock_irqsave(&kernfs_rename_lock, flags);  	ret = kernfs_name_locked(kn, buf, buflen); -	spin_unlock_irqrestore(&kernfs_rename_lock, flags); +	read_unlock_irqrestore(&kernfs_rename_lock, flags);  	return ret;  } @@ -224,9 +224,9 @@ int kernfs_path_from_node(struct kernfs_node *to, struct kernfs_node *from,  	unsigned long flags;  	int ret; -	spin_lock_irqsave(&kernfs_rename_lock, flags); +	read_lock_irqsave(&kernfs_rename_lock, flags);  	ret = kernfs_path_from_node_locked(to, from, buf, buflen); -	spin_unlock_irqrestore(&kernfs_rename_lock, flags); +	read_unlock_irqrestore(&kernfs_rename_lock, flags);  	return ret;  }  EXPORT_SYMBOL_GPL(kernfs_path_from_node); @@ -294,10 +294,10 @@ struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn)  	struct kernfs_node *parent;  	unsigned long flags; -	spin_lock_irqsave(&kernfs_rename_lock, flags); +	read_lock_irqsave(&kernfs_rename_lock, flags);  	parent = kn->parent;  	kernfs_get(parent); -	spin_unlock_irqrestore(&kernfs_rename_lock, flags); +	read_unlock_irqrestore(&kernfs_rename_lock, flags);  	return parent;  } @@ -770,12 +770,15 @@ int kernfs_add_one(struct kernfs_node *kn)  		goto out_unlock;  	/* Update timestamps on the parent */ +	down_write(&root->kernfs_iattr_rwsem); +  	ps_iattr = parent->iattr;  	if (ps_iattr) {  		ktime_get_real_ts64(&ps_iattr->ia_ctime);  		ps_iattr->ia_mtime = ps_iattr->ia_ctime;  	} +	up_write(&root->kernfs_iattr_rwsem);  	up_write(&root->kernfs_rwsem);  	/* @@ -940,6 +943,8 @@ struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,  	idr_init(&root->ino_idr);  	init_rwsem(&root->kernfs_rwsem); +	init_rwsem(&root->kernfs_iattr_rwsem); +	init_rwsem(&root->kernfs_supers_rwsem);  	INIT_LIST_HEAD(&root->supers);  	/* @@ -1462,11 +1467,14 @@ static void __kernfs_remove(struct kernfs_node *kn)  				pos->parent ? pos->parent->iattr : NULL;  			/* update timestamps on the parent */ +			down_write(&kernfs_root(kn)->kernfs_iattr_rwsem); +  			if (ps_iattr) {  				ktime_get_real_ts64(&ps_iattr->ia_ctime);  				ps_iattr->ia_mtime = ps_iattr->ia_ctime;  			} +			up_write(&kernfs_root(kn)->kernfs_iattr_rwsem);  			kernfs_put(pos);  		} @@ -1723,7 +1731,7 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,  	kernfs_get(new_parent);  	/* rename_lock protects ->parent and ->name accessors */ -	spin_lock_irq(&kernfs_rename_lock); +	write_lock_irq(&kernfs_rename_lock);  	old_parent = kn->parent;  	kn->parent = new_parent; @@ -1734,7 +1742,7 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,  		kn->name = new_name;  	} -	spin_unlock_irq(&kernfs_rename_lock); +	write_unlock_irq(&kernfs_rename_lock);  	kn->hash = kernfs_name_hash(kn->name, kn->ns);  	kernfs_link_sibling(kn); @@ -1748,12 +1756,6 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,  	return error;  } -/* Relationship between mode and the DT_xxx types */ -static inline unsigned char dt_type(struct kernfs_node *kn) -{ -	return (kn->mode >> 12) & 15; -} -  static int kernfs_dir_fop_release(struct inode *inode, struct file *filp)  {  	kernfs_put(filp->private_data); @@ -1831,7 +1833,7 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx)  	     pos;  	     pos = kernfs_dir_next_pos(ns, parent, ctx->pos, pos)) {  		const char *name = pos->name; -		unsigned int type = dt_type(pos); +		unsigned int type = fs_umode_to_dtype(pos->mode);  		int len = strlen(name);  		ino_t ino = kernfs_ino(pos);  |