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