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