diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/cramfs/inode.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'fs/cramfs/inode.c')
-rw-r--r-- | fs/cramfs/inode.c | 135 |
1 files changed, 82 insertions, 53 deletions
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 1e7a33028d33..739fb59bcdc2 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c | |||
@@ -34,57 +34,81 @@ static const struct address_space_operations cramfs_aops; | |||
34 | static DEFINE_MUTEX(read_mutex); | 34 | static DEFINE_MUTEX(read_mutex); |
35 | 35 | ||
36 | 36 | ||
37 | /* These two macros may change in future, to provide better st_ino | 37 | /* These macros may change in future, to provide better st_ino semantics. */ |
38 | semantics. */ | ||
39 | #define CRAMINO(x) (((x)->offset && (x)->size)?(x)->offset<<2:1) | ||
40 | #define OFFSET(x) ((x)->i_ino) | 38 | #define OFFSET(x) ((x)->i_ino) |
41 | 39 | ||
42 | static void setup_inode(struct inode *inode, struct cramfs_inode * cramfs_inode) | 40 | static unsigned long cramino(const struct cramfs_inode *cino, unsigned int offset) |
43 | { | 41 | { |
42 | if (!cino->offset) | ||
43 | return offset + 1; | ||
44 | if (!cino->size) | ||
45 | return offset + 1; | ||
46 | |||
47 | /* | ||
48 | * The file mode test fixes buggy mkcramfs implementations where | ||
49 | * cramfs_inode->offset is set to a non zero value for entries | ||
50 | * which did not contain data, like devices node and fifos. | ||
51 | */ | ||
52 | switch (cino->mode & S_IFMT) { | ||
53 | case S_IFREG: | ||
54 | case S_IFDIR: | ||
55 | case S_IFLNK: | ||
56 | return cino->offset << 2; | ||
57 | default: | ||
58 | break; | ||
59 | } | ||
60 | return offset + 1; | ||
61 | } | ||
62 | |||
63 | static struct inode *get_cramfs_inode(struct super_block *sb, | ||
64 | const struct cramfs_inode *cramfs_inode, unsigned int offset) | ||
65 | { | ||
66 | struct inode *inode; | ||
44 | static struct timespec zerotime; | 67 | static struct timespec zerotime; |
68 | |||
69 | inode = iget_locked(sb, cramino(cramfs_inode, offset)); | ||
70 | if (!inode) | ||
71 | return ERR_PTR(-ENOMEM); | ||
72 | if (!(inode->i_state & I_NEW)) | ||
73 | return inode; | ||
74 | |||
75 | switch (cramfs_inode->mode & S_IFMT) { | ||
76 | case S_IFREG: | ||
77 | inode->i_fop = &generic_ro_fops; | ||
78 | inode->i_data.a_ops = &cramfs_aops; | ||
79 | break; | ||
80 | case S_IFDIR: | ||
81 | inode->i_op = &cramfs_dir_inode_operations; | ||
82 | inode->i_fop = &cramfs_directory_operations; | ||
83 | break; | ||
84 | case S_IFLNK: | ||
85 | inode->i_op = &page_symlink_inode_operations; | ||
86 | inode->i_data.a_ops = &cramfs_aops; | ||
87 | break; | ||
88 | default: | ||
89 | init_special_inode(inode, cramfs_inode->mode, | ||
90 | old_decode_dev(cramfs_inode->size)); | ||
91 | } | ||
92 | |||
45 | inode->i_mode = cramfs_inode->mode; | 93 | inode->i_mode = cramfs_inode->mode; |
46 | inode->i_uid = cramfs_inode->uid; | 94 | inode->i_uid = cramfs_inode->uid; |
47 | inode->i_size = cramfs_inode->size; | ||
48 | inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; | ||
49 | inode->i_gid = cramfs_inode->gid; | 95 | inode->i_gid = cramfs_inode->gid; |
96 | |||
97 | /* if the lower 2 bits are zero, the inode contains data */ | ||
98 | if (!(inode->i_ino & 3)) { | ||
99 | inode->i_size = cramfs_inode->size; | ||
100 | inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; | ||
101 | } | ||
102 | |||
50 | /* Struct copy intentional */ | 103 | /* Struct copy intentional */ |
51 | inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; | 104 | inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; |
52 | /* inode->i_nlink is left 1 - arguably wrong for directories, | 105 | /* inode->i_nlink is left 1 - arguably wrong for directories, |
53 | but it's the best we can do without reading the directory | 106 | but it's the best we can do without reading the directory |
54 | contents. 1 yields the right result in GNU find, even | 107 | contents. 1 yields the right result in GNU find, even |
55 | without -noleaf option. */ | 108 | without -noleaf option. */ |
56 | if (S_ISREG(inode->i_mode)) { | ||
57 | inode->i_fop = &generic_ro_fops; | ||
58 | inode->i_data.a_ops = &cramfs_aops; | ||
59 | } else if (S_ISDIR(inode->i_mode)) { | ||
60 | inode->i_op = &cramfs_dir_inode_operations; | ||
61 | inode->i_fop = &cramfs_directory_operations; | ||
62 | } else if (S_ISLNK(inode->i_mode)) { | ||
63 | inode->i_op = &page_symlink_inode_operations; | ||
64 | inode->i_data.a_ops = &cramfs_aops; | ||
65 | } else { | ||
66 | init_special_inode(inode, inode->i_mode, | ||
67 | old_decode_dev(cramfs_inode->size)); | ||
68 | } | ||
69 | } | ||
70 | 109 | ||
71 | static struct inode *get_cramfs_inode(struct super_block *sb, | 110 | unlock_new_inode(inode); |
72 | struct cramfs_inode * cramfs_inode) | 111 | |
73 | { | ||
74 | struct inode *inode; | ||
75 | if (CRAMINO(cramfs_inode) == 1) { | ||
76 | inode = new_inode(sb); | ||
77 | if (inode) { | ||
78 | inode->i_ino = 1; | ||
79 | setup_inode(inode, cramfs_inode); | ||
80 | } | ||
81 | } else { | ||
82 | inode = iget_locked(sb, CRAMINO(cramfs_inode)); | ||
83 | if (inode && (inode->i_state & I_NEW)) { | ||
84 | setup_inode(inode, cramfs_inode); | ||
85 | unlock_new_inode(inode); | ||
86 | } | ||
87 | } | ||
88 | return inode; | 112 | return inode; |
89 | } | 113 | } |
90 | 114 | ||
@@ -265,6 +289,9 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent) | |||
265 | printk(KERN_ERR "cramfs: root is not a directory\n"); | 289 | printk(KERN_ERR "cramfs: root is not a directory\n"); |
266 | goto out; | 290 | goto out; |
267 | } | 291 | } |
292 | /* correct strange, hard-coded permissions of mkcramfs */ | ||
293 | super.root.mode |= (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); | ||
294 | |||
268 | root_offset = super.root.offset << 2; | 295 | root_offset = super.root.offset << 2; |
269 | if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) { | 296 | if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) { |
270 | sbi->size=super.size; | 297 | sbi->size=super.size; |
@@ -289,8 +316,8 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent) | |||
289 | 316 | ||
290 | /* Set it all up.. */ | 317 | /* Set it all up.. */ |
291 | sb->s_op = &cramfs_ops; | 318 | sb->s_op = &cramfs_ops; |
292 | root = get_cramfs_inode(sb, &super.root); | 319 | root = get_cramfs_inode(sb, &super.root, 0); |
293 | if (!root) | 320 | if (IS_ERR(root)) |
294 | goto out; | 321 | goto out; |
295 | sb->s_root = d_alloc_root(root); | 322 | sb->s_root = d_alloc_root(root); |
296 | if (!sb->s_root) { | 323 | if (!sb->s_root) { |
@@ -365,7 +392,7 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
365 | */ | 392 | */ |
366 | namelen = de->namelen << 2; | 393 | namelen = de->namelen << 2; |
367 | memcpy(buf, name, namelen); | 394 | memcpy(buf, name, namelen); |
368 | ino = CRAMINO(de); | 395 | ino = cramino(de, OFFSET(inode) + offset); |
369 | mode = de->mode; | 396 | mode = de->mode; |
370 | mutex_unlock(&read_mutex); | 397 | mutex_unlock(&read_mutex); |
371 | nextoffset = offset + sizeof(*de) + namelen; | 398 | nextoffset = offset + sizeof(*de) + namelen; |
@@ -396,6 +423,7 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
396 | static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 423 | static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
397 | { | 424 | { |
398 | unsigned int offset = 0; | 425 | unsigned int offset = 0; |
426 | struct inode *inode = NULL; | ||
399 | int sorted; | 427 | int sorted; |
400 | 428 | ||
401 | mutex_lock(&read_mutex); | 429 | mutex_lock(&read_mutex); |
@@ -404,8 +432,9 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s | |||
404 | struct cramfs_inode *de; | 432 | struct cramfs_inode *de; |
405 | char *name; | 433 | char *name; |
406 | int namelen, retval; | 434 | int namelen, retval; |
435 | int dir_off = OFFSET(dir) + offset; | ||
407 | 436 | ||
408 | de = cramfs_read(dir->i_sb, OFFSET(dir) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN); | 437 | de = cramfs_read(dir->i_sb, dir_off, sizeof(*de)+CRAMFS_MAXPATHLEN); |
409 | name = (char *)(de+1); | 438 | name = (char *)(de+1); |
410 | 439 | ||
411 | /* Try to take advantage of sorted directories */ | 440 | /* Try to take advantage of sorted directories */ |
@@ -421,8 +450,8 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s | |||
421 | 450 | ||
422 | for (;;) { | 451 | for (;;) { |
423 | if (!namelen) { | 452 | if (!namelen) { |
424 | mutex_unlock(&read_mutex); | 453 | inode = ERR_PTR(-EIO); |
425 | return ERR_PTR(-EIO); | 454 | goto out; |
426 | } | 455 | } |
427 | if (name[namelen-1]) | 456 | if (name[namelen-1]) |
428 | break; | 457 | break; |
@@ -434,17 +463,18 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s | |||
434 | if (retval > 0) | 463 | if (retval > 0) |
435 | continue; | 464 | continue; |
436 | if (!retval) { | 465 | if (!retval) { |
437 | struct cramfs_inode entry = *de; | 466 | inode = get_cramfs_inode(dir->i_sb, de, dir_off); |
438 | mutex_unlock(&read_mutex); | 467 | break; |
439 | d_add(dentry, get_cramfs_inode(dir->i_sb, &entry)); | ||
440 | return NULL; | ||
441 | } | 468 | } |
442 | /* else (retval < 0) */ | 469 | /* else (retval < 0) */ |
443 | if (sorted) | 470 | if (sorted) |
444 | break; | 471 | break; |
445 | } | 472 | } |
473 | out: | ||
446 | mutex_unlock(&read_mutex); | 474 | mutex_unlock(&read_mutex); |
447 | d_add(dentry, NULL); | 475 | if (IS_ERR(inode)) |
476 | return ERR_CAST(inode); | ||
477 | d_add(dentry, inode); | ||
448 | return NULL; | 478 | return NULL; |
449 | } | 479 | } |
450 | 480 | ||
@@ -533,17 +563,16 @@ static const struct super_operations cramfs_ops = { | |||
533 | .statfs = cramfs_statfs, | 563 | .statfs = cramfs_statfs, |
534 | }; | 564 | }; |
535 | 565 | ||
536 | static int cramfs_get_sb(struct file_system_type *fs_type, | 566 | static struct dentry *cramfs_mount(struct file_system_type *fs_type, |
537 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 567 | int flags, const char *dev_name, void *data) |
538 | { | 568 | { |
539 | return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super, | 569 | return mount_bdev(fs_type, flags, dev_name, data, cramfs_fill_super); |
540 | mnt); | ||
541 | } | 570 | } |
542 | 571 | ||
543 | static struct file_system_type cramfs_fs_type = { | 572 | static struct file_system_type cramfs_fs_type = { |
544 | .owner = THIS_MODULE, | 573 | .owner = THIS_MODULE, |
545 | .name = "cramfs", | 574 | .name = "cramfs", |
546 | .get_sb = cramfs_get_sb, | 575 | .mount = cramfs_mount, |
547 | .kill_sb = kill_block_super, | 576 | .kill_sb = kill_block_super, |
548 | .fs_flags = FS_REQUIRES_DEV, | 577 | .fs_flags = FS_REQUIRES_DEV, |
549 | }; | 578 | }; |