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