diff options
Diffstat (limited to 'fs/hostfs')
| -rw-r--r-- | fs/hostfs/hostfs.h | 7 | ||||
| -rw-r--r-- | fs/hostfs/hostfs_kern.c | 201 | ||||
| -rw-r--r-- | fs/hostfs/hostfs_user.c | 6 | 
3 files changed, 110 insertions, 104 deletions
diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h index bf15a43016b..9c88da0e855 100644 --- a/fs/hostfs/hostfs.h +++ b/fs/hostfs/hostfs.h @@ -1,7 +1,7 @@  #ifndef __UM_FS_HOSTFS  #define __UM_FS_HOSTFS -#include "os.h" +#include <os.h>  /*   * These are exactly the same definitions as in fs.h, but the names are @@ -39,7 +39,7 @@  struct hostfs_iattr {  	unsigned int	ia_valid; -	mode_t		ia_mode; +	unsigned short	ia_mode;  	uid_t		ia_uid;  	gid_t		ia_gid;  	loff_t		ia_size; @@ -67,7 +67,8 @@ extern int access_file(char *path, int r, int w, int x);  extern int open_file(char *path, int r, int w, int append);  extern void *open_dir(char *path, int *err_out);  extern char *read_dir(void *stream, unsigned long long *pos, -		      unsigned long long *ino_out, int *len_out); +		      unsigned long long *ino_out, int *len_out, +		      unsigned int *type_out);  extern void close_file(void *stream);  extern int replace_file(int oldfd, int fd);  extern void close_dir(void *stream); diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 2c0f148a49e..bb529f3b7f2 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -7,6 +7,7 @@   */  #include <linux/fs.h> +#include <linux/magic.h>  #include <linux/module.h>  #include <linux/mm.h>  #include <linux/pagemap.h> @@ -16,8 +17,8 @@  #include <linux/mount.h>  #include <linux/namei.h>  #include "hostfs.h" -#include "init.h" -#include "kern.h" +#include <init.h> +#include <kern.h>  struct hostfs_inode_info {  	int fd; @@ -30,23 +31,12 @@ static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode)  	return list_entry(inode, struct hostfs_inode_info, vfs_inode);  } -#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_path.dentry->d_inode) - -static int hostfs_d_delete(struct dentry *dentry) -{ -	return 1; -} - -static const struct dentry_operations hostfs_dentry_ops = { -	.d_delete		= hostfs_d_delete, -}; +#define FILE_HOSTFS_I(file) HOSTFS_I(file_inode(file))  /* Changed in hostfs_args before the kernel starts running */  static char *root_ino = "";  static int append = 0; -#define HOSTFS_SUPER_MAGIC 0x00c0ffee -  static const struct inode_operations hostfs_iops;  static const struct inode_operations hostfs_dir_iops;  static const struct inode_operations hostfs_link_iops; @@ -92,12 +82,10 @@ __uml_setup("hostfs=", hostfs_args,  static char *__dentry_name(struct dentry *dentry, char *name)  { -	char *p = __dentry_path(dentry, name, PATH_MAX); +	char *p = dentry_path_raw(dentry, name, PATH_MAX);  	char *root;  	size_t len; -	spin_unlock(&dcache_lock); -  	root = dentry->d_sb->s_fs_info;  	len = strlen(root);  	if (IS_ERR(p)) { @@ -123,25 +111,23 @@ static char *dentry_name(struct dentry *dentry)  	if (!name)  		return NULL; -	spin_lock(&dcache_lock); -	return __dentry_name(dentry, name); /* will unlock */ +	return __dentry_name(dentry, name);  }  static char *inode_name(struct inode *ino)  {  	struct dentry *dentry; -	char *name = __getname(); -	if (!name) -		return NULL; +	char *name; -	spin_lock(&dcache_lock); -	if (list_empty(&ino->i_dentry)) { -		spin_unlock(&dcache_lock); -		__putname(name); +	dentry = d_find_alias(ino); +	if (!dentry)  		return NULL; -	} -	dentry = list_first_entry(&ino->i_dentry, struct dentry, d_alias); -	return __dentry_name(dentry, name); /* will unlock */ + +	name = dentry_name(dentry); + +	dput(dentry); + +	return name;  }  static char *follow_link(char *link) @@ -200,7 +186,7 @@ static struct inode *hostfs_iget(struct super_block *sb)  	return inode;  } -int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf) +static int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)  {  	/*  	 * do_statfs uses struct statfs64 internally, but the linux kernel @@ -233,32 +219,39 @@ static struct inode *hostfs_alloc_inode(struct super_block *sb)  {  	struct hostfs_inode_info *hi; -	hi = kzalloc(sizeof(*hi), GFP_KERNEL); +	hi = kmalloc(sizeof(*hi), GFP_KERNEL);  	if (hi == NULL)  		return NULL;  	hi->fd = -1; +	hi->mode = 0;  	inode_init_once(&hi->vfs_inode);  	return &hi->vfs_inode;  }  static void hostfs_evict_inode(struct inode *inode)  { -	truncate_inode_pages(&inode->i_data, 0); -	end_writeback(inode); +	truncate_inode_pages_final(&inode->i_data); +	clear_inode(inode);  	if (HOSTFS_I(inode)->fd != -1) {  		close_file(&HOSTFS_I(inode)->fd);  		HOSTFS_I(inode)->fd = -1;  	}  } -static void hostfs_destroy_inode(struct inode *inode) +static void hostfs_i_callback(struct rcu_head *head)  { +	struct inode *inode = container_of(head, struct inode, i_rcu);  	kfree(HOSTFS_I(inode));  } -static int hostfs_show_options(struct seq_file *seq, struct vfsmount *vfs) +static void hostfs_destroy_inode(struct inode *inode) +{ +	call_rcu(&inode->i_rcu, hostfs_i_callback); +} + +static int hostfs_show_options(struct seq_file *seq, struct dentry *root)  { -	const char *root_path = vfs->mnt_sb->s_fs_info; +	const char *root_path = root->d_sb->s_fs_info;  	size_t offset = strlen(root_ino) + 1;  	if (strlen(root_path) > offset) @@ -275,12 +268,13 @@ static const struct super_operations hostfs_sbops = {  	.show_options	= hostfs_show_options,  }; -int hostfs_readdir(struct file *file, void *ent, filldir_t filldir) +static int hostfs_readdir(struct file *file, struct dir_context *ctx)  {  	void *dir;  	char *name;  	unsigned long long next, ino;  	int error, len; +	unsigned int type;  	name = dentry_name(file->f_path.dentry);  	if (name == NULL) @@ -289,18 +283,17 @@ int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)  	__putname(name);  	if (dir == NULL)  		return -error; -	next = file->f_pos; -	while ((name = read_dir(dir, &next, &ino, &len)) != NULL) { -		error = (*filldir)(ent, name, len, file->f_pos, -				   ino, DT_UNKNOWN); -		if (error) break; -		file->f_pos = next; +	next = ctx->pos; +	while ((name = read_dir(dir, &next, &ino, &len, &type)) != NULL) { +		if (!dir_emit(ctx, name, len, ino, type)) +			break; +		ctx->pos = next;  	}  	close_dir(dir);  	return 0;  } -int hostfs_file_open(struct inode *ino, struct file *file) +static int hostfs_file_open(struct inode *ino, struct file *file)  {  	static DEFINE_MUTEX(open_mutex);  	char *name; @@ -359,31 +352,50 @@ retry:  	return 0;  } -int hostfs_fsync(struct file *file, int datasync) +static int hostfs_file_release(struct inode *inode, struct file *file)  { -	return fsync_file(HOSTFS_I(file->f_mapping->host)->fd, datasync); +	filemap_write_and_wait(inode->i_mapping); + +	return 0; +} + +static int hostfs_fsync(struct file *file, loff_t start, loff_t end, +			int datasync) +{ +	struct inode *inode = file->f_mapping->host; +	int ret; + +	ret = filemap_write_and_wait_range(inode->i_mapping, start, end); +	if (ret) +		return ret; + +	mutex_lock(&inode->i_mutex); +	ret = fsync_file(HOSTFS_I(inode)->fd, datasync); +	mutex_unlock(&inode->i_mutex); + +	return ret;  }  static const struct file_operations hostfs_file_fops = {  	.llseek		= generic_file_llseek, -	.read		= do_sync_read, +	.read		= new_sync_read,  	.splice_read	= generic_file_splice_read, -	.aio_read	= generic_file_aio_read, -	.aio_write	= generic_file_aio_write, -	.write		= do_sync_write, +	.read_iter	= generic_file_read_iter, +	.write_iter	= generic_file_write_iter, +	.write		= new_sync_write,  	.mmap		= generic_file_mmap,  	.open		= hostfs_file_open, -	.release	= NULL, +	.release	= hostfs_file_release,  	.fsync		= hostfs_fsync,  };  static const struct file_operations hostfs_dir_fops = {  	.llseek		= generic_file_llseek, -	.readdir	= hostfs_readdir, +	.iterate	= hostfs_readdir,  	.read		= generic_read_dir,  }; -int hostfs_writepage(struct page *page, struct writeback_control *wbc) +static int hostfs_writepage(struct page *page, struct writeback_control *wbc)  {  	struct address_space *mapping = page->mapping;  	struct inode *inode = mapping->host; @@ -419,7 +431,7 @@ int hostfs_writepage(struct page *page, struct writeback_control *wbc)  	return err;  } -int hostfs_readpage(struct file *file, struct page *page) +static int hostfs_readpage(struct file *file, struct page *page)  {  	char *buffer;  	long long start; @@ -444,9 +456,9 @@ int hostfs_readpage(struct file *file, struct page *page)  	return err;  } -int hostfs_write_begin(struct file *file, struct address_space *mapping, -			loff_t pos, unsigned len, unsigned flags, -			struct page **pagep, void **fsdata) +static int hostfs_write_begin(struct file *file, struct address_space *mapping, +			      loff_t pos, unsigned len, unsigned flags, +			      struct page **pagep, void **fsdata)  {  	pgoff_t index = pos >> PAGE_CACHE_SHIFT; @@ -456,9 +468,9 @@ int hostfs_write_begin(struct file *file, struct address_space *mapping,  	return 0;  } -int hostfs_write_end(struct file *file, struct address_space *mapping, -			loff_t pos, unsigned len, unsigned copied, -			struct page *page, void *fsdata) +static int hostfs_write_end(struct file *file, struct address_space *mapping, +			    loff_t pos, unsigned len, unsigned copied, +			    struct page *page, void *fsdata)  {  	struct inode *inode = mapping->host;  	void *buffer; @@ -527,9 +539,9 @@ static int read_name(struct inode *ino, char *name)  	ino->i_ino = st.ino;  	ino->i_mode = st.mode; -	ino->i_nlink = st.nlink; -	ino->i_uid = st.uid; -	ino->i_gid = st.gid; +	set_nlink(ino, st.nlink); +	i_uid_write(ino, st.uid); +	i_gid_write(ino, st.gid);  	ino->i_atime = st.atime;  	ino->i_mtime = st.mtime;  	ino->i_ctime = st.ctime; @@ -538,8 +550,8 @@ static int read_name(struct inode *ino, char *name)  	return 0;  } -int hostfs_create(struct inode *dir, struct dentry *dentry, int mode, -		  struct nameidata *nd) +static int hostfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, +			 bool excl)  {  	struct inode *inode;  	char *name; @@ -580,8 +592,8 @@ int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,  	return error;  } -struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry, -			     struct nameidata *nd) +static struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry, +				    unsigned int flags)  {  	struct inode *inode;  	char *name; @@ -609,7 +621,6 @@ struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,  		goto out_put;  	d_add(dentry, inode); -	dentry->d_op = &hostfs_dentry_ops;  	return NULL;   out_put: @@ -618,7 +629,8 @@ struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,  	return ERR_PTR(err);  } -int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from) +static int hostfs_link(struct dentry *to, struct inode *ino, +		       struct dentry *from)  {  	char *from_name, *to_name;  	int err; @@ -636,7 +648,7 @@ int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from)  	return err;  } -int hostfs_unlink(struct inode *ino, struct dentry *dentry) +static int hostfs_unlink(struct inode *ino, struct dentry *dentry)  {  	char *file;  	int err; @@ -652,7 +664,8 @@ int hostfs_unlink(struct inode *ino, struct dentry *dentry)  	return err;  } -int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to) +static int hostfs_symlink(struct inode *ino, struct dentry *dentry, +			  const char *to)  {  	char *file;  	int err; @@ -664,7 +677,7 @@ int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)  	return err;  } -int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode) +static int hostfs_mkdir(struct inode *ino, struct dentry *dentry, umode_t mode)  {  	char *file;  	int err; @@ -676,7 +689,7 @@ int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode)  	return err;  } -int hostfs_rmdir(struct inode *ino, struct dentry *dentry) +static int hostfs_rmdir(struct inode *ino, struct dentry *dentry)  {  	char *file;  	int err; @@ -688,7 +701,7 @@ int hostfs_rmdir(struct inode *ino, struct dentry *dentry)  	return err;  } -int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +static int hostfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)  {  	struct inode *inode;  	char *name; @@ -728,8 +741,8 @@ int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)  	return err;  } -int hostfs_rename(struct inode *from_ino, struct dentry *from, -		  struct inode *to_ino, struct dentry *to) +static int hostfs_rename(struct inode *from_ino, struct dentry *from, +			 struct inode *to_ino, struct dentry *to)  {  	char *from_name, *to_name;  	int err; @@ -746,11 +759,14 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from,  	return err;  } -int hostfs_permission(struct inode *ino, int desired) +static int hostfs_permission(struct inode *ino, int desired)  {  	char *name;  	int r = 0, w = 0, x = 0, err; +	if (desired & MAY_NOT_BLOCK) +		return -ECHILD; +  	if (desired & MAY_READ) r = 1;  	if (desired & MAY_WRITE) w = 1;  	if (desired & MAY_EXEC) x = 1; @@ -765,11 +781,11 @@ int hostfs_permission(struct inode *ino, int desired)  		err = access_file(name, r, w, x);  	__putname(name);  	if (!err) -		err = generic_permission(ino, desired, NULL); +		err = generic_permission(ino, desired);  	return err;  } -int hostfs_setattr(struct dentry *dentry, struct iattr *attr) +static int hostfs_setattr(struct dentry *dentry, struct iattr *attr)  {  	struct inode *inode = dentry->d_inode;  	struct hostfs_iattr attrs; @@ -792,11 +808,11 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)  	}  	if (attr->ia_valid & ATTR_UID) {  		attrs.ia_valid |= HOSTFS_ATTR_UID; -		attrs.ia_uid = attr->ia_uid; +		attrs.ia_uid = from_kuid(&init_user_ns, attr->ia_uid);  	}  	if (attr->ia_valid & ATTR_GID) {  		attrs.ia_valid |= HOSTFS_ATTR_GID; -		attrs.ia_gid = attr->ia_gid; +		attrs.ia_gid = from_kgid(&init_user_ns, attr->ia_gid);  	}  	if (attr->ia_valid & ATTR_SIZE) {  		attrs.ia_valid |= HOSTFS_ATTR_SIZE; @@ -829,13 +845,8 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)  		return err;  	if ((attr->ia_valid & ATTR_SIZE) && -	    attr->ia_size != i_size_read(inode)) { -		int error; - -		error = vmtruncate(inode, attr->ia_size); -		if (err) -			return err; -	} +	    attr->ia_size != i_size_read(inode)) +		truncate_setsize(inode, attr->ia_size);  	setattr_copy(inode, attr);  	mark_inode_dirty(inode); @@ -843,14 +854,6 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)  }  static const struct inode_operations hostfs_iops = { -	.create		= hostfs_create, -	.link		= hostfs_link, -	.unlink		= hostfs_unlink, -	.symlink	= hostfs_symlink, -	.mkdir		= hostfs_mkdir, -	.rmdir		= hostfs_rmdir, -	.mknod		= hostfs_mknod, -	.rename		= hostfs_rename,  	.permission	= hostfs_permission,  	.setattr	= hostfs_setattr,  }; @@ -916,6 +919,7 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)  	sb->s_blocksize_bits = 10;  	sb->s_magic = HOSTFS_SUPER_MAGIC;  	sb->s_op = &hostfs_sbops; +	sb->s_d_op = &simple_dentry_operations;  	sb->s_maxbytes = MAX_LFS_FILESIZE;  	/* NULL is printed as <NULL> by sprintf: avoid that. */ @@ -950,9 +954,9 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)  	}  	err = -ENOMEM; -	sb->s_root = d_alloc_root(root_inode); +	sb->s_root = d_make_root(root_inode);  	if (sb->s_root == NULL) -		goto out_put; +		goto out;  	return 0; @@ -982,6 +986,7 @@ static struct file_system_type hostfs_type = {  	.kill_sb	= hostfs_kill_sb,  	.fs_flags 	= 0,  }; +MODULE_ALIAS_FS("hostfs");  static int __init init_hostfs(void)  { diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c index d51a98384bc..67838f3aa20 100644 --- a/fs/hostfs/hostfs_user.c +++ b/fs/hostfs/hostfs_user.c @@ -15,8 +15,6 @@  #include <sys/types.h>  #include <sys/vfs.h>  #include "hostfs.h" -#include "os.h" -#include "user.h"  #include <utime.h>  static void stat64_to_hostfs(const struct stat64 *buf, struct hostfs_stat *p) @@ -99,7 +97,8 @@ void *open_dir(char *path, int *err_out)  }  char *read_dir(void *stream, unsigned long long *pos, -	       unsigned long long *ino_out, int *len_out) +	       unsigned long long *ino_out, int *len_out, +	       unsigned int *type_out)  {  	DIR *dir = stream;  	struct dirent *ent; @@ -110,6 +109,7 @@ char *read_dir(void *stream, unsigned long long *pos,  		return NULL;  	*len_out = strlen(ent->d_name);  	*ino_out = ent->d_ino; +	*type_out = ent->d_type;  	*pos = telldir(dir);  	return ent->d_name;  }  | 
