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