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