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