aboutsummaryrefslogtreecommitdiff
path: root/fs/hostfs/hostfs_kern.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/hostfs/hostfs_kern.c')
-rw-r--r--fs/hostfs/hostfs_kern.c201
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)
{