diff options
Diffstat (limited to 'fs/cramfs')
-rw-r--r-- | fs/cramfs/inode.c | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 6c285efa2004..7fe85415ae7c 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c | |||
@@ -39,12 +39,47 @@ static DECLARE_MUTEX(read_mutex); | |||
39 | #define CRAMINO(x) ((x)->offset?(x)->offset<<2:1) | 39 | #define CRAMINO(x) ((x)->offset?(x)->offset<<2:1) |
40 | #define OFFSET(x) ((x)->i_ino) | 40 | #define OFFSET(x) ((x)->i_ino) |
41 | 41 | ||
42 | static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode) | 42 | |
43 | static int cramfs_iget5_test(struct inode *inode, void *opaque) | ||
44 | { | ||
45 | struct cramfs_inode *cramfs_inode = opaque; | ||
46 | |||
47 | if (inode->i_ino != CRAMINO(cramfs_inode)) | ||
48 | return 0; /* does not match */ | ||
49 | |||
50 | if (inode->i_ino != 1) | ||
51 | return 1; | ||
52 | |||
53 | /* all empty directories, char, block, pipe, and sock, share inode #1 */ | ||
54 | |||
55 | if ((inode->i_mode != cramfs_inode->mode) || | ||
56 | (inode->i_gid != cramfs_inode->gid) || | ||
57 | (inode->i_uid != cramfs_inode->uid)) | ||
58 | return 0; /* does not match */ | ||
59 | |||
60 | if ((S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) && | ||
61 | (inode->i_rdev != old_decode_dev(cramfs_inode->size))) | ||
62 | return 0; /* does not match */ | ||
63 | |||
64 | return 1; /* matches */ | ||
65 | } | ||
66 | |||
67 | static int cramfs_iget5_set(struct inode *inode, void *opaque) | ||
68 | { | ||
69 | struct cramfs_inode *cramfs_inode = opaque; | ||
70 | inode->i_ino = CRAMINO(cramfs_inode); | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static struct inode *get_cramfs_inode(struct super_block *sb, | ||
75 | struct cramfs_inode * cramfs_inode) | ||
43 | { | 76 | { |
44 | struct inode * inode = new_inode(sb); | 77 | struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode), |
78 | cramfs_iget5_test, cramfs_iget5_set, | ||
79 | cramfs_inode); | ||
45 | static struct timespec zerotime; | 80 | static struct timespec zerotime; |
46 | 81 | ||
47 | if (inode) { | 82 | if (inode && (inode->i_state & I_NEW)) { |
48 | inode->i_mode = cramfs_inode->mode; | 83 | inode->i_mode = cramfs_inode->mode; |
49 | inode->i_uid = cramfs_inode->uid; | 84 | inode->i_uid = cramfs_inode->uid; |
50 | inode->i_size = cramfs_inode->size; | 85 | inode->i_size = cramfs_inode->size; |
@@ -58,7 +93,6 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inod | |||
58 | but it's the best we can do without reading the directory | 93 | but it's the best we can do without reading the directory |
59 | contents. 1 yields the right result in GNU find, even | 94 | contents. 1 yields the right result in GNU find, even |
60 | without -noleaf option. */ | 95 | without -noleaf option. */ |
61 | insert_inode_hash(inode); | ||
62 | if (S_ISREG(inode->i_mode)) { | 96 | if (S_ISREG(inode->i_mode)) { |
63 | inode->i_fop = &generic_ro_fops; | 97 | inode->i_fop = &generic_ro_fops; |
64 | inode->i_data.a_ops = &cramfs_aops; | 98 | inode->i_data.a_ops = &cramfs_aops; |
@@ -74,6 +108,7 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inod | |||
74 | init_special_inode(inode, inode->i_mode, | 108 | init_special_inode(inode, inode->i_mode, |
75 | old_decode_dev(cramfs_inode->size)); | 109 | old_decode_dev(cramfs_inode->size)); |
76 | } | 110 | } |
111 | unlock_new_inode(inode); | ||
77 | } | 112 | } |
78 | return inode; | 113 | return inode; |
79 | } | 114 | } |