aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cramfs/inode.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/cramfs/inode.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (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.c135
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;
34static DEFINE_MUTEX(read_mutex); 34static 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
42static void setup_inode(struct inode *inode, struct cramfs_inode * cramfs_inode) 40static 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
63static 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
71static 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)
396static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) 423static 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 }
473out:
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
536static int cramfs_get_sb(struct file_system_type *fs_type, 566static 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
543static struct file_system_type cramfs_fs_type = { 572static 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};