diff options
| author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-06-02 09:54:12 +0200 | 
|---|---|---|
| committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-06-02 09:54:12 +0200 | 
| commit | 5599617ec0719dba3b1f85a4abca2a6c93368ae3 (patch) | |
| tree | 7d2f9bb6a538ee8ed5cfa391f2cfa72a3e2daa9f /fs/kernfs | |
| parent | 8d19d7d9dbc25d1a1ffa602ed9eff25a88c98163 (diff) | |
| parent | 66fd7a66e8b9e11e49f46ea77910f935c4dee5c3 (diff) | |
Merge remote-tracking branch 'airlied/drm-next' into drm-intel-next-queued
Git got absolutely destroyed with all our cherry-picking from
drm-intel-next-queued to various branches. It ended up inserting
intel_crtc_page_flip 2x even in intel_display.c.
Backmerge to get back to sanity.
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'fs/kernfs')
| -rw-r--r-- | fs/kernfs/dir.c | 31 | ||||
| -rw-r--r-- | fs/kernfs/file.c | 51 | ||||
| -rw-r--r-- | fs/kernfs/inode.c | 32 | ||||
| -rw-r--r-- | fs/kernfs/kernfs-internal.h | 7 | ||||
| -rw-r--r-- | fs/kernfs/mount.c | 20 | 
5 files changed, 79 insertions, 62 deletions
| diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index 03b688d19f69..8a652404eef6 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c @@ -153,9 +153,9 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,  	p = buf + len + nlen;  	*p = '\0';  	for (kn = kn_to; kn != common; kn = kn->parent) { -		nlen = strlen(kn->name); -		p -= nlen; -		memcpy(p, kn->name, nlen); +		size_t tmp = strlen(kn->name); +		p -= tmp; +		memcpy(p, kn->name, tmp);  		*(--p) = '/';  	} @@ -753,7 +753,8 @@ int kernfs_add_one(struct kernfs_node *kn)  	ps_iattr = parent->iattr;  	if (ps_iattr) {  		struct iattr *ps_iattrs = &ps_iattr->ia_iattr; -		ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; +		ktime_get_real_ts(&ps_iattrs->ia_ctime); +		ps_iattrs->ia_mtime = ps_iattrs->ia_ctime;  	}  	mutex_unlock(&kernfs_mutex); @@ -1279,8 +1280,9 @@ static void __kernfs_remove(struct kernfs_node *kn)  			/* update timestamps on the parent */  			if (ps_iattr) { -				ps_iattr->ia_iattr.ia_ctime = CURRENT_TIME; -				ps_iattr->ia_iattr.ia_mtime = CURRENT_TIME; +				ktime_get_real_ts(&ps_iattr->ia_iattr.ia_ctime); +				ps_iattr->ia_iattr.ia_mtime = +					ps_iattr->ia_iattr.ia_ctime;  			}  			kernfs_put(pos); @@ -1643,22 +1645,9 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx)  	return 0;  } -static loff_t kernfs_dir_fop_llseek(struct file *file, loff_t offset, -				    int whence) -{ -	struct inode *inode = file_inode(file); -	loff_t ret; - -	inode_lock(inode); -	ret = generic_file_llseek(file, offset, whence); -	inode_unlock(inode); - -	return ret; -} -  const struct file_operations kernfs_dir_fops = {  	.read		= generic_read_dir, -	.iterate	= kernfs_fop_readdir, +	.iterate_shared	= kernfs_fop_readdir,  	.release	= kernfs_dir_fop_release, -	.llseek		= kernfs_dir_fop_llseek, +	.llseek		= generic_file_llseek,  }; diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c index 7247252ee9b1..e1574008adc9 100644 --- a/fs/kernfs/file.c +++ b/fs/kernfs/file.c @@ -190,15 +190,16 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of,  	char *buf;  	buf = of->prealloc_buf; -	if (!buf) +	if (buf) +		mutex_lock(&of->prealloc_mutex); +	else  		buf = kmalloc(len, GFP_KERNEL);  	if (!buf)  		return -ENOMEM;  	/*  	 * @of->mutex nests outside active ref and is used both to ensure that -	 * the ops aren't called concurrently for the same open file, and -	 * to provide exclusive access to ->prealloc_buf (when that exists). +	 * the ops aren't called concurrently for the same open file.  	 */  	mutex_lock(&of->mutex);  	if (!kernfs_get_active(of->kn)) { @@ -214,21 +215,23 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of,  	else  		len = -EINVAL; +	kernfs_put_active(of->kn); +	mutex_unlock(&of->mutex); +  	if (len < 0) -		goto out_unlock; +		goto out_free;  	if (copy_to_user(user_buf, buf, len)) {  		len = -EFAULT; -		goto out_unlock; +		goto out_free;  	}  	*ppos += len; - out_unlock: -	kernfs_put_active(of->kn); -	mutex_unlock(&of->mutex);   out_free: -	if (buf != of->prealloc_buf) +	if (buf == of->prealloc_buf) +		mutex_unlock(&of->prealloc_mutex); +	else  		kfree(buf);  	return len;  } @@ -284,15 +287,22 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,  	}  	buf = of->prealloc_buf; -	if (!buf) +	if (buf) +		mutex_lock(&of->prealloc_mutex); +	else  		buf = kmalloc(len + 1, GFP_KERNEL);  	if (!buf)  		return -ENOMEM; +	if (copy_from_user(buf, user_buf, len)) { +		len = -EFAULT; +		goto out_free; +	} +	buf[len] = '\0';	/* guarantee string termination */ +  	/*  	 * @of->mutex nests outside active ref and is used both to ensure that -	 * the ops aren't called concurrently for the same open file, and -	 * to provide exclusive access to ->prealloc_buf (when that exists). +	 * the ops aren't called concurrently for the same open file.  	 */  	mutex_lock(&of->mutex);  	if (!kernfs_get_active(of->kn)) { @@ -301,26 +311,22 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,  		goto out_free;  	} -	if (copy_from_user(buf, user_buf, len)) { -		len = -EFAULT; -		goto out_unlock; -	} -	buf[len] = '\0';	/* guarantee string termination */ -  	ops = kernfs_ops(of->kn);  	if (ops->write)  		len = ops->write(of, buf, len, *ppos);  	else  		len = -EINVAL; +	kernfs_put_active(of->kn); +	mutex_unlock(&of->mutex); +  	if (len > 0)  		*ppos += len; -out_unlock: -	kernfs_put_active(of->kn); -	mutex_unlock(&of->mutex);  out_free: -	if (buf != of->prealloc_buf) +	if (buf == of->prealloc_buf) +		mutex_unlock(&of->prealloc_mutex); +	else  		kfree(buf);  	return len;  } @@ -687,6 +693,7 @@ static int kernfs_fop_open(struct inode *inode, struct file *file)  		error = -ENOMEM;  		if (!of->prealloc_buf)  			goto err_free; +		mutex_init(&of->prealloc_mutex);  	}  	/* diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index 16405ae88d2d..63b925d5ba1e 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c @@ -54,7 +54,10 @@ static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)  	iattrs->ia_mode = kn->mode;  	iattrs->ia_uid = GLOBAL_ROOT_UID;  	iattrs->ia_gid = GLOBAL_ROOT_GID; -	iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME; + +	ktime_get_real_ts(&iattrs->ia_atime); +	iattrs->ia_mtime = iattrs->ia_atime; +	iattrs->ia_ctime = iattrs->ia_atime;  	simple_xattrs_init(&kn->iattr->xattrs);  out_unlock: @@ -157,10 +160,11 @@ static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,  	return 0;  } -int kernfs_iop_setxattr(struct dentry *dentry, const char *name, -			const void *value, size_t size, int flags) +int kernfs_iop_setxattr(struct dentry *unused, struct inode *inode, +			const char *name, const void *value, +			size_t size, int flags)  { -	struct kernfs_node *kn = dentry->d_fsdata; +	struct kernfs_node *kn = inode->i_private;  	struct kernfs_iattrs *attrs;  	void *secdata;  	int error; @@ -172,11 +176,11 @@ int kernfs_iop_setxattr(struct dentry *dentry, const char *name,  	if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {  		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; -		error = security_inode_setsecurity(d_inode(dentry), suffix, +		error = security_inode_setsecurity(inode, suffix,  						value, size, flags);  		if (error)  			return error; -		error = security_inode_getsecctx(d_inode(dentry), +		error = security_inode_getsecctx(inode,  						&secdata, &secdata_len);  		if (error)  			return error; @@ -208,10 +212,10 @@ int kernfs_iop_removexattr(struct dentry *dentry, const char *name)  	return simple_xattr_set(&attrs->xattrs, name, NULL, 0, XATTR_REPLACE);  } -ssize_t kernfs_iop_getxattr(struct dentry *dentry, const char *name, void *buf, -			    size_t size) +ssize_t kernfs_iop_getxattr(struct dentry *unused, struct inode *inode, +			    const char *name, void *buf, size_t size)  { -	struct kernfs_node *kn = dentry->d_fsdata; +	struct kernfs_node *kn = inode->i_private;  	struct kernfs_iattrs *attrs;  	attrs = kernfs_iattrs(kn); @@ -236,16 +240,18 @@ ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)  static inline void set_default_inode_attr(struct inode *inode, umode_t mode)  {  	inode->i_mode = mode; -	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; +	inode->i_atime = inode->i_mtime = +		inode->i_ctime = current_fs_time(inode->i_sb);  }  static inline void set_inode_attr(struct inode *inode, struct iattr *iattr)  { +	struct super_block *sb = inode->i_sb;  	inode->i_uid = iattr->ia_uid;  	inode->i_gid = iattr->ia_gid; -	inode->i_atime = iattr->ia_atime; -	inode->i_mtime = iattr->ia_mtime; -	inode->i_ctime = iattr->ia_ctime; +	inode->i_atime = timespec_trunc(iattr->ia_atime, sb->s_time_gran); +	inode->i_mtime = timespec_trunc(iattr->ia_mtime, sb->s_time_gran); +	inode->i_ctime = timespec_trunc(iattr->ia_ctime, sb->s_time_gran);  }  static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 6762bfbd8207..37159235ac10 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -81,11 +81,12 @@ int kernfs_iop_permission(struct inode *inode, int mask);  int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr);  int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry,  		       struct kstat *stat); -int kernfs_iop_setxattr(struct dentry *dentry, const char *name, const void *value, +int kernfs_iop_setxattr(struct dentry *dentry, struct inode *inode, +			const char *name, const void *value,  			size_t size, int flags);  int kernfs_iop_removexattr(struct dentry *dentry, const char *name); -ssize_t kernfs_iop_getxattr(struct dentry *dentry, const char *name, void *buf, -			    size_t size); +ssize_t kernfs_iop_getxattr(struct dentry *dentry, struct inode *inode, +			    const char *name, void *buf, size_t size);  ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size);  /* diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c index f73541fbe7af..63534f5f9073 100644 --- a/fs/kernfs/mount.c +++ b/fs/kernfs/mount.c @@ -15,6 +15,7 @@  #include <linux/slab.h>  #include <linux/pagemap.h>  #include <linux/namei.h> +#include <linux/seq_file.h>  #include "kernfs-internal.h" @@ -40,6 +41,19 @@ static int kernfs_sop_show_options(struct seq_file *sf, struct dentry *dentry)  	return 0;  } +static int kernfs_sop_show_path(struct seq_file *sf, struct dentry *dentry) +{ +	struct kernfs_node *node = dentry->d_fsdata; +	struct kernfs_root *root = kernfs_root(node); +	struct kernfs_syscall_ops *scops = root->syscall_ops; + +	if (scops && scops->show_path) +		return scops->show_path(sf, node, root); + +	seq_dentry(sf, dentry, " \t\n\\"); +	return 0; +} +  const struct super_operations kernfs_sops = {  	.statfs		= simple_statfs,  	.drop_inode	= generic_delete_inode, @@ -47,6 +61,7 @@ const struct super_operations kernfs_sops = {  	.remount_fs	= kernfs_sop_remount_fs,  	.show_options	= kernfs_sop_show_options, +	.show_path	= kernfs_sop_show_path,  };  /** @@ -120,9 +135,8 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn,  		kntmp = find_next_ancestor(kn, knparent);  		if (WARN_ON(!kntmp))  			return ERR_PTR(-EINVAL); -		mutex_lock(&d_inode(dentry)->i_mutex); -		dtmp = lookup_one_len(kntmp->name, dentry, strlen(kntmp->name)); -		mutex_unlock(&d_inode(dentry)->i_mutex); +		dtmp = lookup_one_len_unlocked(kntmp->name, dentry, +					       strlen(kntmp->name));  		dput(dentry);  		if (IS_ERR(dtmp))  			return dtmp; | 
