procfs: provide stack information for threads
[linux-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>
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;
aeb5d727 23 fmode_t mode;
1da177e4
LT
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 33
e16404ed 34static int hostfs_d_delete(struct dentry *dentry)
1da177e4 35{
f1adc05e 36 return 1;
1da177e4
LT
37}
38
e16404ed 39static const struct dentry_operations hostfs_dentry_ops = {
1da177e4
LT
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
ea7e743e 171 n = hostfs_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;
aeb5d727
AV
376 fmode_t mode = 0;
377 int r = 0, w = 0, fd;
1da177e4
LT
378
379 mode = file->f_mode & (FMODE_READ | FMODE_WRITE);
84b3db04 380 if ((mode & HOSTFS_I(ino)->mode) == mode)
f1adc05e 381 return 0;
1da177e4 382
84b3db04
JD
383 /*
384 * The file may already have been opened, but with the wrong access,
1da177e4
LT
385 * so this resets things and reopens the file with the new access.
386 */
84b3db04 387 if (HOSTFS_I(ino)->fd != -1) {
1da177e4
LT
388 close_file(&HOSTFS_I(ino)->fd);
389 HOSTFS_I(ino)->fd = -1;
390 }
391
392 HOSTFS_I(ino)->mode |= mode;
84b3db04 393 if (HOSTFS_I(ino)->mode & FMODE_READ)
1da177e4 394 r = 1;
84b3db04 395 if (HOSTFS_I(ino)->mode & FMODE_WRITE)
1da177e4 396 w = 1;
84b3db04 397 if (w)
1da177e4
LT
398 r = 1;
399
680b0da9 400 name = dentry_name(file->f_path.dentry, 0);
84b3db04 401 if (name == NULL)
f1adc05e 402 return -ENOMEM;
1da177e4
LT
403
404 fd = open_file(name, r, w, append);
405 kfree(name);
84b3db04 406 if (fd < 0)
f1adc05e 407 return fd;
1da177e4
LT
408 FILE_HOSTFS_I(file)->fd = fd;
409
f1adc05e 410 return 0;
1da177e4
LT
411}
412
413int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
414{
a2d76bd8 415 return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync);
1da177e4
LT
416}
417
4b6f5d20 418static const struct file_operations hostfs_file_fops = {
1da177e4 419 .llseek = generic_file_llseek,
543ade1f 420 .read = do_sync_read,
5ffc4ef4 421 .splice_read = generic_file_splice_read,
1da177e4
LT
422 .aio_read = generic_file_aio_read,
423 .aio_write = generic_file_aio_write,
543ade1f 424 .write = do_sync_write,
1da177e4
LT
425 .mmap = generic_file_mmap,
426 .open = hostfs_file_open,
427 .release = NULL,
428 .fsync = hostfs_fsync,
429};
430
4b6f5d20 431static const struct file_operations hostfs_dir_fops = {
1da177e4
LT
432 .llseek = generic_file_llseek,
433 .readdir = hostfs_readdir,
434 .read = generic_read_dir,
435};
436
437int hostfs_writepage(struct page *page, struct writeback_control *wbc)
438{
439 struct address_space *mapping = page->mapping;
440 struct inode *inode = mapping->host;
441 char *buffer;
442 unsigned long long base;
443 int count = PAGE_CACHE_SIZE;
444 int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
445 int err;
446
447 if (page->index >= end_index)
448 count = inode->i_size & (PAGE_CACHE_SIZE-1);
449
450 buffer = kmap(page);
451 base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
452
453 err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count);
84b3db04 454 if (err != count) {
1da177e4
LT
455 ClearPageUptodate(page);
456 goto out;
457 }
458
459 if (base > inode->i_size)
460 inode->i_size = base;
461
462 if (PageError(page))
463 ClearPageError(page);
464 err = 0;
465
466 out:
467 kunmap(page);
468
469 unlock_page(page);
470 return err;
471}
472
473int hostfs_readpage(struct file *file, struct page *page)
474{
475 char *buffer;
476 long long start;
477 int err = 0;
478
479 start = (long long) page->index << PAGE_CACHE_SHIFT;
480 buffer = kmap(page);
481 err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
482 PAGE_CACHE_SIZE);
84b3db04
JD
483 if (err < 0)
484 goto out;
1da177e4
LT
485
486 memset(&buffer[err], 0, PAGE_CACHE_SIZE - err);
487
488 flush_dcache_page(page);
489 SetPageUptodate(page);
490 if (PageError(page)) ClearPageError(page);
491 err = 0;
492 out:
493 kunmap(page);
494 unlock_page(page);
f1adc05e 495 return err;
1da177e4
LT
496}
497
ae361ff4
NP
498int hostfs_write_begin(struct file *file, struct address_space *mapping,
499 loff_t pos, unsigned len, unsigned flags,
500 struct page **pagep, void **fsdata)
1da177e4 501{
ae361ff4 502 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
1da177e4 503
54566b2c 504 *pagep = grab_cache_page_write_begin(mapping, index, flags);
ae361ff4
NP
505 if (!*pagep)
506 return -ENOMEM;
507 return 0;
1da177e4
LT
508}
509
ae361ff4
NP
510int hostfs_write_end(struct file *file, struct address_space *mapping,
511 loff_t pos, unsigned len, unsigned copied,
512 struct page *page, void *fsdata)
1da177e4 513{
1da177e4 514 struct inode *inode = mapping->host;
ae361ff4
NP
515 void *buffer;
516 unsigned from = pos & (PAGE_CACHE_SIZE - 1);
517 int err;
1da177e4 518
1da177e4 519 buffer = kmap(page);
ae361ff4
NP
520 err = write_file(FILE_HOSTFS_I(file)->fd, &pos, buffer + from, copied);
521 kunmap(page);
30f04a4e 522
ae361ff4
NP
523 if (!PageUptodate(page) && err == PAGE_CACHE_SIZE)
524 SetPageUptodate(page);
30f04a4e 525
84b3db04
JD
526 /*
527 * If err > 0, write_file has added err to pos, so we are comparing
ae361ff4
NP
528 * i_size against the last byte written.
529 */
530 if (err > 0 && (pos > inode->i_size))
531 inode->i_size = pos;
532 unlock_page(page);
533 page_cache_release(page);
1da177e4 534
f1adc05e 535 return err;
1da177e4
LT
536}
537
f5e54d6e 538static const struct address_space_operations hostfs_aops = {
1da177e4
LT
539 .writepage = hostfs_writepage,
540 .readpage = hostfs_readpage,
ffa0aea6 541 .set_page_dirty = __set_page_dirty_nobuffers,
ae361ff4
NP
542 .write_begin = hostfs_write_begin,
543 .write_end = hostfs_write_end,
1da177e4
LT
544};
545
546static int init_inode(struct inode *inode, struct dentry *dentry)
547{
548 char *name;
549 int type, err = -ENOMEM;
550 int maj, min;
551 dev_t rdev = 0;
552
84b3db04 553 if (dentry) {
1da177e4 554 name = dentry_name(dentry, 0);
84b3db04 555 if (name == NULL)
1da177e4
LT
556 goto out;
557 type = file_type(name, &maj, &min);
84b3db04 558 /* Reencode maj and min with the kernel encoding.*/
1da177e4
LT
559 rdev = MKDEV(maj, min);
560 kfree(name);
561 }
562 else type = OS_TYPE_DIR;
563
564 err = 0;
84b3db04 565 if (type == OS_TYPE_SYMLINK)
1da177e4 566 inode->i_op = &page_symlink_inode_operations;
84b3db04 567 else if (type == OS_TYPE_DIR)
1da177e4
LT
568 inode->i_op = &hostfs_dir_iops;
569 else inode->i_op = &hostfs_iops;
570
84b3db04 571 if (type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops;
1da177e4
LT
572 else inode->i_fop = &hostfs_file_fops;
573
84b3db04 574 if (type == OS_TYPE_SYMLINK)
1da177e4
LT
575 inode->i_mapping->a_ops = &hostfs_link_aops;
576 else inode->i_mapping->a_ops = &hostfs_aops;
577
578 switch (type) {
579 case OS_TYPE_CHARDEV:
580 init_special_inode(inode, S_IFCHR, rdev);
581 break;
582 case OS_TYPE_BLOCKDEV:
583 init_special_inode(inode, S_IFBLK, rdev);
584 break;
585 case OS_TYPE_FIFO:
586 init_special_inode(inode, S_IFIFO, 0);
587 break;
588 case OS_TYPE_SOCK:
589 init_special_inode(inode, S_IFSOCK, 0);
590 break;
591 }
592 out:
f1adc05e 593 return err;
1da177e4
LT
594}
595
596int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
84b3db04 597 struct nameidata *nd)
1da177e4
LT
598{
599 struct inode *inode;
600 char *name;
601 int error, fd;
602
0a370e5d
DH
603 inode = hostfs_iget(dir->i_sb);
604 if (IS_ERR(inode)) {
605 error = PTR_ERR(inode);
84b3db04 606 goto out;
0a370e5d 607 }
1da177e4
LT
608
609 error = init_inode(inode, dentry);
84b3db04 610 if (error)
1da177e4
LT
611 goto out_put;
612
613 error = -ENOMEM;
614 name = dentry_name(dentry, 0);
84b3db04 615 if (name == NULL)
1da177e4
LT
616 goto out_put;
617
618 fd = file_create(name,
619 mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR,
620 mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP,
621 mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH);
84b3db04 622 if (fd < 0)
1da177e4
LT
623 error = fd;
624 else error = read_name(inode, name);
625
626 kfree(name);
84b3db04 627 if (error)
1da177e4
LT
628 goto out_put;
629
630 HOSTFS_I(inode)->fd = fd;
631 HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE;
632 d_instantiate(dentry, inode);
f1adc05e 633 return 0;
1da177e4
LT
634
635 out_put:
636 iput(inode);
637 out:
f1adc05e 638 return error;
1da177e4
LT
639}
640
641struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
f1adc05e 642 struct nameidata *nd)
1da177e4
LT
643{
644 struct inode *inode;
645 char *name;
646 int err;
647
0a370e5d
DH
648 inode = hostfs_iget(ino->i_sb);
649 if (IS_ERR(inode)) {
650 err = PTR_ERR(inode);
1da177e4 651 goto out;
0a370e5d 652 }
1da177e4
LT
653
654 err = init_inode(inode, dentry);
84b3db04 655 if (err)
1da177e4
LT
656 goto out_put;
657
658 err = -ENOMEM;
659 name = dentry_name(dentry, 0);
84b3db04 660 if (name == NULL)
1da177e4
LT
661 goto out_put;
662
663 err = read_name(inode, name);
664 kfree(name);
84b3db04 665 if (err == -ENOENT) {
1da177e4
LT
666 iput(inode);
667 inode = NULL;
668 }
84b3db04 669 else if (err)
1da177e4
LT
670 goto out_put;
671
672 d_add(dentry, inode);
673 dentry->d_op = &hostfs_dentry_ops;
f1adc05e 674 return NULL;
1da177e4
LT
675
676 out_put:
677 iput(inode);
678 out:
f1adc05e 679 return ERR_PTR(err);
1da177e4
LT
680}
681
682static char *inode_dentry_name(struct inode *ino, struct dentry *dentry)
683{
f1adc05e 684 char *file;
1da177e4
LT
685 int len;
686
687 file = inode_name(ino, dentry->d_name.len + 1);
84b3db04 688 if (file == NULL)
f1adc05e
JD
689 return NULL;
690 strcat(file, "/");
1da177e4 691 len = strlen(file);
f1adc05e 692 strncat(file, dentry->d_name.name, dentry->d_name.len);
1da177e4 693 file[len + dentry->d_name.len] = '\0';
f1adc05e 694 return file;
1da177e4
LT
695}
696
697int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
698{
f1adc05e
JD
699 char *from_name, *to_name;
700 int err;
1da177e4 701
84b3db04 702 if ((from_name = inode_dentry_name(ino, from)) == NULL)
f1adc05e
JD
703 return -ENOMEM;
704 to_name = dentry_name(to, 0);
84b3db04 705 if (to_name == NULL) {
1da177e4 706 kfree(from_name);
f1adc05e 707 return -ENOMEM;
1da177e4 708 }
f1adc05e
JD
709 err = link_file(to_name, from_name);
710 kfree(from_name);
711 kfree(to_name);
712 return err;
1da177e4
LT
713}
714
715int hostfs_unlink(struct inode *ino, struct dentry *dentry)
716{
717 char *file;
718 int err;
719
84b3db04 720 if ((file = inode_dentry_name(ino, dentry)) == NULL)
f1adc05e 721 return -ENOMEM;
84b3db04 722 if (append)
f1adc05e 723 return -EPERM;
1da177e4
LT
724
725 err = unlink_file(file);
726 kfree(file);
f1adc05e 727 return err;
1da177e4
LT
728}
729
730int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
731{
732 char *file;
733 int err;
734
84b3db04 735 if ((file = inode_dentry_name(ino, dentry)) == NULL)
f1adc05e 736 return -ENOMEM;
1da177e4
LT
737 err = make_symlink(file, to);
738 kfree(file);
f1adc05e 739 return err;
1da177e4
LT
740}
741
742int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode)
743{
744 char *file;
745 int err;
746
84b3db04 747 if ((file = inode_dentry_name(ino, dentry)) == NULL)
f1adc05e 748 return -ENOMEM;
1da177e4
LT
749 err = do_mkdir(file, mode);
750 kfree(file);
f1adc05e 751 return err;
1da177e4
LT
752}
753
754int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
755{
756 char *file;
757 int err;
758
84b3db04 759 if ((file = inode_dentry_name(ino, dentry)) == NULL)
f1adc05e 760 return -ENOMEM;
1da177e4
LT
761 err = do_rmdir(file);
762 kfree(file);
f1adc05e 763 return err;
1da177e4
LT
764}
765
766int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
767{
768 struct inode *inode;
769 char *name;
0a370e5d 770 int err;
1da177e4 771
0a370e5d
DH
772 inode = hostfs_iget(dir->i_sb);
773 if (IS_ERR(inode)) {
774 err = PTR_ERR(inode);
1da177e4 775 goto out;
0a370e5d 776 }
1da177e4
LT
777
778 err = init_inode(inode, dentry);
84b3db04 779 if (err)
1da177e4
LT
780 goto out_put;
781
782 err = -ENOMEM;
783 name = dentry_name(dentry, 0);
84b3db04 784 if (name == NULL)
1da177e4
LT
785 goto out_put;
786
787 init_special_inode(inode, mode, dev);
88f6cd0c 788 err = do_mknod(name, mode, MAJOR(dev), MINOR(dev));
84b3db04 789 if (err)
1da177e4
LT
790 goto out_free;
791
792 err = read_name(inode, name);
793 kfree(name);
84b3db04 794 if (err)
1da177e4
LT
795 goto out_put;
796
797 d_instantiate(dentry, inode);
f1adc05e 798 return 0;
1da177e4
LT
799
800 out_free:
801 kfree(name);
802 out_put:
803 iput(inode);
804 out:
f1adc05e 805 return err;
1da177e4
LT
806}
807
808int hostfs_rename(struct inode *from_ino, struct dentry *from,
809 struct inode *to_ino, struct dentry *to)
810{
811 char *from_name, *to_name;
812 int err;
813
84b3db04 814 if ((from_name = inode_dentry_name(from_ino, from)) == NULL)
f1adc05e 815 return -ENOMEM;
84b3db04 816 if ((to_name = inode_dentry_name(to_ino, to)) == NULL) {
1da177e4 817 kfree(from_name);
f1adc05e 818 return -ENOMEM;
1da177e4
LT
819 }
820 err = rename_file(from_name, to_name);
821 kfree(from_name);
822 kfree(to_name);
f1adc05e 823 return err;
1da177e4
LT
824}
825
e6305c43 826int hostfs_permission(struct inode *ino, int desired)
1da177e4
LT
827{
828 char *name;
829 int r = 0, w = 0, x = 0, err;
830
831 if (desired & MAY_READ) r = 1;
832 if (desired & MAY_WRITE) w = 1;
833 if (desired & MAY_EXEC) x = 1;
834 name = inode_name(ino, 0);
f1adc05e
JD
835 if (name == NULL)
836 return -ENOMEM;
1da177e4
LT
837
838 if (S_ISCHR(ino->i_mode) || S_ISBLK(ino->i_mode) ||
84b3db04 839 S_ISFIFO(ino->i_mode) || S_ISSOCK(ino->i_mode))
1da177e4
LT
840 err = 0;
841 else
842 err = access_file(name, r, w, x);
843 kfree(name);
84b3db04 844 if (!err)
1da177e4
LT
845 err = generic_permission(ino, desired, NULL);
846 return err;
847}
848
849int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
850{
851 struct hostfs_iattr attrs;
852 char *name;
853 int err;
854
5822b7fa
AB
855 int fd = HOSTFS_I(dentry->d_inode)->fd;
856
1da177e4
LT
857 err = inode_change_ok(dentry->d_inode, attr);
858 if (err)
859 return err;
860
84b3db04 861 if (append)
1da177e4
LT
862 attr->ia_valid &= ~ATTR_SIZE;
863
864 attrs.ia_valid = 0;
84b3db04 865 if (attr->ia_valid & ATTR_MODE) {
1da177e4
LT
866 attrs.ia_valid |= HOSTFS_ATTR_MODE;
867 attrs.ia_mode = attr->ia_mode;
868 }
84b3db04 869 if (attr->ia_valid & ATTR_UID) {
1da177e4
LT
870 attrs.ia_valid |= HOSTFS_ATTR_UID;
871 attrs.ia_uid = attr->ia_uid;
872 }
84b3db04 873 if (attr->ia_valid & ATTR_GID) {
1da177e4
LT
874 attrs.ia_valid |= HOSTFS_ATTR_GID;
875 attrs.ia_gid = attr->ia_gid;
876 }
84b3db04 877 if (attr->ia_valid & ATTR_SIZE) {
1da177e4
LT
878 attrs.ia_valid |= HOSTFS_ATTR_SIZE;
879 attrs.ia_size = attr->ia_size;
880 }
84b3db04 881 if (attr->ia_valid & ATTR_ATIME) {
1da177e4
LT
882 attrs.ia_valid |= HOSTFS_ATTR_ATIME;
883 attrs.ia_atime = attr->ia_atime;
884 }
84b3db04 885 if (attr->ia_valid & ATTR_MTIME) {
1da177e4
LT
886 attrs.ia_valid |= HOSTFS_ATTR_MTIME;
887 attrs.ia_mtime = attr->ia_mtime;
888 }
84b3db04 889 if (attr->ia_valid & ATTR_CTIME) {
1da177e4
LT
890 attrs.ia_valid |= HOSTFS_ATTR_CTIME;
891 attrs.ia_ctime = attr->ia_ctime;
892 }
84b3db04 893 if (attr->ia_valid & ATTR_ATIME_SET) {
1da177e4
LT
894 attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET;
895 }
84b3db04 896 if (attr->ia_valid & ATTR_MTIME_SET) {
1da177e4
LT
897 attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET;
898 }
899 name = dentry_name(dentry, 0);
84b3db04 900 if (name == NULL)
f1adc05e 901 return -ENOMEM;
5822b7fa 902 err = set_attr(name, &attrs, fd);
1da177e4 903 kfree(name);
84b3db04 904 if (err)
f1adc05e 905 return err;
1da177e4 906
f1adc05e 907 return inode_setattr(dentry->d_inode, attr);
1da177e4
LT
908}
909
92e1d5be 910static const struct inode_operations hostfs_iops = {
1da177e4
LT
911 .create = hostfs_create,
912 .link = hostfs_link,
913 .unlink = hostfs_unlink,
914 .symlink = hostfs_symlink,
915 .mkdir = hostfs_mkdir,
916 .rmdir = hostfs_rmdir,
917 .mknod = hostfs_mknod,
918 .rename = hostfs_rename,
1da177e4
LT
919 .permission = hostfs_permission,
920 .setattr = hostfs_setattr,
1da177e4
LT
921};
922
92e1d5be 923static const struct inode_operations hostfs_dir_iops = {
1da177e4
LT
924 .create = hostfs_create,
925 .lookup = hostfs_lookup,
926 .link = hostfs_link,
927 .unlink = hostfs_unlink,
928 .symlink = hostfs_symlink,
929 .mkdir = hostfs_mkdir,
930 .rmdir = hostfs_rmdir,
931 .mknod = hostfs_mknod,
932 .rename = hostfs_rename,
1da177e4
LT
933 .permission = hostfs_permission,
934 .setattr = hostfs_setattr,
1da177e4
LT
935};
936
937int hostfs_link_readpage(struct file *file, struct page *page)
938{
939 char *buffer, *name;
1da177e4
LT
940 int err;
941
1da177e4
LT
942 buffer = kmap(page);
943 name = inode_name(page->mapping->host, 0);
84b3db04 944 if (name == NULL)
f1adc05e 945 return -ENOMEM;
ea7e743e 946 err = hostfs_do_readlink(name, buffer, PAGE_CACHE_SIZE);
1da177e4 947 kfree(name);
84b3db04 948 if (err == PAGE_CACHE_SIZE)
1da177e4 949 err = -E2BIG;
84b3db04 950 else if (err > 0) {
1da177e4
LT
951 flush_dcache_page(page);
952 SetPageUptodate(page);
953 if (PageError(page)) ClearPageError(page);
954 err = 0;
955 }
956 kunmap(page);
957 unlock_page(page);
f1adc05e 958 return err;
1da177e4
LT
959}
960
f5e54d6e 961static const struct address_space_operations hostfs_link_aops = {
1da177e4
LT
962 .readpage = hostfs_link_readpage,
963};
964
965static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
966{
967 struct inode *root_inode;
75e8defb 968 char *host_root_path, *req_root = d;
1da177e4
LT
969 int err;
970
971 sb->s_blocksize = 1024;
972 sb->s_blocksize_bits = 10;
973 sb->s_magic = HOSTFS_SUPER_MAGIC;
974 sb->s_op = &hostfs_sbops;
752fa51e 975 sb->s_maxbytes = MAX_LFS_FILESIZE;
1da177e4 976
a6eb0be6 977 /* NULL is printed as <NULL> by sprintf: avoid that. */
75e8defb
PBG
978 if (req_root == NULL)
979 req_root = "";
1da177e4
LT
980
981 err = -ENOMEM;
75e8defb
PBG
982 host_root_path = kmalloc(strlen(root_ino) + 1
983 + strlen(req_root) + 1, GFP_KERNEL);
84b3db04 984 if (host_root_path == NULL)
1da177e4
LT
985 goto out;
986
75e8defb 987 sprintf(host_root_path, "%s/%s", root_ino, req_root);
1da177e4 988
0a370e5d
DH
989 root_inode = hostfs_iget(sb);
990 if (IS_ERR(root_inode)) {
991 err = PTR_ERR(root_inode);
1da177e4 992 goto out_free;
0a370e5d 993 }
1da177e4
LT
994
995 err = init_inode(root_inode, NULL);
84b3db04 996 if (err)
1da177e4
LT
997 goto out_put;
998
75e8defb 999 HOSTFS_I(root_inode)->host_filename = host_root_path;
84b3db04
JD
1000 /*
1001 * Avoid that in the error path, iput(root_inode) frees again
1002 * host_root_path through hostfs_destroy_inode!
1003 */
75e8defb 1004 host_root_path = NULL;
1da177e4
LT
1005
1006 err = -ENOMEM;
1007 sb->s_root = d_alloc_root(root_inode);
84b3db04 1008 if (sb->s_root == NULL)
1da177e4
LT
1009 goto out_put;
1010
0a370e5d 1011 err = hostfs_read_inode(root_inode);
84b3db04 1012 if (err) {
f1adc05e
JD
1013 /* No iput in this case because the dput does that for us */
1014 dput(sb->s_root);
1015 sb->s_root = NULL;
bca27113 1016 goto out;
f1adc05e 1017 }
1da177e4 1018
f1adc05e 1019 return 0;
1da177e4 1020
f1adc05e
JD
1021out_put:
1022 iput(root_inode);
1023out_free:
75e8defb 1024 kfree(host_root_path);
f1adc05e
JD
1025out:
1026 return err;
1da177e4
LT
1027}
1028
454e2398
DH
1029static int hostfs_read_sb(struct file_system_type *type,
1030 int flags, const char *dev_name,
1031 void *data, struct vfsmount *mnt)
1da177e4 1032{
454e2398 1033 return get_sb_nodev(type, flags, data, hostfs_fill_sb_common, mnt);
1da177e4
LT
1034}
1035
1036static struct file_system_type hostfs_type = {
1037 .owner = THIS_MODULE,
1038 .name = "hostfs",
1039 .get_sb = hostfs_read_sb,
1040 .kill_sb = kill_anon_super,
1041 .fs_flags = 0,
1042};
1043
1044static int __init init_hostfs(void)
1045{
f1adc05e 1046 return register_filesystem(&hostfs_type);
1da177e4
LT
1047}
1048
1049static void __exit exit_hostfs(void)
1050{
1051 unregister_filesystem(&hostfs_type);
1052}
1053
1054module_init(init_hostfs)
1055module_exit(exit_hostfs)
1056MODULE_LICENSE("GPL");