 20b4fb4852
			
		
	
	
	20b4fb4852
	
	
	
		
			
			Pull VFS updates from Al Viro,
Misc cleanups all over the place, mainly wrt /proc interfaces (switch
create_proc_entry to proc_create(), get rid of the deprecated
create_proc_read_entry() in favor of using proc_create_data() and
seq_file etc).
7kloc removed.
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (204 commits)
  don't bother with deferred freeing of fdtables
  proc: Move non-public stuff from linux/proc_fs.h to fs/proc/internal.h
  proc: Make the PROC_I() and PDE() macros internal to procfs
  proc: Supply a function to remove a proc entry by PDE
  take cgroup_open() and cpuset_open() to fs/proc/base.c
  ppc: Clean up scanlog
  ppc: Clean up rtas_flash driver somewhat
  hostap: proc: Use remove_proc_subtree()
  drm: proc: Use remove_proc_subtree()
  drm: proc: Use minor->index to label things, not PDE->name
  drm: Constify drm_proc_list[]
  zoran: Don't print proc_dir_entry data in debug
  reiserfs: Don't access the proc_dir_entry in r_open(), r_start() r_show()
  proc: Supply an accessor for getting the data from a PDE's parent
  airo: Use remove_proc_subtree()
  rtl8192u: Don't need to save device proc dir PDE
  rtl8187se: Use a dir under /proc/net/r8180/
  proc: Add proc_mkdir_data()
  proc: Move some bits from linux/proc_fs.h to linux/{of.h,signal.h,tty.h}
  proc: Move PDE_NET() to fs/proc/proc_net.c
  ...
		
	
			
		
			
				
	
	
		
			106 lines
		
	
	
	
		
			2.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
	
		
			2.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2012 Red Hat, Inc.
 | |
|  * Copyright (C) 2012 Jeremy Kerr <jeremy.kerr@canonical.com>
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify
 | |
|  * it under the terms of the GNU General Public License version 2 as
 | |
|  * published by the Free Software Foundation.
 | |
|  */
 | |
| 
 | |
| #include <linux/efi.h>
 | |
| #include <linux/fs.h>
 | |
| #include <linux/slab.h>
 | |
| 
 | |
| #include "internal.h"
 | |
| 
 | |
| static ssize_t efivarfs_file_write(struct file *file,
 | |
| 		const char __user *userbuf, size_t count, loff_t *ppos)
 | |
| {
 | |
| 	struct efivar_entry *var = file->private_data;
 | |
| 	void *data;
 | |
| 	u32 attributes;
 | |
| 	struct inode *inode = file->f_mapping->host;
 | |
| 	unsigned long datasize = count - sizeof(attributes);
 | |
| 	ssize_t bytes = 0;
 | |
| 	bool set = false;
 | |
| 
 | |
| 	if (count < sizeof(attributes))
 | |
| 		return -EINVAL;
 | |
| 
 | |
| 	if (copy_from_user(&attributes, userbuf, sizeof(attributes)))
 | |
| 		return -EFAULT;
 | |
| 
 | |
| 	if (attributes & ~(EFI_VARIABLE_MASK))
 | |
| 		return -EINVAL;
 | |
| 
 | |
| 	data = kmalloc(datasize, GFP_KERNEL);
 | |
| 	if (!data)
 | |
| 		return -ENOMEM;
 | |
| 
 | |
| 	if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) {
 | |
| 		bytes = -EFAULT;
 | |
| 		goto out;
 | |
| 	}
 | |
| 
 | |
| 	bytes = efivar_entry_set_get_size(var, attributes, &datasize,
 | |
| 					  data, &set);
 | |
| 	if (!set && bytes)
 | |
| 		goto out;
 | |
| 
 | |
| 	if (bytes == -ENOENT) {
 | |
| 		drop_nlink(inode);
 | |
| 		d_delete(file->f_dentry);
 | |
| 		dput(file->f_dentry);
 | |
| 	} else {
 | |
| 		mutex_lock(&inode->i_mutex);
 | |
| 		i_size_write(inode, datasize + sizeof(attributes));
 | |
| 		mutex_unlock(&inode->i_mutex);
 | |
| 	}
 | |
| 
 | |
| 	bytes = count;
 | |
| 
 | |
| out:
 | |
| 	kfree(data);
 | |
| 
 | |
| 	return bytes;
 | |
| }
 | |
| 
 | |
| static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
 | |
| 		size_t count, loff_t *ppos)
 | |
| {
 | |
| 	struct efivar_entry *var = file->private_data;
 | |
| 	unsigned long datasize = 0;
 | |
| 	u32 attributes;
 | |
| 	void *data;
 | |
| 	ssize_t size = 0;
 | |
| 	int err;
 | |
| 
 | |
| 	err = efivar_entry_size(var, &datasize);
 | |
| 	if (err)
 | |
| 		return err;
 | |
| 
 | |
| 	data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL);
 | |
| 
 | |
| 	if (!data)
 | |
| 		return -ENOMEM;
 | |
| 
 | |
| 	size = efivar_entry_get(var, &attributes, &datasize,
 | |
| 				data + sizeof(attributes));
 | |
| 	if (size)
 | |
| 		goto out_free;
 | |
| 
 | |
| 	memcpy(data, &attributes, sizeof(attributes));
 | |
| 	size = simple_read_from_buffer(userbuf, count, ppos,
 | |
| 				       data, datasize + sizeof(attributes));
 | |
| out_free:
 | |
| 	kfree(data);
 | |
| 
 | |
| 	return size;
 | |
| }
 | |
| 
 | |
| const struct file_operations efivarfs_file_operations = {
 | |
| 	.open	= simple_open,
 | |
| 	.read	= efivarfs_file_read,
 | |
| 	.write	= efivarfs_file_write,
 | |
| 	.llseek	= no_llseek,
 | |
| };
 |