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