diff options
Diffstat (limited to 'fs/hostfs/hostfs_kern.c')
| -rw-r--r-- | fs/hostfs/hostfs_kern.c | 201 |
1 files changed, 103 insertions, 98 deletions
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) { |
