]> bbs.cooldavid.org Git - net-next-2.6.git/blame - fs/hostfs/hostfs_kern.c
switch stat_file() to passing a single struct rather than fsckloads of pointers
[net-next-2.6.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>
1da177e4 17#include "hostfs.h"
1da177e4 18#include "init.h"
84b3db04 19#include "kern.h"
1da177e4
LT
20
21struct hostfs_inode_info {
1da177e4 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
601d2c38 105 root = parent->d_sb->s_fs_info;
1da177e4
LT
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{
39b743c6
AV
134 struct hostfs_stat st;
135 int err = stat_file(name, &st, -1);
84b3db04 136 if (err)
f1adc05e 137 return err;
1da177e4 138
39b743c6
AV
139 ino->i_ino = st.ino;
140 ino->i_mode = st.mode;
141 ino->i_nlink = st.nlink;
142 ino->i_uid = st.uid;
143 ino->i_gid = st.gid;
144 ino->i_atime = st.atime;
145 ino->i_mtime = st.mtime;
146 ino->i_ctime = st.ctime;
147 ino->i_size = st.size;
148 ino->i_blocks = st.blocks;
f1adc05e 149 return 0;
1da177e4
LT
150}
151
152static char *follow_link(char *link)
153{
154 int len, n;
155 char *name, *resolved, *end;
156
157 len = 64;
84b3db04 158 while (1) {
1da177e4
LT
159 n = -ENOMEM;
160 name = kmalloc(len, GFP_KERNEL);
84b3db04 161 if (name == NULL)
1da177e4
LT
162 goto out;
163
ea7e743e 164 n = hostfs_do_readlink(link, name, len);
84b3db04 165 if (n < len)
1da177e4
LT
166 break;
167 len *= 2;
168 kfree(name);
169 }
84b3db04 170 if (n < 0)
1da177e4
LT
171 goto out_free;
172
84b3db04 173 if (*name == '/')
f1adc05e 174 return name;
1da177e4
LT
175
176 end = strrchr(link, '/');
84b3db04 177 if (end == NULL)
f1adc05e 178 return name;
1da177e4
LT
179
180 *(end + 1) = '\0';
181 len = strlen(link) + strlen(name) + 1;
182
183 resolved = kmalloc(len, GFP_KERNEL);
84b3db04 184 if (resolved == NULL) {
1da177e4
LT
185 n = -ENOMEM;
186 goto out_free;
187 }
188
189 sprintf(resolved, "%s%s", link, name);
190 kfree(name);
191 kfree(link);
f1adc05e 192 return resolved;
1da177e4
LT
193
194 out_free:
195 kfree(name);
196 out:
f1adc05e 197 return ERR_PTR(n);
1da177e4
LT
198}
199
0a370e5d
DH
200static struct inode *hostfs_iget(struct super_block *sb)
201{
52b209f7 202 struct inode *inode = new_inode(sb);
0a370e5d
DH
203 if (!inode)
204 return ERR_PTR(-ENOMEM);
0a370e5d
DH
205 return inode;
206}
207
726c3342 208int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
1da177e4 209{
84b3db04
JD
210 /*
211 * do_statfs uses struct statfs64 internally, but the linux kernel
1da177e4
LT
212 * struct statfs still has 32-bit versions for most of these fields,
213 * so we convert them here
214 */
215 int err;
216 long long f_blocks;
217 long long f_bfree;
218 long long f_bavail;
219 long long f_files;
220 long long f_ffree;
221
601d2c38 222 err = do_statfs(dentry->d_sb->s_fs_info,
1da177e4
LT
223 &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
224 &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
225 &sf->f_namelen, sf->f_spare);
84b3db04 226 if (err)
f1adc05e 227 return err;
1da177e4
LT
228 sf->f_blocks = f_blocks;
229 sf->f_bfree = f_bfree;
230 sf->f_bavail = f_bavail;
231 sf->f_files = f_files;
232 sf->f_ffree = f_ffree;
233 sf->f_type = HOSTFS_SUPER_MAGIC;
f1adc05e 234 return 0;
1da177e4
LT
235}
236
237static struct inode *hostfs_alloc_inode(struct super_block *sb)
238{
239 struct hostfs_inode_info *hi;
240
601d2c38 241 hi = kzalloc(sizeof(*hi), GFP_KERNEL);
84b3db04 242 if (hi == NULL)
f1adc05e 243 return NULL;
601d2c38 244 hi->fd = -1;
1da177e4 245 inode_init_once(&hi->vfs_inode);
f1adc05e 246 return &hi->vfs_inode;
1da177e4
LT
247}
248
e971a6d7 249static void hostfs_evict_inode(struct inode *inode)
1da177e4 250{
fef26658 251 truncate_inode_pages(&inode->i_data, 0);
e971a6d7 252 end_writeback(inode);
84b3db04 253 if (HOSTFS_I(inode)->fd != -1) {
1da177e4
LT
254 close_file(&HOSTFS_I(inode)->fd);
255 HOSTFS_I(inode)->fd = -1;
256 }
1da177e4
LT
257}
258
259static void hostfs_destroy_inode(struct inode *inode)
260{
1da177e4
LT
261 kfree(HOSTFS_I(inode));
262}
263
dd2cc4df
MS
264static int hostfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
265{
601d2c38 266 const char *root_path = vfs->mnt_sb->s_fs_info;
dd2cc4df
MS
267 size_t offset = strlen(root_ino) + 1;
268
269 if (strlen(root_path) > offset)
270 seq_printf(seq, ",%s", root_path + offset);
271
272 return 0;
273}
274
ee9b6d61 275static const struct super_operations hostfs_sbops = {
1da177e4 276 .alloc_inode = hostfs_alloc_inode,
1da177e4 277 .destroy_inode = hostfs_destroy_inode,
e971a6d7 278 .evict_inode = hostfs_evict_inode,
1da177e4 279 .statfs = hostfs_statfs,
dd2cc4df 280 .show_options = hostfs_show_options,
1da177e4
LT
281};
282
283int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
284{
285 void *dir;
286 char *name;
287 unsigned long long next, ino;
288 int error, len;
289
680b0da9 290 name = dentry_name(file->f_path.dentry, 0);
84b3db04 291 if (name == NULL)
f1adc05e 292 return -ENOMEM;
1da177e4
LT
293 dir = open_dir(name, &error);
294 kfree(name);
84b3db04 295 if (dir == NULL)
f1adc05e 296 return -error;
1da177e4 297 next = file->f_pos;
84b3db04 298 while ((name = read_dir(dir, &next, &ino, &len)) != NULL) {
1da177e4
LT
299 error = (*filldir)(ent, name, len, file->f_pos,
300 ino, DT_UNKNOWN);
84b3db04 301 if (error) break;
1da177e4
LT
302 file->f_pos = next;
303 }
304 close_dir(dir);
f1adc05e 305 return 0;
1da177e4
LT
306}
307
308int hostfs_file_open(struct inode *ino, struct file *file)
309{
310 char *name;
aeb5d727
AV
311 fmode_t mode = 0;
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
84b3db04
JD
318 /*
319 * The file may already have been opened, but with the wrong access,
1da177e4
LT
320 * so this resets things and reopens the file with the new access.
321 */
84b3db04 322 if (HOSTFS_I(ino)->fd != -1) {
1da177e4
LT
323 close_file(&HOSTFS_I(ino)->fd);
324 HOSTFS_I(ino)->fd = -1;
325 }
326
327 HOSTFS_I(ino)->mode |= mode;
84b3db04 328 if (HOSTFS_I(ino)->mode & FMODE_READ)
1da177e4 329 r = 1;
84b3db04 330 if (HOSTFS_I(ino)->mode & FMODE_WRITE)
1da177e4 331 w = 1;
84b3db04 332 if (w)
1da177e4
LT
333 r = 1;
334
680b0da9 335 name = dentry_name(file->f_path.dentry, 0);
84b3db04 336 if (name == NULL)
f1adc05e 337 return -ENOMEM;
1da177e4
LT
338
339 fd = open_file(name, r, w, append);
340 kfree(name);
84b3db04 341 if (fd < 0)
f1adc05e 342 return fd;
1da177e4
LT
343 FILE_HOSTFS_I(file)->fd = fd;
344
f1adc05e 345 return 0;
1da177e4
LT
346}
347
7ea80859 348int hostfs_fsync(struct file *file, int datasync)
1da177e4 349{
7ea80859 350 return fsync_file(HOSTFS_I(file->f_mapping->host)->fd, datasync);
1da177e4
LT
351}
352
4b6f5d20 353static const struct file_operations hostfs_file_fops = {
1da177e4 354 .llseek = generic_file_llseek,
543ade1f 355 .read = do_sync_read,
5ffc4ef4 356 .splice_read = generic_file_splice_read,
1da177e4
LT
357 .aio_read = generic_file_aio_read,
358 .aio_write = generic_file_aio_write,
543ade1f 359 .write = do_sync_write,
1da177e4
LT
360 .mmap = generic_file_mmap,
361 .open = hostfs_file_open,
362 .release = NULL,
363 .fsync = hostfs_fsync,
364};
365
4b6f5d20 366static const struct file_operations hostfs_dir_fops = {
1da177e4
LT
367 .llseek = generic_file_llseek,
368 .readdir = hostfs_readdir,
369 .read = generic_read_dir,
370};
371
372int hostfs_writepage(struct page *page, struct writeback_control *wbc)
373{
374 struct address_space *mapping = page->mapping;
375 struct inode *inode = mapping->host;
376 char *buffer;
377 unsigned long long base;
378 int count = PAGE_CACHE_SIZE;
379 int end_index = inode->i_size >> PAGE_CACHE_SHIFT;
380 int err;
381
382 if (page->index >= end_index)
383 count = inode->i_size & (PAGE_CACHE_SIZE-1);
384
385 buffer = kmap(page);
386 base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT;
387
388 err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count);
84b3db04 389 if (err != count) {
1da177e4
LT
390 ClearPageUptodate(page);
391 goto out;
392 }
393
394 if (base > inode->i_size)
395 inode->i_size = base;
396
397 if (PageError(page))
398 ClearPageError(page);
399 err = 0;
400
401 out:
402 kunmap(page);
403
404 unlock_page(page);
405 return err;
406}
407
408int hostfs_readpage(struct file *file, struct page *page)
409{
410 char *buffer;
411 long long start;
412 int err = 0;
413
414 start = (long long) page->index << PAGE_CACHE_SHIFT;
415 buffer = kmap(page);
416 err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer,
417 PAGE_CACHE_SIZE);
84b3db04
JD
418 if (err < 0)
419 goto out;
1da177e4
LT
420
421 memset(&buffer[err], 0, PAGE_CACHE_SIZE - err);
422
423 flush_dcache_page(page);
424 SetPageUptodate(page);
425 if (PageError(page)) ClearPageError(page);
426 err = 0;
427 out:
428 kunmap(page);
429 unlock_page(page);
f1adc05e 430 return err;
1da177e4
LT
431}
432
ae361ff4
NP
433int hostfs_write_begin(struct file *file, struct address_space *mapping,
434 loff_t pos, unsigned len, unsigned flags,
435 struct page **pagep, void **fsdata)
1da177e4 436{
ae361ff4 437 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
1da177e4 438
54566b2c 439 *pagep = grab_cache_page_write_begin(mapping, index, flags);
ae361ff4
NP
440 if (!*pagep)
441 return -ENOMEM;
442 return 0;
1da177e4
LT
443}
444
ae361ff4
NP
445int hostfs_write_end(struct file *file, struct address_space *mapping,
446 loff_t pos, unsigned len, unsigned copied,
447 struct page *page, void *fsdata)
1da177e4 448{
1da177e4 449 struct inode *inode = mapping->host;
ae361ff4
NP
450 void *buffer;
451 unsigned from = pos & (PAGE_CACHE_SIZE - 1);
452 int err;
1da177e4 453
1da177e4 454 buffer = kmap(page);
ae361ff4
NP
455 err = write_file(FILE_HOSTFS_I(file)->fd, &pos, buffer + from, copied);
456 kunmap(page);
30f04a4e 457
ae361ff4
NP
458 if (!PageUptodate(page) && err == PAGE_CACHE_SIZE)
459 SetPageUptodate(page);
30f04a4e 460
84b3db04
JD
461 /*
462 * If err > 0, write_file has added err to pos, so we are comparing
ae361ff4
NP
463 * i_size against the last byte written.
464 */
465 if (err > 0 && (pos > inode->i_size))
466 inode->i_size = pos;
467 unlock_page(page);
468 page_cache_release(page);
1da177e4 469
f1adc05e 470 return err;
1da177e4
LT
471}
472
f5e54d6e 473static const struct address_space_operations hostfs_aops = {
1da177e4
LT
474 .writepage = hostfs_writepage,
475 .readpage = hostfs_readpage,
ffa0aea6 476 .set_page_dirty = __set_page_dirty_nobuffers,
ae361ff4
NP
477 .write_begin = hostfs_write_begin,
478 .write_end = hostfs_write_end,
1da177e4
LT
479};
480
5e2df28c 481static void init_inode(struct inode *inode, char *path)
1da177e4 482{
5e2df28c 483 int type;
1da177e4
LT
484 int maj, min;
485 dev_t rdev = 0;
486
5e2df28c
AV
487 type = file_type(path, &maj, &min);
488 /* Reencode maj and min with the kernel encoding.*/
489 rdev = MKDEV(maj, min);
1da177e4 490
84b3db04 491 if (type == OS_TYPE_SYMLINK)
1da177e4 492 inode->i_op = &page_symlink_inode_operations;
84b3db04 493 else if (type == OS_TYPE_DIR)
1da177e4
LT
494 inode->i_op = &hostfs_dir_iops;
495 else inode->i_op = &hostfs_iops;
496
84b3db04 497 if (type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops;
1da177e4
LT
498 else inode->i_fop = &hostfs_file_fops;
499
84b3db04 500 if (type == OS_TYPE_SYMLINK)
1da177e4
LT
501 inode->i_mapping->a_ops = &hostfs_link_aops;
502 else inode->i_mapping->a_ops = &hostfs_aops;
503
504 switch (type) {
505 case OS_TYPE_CHARDEV:
506 init_special_inode(inode, S_IFCHR, rdev);
507 break;
508 case OS_TYPE_BLOCKDEV:
509 init_special_inode(inode, S_IFBLK, rdev);
510 break;
511 case OS_TYPE_FIFO:
512 init_special_inode(inode, S_IFIFO, 0);
513 break;
514 case OS_TYPE_SOCK:
515 init_special_inode(inode, S_IFSOCK, 0);
516 break;
517 }
1da177e4
LT
518}
519
520int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
84b3db04 521 struct nameidata *nd)
1da177e4
LT
522{
523 struct inode *inode;
524 char *name;
525 int error, fd;
526
0a370e5d
DH
527 inode = hostfs_iget(dir->i_sb);
528 if (IS_ERR(inode)) {
529 error = PTR_ERR(inode);
84b3db04 530 goto out;
0a370e5d 531 }
1da177e4 532
1da177e4
LT
533 error = -ENOMEM;
534 name = dentry_name(dentry, 0);
84b3db04 535 if (name == NULL)
1da177e4
LT
536 goto out_put;
537
538 fd = file_create(name,
539 mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR,
540 mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP,
541 mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH);
5e2df28c 542 if (fd < 0) {
1da177e4 543 error = fd;
5e2df28c
AV
544 } else {
545 error = read_name(inode, name);
546 init_inode(inode, name);
547 }
1da177e4
LT
548
549 kfree(name);
84b3db04 550 if (error)
1da177e4
LT
551 goto out_put;
552
553 HOSTFS_I(inode)->fd = fd;
554 HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE;
555 d_instantiate(dentry, inode);
f1adc05e 556 return 0;
1da177e4
LT
557
558 out_put:
559 iput(inode);
560 out:
f1adc05e 561 return error;
1da177e4
LT
562}
563
564struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
f1adc05e 565 struct nameidata *nd)
1da177e4
LT
566{
567 struct inode *inode;
568 char *name;
569 int err;
570
0a370e5d
DH
571 inode = hostfs_iget(ino->i_sb);
572 if (IS_ERR(inode)) {
573 err = PTR_ERR(inode);
1da177e4 574 goto out;
0a370e5d 575 }
1da177e4 576
1da177e4
LT
577 err = -ENOMEM;
578 name = dentry_name(dentry, 0);
84b3db04 579 if (name == NULL)
1da177e4
LT
580 goto out_put;
581
582 err = read_name(inode, name);
5e2df28c
AV
583 init_inode(inode, name);
584
1da177e4 585 kfree(name);
84b3db04 586 if (err == -ENOENT) {
1da177e4
LT
587 iput(inode);
588 inode = NULL;
589 }
84b3db04 590 else if (err)
1da177e4
LT
591 goto out_put;
592
593 d_add(dentry, inode);
594 dentry->d_op = &hostfs_dentry_ops;
f1adc05e 595 return NULL;
1da177e4
LT
596
597 out_put:
598 iput(inode);
599 out:
f1adc05e 600 return ERR_PTR(err);
1da177e4
LT
601}
602
603static char *inode_dentry_name(struct inode *ino, struct dentry *dentry)
604{
f1adc05e 605 char *file;
1da177e4
LT
606 int len;
607
608 file = inode_name(ino, dentry->d_name.len + 1);
84b3db04 609 if (file == NULL)
f1adc05e
JD
610 return NULL;
611 strcat(file, "/");
1da177e4 612 len = strlen(file);
f1adc05e 613 strncat(file, dentry->d_name.name, dentry->d_name.len);
1da177e4 614 file[len + dentry->d_name.len] = '\0';
f1adc05e 615 return file;
1da177e4
LT
616}
617
618int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
619{
f1adc05e
JD
620 char *from_name, *to_name;
621 int err;
1da177e4 622
84b3db04 623 if ((from_name = inode_dentry_name(ino, from)) == NULL)
f1adc05e
JD
624 return -ENOMEM;
625 to_name = dentry_name(to, 0);
84b3db04 626 if (to_name == NULL) {
1da177e4 627 kfree(from_name);
f1adc05e 628 return -ENOMEM;
1da177e4 629 }
f1adc05e
JD
630 err = link_file(to_name, from_name);
631 kfree(from_name);
632 kfree(to_name);
633 return err;
1da177e4
LT
634}
635
636int hostfs_unlink(struct inode *ino, struct dentry *dentry)
637{
638 char *file;
639 int err;
640
84b3db04 641 if ((file = inode_dentry_name(ino, dentry)) == NULL)
f1adc05e 642 return -ENOMEM;
84b3db04 643 if (append)
f1adc05e 644 return -EPERM;
1da177e4
LT
645
646 err = unlink_file(file);
647 kfree(file);
f1adc05e 648 return err;
1da177e4
LT
649}
650
651int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to)
652{
653 char *file;
654 int err;
655
84b3db04 656 if ((file = inode_dentry_name(ino, dentry)) == NULL)
f1adc05e 657 return -ENOMEM;
1da177e4
LT
658 err = make_symlink(file, to);
659 kfree(file);
f1adc05e 660 return err;
1da177e4
LT
661}
662
663int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode)
664{
665 char *file;
666 int err;
667
84b3db04 668 if ((file = inode_dentry_name(ino, dentry)) == NULL)
f1adc05e 669 return -ENOMEM;
1da177e4
LT
670 err = do_mkdir(file, mode);
671 kfree(file);
f1adc05e 672 return err;
1da177e4
LT
673}
674
675int hostfs_rmdir(struct inode *ino, struct dentry *dentry)
676{
677 char *file;
678 int err;
679
84b3db04 680 if ((file = inode_dentry_name(ino, dentry)) == NULL)
f1adc05e 681 return -ENOMEM;
1da177e4
LT
682 err = do_rmdir(file);
683 kfree(file);
f1adc05e 684 return err;
1da177e4
LT
685}
686
687int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
688{
689 struct inode *inode;
690 char *name;
0a370e5d 691 int err;
1da177e4 692
0a370e5d
DH
693 inode = hostfs_iget(dir->i_sb);
694 if (IS_ERR(inode)) {
695 err = PTR_ERR(inode);
1da177e4 696 goto out;
0a370e5d 697 }
1da177e4 698
1da177e4
LT
699 err = -ENOMEM;
700 name = dentry_name(dentry, 0);
84b3db04 701 if (name == NULL)
1da177e4
LT
702 goto out_put;
703
704 init_special_inode(inode, mode, dev);
88f6cd0c 705 err = do_mknod(name, mode, MAJOR(dev), MINOR(dev));
84b3db04 706 if (err)
1da177e4
LT
707 goto out_free;
708
709 err = read_name(inode, name);
5e2df28c
AV
710 init_inode(inode, name);
711 if (err)
712 goto out_put;
1da177e4 713 kfree(name);
84b3db04 714 if (err)
1da177e4
LT
715 goto out_put;
716
717 d_instantiate(dentry, inode);
f1adc05e 718 return 0;
1da177e4
LT
719
720 out_free:
721 kfree(name);
722 out_put:
723 iput(inode);
724 out:
f1adc05e 725 return err;
1da177e4
LT
726}
727
728int hostfs_rename(struct inode *from_ino, struct dentry *from,
729 struct inode *to_ino, struct dentry *to)
730{
731 char *from_name, *to_name;
732 int err;
733
84b3db04 734 if ((from_name = inode_dentry_name(from_ino, from)) == NULL)
f1adc05e 735 return -ENOMEM;
84b3db04 736 if ((to_name = inode_dentry_name(to_ino, to)) == NULL) {
1da177e4 737 kfree(from_name);
f1adc05e 738 return -ENOMEM;
1da177e4
LT
739 }
740 err = rename_file(from_name, to_name);
741 kfree(from_name);
742 kfree(to_name);
f1adc05e 743 return err;
1da177e4
LT
744}
745
e6305c43 746int hostfs_permission(struct inode *ino, int desired)
1da177e4
LT
747{
748 char *name;
749 int r = 0, w = 0, x = 0, err;
750
751 if (desired & MAY_READ) r = 1;
752 if (desired & MAY_WRITE) w = 1;
753 if (desired & MAY_EXEC) x = 1;
754 name = inode_name(ino, 0);
f1adc05e
JD
755 if (name == NULL)
756 return -ENOMEM;
1da177e4
LT
757
758 if (S_ISCHR(ino->i_mode) || S_ISBLK(ino->i_mode) ||
84b3db04 759 S_ISFIFO(ino->i_mode) || S_ISSOCK(ino->i_mode))
1da177e4
LT
760 err = 0;
761 else
762 err = access_file(name, r, w, x);
763 kfree(name);
84b3db04 764 if (!err)
1da177e4
LT
765 err = generic_permission(ino, desired, NULL);
766 return err;
767}
768
769int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
770{
1025774c 771 struct inode *inode = dentry->d_inode;
1da177e4
LT
772 struct hostfs_iattr attrs;
773 char *name;
774 int err;
775
1025774c 776 int fd = HOSTFS_I(inode)->fd;
5822b7fa 777
1025774c 778 err = inode_change_ok(inode, attr);
1da177e4
LT
779 if (err)
780 return err;
781
84b3db04 782 if (append)
1da177e4
LT
783 attr->ia_valid &= ~ATTR_SIZE;
784
785 attrs.ia_valid = 0;
84b3db04 786 if (attr->ia_valid & ATTR_MODE) {
1da177e4
LT
787 attrs.ia_valid |= HOSTFS_ATTR_MODE;
788 attrs.ia_mode = attr->ia_mode;
789 }
84b3db04 790 if (attr->ia_valid & ATTR_UID) {
1da177e4
LT
791 attrs.ia_valid |= HOSTFS_ATTR_UID;
792 attrs.ia_uid = attr->ia_uid;
793 }
84b3db04 794 if (attr->ia_valid & ATTR_GID) {
1da177e4
LT
795 attrs.ia_valid |= HOSTFS_ATTR_GID;
796 attrs.ia_gid = attr->ia_gid;
797 }
84b3db04 798 if (attr->ia_valid & ATTR_SIZE) {
1da177e4
LT
799 attrs.ia_valid |= HOSTFS_ATTR_SIZE;
800 attrs.ia_size = attr->ia_size;
801 }
84b3db04 802 if (attr->ia_valid & ATTR_ATIME) {
1da177e4
LT
803 attrs.ia_valid |= HOSTFS_ATTR_ATIME;
804 attrs.ia_atime = attr->ia_atime;
805 }
84b3db04 806 if (attr->ia_valid & ATTR_MTIME) {
1da177e4
LT
807 attrs.ia_valid |= HOSTFS_ATTR_MTIME;
808 attrs.ia_mtime = attr->ia_mtime;
809 }
84b3db04 810 if (attr->ia_valid & ATTR_CTIME) {
1da177e4
LT
811 attrs.ia_valid |= HOSTFS_ATTR_CTIME;
812 attrs.ia_ctime = attr->ia_ctime;
813 }
84b3db04 814 if (attr->ia_valid & ATTR_ATIME_SET) {
1da177e4
LT
815 attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET;
816 }
84b3db04 817 if (attr->ia_valid & ATTR_MTIME_SET) {
1da177e4
LT
818 attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET;
819 }
820 name = dentry_name(dentry, 0);
84b3db04 821 if (name == NULL)
f1adc05e 822 return -ENOMEM;
5822b7fa 823 err = set_attr(name, &attrs, fd);
1da177e4 824 kfree(name);
84b3db04 825 if (err)
f1adc05e 826 return err;
1da177e4 827
1025774c
CH
828 if ((attr->ia_valid & ATTR_SIZE) &&
829 attr->ia_size != i_size_read(inode)) {
830 int error;
831
832 error = vmtruncate(inode, attr->ia_size);
833 if (err)
834 return err;
835 }
836
837 setattr_copy(inode, attr);
838 mark_inode_dirty(inode);
839 return 0;
1da177e4
LT
840}
841
92e1d5be 842static const struct inode_operations hostfs_iops = {
1da177e4
LT
843 .create = hostfs_create,
844 .link = hostfs_link,
845 .unlink = hostfs_unlink,
846 .symlink = hostfs_symlink,
847 .mkdir = hostfs_mkdir,
848 .rmdir = hostfs_rmdir,
849 .mknod = hostfs_mknod,
850 .rename = hostfs_rename,
1da177e4
LT
851 .permission = hostfs_permission,
852 .setattr = hostfs_setattr,
1da177e4
LT
853};
854
92e1d5be 855static const struct inode_operations hostfs_dir_iops = {
1da177e4
LT
856 .create = hostfs_create,
857 .lookup = hostfs_lookup,
858 .link = hostfs_link,
859 .unlink = hostfs_unlink,
860 .symlink = hostfs_symlink,
861 .mkdir = hostfs_mkdir,
862 .rmdir = hostfs_rmdir,
863 .mknod = hostfs_mknod,
864 .rename = hostfs_rename,
1da177e4
LT
865 .permission = hostfs_permission,
866 .setattr = hostfs_setattr,
1da177e4
LT
867};
868
869int hostfs_link_readpage(struct file *file, struct page *page)
870{
871 char *buffer, *name;
1da177e4
LT
872 int err;
873
1da177e4
LT
874 buffer = kmap(page);
875 name = inode_name(page->mapping->host, 0);
84b3db04 876 if (name == NULL)
f1adc05e 877 return -ENOMEM;
ea7e743e 878 err = hostfs_do_readlink(name, buffer, PAGE_CACHE_SIZE);
1da177e4 879 kfree(name);
84b3db04 880 if (err == PAGE_CACHE_SIZE)
1da177e4 881 err = -E2BIG;
84b3db04 882 else if (err > 0) {
1da177e4
LT
883 flush_dcache_page(page);
884 SetPageUptodate(page);
885 if (PageError(page)) ClearPageError(page);
886 err = 0;
887 }
888 kunmap(page);
889 unlock_page(page);
f1adc05e 890 return err;
1da177e4
LT
891}
892
f5e54d6e 893static const struct address_space_operations hostfs_link_aops = {
1da177e4
LT
894 .readpage = hostfs_link_readpage,
895};
896
897static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
898{
899 struct inode *root_inode;
75e8defb 900 char *host_root_path, *req_root = d;
1da177e4
LT
901 int err;
902
903 sb->s_blocksize = 1024;
904 sb->s_blocksize_bits = 10;
905 sb->s_magic = HOSTFS_SUPER_MAGIC;
906 sb->s_op = &hostfs_sbops;
752fa51e 907 sb->s_maxbytes = MAX_LFS_FILESIZE;
1da177e4 908
a6eb0be6 909 /* NULL is printed as <NULL> by sprintf: avoid that. */
75e8defb
PBG
910 if (req_root == NULL)
911 req_root = "";
1da177e4
LT
912
913 err = -ENOMEM;
601d2c38
AV
914 sb->s_fs_info = host_root_path =
915 kmalloc(strlen(root_ino) + strlen(req_root) + 2, GFP_KERNEL);
84b3db04 916 if (host_root_path == NULL)
1da177e4
LT
917 goto out;
918
75e8defb 919 sprintf(host_root_path, "%s/%s", root_ino, req_root);
1da177e4 920
52b209f7
AV
921 root_inode = new_inode(sb);
922 if (!root_inode)
601d2c38 923 goto out;
1da177e4 924
52b209f7
AV
925 root_inode->i_op = &hostfs_dir_iops;
926 root_inode->i_fop = &hostfs_dir_fops;
927
928 if (file_type(host_root_path, NULL, NULL) == OS_TYPE_SYMLINK) {
929 char *name = follow_link(host_root_path);
930 if (IS_ERR(name))
931 err = PTR_ERR(name);
932 else
933 err = read_name(root_inode, name);
934 kfree(name);
935 } else {
936 err = read_name(root_inode, host_root_path);
937 }
84b3db04 938 if (err)
1da177e4
LT
939 goto out_put;
940
1da177e4
LT
941 err = -ENOMEM;
942 sb->s_root = d_alloc_root(root_inode);
84b3db04 943 if (sb->s_root == NULL)
1da177e4
LT
944 goto out_put;
945
f1adc05e 946 return 0;
1da177e4 947
f1adc05e
JD
948out_put:
949 iput(root_inode);
f1adc05e
JD
950out:
951 return err;
1da177e4
LT
952}
953
454e2398
DH
954static int hostfs_read_sb(struct file_system_type *type,
955 int flags, const char *dev_name,
956 void *data, struct vfsmount *mnt)
1da177e4 957{
454e2398 958 return get_sb_nodev(type, flags, data, hostfs_fill_sb_common, mnt);
1da177e4
LT
959}
960
601d2c38
AV
961static void hostfs_kill_sb(struct super_block *s)
962{
963 kill_anon_super(s);
964 kfree(s->s_fs_info);
965}
966
1da177e4
LT
967static struct file_system_type hostfs_type = {
968 .owner = THIS_MODULE,
969 .name = "hostfs",
970 .get_sb = hostfs_read_sb,
601d2c38 971 .kill_sb = hostfs_kill_sb,
1da177e4
LT
972 .fs_flags = 0,
973};
974
975static int __init init_hostfs(void)
976{
f1adc05e 977 return register_filesystem(&hostfs_type);
1da177e4
LT
978}
979
980static void __exit exit_hostfs(void)
981{
982 unregister_filesystem(&hostfs_type);
983}
984
985module_init(init_hostfs)
986module_exit(exit_hostfs)
987MODULE_LICENSE("GPL");