Commit 6f772fe65c7aa1a4679739d885775f07492a6eea

Authored by Stefani Seibold
Committed by Linus Torvalds
1 parent beeae05138

cramfs: generate unique inode number for better inode cache usage

Generate a unique inode numbers for any entries in the cram file system.
For files which did not contain data's (device nodes, fifos and sockets)
the offset of the directory entry inside the cramfs plus 1 will be used as
inode number.

The + 1 for the inode will it make possible to distinguish between a file
which contains no data and files which has data, the later one has a inode
value where the lower two bits are always 0.

It also reimplements the behavior to set the size and the number of block
to 0 for special file, which is the right value for empty files, devices,
fifos and sockets

As a little benefit it will be also more compatible which older mkcramfs,
because it will never use the cramfs_inode->offset for creating a inode
number for special files.

[akpm@linux-foundation.org: trivial comment fix]
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 69 additions and 41 deletions Side-by-side Diff

... ... @@ -34,57 +34,81 @@
34 34 static DEFINE_MUTEX(read_mutex);
35 35  
36 36  
37   -/* These two macros may change in future, to provide better st_ino
38   - semantics. */
39   -#define CRAMINO(x) (((x)->offset && (x)->size)?(x)->offset<<2:1)
  37 +/* These macros may change in future, to provide better st_ino semantics. */
40 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(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 + struct cramfs_inode *cramfs_inode, unsigned int offset)
  65 +{
  66 + struct inode *inode;
44 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 93 inode->i_mode = cramfs_inode->mode;
46 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 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 103 /* Struct copy intentional */
51 104 inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime;
52 105 /* inode->i_nlink is left 1 - arguably wrong for directories,
53 106 but it's the best we can do without reading the directory
54 107 contents. 1 yields the right result in GNU find, even
55 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,
72   - struct cramfs_inode * cramfs_inode)
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   - }
  110 + unlock_new_inode(inode);
  111 +
88 112 return inode;
89 113 }
90 114  
... ... @@ -265,6 +289,9 @@
265 289 printk(KERN_ERR "cramfs: root is not a directory\n");
266 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 295 root_offset = super.root.offset << 2;
269 296 if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) {
270 297 sbi->size=super.size;
... ... @@ -289,7 +316,7 @@
289 316  
290 317 /* Set it all up.. */
291 318 sb->s_op = &cramfs_ops;
292   - root = get_cramfs_inode(sb, &super.root);
  319 + root = get_cramfs_inode(sb, &super.root, 0);
293 320 if (!root)
294 321 goto out;
295 322 sb->s_root = d_alloc_root(root);
... ... @@ -365,7 +392,7 @@
365 392 */
366 393 namelen = de->namelen << 2;
367 394 memcpy(buf, name, namelen);
368   - ino = CRAMINO(de);
  395 + ino = cramino(de, OFFSET(inode) + offset);
369 396 mode = de->mode;
370 397 mutex_unlock(&read_mutex);
371 398 nextoffset = offset + sizeof(*de) + namelen;
372 399  
... ... @@ -404,8 +431,9 @@
404 431 struct cramfs_inode *de;
405 432 char *name;
406 433 int namelen, retval;
  434 + int dir_off = OFFSET(dir) + offset;
407 435  
408   - de = cramfs_read(dir->i_sb, OFFSET(dir) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN);
  436 + de = cramfs_read(dir->i_sb, dir_off, sizeof(*de)+CRAMFS_MAXPATHLEN);
409 437 name = (char *)(de+1);
410 438  
411 439 /* Try to take advantage of sorted directories */
... ... @@ -436,7 +464,7 @@
436 464 if (!retval) {
437 465 struct cramfs_inode entry = *de;
438 466 mutex_unlock(&read_mutex);
439   - d_add(dentry, get_cramfs_inode(dir->i_sb, &entry));
  467 + d_add(dentry, get_cramfs_inode(dir->i_sb, &entry, dir_off));
440 468 return NULL;
441 469 }
442 470 /* else (retval < 0) */