diff options
Diffstat (limited to 'fs/pstore/inode.c')
-rw-r--r-- | fs/pstore/inode.c | 116 |
1 files changed, 56 insertions, 60 deletions
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 549d245d0b42..08342232cb1c 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c | |||
@@ -40,9 +40,29 @@ | |||
40 | struct pstore_private { | 40 | struct pstore_private { |
41 | u64 id; | 41 | u64 id; |
42 | int (*erase)(u64); | 42 | int (*erase)(u64); |
43 | ssize_t size; | ||
44 | char data[]; | ||
43 | }; | 45 | }; |
44 | 46 | ||
45 | #define pstore_get_inode ramfs_get_inode | 47 | static int pstore_file_open(struct inode *inode, struct file *file) |
48 | { | ||
49 | file->private_data = inode->i_private; | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static ssize_t pstore_file_read(struct file *file, char __user *userbuf, | ||
54 | size_t count, loff_t *ppos) | ||
55 | { | ||
56 | struct pstore_private *ps = file->private_data; | ||
57 | |||
58 | return simple_read_from_buffer(userbuf, count, ppos, ps->data, ps->size); | ||
59 | } | ||
60 | |||
61 | static const struct file_operations pstore_file_operations = { | ||
62 | .open = pstore_file_open, | ||
63 | .read = pstore_file_read, | ||
64 | .llseek = default_llseek, | ||
65 | }; | ||
46 | 66 | ||
47 | /* | 67 | /* |
48 | * When a file is unlinked from our file system we call the | 68 | * When a file is unlinked from our file system we call the |
@@ -63,6 +83,30 @@ static const struct inode_operations pstore_dir_inode_operations = { | |||
63 | .unlink = pstore_unlink, | 83 | .unlink = pstore_unlink, |
64 | }; | 84 | }; |
65 | 85 | ||
86 | static struct inode *pstore_get_inode(struct super_block *sb, | ||
87 | const struct inode *dir, int mode, dev_t dev) | ||
88 | { | ||
89 | struct inode *inode = new_inode(sb); | ||
90 | |||
91 | if (inode) { | ||
92 | inode->i_ino = get_next_ino(); | ||
93 | inode->i_uid = inode->i_gid = 0; | ||
94 | inode->i_mode = mode; | ||
95 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
96 | switch (mode & S_IFMT) { | ||
97 | case S_IFREG: | ||
98 | inode->i_fop = &pstore_file_operations; | ||
99 | break; | ||
100 | case S_IFDIR: | ||
101 | inode->i_op = &pstore_dir_inode_operations; | ||
102 | inode->i_fop = &simple_dir_operations; | ||
103 | inc_nlink(inode); | ||
104 | break; | ||
105 | } | ||
106 | } | ||
107 | return inode; | ||
108 | } | ||
109 | |||
66 | static const struct super_operations pstore_ops = { | 110 | static const struct super_operations pstore_ops = { |
67 | .statfs = simple_statfs, | 111 | .statfs = simple_statfs, |
68 | .drop_inode = generic_delete_inode, | 112 | .drop_inode = generic_delete_inode, |
@@ -70,37 +114,10 @@ static const struct super_operations pstore_ops = { | |||
70 | }; | 114 | }; |
71 | 115 | ||
72 | static struct super_block *pstore_sb; | 116 | static struct super_block *pstore_sb; |
73 | static struct vfsmount *pstore_mnt; | ||
74 | 117 | ||
75 | int pstore_is_mounted(void) | 118 | int pstore_is_mounted(void) |
76 | { | 119 | { |
77 | return pstore_mnt != NULL; | 120 | return pstore_sb != NULL; |
78 | } | ||
79 | |||
80 | /* | ||
81 | * Set up a file structure as if we had opened this file and | ||
82 | * write our data to it. | ||
83 | */ | ||
84 | static int pstore_writefile(struct inode *inode, struct dentry *dentry, | ||
85 | char *data, size_t size) | ||
86 | { | ||
87 | struct file f; | ||
88 | ssize_t n; | ||
89 | mm_segment_t old_fs = get_fs(); | ||
90 | |||
91 | memset(&f, '0', sizeof f); | ||
92 | f.f_mapping = inode->i_mapping; | ||
93 | f.f_path.dentry = dentry; | ||
94 | f.f_path.mnt = pstore_mnt; | ||
95 | f.f_pos = 0; | ||
96 | f.f_op = inode->i_fop; | ||
97 | set_fs(KERNEL_DS); | ||
98 | n = do_sync_write(&f, data, size, &f.f_pos); | ||
99 | set_fs(old_fs); | ||
100 | |||
101 | fsnotify_modify(&f); | ||
102 | |||
103 | return n == size; | ||
104 | } | 121 | } |
105 | 122 | ||
106 | /* | 123 | /* |
@@ -123,8 +140,7 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, | |||
123 | inode = pstore_get_inode(pstore_sb, root->d_inode, S_IFREG | 0444, 0); | 140 | inode = pstore_get_inode(pstore_sb, root->d_inode, S_IFREG | 0444, 0); |
124 | if (!inode) | 141 | if (!inode) |
125 | goto fail; | 142 | goto fail; |
126 | inode->i_uid = inode->i_gid = 0; | 143 | private = kmalloc(sizeof *private + size, GFP_KERNEL); |
127 | private = kmalloc(sizeof *private, GFP_KERNEL); | ||
128 | if (!private) | 144 | if (!private) |
129 | goto fail_alloc; | 145 | goto fail_alloc; |
130 | private->id = id; | 146 | private->id = id; |
@@ -152,28 +168,19 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, | |||
152 | if (IS_ERR(dentry)) | 168 | if (IS_ERR(dentry)) |
153 | goto fail_lockedalloc; | 169 | goto fail_lockedalloc; |
154 | 170 | ||
155 | d_add(dentry, inode); | 171 | memcpy(private->data, data, size); |
156 | 172 | inode->i_size = private->size = size; | |
157 | mutex_unlock(&root->d_inode->i_mutex); | ||
158 | |||
159 | if (!pstore_writefile(inode, dentry, data, size)) | ||
160 | goto fail_write; | ||
161 | 173 | ||
162 | inode->i_private = private; | 174 | inode->i_private = private; |
163 | 175 | ||
164 | if (time.tv_sec) | 176 | if (time.tv_sec) |
165 | inode->i_mtime = inode->i_ctime = time; | 177 | inode->i_mtime = inode->i_ctime = time; |
166 | 178 | ||
167 | return 0; | 179 | d_add(dentry, inode); |
168 | 180 | ||
169 | fail_write: | ||
170 | kfree(private); | ||
171 | inode->i_nlink--; | ||
172 | mutex_lock(&root->d_inode->i_mutex); | ||
173 | d_delete(dentry); | ||
174 | dput(dentry); | ||
175 | mutex_unlock(&root->d_inode->i_mutex); | 181 | mutex_unlock(&root->d_inode->i_mutex); |
176 | goto fail; | 182 | |
183 | return 0; | ||
177 | 184 | ||
178 | fail_lockedalloc: | 185 | fail_lockedalloc: |
179 | mutex_unlock(&root->d_inode->i_mutex); | 186 | mutex_unlock(&root->d_inode->i_mutex); |
@@ -225,32 +232,21 @@ fail: | |||
225 | return err; | 232 | return err; |
226 | } | 233 | } |
227 | 234 | ||
228 | static int pstore_get_sb(struct file_system_type *fs_type, | 235 | static struct dentry *pstore_mount(struct file_system_type *fs_type, |
229 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 236 | int flags, const char *dev_name, void *data) |
230 | { | 237 | { |
231 | struct dentry *root; | 238 | return mount_single(fs_type, flags, data, pstore_fill_super); |
232 | |||
233 | root = mount_nodev(fs_type, flags, data, pstore_fill_super); | ||
234 | if (IS_ERR(root)) | ||
235 | return -ENOMEM; | ||
236 | |||
237 | mnt->mnt_root = root; | ||
238 | mnt->mnt_sb = root->d_sb; | ||
239 | pstore_mnt = mnt; | ||
240 | |||
241 | return 0; | ||
242 | } | 239 | } |
243 | 240 | ||
244 | static void pstore_kill_sb(struct super_block *sb) | 241 | static void pstore_kill_sb(struct super_block *sb) |
245 | { | 242 | { |
246 | kill_litter_super(sb); | 243 | kill_litter_super(sb); |
247 | pstore_sb = NULL; | 244 | pstore_sb = NULL; |
248 | pstore_mnt = NULL; | ||
249 | } | 245 | } |
250 | 246 | ||
251 | static struct file_system_type pstore_fs_type = { | 247 | static struct file_system_type pstore_fs_type = { |
252 | .name = "pstore", | 248 | .name = "pstore", |
253 | .get_sb = pstore_get_sb, | 249 | .mount = pstore_mount, |
254 | .kill_sb = pstore_kill_sb, | 250 | .kill_sb = pstore_kill_sb, |
255 | }; | 251 | }; |
256 | 252 | ||