new helper: file_inode(file)
[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>
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"
37185b33
AV
19#include <init.h>
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
496ad9aa 33#define FILE_HOSTFS_I(file) HOSTFS_I(file_inode(file))
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);
dbd5768f 243 clear_inode(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;
3ee6bd8e 286 unsigned int type;
1da177e4 287
c5322220 288 name = dentry_name(file->f_path.dentry);
84b3db04 289 if (name == NULL)
f1adc05e 290 return -ENOMEM;
1da177e4 291 dir = open_dir(name, &error);
e9193059 292 __putname(name);
84b3db04 293 if (dir == NULL)
f1adc05e 294 return -error;
1da177e4 295 next = file->f_pos;
3ee6bd8e 296 while ((name = read_dir(dir, &next, &ino, &len, &type)) != NULL) {
1da177e4 297 error = (*filldir)(ent, name, len, file->f_pos,
3ee6bd8e 298 ino, type);
84b3db04 299 if (error) break;
1da177e4
LT
300 file->f_pos = next;
301 }
302 close_dir(dir);
f1adc05e 303 return 0;
1da177e4
LT
304}
305
306int hostfs_file_open(struct inode *ino, struct file *file)
307{
f8ad850f 308 static DEFINE_MUTEX(open_mutex);
1da177e4 309 char *name;
aeb5d727 310 fmode_t mode = 0;
f8ad850f 311 int err;
aeb5d727 312 int r = 0, w = 0, fd;
1da177e4
LT
313
314 mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
84b3db04 315 if ((mode & HOSTFS_I(ino)->mode) == mode)
f1adc05e 316 return 0;
1da177e4 317
f8ad850f 318 mode |= HOSTFS_I(ino)->mode;
1da177e4 319
f8ad850f
AV
320retry:
321 if (mode & FMODE_READ)
1da177e4 322 r = 1;
f8ad850f 323 if (mode & FMODE_WRITE)
1da177e4 324 w = 1;
84b3db04 325 if (w)
1da177e4
LT
326 r = 1;
327
c5322220 328 name = dentry_name(file->f_path.dentry);
84b3db04 329 if (name == NULL)
f1adc05e 330 return -ENOMEM;
1da177e4
LT
331
332 fd = open_file(name, r, w, append);
e9193059 333 __putname(name);
84b3db04 334 if (fd < 0)
f1adc05e 335 return fd;
f8ad850f
AV
336
337 mutex_lock(&open_mutex);
338 /* somebody else had handled it first? */
339 if ((mode & HOSTFS_I(ino)->mode) == mode) {
340 mutex_unlock(&open_mutex);
341 return 0;
342 }
343 if ((mode | HOSTFS_I(ino)->mode) != mode) {
344 mode |= HOSTFS_I(ino)->mode;
345 mutex_unlock(&open_mutex);
346 close_file(&fd);
347 goto retry;
348 }
349 if (HOSTFS_I(ino)->fd == -1) {
350 HOSTFS_I(ino)->fd = fd;
351 } else {
352 err = replace_file(fd, HOSTFS_I(ino)->fd);
353 close_file(&fd);
354 if (err < 0) {
355 mutex_unlock(&open_mutex);
356 return err;
357 }
358 }
359 HOSTFS_I(ino)->mode = mode;
360 mutex_unlock(&open_mutex);
1da177e4 361
f1adc05e 362 return 0;
1da177e4
LT
363}
364
02c24a82 365int hostfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
1da177e4 366{
02c24a82
JB
367 struct inode *inode = file->f_mapping->host;
368 int ret;
369
370 ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
371 if (ret)
372 return ret;
373
374 mutex_lock(&inode->i_mutex);
375 ret = fsync_file(HOSTFS_I(inode)->fd, datasync);
376 mutex_unlock(&inode->i_mutex);
377
378 return ret;
1da177e4
LT
379}
380
4b6f5d20 381static const struct file_operations hostfs_file_fops = {
1da177e4 382 .llseek = generic_file_llseek,
543ade1f 383 .read = do_sync_read,
5ffc4ef4 384 .splice_read = generic_file_splice_read,
1da177e4
LT
385 .aio_read = generic_file_aio_read,
386 .aio_write = generic_file_aio_write,
543ade1f 387 .write = do_sync_write,
1da177e4
LT
388 .mmap = generic_file_mmap,
389 .open = hostfs_file_open,
390 .release = NULL,
391 .fsync = hostfs_fsync,
392};
393
4b6f5d20 394static const struct file_operations hostfs_dir_fops = {
1da177e4
LT
395 .llseek = generic_file_llseek,
396 .readdir = hostfs_readdir,
397 .read = generic_read_dir,
398};
399
400int hostfs_writepage(struct page *page, struct writeback_control *wbc)
401{
402 struct address_space *mapping = page->mapping;
403 struct inode *inode = mapping->host;
404 char *buffer;
405 unsigned long long base;
406 int count = PAGE_CACHE_SIZE;
407 int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
408 int err;
409
410 if (page->index >= end_index)
411 count = inode->i_size & (PAGE_CACHE_SIZE-1);
412
413 buffer = kmap(page);
414 base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
415
416 err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count);
84b3db04 417 if (err != count) {
1da177e4
LT
418 ClearPageUptodate(page);
419 goto out;
420 }
421
422 if (base > inode->i_size)
423 inode->i_size = base;
424
425 if (PageError(page))
426 ClearPageError(page);
427 err = 0;
428
429 out:
430 kunmap(page);
431
432 unlock_page(page);
433 return err;
434}
435
436int hostfs_readpage(struct file *file, struct page *page)
437{
438 char *buffer;
439 long long start;
440 int err = 0;
441
442 start = (long long) page->index << PAGE_CACHE_SHIFT;
443 buffer = kmap(page);
444 err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
445 PAGE_CACHE_SIZE);
84b3db04
JD
446 if (err < 0)
447 goto out;
1da177e4
LT
448
449 memset(&buffer[err], 0, PAGE_CACHE_SIZE - err);
450
451 flush_dcache_page(page);
452 SetPageUptodate(page);
453 if (PageError(page)) ClearPageError(page);
454 err = 0;
455 out:
456 kunmap(page);
457 unlock_page(page);
f1adc05e 458 return err;
1da177e4
LT
459}
460
ae361ff4
NP
461int hostfs_write_begin(struct file *file, struct address_space *mapping,
462 loff_t pos, unsigned len, unsigned flags,
463 struct page **pagep, void **fsdata)
1da177e4 464{
ae361ff4 465 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
1da177e4 466
54566b2c 467 *pagep = grab_cache_page_write_begin(mapping, index, flags);
ae361ff4
NP
468 if (!*pagep)
469 return -ENOMEM;
470 return 0;
1da177e4
LT
471}
472
ae361ff4
NP
473int hostfs_write_end(struct file *file, struct address_space *mapping,
474 loff_t pos, unsigned len, unsigned copied,
475 struct page *page, void *fsdata)
1da177e4 476{
1da177e4 477 struct inode *inode = mapping->host;
ae361ff4
NP
478 void *buffer;
479 unsigned from = pos & (PAGE_CACHE_SIZE - 1);
480 int err;
1da177e4 481
1da177e4 482 buffer = kmap(page);
ae361ff4
NP
483 err = write_file(FILE_HOSTFS_I(file)->fd, &pos, buffer + from, copied);
484 kunmap(page);
30f04a4e 485
ae361ff4
NP
486 if (!PageUptodate(page) && err == PAGE_CACHE_SIZE)
487 SetPageUptodate(page);
30f04a4e 488
84b3db04
JD
489 /*
490 * If err > 0, write_file has added err to pos, so we are comparing
ae361ff4
NP
491 * i_size against the last byte written.
492 */
493 if (err > 0 && (pos > inode->i_size))
494 inode->i_size = pos;
495 unlock_page(page);
496 page_cache_release(page);
1da177e4 497
f1adc05e 498 return err;
1da177e4
LT
499}
500
f5e54d6e 501static const struct address_space_operations hostfs_aops = {
1da177e4
LT
502 .writepage = hostfs_writepage,
503 .readpage = hostfs_readpage,
ffa0aea6 504 .set_page_dirty = __set_page_dirty_nobuffers,
ae361ff4
NP
505 .write_begin = hostfs_write_begin,
506 .write_end = hostfs_write_end,
1da177e4
LT
507};
508
4754b825 509static int read_name(struct inode *ino, char *name)
1da177e4 510{
4754b825
AV
511 dev_t rdev;
512 struct hostfs_stat st;
513 int err = stat_file(name, &st, -1);
514 if (err)
515 return err;
1da177e4 516
5e2df28c 517 /* Reencode maj and min with the kernel encoding.*/
4754b825 518 rdev = MKDEV(st.maj, st.min);
1da177e4 519
4754b825
AV
520 switch (st.mode & S_IFMT) {
521 case S_IFLNK:
d0352d3e 522 ino->i_op = &hostfs_link_iops;
1da177e4 523 break;
4754b825
AV
524 case S_IFDIR:
525 ino->i_op = &hostfs_dir_iops;
526 ino->i_fop = &hostfs_dir_fops;
1da177e4 527 break;
4754b825
AV
528 case S_IFCHR:
529 case S_IFBLK:
530 case S_IFIFO:
531 case S_IFSOCK:
532 init_special_inode(ino, st.mode & S_IFMT, rdev);
533 ino->i_op = &hostfs_iops;
1da177e4 534 break;
4754b825
AV
535
536 default:
537 ino->i_op = &hostfs_iops;
538 ino->i_fop = &hostfs_file_fops;
539 ino->i_mapping->a_ops = &hostfs_aops;
1da177e4 540 }
4754b825
AV
541
542 ino->i_ino = st.ino;
543 ino->i_mode = st.mode;
bfe86848 544 set_nlink(ino, st.nlink);
29f82ae5
EB
545 i_uid_write(ino, st.uid);
546 i_gid_write(ino, st.gid);
4754b825
AV
547 ino->i_atime = st.atime;
548 ino->i_mtime = st.mtime;
549 ino->i_ctime = st.ctime;
550 ino->i_size = st.size;
551 ino->i_blocks = st.blocks;
552 return 0;
1da177e4
LT
553}
554
4acdaf27 555int hostfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
ebfc3b49 556 bool excl)
1da177e4
LT
557{
558 struct inode *inode;
559 char *name;
560 int error, fd;
561
0a370e5d
DH
562 inode = hostfs_iget(dir->i_sb);
563 if (IS_ERR(inode)) {
564 error = PTR_ERR(inode);
84b3db04 565 goto out;
0a370e5d 566 }
1da177e4 567
1da177e4 568 error = -ENOMEM;
c5322220 569 name = dentry_name(dentry);
84b3db04 570 if (name == NULL)
1da177e4
LT
571 goto out_put;
572
573 fd = file_create(name,
574 mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR,
575 mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP,
576 mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH);
4754b825 577 if (fd < 0)
1da177e4 578 error = fd;
4754b825 579 else
5e2df28c 580 error = read_name(inode, name);
1da177e4 581
e9193059 582 __putname(name);
84b3db04 583 if (error)
1da177e4
LT
584 goto out_put;
585
586 HOSTFS_I(inode)->fd = fd;
587 HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE;
588 d_instantiate(dentry, inode);
f1adc05e 589 return 0;
1da177e4
LT
590
591 out_put:
592 iput(inode);
593 out:
f1adc05e 594 return error;
1da177e4
LT
595}
596
597struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
00cd8dd3 598 unsigned int flags)
1da177e4
LT
599{
600 struct inode *inode;
601 char *name;
602 int err;
603
0a370e5d
DH
604 inode = hostfs_iget(ino->i_sb);
605 if (IS_ERR(inode)) {
606 err = PTR_ERR(inode);
1da177e4 607 goto out;
0a370e5d 608 }
1da177e4 609
1da177e4 610 err = -ENOMEM;
c5322220 611 name = dentry_name(dentry);
84b3db04 612 if (name == NULL)
1da177e4
LT
613 goto out_put;
614
615 err = read_name(inode, name);
5e2df28c 616
e9193059 617 __putname(name);
84b3db04 618 if (err == -ENOENT) {
1da177e4
LT
619 iput(inode);
620 inode = NULL;
621 }
84b3db04 622 else if (err)
1da177e4
LT
623 goto out_put;
624
625 d_add(dentry, inode);
f1adc05e 626 return NULL;
1da177e4
LT
627
628 out_put:
629 iput(inode);
630 out:
f1adc05e 631 return ERR_PTR(err);
1da177e4
LT
632}
633
1da177e4
LT
634int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
635{
f1adc05e
JD
636 char *from_name, *to_name;
637 int err;
1da177e4 638
c5322220 639 if ((from_name = dentry_name(from)) == NULL)
f1adc05e 640 return -ENOMEM;
c5322220 641 to_name = dentry_name(to);
84b3db04 642 if (to_name == NULL) {
e9193059 643 __putname(from_name);
f1adc05e 644 return -ENOMEM;
1da177e4 645 }
f1adc05e 646 err = link_file(to_name, from_name);
e9193059
AV
647 __putname(from_name);
648 __putname(to_name);
f1adc05e 649 return err;
1da177e4
LT
650}
651
652int hostfs_unlink(struct inode *ino, struct dentry *dentry)
653{
654 char *file;
655 int err;
656
84b3db04 657 if (append)
f1adc05e 658 return -EPERM;
1da177e4 659
f8d7e187
AV
660 if ((file = dentry_name(dentry)) == NULL)
661 return -ENOMEM;
662
1da177e4 663 err = unlink_file(file);
e9193059 664 __putname(file);
f1adc05e 665 return err;
1da177e4
LT
666}
667
668int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
669{
670 char *file;
671 int err;
672
c5322220 673 if ((file = dentry_name(dentry)) == NULL)
f1adc05e 674 return -ENOMEM;
1da177e4 675 err = make_symlink(file, to);
e9193059 676 __putname(file);
f1adc05e 677 return err;
1da177e4
LT
678}
679
18bb1db3 680int hostfs_mkdir(struct inode *ino, struct dentry *dentry, umode_t mode)
1da177e4
LT
681{
682 char *file;
683 int err;
684
c5322220 685 if ((file = dentry_name(dentry)) == NULL)
f1adc05e 686 return -ENOMEM;
1da177e4 687 err = do_mkdir(file, mode);
e9193059 688 __putname(file);
f1adc05e 689 return err;
1da177e4
LT
690}
691
692int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
693{
694 char *file;
695 int err;
696
c5322220 697 if ((file = dentry_name(dentry)) == NULL)
f1adc05e 698 return -ENOMEM;
1da177e4 699 err = do_rmdir(file);
e9193059 700 __putname(file);
f1adc05e 701 return err;
1da177e4
LT
702}
703
1a67aafb 704static int hostfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
1da177e4
LT
705{
706 struct inode *inode;
707 char *name;
0a370e5d 708 int err;
1da177e4 709
0a370e5d
DH
710 inode = hostfs_iget(dir->i_sb);
711 if (IS_ERR(inode)) {
712 err = PTR_ERR(inode);
1da177e4 713 goto out;
0a370e5d 714 }
1da177e4 715
1da177e4 716 err = -ENOMEM;
c5322220 717 name = dentry_name(dentry);
84b3db04 718 if (name == NULL)
1da177e4
LT
719 goto out_put;
720
721 init_special_inode(inode, mode, dev);
88f6cd0c 722 err = do_mknod(name, mode, MAJOR(dev), MINOR(dev));
e9193059 723 if (!err)
1da177e4
LT
724 goto out_free;
725
726 err = read_name(inode, name);
e9193059 727 __putname(name);
5e2df28c
AV
728 if (err)
729 goto out_put;
84b3db04 730 if (err)
1da177e4
LT
731 goto out_put;
732
733 d_instantiate(dentry, inode);
f1adc05e 734 return 0;
1da177e4
LT
735
736 out_free:
e9193059 737 __putname(name);
1da177e4
LT
738 out_put:
739 iput(inode);
740 out:
f1adc05e 741 return err;
1da177e4
LT
742}
743
744int hostfs_rename(struct inode *from_ino, struct dentry *from,
745 struct inode *to_ino, struct dentry *to)
746{
747 char *from_name, *to_name;
748 int err;
749
c5322220 750 if ((from_name = dentry_name(from)) == NULL)
f1adc05e 751 return -ENOMEM;
c5322220 752 if ((to_name = dentry_name(to)) == NULL) {
e9193059 753 __putname(from_name);
f1adc05e 754 return -ENOMEM;
1da177e4
LT
755 }
756 err = rename_file(from_name, to_name);
e9193059
AV
757 __putname(from_name);
758 __putname(to_name);
f1adc05e 759 return err;
1da177e4
LT
760}
761
10556cb2 762int hostfs_permission(struct inode *ino, int desired)
1da177e4
LT
763{
764 char *name;
765 int r = 0, w = 0, x = 0, err;
766
10556cb2 767 if (desired & MAY_NOT_BLOCK)
b74c79e9
NP
768 return -ECHILD;
769
1da177e4
LT
770 if (desired & MAY_READ) r = 1;
771 if (desired & MAY_WRITE) w = 1;
772 if (desired & MAY_EXEC) x = 1;
c5322220 773 name = inode_name(ino);
f1adc05e
JD
774 if (name == NULL)
775 return -ENOMEM;
1da177e4
LT
776
777 if (S_ISCHR(ino->i_mode) || S_ISBLK(ino->i_mode) ||
84b3db04 778 S_ISFIFO(ino->i_mode) || S_ISSOCK(ino->i_mode))
1da177e4
LT
779 err = 0;
780 else
781 err = access_file(name, r, w, x);
e9193059 782 __putname(name);
84b3db04 783 if (!err)
2830ba7f 784 err = generic_permission(ino, desired);
1da177e4
LT
785 return err;
786}
787
788int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
789{
1025774c 790 struct inode *inode = dentry->d_inode;
1da177e4
LT
791 struct hostfs_iattr attrs;
792 char *name;
793 int err;
794
1025774c 795 int fd = HOSTFS_I(inode)->fd;
5822b7fa 796
1025774c 797 err = inode_change_ok(inode, attr);
1da177e4
LT
798 if (err)
799 return err;
800
84b3db04 801 if (append)
1da177e4
LT
802 attr->ia_valid &= ~ATTR_SIZE;
803
804 attrs.ia_valid = 0;
84b3db04 805 if (attr->ia_valid & ATTR_MODE) {
1da177e4
LT
806 attrs.ia_valid |= HOSTFS_ATTR_MODE;
807 attrs.ia_mode = attr->ia_mode;
808 }
84b3db04 809 if (attr->ia_valid & ATTR_UID) {
1da177e4 810 attrs.ia_valid |= HOSTFS_ATTR_UID;
29f82ae5 811 attrs.ia_uid = from_kuid(&init_user_ns, attr->ia_uid);
1da177e4 812 }
84b3db04 813 if (attr->ia_valid & ATTR_GID) {
1da177e4 814 attrs.ia_valid |= HOSTFS_ATTR_GID;
29f82ae5 815 attrs.ia_gid = from_kgid(&init_user_ns, attr->ia_gid);
1da177e4 816 }
84b3db04 817 if (attr->ia_valid & ATTR_SIZE) {
1da177e4
LT
818 attrs.ia_valid |= HOSTFS_ATTR_SIZE;
819 attrs.ia_size = attr->ia_size;
820 }
84b3db04 821 if (attr->ia_valid & ATTR_ATIME) {
1da177e4
LT
822 attrs.ia_valid |= HOSTFS_ATTR_ATIME;
823 attrs.ia_atime = attr->ia_atime;
824 }
84b3db04 825 if (attr->ia_valid & ATTR_MTIME) {
1da177e4
LT
826 attrs.ia_valid |= HOSTFS_ATTR_MTIME;
827 attrs.ia_mtime = attr->ia_mtime;
828 }
84b3db04 829 if (attr->ia_valid & ATTR_CTIME) {
1da177e4
LT
830 attrs.ia_valid |= HOSTFS_ATTR_CTIME;
831 attrs.ia_ctime = attr->ia_ctime;
832 }
84b3db04 833 if (attr->ia_valid & ATTR_ATIME_SET) {
1da177e4
LT
834 attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET;
835 }
84b3db04 836 if (attr->ia_valid & ATTR_MTIME_SET) {
1da177e4
LT
837 attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET;
838 }
c5322220 839 name = dentry_name(dentry);
84b3db04 840 if (name == NULL)
f1adc05e 841 return -ENOMEM;
5822b7fa 842 err = set_attr(name, &attrs, fd);
e9193059 843 __putname(name);
84b3db04 844 if (err)
f1adc05e 845 return err;
1da177e4 846
1025774c
CH
847 if ((attr->ia_valid & ATTR_SIZE) &&
848 attr->ia_size != i_size_read(inode)) {
849 int error;
850
3be2be0a
MS
851 error = inode_newsize_ok(inode, attr->ia_size);
852 if (error)
853 return error;
854
855 truncate_setsize(inode, attr->ia_size);
1025774c
CH
856 }
857
858 setattr_copy(inode, attr);
859 mark_inode_dirty(inode);
860 return 0;
1da177e4
LT
861}
862
92e1d5be 863static const struct inode_operations hostfs_iops = {
1da177e4
LT
864 .create = hostfs_create,
865 .link = hostfs_link,
866 .unlink = hostfs_unlink,
867 .symlink = hostfs_symlink,
868 .mkdir = hostfs_mkdir,
869 .rmdir = hostfs_rmdir,
870 .mknod = hostfs_mknod,
871 .rename = hostfs_rename,
1da177e4
LT
872 .permission = hostfs_permission,
873 .setattr = hostfs_setattr,
1da177e4
LT
874};
875
92e1d5be 876static const struct inode_operations hostfs_dir_iops = {
1da177e4
LT
877 .create = hostfs_create,
878 .lookup = hostfs_lookup,
879 .link = hostfs_link,
880 .unlink = hostfs_unlink,
881 .symlink = hostfs_symlink,
882 .mkdir = hostfs_mkdir,
883 .rmdir = hostfs_rmdir,
884 .mknod = hostfs_mknod,
885 .rename = hostfs_rename,
1da177e4
LT
886 .permission = hostfs_permission,
887 .setattr = hostfs_setattr,
1da177e4
LT
888};
889
d0352d3e
AV
890static void *hostfs_follow_link(struct dentry *dentry, struct nameidata *nd)
891{
892 char *link = __getname();
893 if (link) {
894 char *path = dentry_name(dentry);
895 int err = -ENOMEM;
896 if (path) {
3b6036d1 897 err = hostfs_do_readlink(path, link, PATH_MAX);
d0352d3e
AV
898 if (err == PATH_MAX)
899 err = -E2BIG;
e9193059 900 __putname(path);
d0352d3e
AV
901 }
902 if (err < 0) {
903 __putname(link);
904 link = ERR_PTR(err);
905 }
906 } else {
907 link = ERR_PTR(-ENOMEM);
1da177e4 908 }
d0352d3e
AV
909
910 nd_set_link(nd, link);
911 return NULL;
912}
913
914static void hostfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
915{
916 char *s = nd_get_link(nd);
917 if (!IS_ERR(s))
918 __putname(s);
1da177e4
LT
919}
920
d0352d3e
AV
921static const struct inode_operations hostfs_link_iops = {
922 .readlink = generic_readlink,
923 .follow_link = hostfs_follow_link,
924 .put_link = hostfs_put_link,
1da177e4
LT
925};
926
927static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
928{
929 struct inode *root_inode;
75e8defb 930 char *host_root_path, *req_root = d;
1da177e4
LT
931 int err;
932
933 sb->s_blocksize = 1024;
934 sb->s_blocksize_bits = 10;
935 sb->s_magic = HOSTFS_SUPER_MAGIC;
936 sb->s_op = &hostfs_sbops;
f772c4a6 937 sb->s_d_op = &hostfs_dentry_ops;
752fa51e 938 sb->s_maxbytes = MAX_LFS_FILESIZE;
1da177e4 939
a6eb0be6 940 /* NULL is printed as <NULL> by sprintf: avoid that. */
75e8defb
PBG
941 if (req_root == NULL)
942 req_root = "";
1da177e4
LT
943
944 err = -ENOMEM;
601d2c38
AV
945 sb->s_fs_info = host_root_path =
946 kmalloc(strlen(root_ino) + strlen(req_root) + 2, GFP_KERNEL);
84b3db04 947 if (host_root_path == NULL)
1da177e4
LT
948 goto out;
949
75e8defb 950 sprintf(host_root_path, "%s/%s", root_ino, req_root);
1da177e4 951
52b209f7
AV
952 root_inode = new_inode(sb);
953 if (!root_inode)
601d2c38 954 goto out;
1da177e4 955
4754b825
AV
956 err = read_name(root_inode, host_root_path);
957 if (err)
958 goto out_put;
52b209f7 959
4754b825 960 if (S_ISLNK(root_inode->i_mode)) {
52b209f7
AV
961 char *name = follow_link(host_root_path);
962 if (IS_ERR(name))
963 err = PTR_ERR(name);
964 else
965 err = read_name(root_inode, name);
966 kfree(name);
4754b825
AV
967 if (err)
968 goto out_put;
52b209f7 969 }
1da177e4 970
1da177e4 971 err = -ENOMEM;
48fde701 972 sb->s_root = d_make_root(root_inode);
84b3db04 973 if (sb->s_root == NULL)
48fde701 974 goto out;
1da177e4 975
f1adc05e 976 return 0;
1da177e4 977
f1adc05e
JD
978out_put:
979 iput(root_inode);
f1adc05e
JD
980out:
981 return err;
1da177e4
LT
982}
983
3c26ff6e 984static struct dentry *hostfs_read_sb(struct file_system_type *type,
454e2398 985 int flags, const char *dev_name,
3c26ff6e 986 void *data)
1da177e4 987{
3c26ff6e 988 return mount_nodev(type, flags, data, hostfs_fill_sb_common);
1da177e4
LT
989}
990
601d2c38
AV
991static void hostfs_kill_sb(struct super_block *s)
992{
993 kill_anon_super(s);
994 kfree(s->s_fs_info);
995}
996
1da177e4
LT
997static struct file_system_type hostfs_type = {
998 .owner = THIS_MODULE,
999 .name = "hostfs",
3c26ff6e 1000 .mount = hostfs_read_sb,
601d2c38 1001 .kill_sb = hostfs_kill_sb,
1da177e4
LT
1002 .fs_flags = 0,
1003};
1004
1005static int __init init_hostfs(void)
1006{
f1adc05e 1007 return register_filesystem(&hostfs_type);
1da177e4
LT
1008}
1009
1010static void __exit exit_hostfs(void)
1011{
1012 unregister_filesystem(&hostfs_type);
1013}
1014
1015module_init(init_hostfs)
1016module_exit(exit_hostfs)
1017MODULE_LICENSE("GPL");