^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1) /*
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 2) * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * Licensed under the GPL
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * Ported the filesystem routines to 2.5.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) * 2003-02-10 Petr Baudis <pasky@ucw.cz>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) #include <linux/fs.h>
2b3b9bb03a9fb (James Hogan 2013-03-27 10:47:13 +0000 10) #include <linux/magic.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) #include <linux/module.h>
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 12) #include <linux/mm.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) #include <linux/pagemap.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) #include <linux/statfs.h>
5a0e3ad6af866 (Tejun Heo 2010-03-24 17:04:11 +0900 15) #include <linux/slab.h>
dd2cc4dff3b08 (Miklos Szeredi 2008-02-08 04:21:43 -0800 16) #include <linux/seq_file.h>
6966a97753854 (Jiri Kosina 2008-02-09 00:10:14 -0800 17) #include <linux/mount.h>
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 18) #include <linux/namei.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 19) #include "hostfs.h"
37185b3324087 (Al Viro 2012-10-08 03:27:32 +0100 20) #include <init.h>
37185b3324087 (Al Viro 2012-10-08 03:27:32 +0100 21) #include <kern.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 22)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 23) struct hostfs_inode_info {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 24) int fd;
aeb5d727062a0 (Al Viro 2008-09-02 15:28:45 -0400 25) fmode_t mode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26) struct inode vfs_inode;
69886e676e895 (Richard Weinberger 2015-02-27 22:55:20 +0100 27) struct mutex open_mutex;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 28) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 29)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 30) static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 31) {
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 32) return list_entry(inode, struct hostfs_inode_info, vfs_inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 33) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 34)
496ad9aa8ef44 (Al Viro 2013-01-23 17:07:38 -0500 35) #define FILE_HOSTFS_I(file) HOSTFS_I(file_inode(file))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 36)
a15f1e41fbf59 (Johannes Berg 2021-01-13 21:31:55 +0100 37) static struct kmem_cache *hostfs_inode_cache;
a15f1e41fbf59 (Johannes Berg 2021-01-13 21:31:55 +0100 38)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 39) /* Changed in hostfs_args before the kernel starts running */
a6eb0be6d5cc1 (Paolo 'Blaisorblade' Giarrusso 2007-03-07 20:41:08 -0800 40) static char *root_ino = "";
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 41) static int append = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 42)
92e1d5be91a0e (Arjan van de Ven 2007-02-12 00:55:39 -0800 43) static const struct inode_operations hostfs_iops;
92e1d5be91a0e (Arjan van de Ven 2007-02-12 00:55:39 -0800 44) static const struct inode_operations hostfs_dir_iops;
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 45) static const struct inode_operations hostfs_link_iops;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 46)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47) #ifndef MODULE
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 48) static int __init hostfs_args(char *options, int *add)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 49) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 50) char *ptr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 51)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 52) ptr = strchr(options, ',');
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 53) if (ptr != NULL)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 54) *ptr++ = '\0';
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 55) if (*options != '\0')
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 56) root_ino = options;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 57)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 58) options = ptr;
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 59) while (options) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 60) ptr = strchr(options, ',');
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 61) if (ptr != NULL)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 62) *ptr++ = '\0';
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 63) if (*options != '\0') {
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 64) if (!strcmp(options, "append"))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 65) append = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 66) else printf("hostfs_args - unsupported option - %s\n",
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 67) options);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 68) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 69) options = ptr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 70) }
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 71) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 73)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 74) __uml_setup("hostfs=", hostfs_args,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 75) "hostfs=<root dir>,<flags>,...\n"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 76) " This is used to set hostfs parameters. The root directory argument\n"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 77) " is used to confine all hostfs mounts to within the specified directory\n"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 78) " tree on the host. If this isn't specified, then a user inside UML can\n"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 79) " mount anything on the host that's accessible to the user that's running\n"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 80) " it.\n"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 81) " The only flag currently supported is 'append', which specifies that all\n"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 82) " files opened by hostfs will be opened in append mode.\n\n"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 83) );
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 84) #endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 85)
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 86) static char *__dentry_name(struct dentry *dentry, char *name)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 87) {
ec2447c278ee9 (Nicholas Piggin 2011-01-07 17:49:29 +1100 88) char *p = dentry_path_raw(dentry, name, PATH_MAX);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 89) char *root;
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 90) size_t len;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 91)
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 92) root = dentry->d_sb->s_fs_info;
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 93) len = strlen(root);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 94) if (IS_ERR(p)) {
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 95) __putname(name);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 96) return NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 97) }
aad50b1e06081 (Richard Weinberger 2015-03-03 23:41:52 +0100 98)
aad50b1e06081 (Richard Weinberger 2015-03-03 23:41:52 +0100 99) /*
aad50b1e06081 (Richard Weinberger 2015-03-03 23:41:52 +0100 100) * This function relies on the fact that dentry_path_raw() will place
aad50b1e06081 (Richard Weinberger 2015-03-03 23:41:52 +0100 101) * the path name at the end of the provided buffer.
aad50b1e06081 (Richard Weinberger 2015-03-03 23:41:52 +0100 102) */
aad50b1e06081 (Richard Weinberger 2015-03-03 23:41:52 +0100 103) BUG_ON(p + strlen(p) + 1 != name + PATH_MAX);
aad50b1e06081 (Richard Weinberger 2015-03-03 23:41:52 +0100 104)
850a496f96971 (Al Viro 2010-08-18 06:18:57 -0400 105) strlcpy(name, root, PATH_MAX);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 106) if (len > p - name) {
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 107) __putname(name);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 108) return NULL;
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 109) }
c278e81b8a029 (Richard Weinberger 2015-03-03 23:42:25 +0100 110)
c278e81b8a029 (Richard Weinberger 2015-03-03 23:42:25 +0100 111) if (p > name + len)
c278e81b8a029 (Richard Weinberger 2015-03-03 23:42:25 +0100 112) strcpy(name + len, p);
c278e81b8a029 (Richard Weinberger 2015-03-03 23:42:25 +0100 113)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 114) return name;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 115) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 116)
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 117) static char *dentry_name(struct dentry *dentry)
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 118) {
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 119) char *name = __getname();
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 120) if (!name)
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 121) return NULL;
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 122)
9dcc5e8a4635d (James Hogan 2013-03-27 10:47:12 +0000 123) return __dentry_name(dentry, name);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 124) }
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 125)
c5322220eb91b (Al Viro 2010-06-06 20:42:10 -0400 126) static char *inode_name(struct inode *ino)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 127) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 128) struct dentry *dentry;
ec2447c278ee9 (Nicholas Piggin 2011-01-07 17:49:29 +1100 129) char *name;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 130)
ec2447c278ee9 (Nicholas Piggin 2011-01-07 17:49:29 +1100 131) dentry = d_find_alias(ino);
ec2447c278ee9 (Nicholas Piggin 2011-01-07 17:49:29 +1100 132) if (!dentry)
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 133) return NULL;
ec2447c278ee9 (Nicholas Piggin 2011-01-07 17:49:29 +1100 134)
ec2447c278ee9 (Nicholas Piggin 2011-01-07 17:49:29 +1100 135) name = dentry_name(dentry);
ec2447c278ee9 (Nicholas Piggin 2011-01-07 17:49:29 +1100 136)
ec2447c278ee9 (Nicholas Piggin 2011-01-07 17:49:29 +1100 137) dput(dentry);
ec2447c278ee9 (Nicholas Piggin 2011-01-07 17:49:29 +1100 138)
ec2447c278ee9 (Nicholas Piggin 2011-01-07 17:49:29 +1100 139) return name;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 140) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 141)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 142) static char *follow_link(char *link)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 143) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 144) char *name, *resolved, *end;
b58c4e96192ee (Andy Shevchenko 2020-03-20 15:07:35 +0200 145) int n;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 146)
7f6c411c9b50c (Al Viro 2021-03-25 14:12:34 -0400 147) name = kmalloc(PATH_MAX, GFP_KERNEL);
7c9509924c711 (Richard Weinberger 2015-03-03 23:55:49 +0100 148) if (!name) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 149) n = -ENOMEM;
7c9509924c711 (Richard Weinberger 2015-03-03 23:55:49 +0100 150) goto out_free;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 151) }
7c9509924c711 (Richard Weinberger 2015-03-03 23:55:49 +0100 152)
7c9509924c711 (Richard Weinberger 2015-03-03 23:55:49 +0100 153) n = hostfs_do_readlink(link, name, PATH_MAX);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 154) if (n < 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 155) goto out_free;
7c9509924c711 (Richard Weinberger 2015-03-03 23:55:49 +0100 156) else if (n == PATH_MAX) {
7c9509924c711 (Richard Weinberger 2015-03-03 23:55:49 +0100 157) n = -E2BIG;
7c9509924c711 (Richard Weinberger 2015-03-03 23:55:49 +0100 158) goto out_free;
7c9509924c711 (Richard Weinberger 2015-03-03 23:55:49 +0100 159) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 160)
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 161) if (*name == '/')
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 162) return name;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 163)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 164) end = strrchr(link, '/');
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 165) if (end == NULL)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 166) return name;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 167)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 168) *(end + 1) = '\0';
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 169)
b58c4e96192ee (Andy Shevchenko 2020-03-20 15:07:35 +0200 170) resolved = kasprintf(GFP_KERNEL, "%s%s", link, name);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 171) if (resolved == NULL) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 172) n = -ENOMEM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 173) goto out_free;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 174) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 175)
7f6c411c9b50c (Al Viro 2021-03-25 14:12:34 -0400 176) kfree(name);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 177) return resolved;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 178)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 179) out_free:
7f6c411c9b50c (Al Viro 2021-03-25 14:12:34 -0400 180) kfree(name);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 181) return ERR_PTR(n);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 182) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 183)
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 184) static struct inode *hostfs_iget(struct super_block *sb)
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 185) {
52b209f7b848a (Al Viro 2010-06-06 18:43:19 -0400 186) struct inode *inode = new_inode(sb);
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 187) if (!inode)
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 188) return ERR_PTR(-ENOMEM);
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 189) return inode;
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 190) }
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 191)
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 192) static int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 193) {
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 194) /*
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 195) * do_statfs uses struct statfs64 internally, but the linux kernel
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 196) * struct statfs still has 32-bit versions for most of these fields,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 197) * so we convert them here
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 198) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 199) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 200) long long f_blocks;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 201) long long f_bfree;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 202) long long f_bavail;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 203) long long f_files;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 204) long long f_ffree;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 205)
601d2c38b9313 (Al Viro 2010-06-06 17:53:01 -0400 206) err = do_statfs(dentry->d_sb->s_fs_info,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 207) &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 208) &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
1b627d5771312 (Richard Weinberger 2010-10-26 14:21:18 -0700 209) &sf->f_namelen);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 210) if (err)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 211) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 212) sf->f_blocks = f_blocks;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 213) sf->f_bfree = f_bfree;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 214) sf->f_bavail = f_bavail;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 215) sf->f_files = f_files;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 216) sf->f_ffree = f_ffree;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 217) sf->f_type = HOSTFS_SUPER_MAGIC;
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 218) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 219) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 220)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 221) static struct inode *hostfs_alloc_inode(struct super_block *sb)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 222) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 223) struct hostfs_inode_info *hi;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 224)
a15f1e41fbf59 (Johannes Berg 2021-01-13 21:31:55 +0100 225) hi = kmem_cache_alloc(hostfs_inode_cache, GFP_KERNEL_ACCOUNT);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 226) if (hi == NULL)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 227) return NULL;
601d2c38b9313 (Al Viro 2010-06-06 17:53:01 -0400 228) hi->fd = -1;
371fdab100335 (James Hogan 2013-03-27 10:47:14 +0000 229) hi->mode = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 230) inode_init_once(&hi->vfs_inode);
69886e676e895 (Richard Weinberger 2015-02-27 22:55:20 +0100 231) mutex_init(&hi->open_mutex);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 232) return &hi->vfs_inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 233) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 234)
e971a6d7b9dae (Al Viro 2010-06-06 15:16:17 -0400 235) static void hostfs_evict_inode(struct inode *inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 236) {
91b0abe36a7b2 (Johannes Weiner 2014-04-03 14:47:49 -0700 237) truncate_inode_pages_final(&inode->i_data);
dbd5768f87ff6 (Jan Kara 2012-05-03 14:48:02 +0200 238) clear_inode(inode);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 239) if (HOSTFS_I(inode)->fd != -1) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 240) close_file(&HOSTFS_I(inode)->fd);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 241) HOSTFS_I(inode)->fd = -1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 242) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 243) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 244)
08ccfc5c363dc (Al Viro 2019-04-15 20:12:11 -0400 245) static void hostfs_free_inode(struct inode *inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 246) {
a15f1e41fbf59 (Johannes Berg 2021-01-13 21:31:55 +0100 247) kmem_cache_free(hostfs_inode_cache, HOSTFS_I(inode));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 248) }
fa0d7e3de6d6f (Nicholas Piggin 2011-01-07 17:49:49 +1100 249)
34c80b1d93e6e (Al Viro 2011-12-08 21:32:45 -0500 250) static int hostfs_show_options(struct seq_file *seq, struct dentry *root)
dd2cc4dff3b08 (Miklos Szeredi 2008-02-08 04:21:43 -0800 251) {
34c80b1d93e6e (Al Viro 2011-12-08 21:32:45 -0500 252) const char *root_path = root->d_sb->s_fs_info;
dd2cc4dff3b08 (Miklos Szeredi 2008-02-08 04:21:43 -0800 253) size_t offset = strlen(root_ino) + 1;
dd2cc4dff3b08 (Miklos Szeredi 2008-02-08 04:21:43 -0800 254)
dd2cc4dff3b08 (Miklos Szeredi 2008-02-08 04:21:43 -0800 255) if (strlen(root_path) > offset)
a068acf2ee776 (Kees Cook 2015-09-04 15:44:57 -0700 256) seq_show_option(seq, root_path + offset, NULL);
dd2cc4dff3b08 (Miklos Szeredi 2008-02-08 04:21:43 -0800 257)
7f74a6687992f (Richard Weinberger 2015-03-04 00:00:54 +0100 258) if (append)
7f74a6687992f (Richard Weinberger 2015-03-04 00:00:54 +0100 259) seq_puts(seq, ",append");
7f74a6687992f (Richard Weinberger 2015-03-04 00:00:54 +0100 260)
dd2cc4dff3b08 (Miklos Szeredi 2008-02-08 04:21:43 -0800 261) return 0;
dd2cc4dff3b08 (Miklos Szeredi 2008-02-08 04:21:43 -0800 262) }
dd2cc4dff3b08 (Miklos Szeredi 2008-02-08 04:21:43 -0800 263)
ee9b6d61a2a43 (Josef 'Jeff' Sipek 2007-02-12 00:55:41 -0800 264) static const struct super_operations hostfs_sbops = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 265) .alloc_inode = hostfs_alloc_inode,
08ccfc5c363dc (Al Viro 2019-04-15 20:12:11 -0400 266) .free_inode = hostfs_free_inode,
e971a6d7b9dae (Al Viro 2010-06-06 15:16:17 -0400 267) .evict_inode = hostfs_evict_inode,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 268) .statfs = hostfs_statfs,
dd2cc4dff3b08 (Miklos Szeredi 2008-02-08 04:21:43 -0800 269) .show_options = hostfs_show_options,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 270) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 271)
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 272) static int hostfs_readdir(struct file *file, struct dir_context *ctx)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 273) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 274) void *dir;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 275) char *name;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 276) unsigned long long next, ino;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 277) int error, len;
3ee6bd8e8dc0c (Geert Uytterhoeven 2012-01-27 19:14:58 +0100 278) unsigned int type;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 279)
c5322220eb91b (Al Viro 2010-06-06 20:42:10 -0400 280) name = dentry_name(file->f_path.dentry);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 281) if (name == NULL)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 282) return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 283) dir = open_dir(name, &error);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 284) __putname(name);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 285) if (dir == NULL)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 286) return -error;
8e28bc7e71c84 (Al Viro 2013-05-22 16:34:19 -0400 287) next = ctx->pos;
0c9bd6365d0b2 (Richard Weinberger 2015-03-24 15:47:38 +0100 288) seek_dir(dir, next);
3ee6bd8e8dc0c (Geert Uytterhoeven 2012-01-27 19:14:58 +0100 289) while ((name = read_dir(dir, &next, &ino, &len, &type)) != NULL) {
8e28bc7e71c84 (Al Viro 2013-05-22 16:34:19 -0400 290) if (!dir_emit(ctx, name, len, ino, type))
8e28bc7e71c84 (Al Viro 2013-05-22 16:34:19 -0400 291) break;
8e28bc7e71c84 (Al Viro 2013-05-22 16:34:19 -0400 292) ctx->pos = next;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 293) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 294) close_dir(dir);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 295) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 296) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 297)
4c6dcafc691bb (Richard Weinberger 2015-03-02 00:09:33 +0100 298) static int hostfs_open(struct inode *ino, struct file *file)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 299) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 300) char *name;
bd1052a245c00 (Richard Weinberger 2015-03-04 00:06:38 +0100 301) fmode_t mode;
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 302) int err;
bd1052a245c00 (Richard Weinberger 2015-03-04 00:06:38 +0100 303) int r, w, fd;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 304)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 305) mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 306) if ((mode & HOSTFS_I(ino)->mode) == mode)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 307) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 308)
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 309) mode |= HOSTFS_I(ino)->mode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 310)
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 311) retry:
a9d1958b4b9a6 (Richard Weinberger 2015-03-04 22:39:48 +0100 312) r = w = 0;
a9d1958b4b9a6 (Richard Weinberger 2015-03-04 22:39:48 +0100 313)
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 314) if (mode & FMODE_READ)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 315) r = 1;
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 316) if (mode & FMODE_WRITE)
112a5da717f86 (Richard Weinberger 2015-03-04 00:05:11 +0100 317) r = w = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 318)
d692d397e8a69 (Al Viro 2021-04-15 22:03:00 -0400 319) name = dentry_name(file_dentry(file));
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 320) if (name == NULL)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 321) return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 322)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 323) fd = open_file(name, r, w, append);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 324) __putname(name);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 325) if (fd < 0)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 326) return fd;
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 327)
69886e676e895 (Richard Weinberger 2015-02-27 22:55:20 +0100 328) mutex_lock(&HOSTFS_I(ino)->open_mutex);
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 329) /* somebody else had handled it first? */
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 330) if ((mode & HOSTFS_I(ino)->mode) == mode) {
69886e676e895 (Richard Weinberger 2015-02-27 22:55:20 +0100 331) mutex_unlock(&HOSTFS_I(ino)->open_mutex);
af9556586a906 (Richard Weinberger 2015-02-27 22:56:28 +0100 332) close_file(&fd);
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 333) return 0;
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 334) }
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 335) if ((mode | HOSTFS_I(ino)->mode) != mode) {
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 336) mode |= HOSTFS_I(ino)->mode;
69886e676e895 (Richard Weinberger 2015-02-27 22:55:20 +0100 337) mutex_unlock(&HOSTFS_I(ino)->open_mutex);
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 338) close_file(&fd);
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 339) goto retry;
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 340) }
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 341) if (HOSTFS_I(ino)->fd == -1) {
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 342) HOSTFS_I(ino)->fd = fd;
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 343) } else {
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 344) err = replace_file(fd, HOSTFS_I(ino)->fd);
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 345) close_file(&fd);
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 346) if (err < 0) {
69886e676e895 (Richard Weinberger 2015-02-27 22:55:20 +0100 347) mutex_unlock(&HOSTFS_I(ino)->open_mutex);
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 348) return err;
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 349) }
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 350) }
f8ad850f11e11 (Al Viro 2010-06-06 23:49:18 -0400 351) HOSTFS_I(ino)->mode = mode;
69886e676e895 (Richard Weinberger 2015-02-27 22:55:20 +0100 352) mutex_unlock(&HOSTFS_I(ino)->open_mutex);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 353)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 354) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 355) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 356)
65984ff9d2179 (Richard Weinberger 2013-08-04 17:23:51 +0000 357) static int hostfs_file_release(struct inode *inode, struct file *file)
65984ff9d2179 (Richard Weinberger 2013-08-04 17:23:51 +0000 358) {
65984ff9d2179 (Richard Weinberger 2013-08-04 17:23:51 +0000 359) filemap_write_and_wait(inode->i_mapping);
65984ff9d2179 (Richard Weinberger 2013-08-04 17:23:51 +0000 360)
65984ff9d2179 (Richard Weinberger 2013-08-04 17:23:51 +0000 361) return 0;
65984ff9d2179 (Richard Weinberger 2013-08-04 17:23:51 +0000 362) }
65984ff9d2179 (Richard Weinberger 2013-08-04 17:23:51 +0000 363)
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 364) static int hostfs_fsync(struct file *file, loff_t start, loff_t end,
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 365) int datasync)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 366) {
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 367) struct inode *inode = file->f_mapping->host;
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 368) int ret;
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 369)
3b49c9a1e984b (Jeff Layton 2017-07-07 15:20:52 -0400 370) ret = file_write_and_wait_range(file, start, end);
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 371) if (ret)
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 372) return ret;
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 373)
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 374) inode_lock(inode);
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 375) ret = fsync_file(HOSTFS_I(inode)->fd, datasync);
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 376) inode_unlock(inode);
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 377)
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 378) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 379) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 380)
4b6f5d20b04dc (Arjan van de Ven 2006-03-28 01:56:42 -0800 381) static const struct file_operations hostfs_file_fops = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 382) .llseek = generic_file_llseek,
5ffc4ef45b3b0 (Jens Axboe 2007-06-01 11:49:19 +0200 383) .splice_read = generic_file_splice_read,
aad4f8bb42af0 (Al Viro 2014-04-02 14:33:16 -0400 384) .read_iter = generic_file_read_iter,
8174202b34c30 (Al Viro 2014-04-03 03:17:43 -0400 385) .write_iter = generic_file_write_iter,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 386) .mmap = generic_file_mmap,
4c6dcafc691bb (Richard Weinberger 2015-03-02 00:09:33 +0100 387) .open = hostfs_open,
65984ff9d2179 (Richard Weinberger 2013-08-04 17:23:51 +0000 388) .release = hostfs_file_release,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 389) .fsync = hostfs_fsync,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 390) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 391)
4b6f5d20b04dc (Arjan van de Ven 2006-03-28 01:56:42 -0800 392) static const struct file_operations hostfs_dir_fops = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 393) .llseek = generic_file_llseek,
552a9d489f141 (Al Viro 2016-05-12 19:49:30 -0400 394) .iterate_shared = hostfs_readdir,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 395) .read = generic_read_dir,
4c6dcafc691bb (Richard Weinberger 2015-03-02 00:09:33 +0100 396) .open = hostfs_open,
4c6dcafc691bb (Richard Weinberger 2015-03-02 00:09:33 +0100 397) .fsync = hostfs_fsync,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 398) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 399)
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 400) static int hostfs_writepage(struct page *page, struct writeback_control *wbc)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 401) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 402) struct address_space *mapping = page->mapping;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 403) struct inode *inode = mapping->host;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 404) char *buffer;
af6aa1b9cad73 (Richard Weinberger 2015-03-04 20:58:39 +0100 405) loff_t base = page_offset(page);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 406) int count = PAGE_SIZE;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 407) int end_index = inode->i_size >> PAGE_SHIFT;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 408) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 409)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 410) if (page->index >= end_index)
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 411) count = inode->i_size & (PAGE_SIZE-1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 412)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 413) buffer = kmap(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 414)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 415) err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 416) if (err != count) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 417) ClearPageUptodate(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 418) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 419) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 420)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 421) if (base > inode->i_size)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 422) inode->i_size = base;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 423)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 424) if (PageError(page))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 425) ClearPageError(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 426) err = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 427)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 428) out:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 429) kunmap(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 430)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 431) unlock_page(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 432) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 433) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 434)
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 435) static int hostfs_readpage(struct file *file, struct page *page)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 436) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 437) char *buffer;
af6aa1b9cad73 (Richard Weinberger 2015-03-04 20:58:39 +0100 438) loff_t start = page_offset(page);
b86b413a32110 (Richard Weinberger 2015-03-04 12:44:03 +0100 439) int bytes_read, ret = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 440)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 441) buffer = kmap(page);
41761ddfaecb3 (Richard Weinberger 2015-03-03 21:40:55 +0100 442) bytes_read = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 443) PAGE_SIZE);
41761ddfaecb3 (Richard Weinberger 2015-03-03 21:40:55 +0100 444) if (bytes_read < 0) {
b86b413a32110 (Richard Weinberger 2015-03-04 12:44:03 +0100 445) ClearPageUptodate(page);
b86b413a32110 (Richard Weinberger 2015-03-04 12:44:03 +0100 446) SetPageError(page);
41761ddfaecb3 (Richard Weinberger 2015-03-03 21:40:55 +0100 447) ret = bytes_read;
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 448) goto out;
41761ddfaecb3 (Richard Weinberger 2015-03-03 21:40:55 +0100 449) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 450)
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 451) memset(buffer + bytes_read, 0, PAGE_SIZE - bytes_read);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 452)
b86b413a32110 (Richard Weinberger 2015-03-04 12:44:03 +0100 453) ClearPageError(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 454) SetPageUptodate(page);
b86b413a32110 (Richard Weinberger 2015-03-04 12:44:03 +0100 455)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 456) out:
b86b413a32110 (Richard Weinberger 2015-03-04 12:44:03 +0100 457) flush_dcache_page(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 458) kunmap(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 459) unlock_page(page);
41761ddfaecb3 (Richard Weinberger 2015-03-03 21:40:55 +0100 460) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 461) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 462)
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 463) static int hostfs_write_begin(struct file *file, struct address_space *mapping,
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 464) loff_t pos, unsigned len, unsigned flags,
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 465) struct page **pagep, void **fsdata)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 466) {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 467) pgoff_t index = pos >> PAGE_SHIFT;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 468)
54566b2c1594c (Nicholas Piggin 2009-01-04 12:00:53 -0800 469) *pagep = grab_cache_page_write_begin(mapping, index, flags);
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 470) if (!*pagep)
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 471) return -ENOMEM;
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 472) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 473) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 474)
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 475) static int hostfs_write_end(struct file *file, struct address_space *mapping,
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 476) loff_t pos, unsigned len, unsigned copied,
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 477) struct page *page, void *fsdata)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 478) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 479) struct inode *inode = mapping->host;
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 480) void *buffer;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 481) unsigned from = pos & (PAGE_SIZE - 1);
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 482) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 483)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 484) buffer = kmap(page);
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 485) err = write_file(FILE_HOSTFS_I(file)->fd, &pos, buffer + from, copied);
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 486) kunmap(page);
30f04a4efa73d (Paolo 'Blaisorblade' Giarrusso 2005-12-29 17:39:57 +0100 487)
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 488) if (!PageUptodate(page) && err == PAGE_SIZE)
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 489) SetPageUptodate(page);
30f04a4efa73d (Paolo 'Blaisorblade' Giarrusso 2005-12-29 17:39:57 +0100 490)
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 491) /*
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 492) * If err > 0, write_file has added err to pos, so we are comparing
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 493) * i_size against the last byte written.
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 494) */
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 495) if (err > 0 && (pos > inode->i_size))
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 496) inode->i_size = pos;
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 497) unlock_page(page);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 498) put_page(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 499)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 500) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 501) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 502)
f5e54d6e53a20 (Christoph Hellwig 2006-06-28 04:26:44 -0700 503) static const struct address_space_operations hostfs_aops = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 504) .writepage = hostfs_writepage,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 505) .readpage = hostfs_readpage,
ffa0aea681a5f (Paolo 'Blaisorblade' Giarrusso 2005-05-01 08:58:56 -0700 506) .set_page_dirty = __set_page_dirty_nobuffers,
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 507) .write_begin = hostfs_write_begin,
ae361ff46ba93 (Nicholas Piggin 2007-10-16 01:25:17 -0700 508) .write_end = hostfs_write_end,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 509) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 510)
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 511) static int read_name(struct inode *ino, char *name)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 512) {
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 513) dev_t rdev;
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 514) struct hostfs_stat st;
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 515) int err = stat_file(name, &st, -1);
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 516) if (err)
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 517) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 518)
5e2df28cc62fd (Al Viro 2010-06-06 19:38:18 -0400 519) /* Reencode maj and min with the kernel encoding.*/
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 520) rdev = MKDEV(st.maj, st.min);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 521)
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 522) switch (st.mode & S_IFMT) {
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 523) case S_IFLNK:
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 524) ino->i_op = &hostfs_link_iops;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 525) break;
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 526) case S_IFDIR:
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 527) ino->i_op = &hostfs_dir_iops;
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 528) ino->i_fop = &hostfs_dir_fops;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 529) break;
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 530) case S_IFCHR:
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 531) case S_IFBLK:
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 532) case S_IFIFO:
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 533) case S_IFSOCK:
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 534) init_special_inode(ino, st.mode & S_IFMT, rdev);
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 535) ino->i_op = &hostfs_iops;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 536) break;
2ad2dca6fd28c (Richard Weinberger 2015-03-02 00:10:25 +0100 537) case S_IFREG:
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 538) ino->i_op = &hostfs_iops;
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 539) ino->i_fop = &hostfs_file_fops;
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 540) ino->i_mapping->a_ops = &hostfs_aops;
2ad2dca6fd28c (Richard Weinberger 2015-03-02 00:10:25 +0100 541) break;
2ad2dca6fd28c (Richard Weinberger 2015-03-02 00:10:25 +0100 542) default:
2ad2dca6fd28c (Richard Weinberger 2015-03-02 00:10:25 +0100 543) return -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 544) }
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 545)
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 546) ino->i_ino = st.ino;
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 547) ino->i_mode = st.mode;
bfe8684869601 (Miklos Szeredi 2011-10-28 14:13:29 +0200 548) set_nlink(ino, st.nlink);
29f82ae56e879 (Eric W. Biederman 2012-02-07 16:28:57 -0800 549) i_uid_write(ino, st.uid);
29f82ae56e879 (Eric W. Biederman 2012-02-07 16:28:57 -0800 550) i_gid_write(ino, st.gid);
bca302651af49 (Arnd Bergmann 2018-06-12 15:31:17 +0200 551) ino->i_atime = (struct timespec64){ st.atime.tv_sec, st.atime.tv_nsec };
bca302651af49 (Arnd Bergmann 2018-06-12 15:31:17 +0200 552) ino->i_mtime = (struct timespec64){ st.mtime.tv_sec, st.mtime.tv_nsec };
bca302651af49 (Arnd Bergmann 2018-06-12 15:31:17 +0200 553) ino->i_ctime = (struct timespec64){ st.ctime.tv_sec, st.ctime.tv_nsec };
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 554) ino->i_size = st.size;
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 555) ino->i_blocks = st.blocks;
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 556) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 557) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 558)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 559) static int hostfs_create(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 560) struct dentry *dentry, umode_t mode, bool excl)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 561) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 562) struct inode *inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 563) char *name;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 564) int error, fd;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 565)
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 566) inode = hostfs_iget(dir->i_sb);
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 567) if (IS_ERR(inode)) {
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 568) error = PTR_ERR(inode);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 569) goto out;
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 570) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 571)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 572) error = -ENOMEM;
c5322220eb91b (Al Viro 2010-06-06 20:42:10 -0400 573) name = dentry_name(dentry);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 574) if (name == NULL)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 575) goto out_put;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 576)
a718c92219b35 (Richard Weinberger 2015-05-04 14:50:29 +0200 577) fd = file_create(name, mode & 0777);
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 578) if (fd < 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 579) error = fd;
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 580) else
5e2df28cc62fd (Al Viro 2010-06-06 19:38:18 -0400 581) error = read_name(inode, name);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 582)
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 583) __putname(name);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 584) if (error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 585) goto out_put;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 586)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 587) HOSTFS_I(inode)->fd = fd;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 588) HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 589) d_instantiate(dentry, inode);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 590) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 591)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 592) out_put:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 593) iput(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 594) out:
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 595) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 596) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 597)
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 598) static struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 599) unsigned int flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 600) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 601) struct inode *inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 602) char *name;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 603) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 604)
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 605) inode = hostfs_iget(ino->i_sb);
50f3074011133 (Al Viro 2018-06-23 20:27:29 -0400 606) if (IS_ERR(inode))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 607) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 608)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 609) err = -ENOMEM;
c5322220eb91b (Al Viro 2010-06-06 20:42:10 -0400 610) name = dentry_name(dentry);
50f3074011133 (Al Viro 2018-06-23 20:27:29 -0400 611) if (name) {
50f3074011133 (Al Viro 2018-06-23 20:27:29 -0400 612) err = read_name(inode, name);
50f3074011133 (Al Viro 2018-06-23 20:27:29 -0400 613) __putname(name);
50f3074011133 (Al Viro 2018-06-23 20:27:29 -0400 614) }
50f3074011133 (Al Viro 2018-06-23 20:27:29 -0400 615) if (err) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 616) iput(inode);
50f3074011133 (Al Viro 2018-06-23 20:27:29 -0400 617) inode = (err == -ENOENT) ? NULL : ERR_PTR(err);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 618) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 619) out:
50f3074011133 (Al Viro 2018-06-23 20:27:29 -0400 620) return d_splice_alias(inode, dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 621) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 622)
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 623) static int hostfs_link(struct dentry *to, struct inode *ino,
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 624) struct dentry *from)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 625) {
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 626) char *from_name, *to_name;
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 627) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 628)
c5322220eb91b (Al Viro 2010-06-06 20:42:10 -0400 629) if ((from_name = dentry_name(from)) == NULL)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 630) return -ENOMEM;
c5322220eb91b (Al Viro 2010-06-06 20:42:10 -0400 631) to_name = dentry_name(to);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 632) if (to_name == NULL) {
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 633) __putname(from_name);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 634) return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 635) }
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 636) err = link_file(to_name, from_name);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 637) __putname(from_name);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 638) __putname(to_name);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 639) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 640) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 641)
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 642) static int hostfs_unlink(struct inode *ino, struct dentry *dentry)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 643) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 644) char *file;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 645) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 646)
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 647) if (append)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 648) return -EPERM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 649)
f8d7e1877e512 (Al Viro 2010-06-06 23:19:04 -0400 650) if ((file = dentry_name(dentry)) == NULL)
f8d7e1877e512 (Al Viro 2010-06-06 23:19:04 -0400 651) return -ENOMEM;
f8d7e1877e512 (Al Viro 2010-06-06 23:19:04 -0400 652)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 653) err = unlink_file(file);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 654) __putname(file);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 655) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 656) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 657)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 658) static int hostfs_symlink(struct user_namespace *mnt_userns, struct inode *ino,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 659) struct dentry *dentry, const char *to)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 660) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 661) char *file;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 662) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 663)
c5322220eb91b (Al Viro 2010-06-06 20:42:10 -0400 664) if ((file = dentry_name(dentry)) == NULL)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 665) return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 666) err = make_symlink(file, to);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 667) __putname(file);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 668) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 669) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 670)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 671) static int hostfs_mkdir(struct user_namespace *mnt_userns, struct inode *ino,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 672) struct dentry *dentry, umode_t mode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 673) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 674) char *file;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 675) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 676)
c5322220eb91b (Al Viro 2010-06-06 20:42:10 -0400 677) if ((file = dentry_name(dentry)) == NULL)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 678) return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 679) err = do_mkdir(file, mode);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 680) __putname(file);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 681) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 682) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 683)
9e443bc369e04 (James Hogan 2013-11-14 21:15:13 +0000 684) static int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 685) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 686) char *file;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 687) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 688)
c5322220eb91b (Al Viro 2010-06-06 20:42:10 -0400 689) if ((file = dentry_name(dentry)) == NULL)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 690) return -ENOMEM;
6380161ce9d08 (Dominik Brodowski 2018-03-11 11:34:48 +0100 691) err = hostfs_do_rmdir(file);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 692) __putname(file);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 693) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 694) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 695)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 696) static int hostfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 697) struct dentry *dentry, umode_t mode, dev_t dev)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 698) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 699) struct inode *inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 700) char *name;
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 701) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 702)
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 703) inode = hostfs_iget(dir->i_sb);
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 704) if (IS_ERR(inode)) {
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 705) err = PTR_ERR(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 706) goto out;
0a370e5de9e5a (David Howells 2008-02-07 00:15:50 -0800 707) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 708)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 709) err = -ENOMEM;
c5322220eb91b (Al Viro 2010-06-06 20:42:10 -0400 710) name = dentry_name(dentry);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 711) if (name == NULL)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 712) goto out_put;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 713)
88f6cd0c3bb5d (Johannes Stezenbach 2007-01-29 13:19:44 -0800 714) err = do_mknod(name, mode, MAJOR(dev), MINOR(dev));
9f2dfda2f2f1c (Vegard Nossum 2015-12-16 21:59:56 +0100 715) if (err)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 716) goto out_free;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 717)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 718) err = read_name(inode, name);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 719) __putname(name);
5e2df28cc62fd (Al Viro 2010-06-06 19:38:18 -0400 720) if (err)
5e2df28cc62fd (Al Viro 2010-06-06 19:38:18 -0400 721) goto out_put;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 722)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 723) d_instantiate(dentry, inode);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 724) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 725)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 726) out_free:
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 727) __putname(name);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 728) out_put:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 729) iput(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 730) out:
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 731) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 732) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 733)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 734) static int hostfs_rename2(struct user_namespace *mnt_userns,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 735) struct inode *old_dir, struct dentry *old_dentry,
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 736) struct inode *new_dir, struct dentry *new_dentry,
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 737) unsigned int flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 738) {
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 739) char *old_name, *new_name;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 740) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 741)
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 742) if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 743) return -EINVAL;
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 744)
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 745) old_name = dentry_name(old_dentry);
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 746) if (old_name == NULL)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 747) return -ENOMEM;
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 748) new_name = dentry_name(new_dentry);
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 749) if (new_name == NULL) {
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 750) __putname(old_name);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 751) return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 752) }
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 753) if (!flags)
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 754) err = rename_file(old_name, new_name);
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 755) else
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 756) err = rename2_file(old_name, new_name, flags);
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 757)
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 758) __putname(old_name);
9a423bb6e3577 (Miklos Szeredi 2014-07-23 15:15:35 +0200 759) __putname(new_name);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 760) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 761) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 762)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 763) static int hostfs_permission(struct user_namespace *mnt_userns,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 764) struct inode *ino, int desired)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 765) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 766) char *name;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 767) int r = 0, w = 0, x = 0, err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 768)
10556cb21a0d0 (Al Viro 2011-06-20 19:28:19 -0400 769) if (desired & MAY_NOT_BLOCK)
b74c79e99389c (Nicholas Piggin 2011-01-07 17:49:58 +1100 770) return -ECHILD;
b74c79e99389c (Nicholas Piggin 2011-01-07 17:49:58 +1100 771)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 772) if (desired & MAY_READ) r = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 773) if (desired & MAY_WRITE) w = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 774) if (desired & MAY_EXEC) x = 1;
c5322220eb91b (Al Viro 2010-06-06 20:42:10 -0400 775) name = inode_name(ino);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 776) if (name == NULL)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 777) return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 778)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 779) if (S_ISCHR(ino->i_mode) || S_ISBLK(ino->i_mode) ||
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 780) S_ISFIFO(ino->i_mode) || S_ISSOCK(ino->i_mode))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 781) err = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 782) else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 783) err = access_file(name, r, w, x);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 784) __putname(name);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 785) if (!err)
47291baa8ddfd (Christian Brauner 2021-01-21 14:19:24 +0100 786) err = generic_permission(&init_user_ns, ino, desired);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 787) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 788) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 789)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 790) static int hostfs_setattr(struct user_namespace *mnt_userns,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 791) struct dentry *dentry, struct iattr *attr)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 792) {
2b0143b5c986b (David Howells 2015-03-17 22:25:59 +0000 793) struct inode *inode = d_inode(dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 794) struct hostfs_iattr attrs;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 795) char *name;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 796) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 797)
1025774ce411f (Christoph Hellwig 2010-06-04 11:30:02 +0200 798) int fd = HOSTFS_I(inode)->fd;
5822b7faca709 (Alberto Bertogli 2007-05-08 00:23:16 -0700 799)
2f221d6f7b881 (Christian Brauner 2021-01-21 14:19:26 +0100 800) err = setattr_prepare(&init_user_ns, dentry, attr);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 801) if (err)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 802) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 803)
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 804) if (append)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 805) attr->ia_valid &= ~ATTR_SIZE;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 806)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 807) attrs.ia_valid = 0;
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 808) if (attr->ia_valid & ATTR_MODE) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 809) attrs.ia_valid |= HOSTFS_ATTR_MODE;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 810) attrs.ia_mode = attr->ia_mode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 811) }
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 812) if (attr->ia_valid & ATTR_UID) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 813) attrs.ia_valid |= HOSTFS_ATTR_UID;
29f82ae56e879 (Eric W. Biederman 2012-02-07 16:28:57 -0800 814) attrs.ia_uid = from_kuid(&init_user_ns, attr->ia_uid);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 815) }
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 816) if (attr->ia_valid & ATTR_GID) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 817) attrs.ia_valid |= HOSTFS_ATTR_GID;
29f82ae56e879 (Eric W. Biederman 2012-02-07 16:28:57 -0800 818) attrs.ia_gid = from_kgid(&init_user_ns, attr->ia_gid);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 819) }
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 820) if (attr->ia_valid & ATTR_SIZE) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 821) attrs.ia_valid |= HOSTFS_ATTR_SIZE;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 822) attrs.ia_size = attr->ia_size;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 823) }
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 824) if (attr->ia_valid & ATTR_ATIME) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 825) attrs.ia_valid |= HOSTFS_ATTR_ATIME;
bca302651af49 (Arnd Bergmann 2018-06-12 15:31:17 +0200 826) attrs.ia_atime = (struct hostfs_timespec)
bca302651af49 (Arnd Bergmann 2018-06-12 15:31:17 +0200 827) { attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 828) }
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 829) if (attr->ia_valid & ATTR_MTIME) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 830) attrs.ia_valid |= HOSTFS_ATTR_MTIME;
bca302651af49 (Arnd Bergmann 2018-06-12 15:31:17 +0200 831) attrs.ia_mtime = (struct hostfs_timespec)
bca302651af49 (Arnd Bergmann 2018-06-12 15:31:17 +0200 832) { attr->ia_mtime.tv_sec, attr->ia_mtime.tv_nsec };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 833) }
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 834) if (attr->ia_valid & ATTR_CTIME) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 835) attrs.ia_valid |= HOSTFS_ATTR_CTIME;
bca302651af49 (Arnd Bergmann 2018-06-12 15:31:17 +0200 836) attrs.ia_ctime = (struct hostfs_timespec)
bca302651af49 (Arnd Bergmann 2018-06-12 15:31:17 +0200 837) { attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 838) }
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 839) if (attr->ia_valid & ATTR_ATIME_SET) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 840) attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 841) }
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 842) if (attr->ia_valid & ATTR_MTIME_SET) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 843) attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 844) }
c5322220eb91b (Al Viro 2010-06-06 20:42:10 -0400 845) name = dentry_name(dentry);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 846) if (name == NULL)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 847) return -ENOMEM;
5822b7faca709 (Alberto Bertogli 2007-05-08 00:23:16 -0700 848) err = set_attr(name, &attrs, fd);
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 849) __putname(name);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 850) if (err)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 851) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 852)
1025774ce411f (Christoph Hellwig 2010-06-04 11:30:02 +0200 853) if ((attr->ia_valid & ATTR_SIZE) &&
bc077320f8f64 (Marco Stornelli 2012-10-20 12:02:59 +0200 854) attr->ia_size != i_size_read(inode))
3be2be0a32c18 (Marco Stornelli 2012-10-06 10:31:13 +0200 855) truncate_setsize(inode, attr->ia_size);
1025774ce411f (Christoph Hellwig 2010-06-04 11:30:02 +0200 856)
2f221d6f7b881 (Christian Brauner 2021-01-21 14:19:26 +0100 857) setattr_copy(&init_user_ns, inode, attr);
1025774ce411f (Christoph Hellwig 2010-06-04 11:30:02 +0200 858) mark_inode_dirty(inode);
1025774ce411f (Christoph Hellwig 2010-06-04 11:30:02 +0200 859) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 860) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 861)
92e1d5be91a0e (Arjan van de Ven 2007-02-12 00:55:39 -0800 862) static const struct inode_operations hostfs_iops = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 863) .permission = hostfs_permission,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 864) .setattr = hostfs_setattr,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 865) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 866)
92e1d5be91a0e (Arjan van de Ven 2007-02-12 00:55:39 -0800 867) static const struct inode_operations hostfs_dir_iops = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 868) .create = hostfs_create,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 869) .lookup = hostfs_lookup,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 870) .link = hostfs_link,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 871) .unlink = hostfs_unlink,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 872) .symlink = hostfs_symlink,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 873) .mkdir = hostfs_mkdir,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 874) .rmdir = hostfs_rmdir,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 875) .mknod = hostfs_mknod,
2773bf00aeb9b (Miklos Szeredi 2016-09-27 11:03:58 +0200 876) .rename = hostfs_rename2,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 877) .permission = hostfs_permission,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 878) .setattr = hostfs_setattr,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 879) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 880)
6b2553918d8b4 (Al Viro 2015-11-17 10:20:54 -0500 881) static const char *hostfs_get_link(struct dentry *dentry,
fceef393a5381 (Al Viro 2015-12-29 15:58:39 -0500 882) struct inode *inode,
fceef393a5381 (Al Viro 2015-12-29 15:58:39 -0500 883) struct delayed_call *done)
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 884) {
6b2553918d8b4 (Al Viro 2015-11-17 10:20:54 -0500 885) char *link;
6b2553918d8b4 (Al Viro 2015-11-17 10:20:54 -0500 886) if (!dentry)
6b2553918d8b4 (Al Viro 2015-11-17 10:20:54 -0500 887) return ERR_PTR(-ECHILD);
fceef393a5381 (Al Viro 2015-12-29 15:58:39 -0500 888) link = kmalloc(PATH_MAX, GFP_KERNEL);
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 889) if (link) {
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 890) char *path = dentry_name(dentry);
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 891) int err = -ENOMEM;
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 892) if (path) {
3b6036d148bad (Al Viro 2010-08-18 06:21:10 -0400 893) err = hostfs_do_readlink(path, link, PATH_MAX);
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 894) if (err == PATH_MAX)
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 895) err = -E2BIG;
e9193059b1b37 (Al Viro 2010-06-06 23:16:34 -0400 896) __putname(path);
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 897) }
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 898) if (err < 0) {
fceef393a5381 (Al Viro 2015-12-29 15:58:39 -0500 899) kfree(link);
680baacbca69d (Al Viro 2015-05-02 13:32:22 -0400 900) return ERR_PTR(err);
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 901) }
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 902) } else {
680baacbca69d (Al Viro 2015-05-02 13:32:22 -0400 903) return ERR_PTR(-ENOMEM);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 904) }
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 905)
fceef393a5381 (Al Viro 2015-12-29 15:58:39 -0500 906) set_delayed_call(done, kfree_link, link);
fceef393a5381 (Al Viro 2015-12-29 15:58:39 -0500 907) return link;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 908) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 909)
d0352d3ed722b (Al Viro 2010-06-06 21:51:16 -0400 910) static const struct inode_operations hostfs_link_iops = {
6b2553918d8b4 (Al Viro 2015-11-17 10:20:54 -0500 911) .get_link = hostfs_get_link,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 912) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 913)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 914) static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 915) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 916) struct inode *root_inode;
75e8defbe4236 (Paolo 'Blaisorblade' Giarrusso 2007-03-29 01:20:33 -0700 917) char *host_root_path, *req_root = d;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 918) int err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 919)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 920) sb->s_blocksize = 1024;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 921) sb->s_blocksize_bits = 10;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 922) sb->s_magic = HOSTFS_SUPER_MAGIC;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 923) sb->s_op = &hostfs_sbops;
b26d4cd385fc5 (Al Viro 2013-10-25 18:47:37 -0400 924) sb->s_d_op = &simple_dentry_operations;
752fa51e4c518 (Wolfgang Illmeyer 2009-06-30 11:41:44 -0700 925) sb->s_maxbytes = MAX_LFS_FILESIZE;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 926)
b58c4e96192ee (Andy Shevchenko 2020-03-20 15:07:35 +0200 927) /* NULL is printed as '(null)' by printf(): avoid that. */
75e8defbe4236 (Paolo 'Blaisorblade' Giarrusso 2007-03-29 01:20:33 -0700 928) if (req_root == NULL)
75e8defbe4236 (Paolo 'Blaisorblade' Giarrusso 2007-03-29 01:20:33 -0700 929) req_root = "";
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 930)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 931) err = -ENOMEM;
601d2c38b9313 (Al Viro 2010-06-06 17:53:01 -0400 932) sb->s_fs_info = host_root_path =
b58c4e96192ee (Andy Shevchenko 2020-03-20 15:07:35 +0200 933) kasprintf(GFP_KERNEL, "%s/%s", root_ino, req_root);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 934) if (host_root_path == NULL)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 935) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 936)
52b209f7b848a (Al Viro 2010-06-06 18:43:19 -0400 937) root_inode = new_inode(sb);
52b209f7b848a (Al Viro 2010-06-06 18:43:19 -0400 938) if (!root_inode)
601d2c38b9313 (Al Viro 2010-06-06 17:53:01 -0400 939) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 940)
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 941) err = read_name(root_inode, host_root_path);
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 942) if (err)
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 943) goto out_put;
52b209f7b848a (Al Viro 2010-06-06 18:43:19 -0400 944)
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 945) if (S_ISLNK(root_inode->i_mode)) {
52b209f7b848a (Al Viro 2010-06-06 18:43:19 -0400 946) char *name = follow_link(host_root_path);
8a545f185145e (Dan Carpenter 2016-07-13 13:12:34 +0300 947) if (IS_ERR(name)) {
52b209f7b848a (Al Viro 2010-06-06 18:43:19 -0400 948) err = PTR_ERR(name);
8a545f185145e (Dan Carpenter 2016-07-13 13:12:34 +0300 949) goto out_put;
8a545f185145e (Dan Carpenter 2016-07-13 13:12:34 +0300 950) }
8a545f185145e (Dan Carpenter 2016-07-13 13:12:34 +0300 951) err = read_name(root_inode, name);
52b209f7b848a (Al Viro 2010-06-06 18:43:19 -0400 952) kfree(name);
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 953) if (err)
4754b825571a6 (Al Viro 2010-06-06 20:33:12 -0400 954) goto out_put;
52b209f7b848a (Al Viro 2010-06-06 18:43:19 -0400 955) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 956)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 957) err = -ENOMEM;
48fde701aff66 (Al Viro 2012-01-08 22:15:13 -0500 958) sb->s_root = d_make_root(root_inode);
84b3db04ca15a (Jeff Dike 2007-10-16 01:27:13 -0700 959) if (sb->s_root == NULL)
48fde701aff66 (Al Viro 2012-01-08 22:15:13 -0500 960) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 961)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 962) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 963)
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 964) out_put:
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 965) iput(root_inode);
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 966) out:
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 967) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 968) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 969)
3c26ff6e499ee (Al Viro 2010-07-25 11:46:36 +0400 970) static struct dentry *hostfs_read_sb(struct file_system_type *type,
454e2398be9b9 (David Howells 2006-06-23 02:02:57 -0700 971) int flags, const char *dev_name,
3c26ff6e499ee (Al Viro 2010-07-25 11:46:36 +0400 972) void *data)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 973) {
3c26ff6e499ee (Al Viro 2010-07-25 11:46:36 +0400 974) return mount_nodev(type, flags, data, hostfs_fill_sb_common);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 975) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 976)
601d2c38b9313 (Al Viro 2010-06-06 17:53:01 -0400 977) static void hostfs_kill_sb(struct super_block *s)
601d2c38b9313 (Al Viro 2010-06-06 17:53:01 -0400 978) {
601d2c38b9313 (Al Viro 2010-06-06 17:53:01 -0400 979) kill_anon_super(s);
601d2c38b9313 (Al Viro 2010-06-06 17:53:01 -0400 980) kfree(s->s_fs_info);
601d2c38b9313 (Al Viro 2010-06-06 17:53:01 -0400 981) }
601d2c38b9313 (Al Viro 2010-06-06 17:53:01 -0400 982)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 983) static struct file_system_type hostfs_type = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 984) .owner = THIS_MODULE,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 985) .name = "hostfs",
3c26ff6e499ee (Al Viro 2010-07-25 11:46:36 +0400 986) .mount = hostfs_read_sb,
601d2c38b9313 (Al Viro 2010-06-06 17:53:01 -0400 987) .kill_sb = hostfs_kill_sb,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 988) .fs_flags = 0,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 989) };
3e64fe5b21852 (Eric W. Biederman 2013-03-11 07:05:42 -0700 990) MODULE_ALIAS_FS("hostfs");
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 991)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 992) static int __init init_hostfs(void)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 993) {
a15f1e41fbf59 (Johannes Berg 2021-01-13 21:31:55 +0100 994) hostfs_inode_cache = KMEM_CACHE(hostfs_inode_info, 0);
a15f1e41fbf59 (Johannes Berg 2021-01-13 21:31:55 +0100 995) if (!hostfs_inode_cache)
a15f1e41fbf59 (Johannes Berg 2021-01-13 21:31:55 +0100 996) return -ENOMEM;
f1adc05e77383 (Jeff Dike 2007-05-08 00:23:18 -0700 997) return register_filesystem(&hostfs_type);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 998) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 999)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1000) static void __exit exit_hostfs(void)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1001) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1002) unregister_filesystem(&hostfs_type);
a15f1e41fbf59 (Johannes Berg 2021-01-13 21:31:55 +0100 1003) kmem_cache_destroy(hostfs_inode_cache);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1004) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1005)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1006) module_init(init_hostfs)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1007) module_exit(exit_hostfs)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1008) MODULE_LICENSE("GPL");