On Tue, Nov 06, 2007 at 02:33:53AM -0800, akpm@linux-foundation.org wrote:
[mmotm.git] / fs / reiser4 / plugin / object.c
blob722f0a261fc513cee991b364482ff7ed6ece4521
1 /* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by
2 * reiser4/README */
4 /*
5 * Examples of object plugins: file, directory, symlink, special file.
7 * Plugins associated with inode:
9 * Plugin of inode is plugin referenced by plugin-id field of on-disk
10 * stat-data. How we store this plugin in in-core inode is not
11 * important. Currently pointers are used, another variant is to store offsets
12 * and do array lookup on each access.
14 * Now, each inode has one selected plugin: object plugin that
15 * determines what type of file this object is: directory, regular etc.
17 * This main plugin can use other plugins that are thus subordinated to
18 * it. Directory instance of object plugin uses hash; regular file
19 * instance uses tail policy plugin.
21 * Object plugin is either taken from id in stat-data or guessed from
22 * i_mode bits. Once it is established we ask it to install its
23 * subordinate plugins, by looking again in stat-data or inheriting them
24 * from parent.
26 * How new inode is initialized during ->read_inode():
27 * 1 read stat-data and initialize inode fields: i_size, i_mode,
28 * i_generation, capabilities etc.
29 * 2 read plugin id from stat data or try to guess plugin id
30 * from inode->i_mode bits if plugin id is missing.
31 * 3 Call ->init_inode() method of stat-data plugin to initialise inode fields.
33 * NIKITA-FIXME-HANS: can you say a little about 1 being done before 3? What
34 * if stat data does contain i_size, etc., due to it being an unusual plugin?
36 * 4 Call ->activate() method of object's plugin. Plugin is either read from
37 * from stat-data or guessed from mode bits
38 * 5 Call ->inherit() method of object plugin to inherit as yet un initialized
39 * plugins from parent.
41 * Easy induction proves that on last step all plugins of inode would be
42 * initialized.
44 * When creating new object:
45 * 1 obtain object plugin id (see next period)
46 * NIKITA-FIXME-HANS: period?
47 * 2 ->install() this plugin
48 * 3 ->inherit() the rest from the parent
50 * We need some examples of creating an object with default and non-default
51 * plugin ids. Nikita, please create them.
54 #include "../inode.h"
56 static int _bugop(void)
58 BUG_ON(1);
59 return 0;
62 #define bugop ((void *)_bugop)
64 static int _dummyop(void)
66 return 0;
69 #define dummyop ((void *)_dummyop)
71 static int change_file(struct inode *inode,
72 reiser4_plugin * plugin,
73 pset_member memb)
75 /* cannot change object plugin of already existing object */
76 if (memb == PSET_FILE)
77 return RETERR(-EINVAL);
79 /* Change PSET_CREATE */
80 return aset_set_unsafe(&reiser4_inode_data(inode)->pset, memb, plugin);
83 static reiser4_plugin_ops file_plugin_ops = {
84 .change = change_file
87 static struct inode_operations null_i_ops = {.create = NULL};
88 static struct file_operations null_f_ops = {.owner = NULL};
89 static struct address_space_operations null_a_ops = {.writepage = NULL};
91 /* VFS methods for regular files */
92 static struct inode_operations regular_file_i_ops = {
93 .permission = reiser4_permission_common,
94 .setattr = reiser4_setattr,
95 .getattr = reiser4_getattr_common
97 static struct file_operations regular_file_f_ops = {
98 .llseek = generic_file_llseek,
99 .read = reiser4_read_careful,
100 .write = reiser4_write_careful,
101 .aio_read = generic_file_aio_read,
102 .ioctl = reiser4_ioctl_careful,
103 .mmap = reiser4_mmap_careful,
104 .open = reiser4_open_careful,
105 .release = reiser4_release_careful,
106 .fsync = reiser4_sync_file_common,
107 .splice_read = generic_file_splice_read,
108 .splice_write = generic_file_splice_write
110 static struct address_space_operations regular_file_a_ops = {
111 .writepage = reiser4_writepage,
112 .readpage = reiser4_readpage,
113 .sync_page = block_sync_page,
114 .writepages = reiser4_writepages,
115 .set_page_dirty = reiser4_set_page_dirty,
116 .readpages = reiser4_readpages,
117 .write_begin = reiser4_write_begin_careful,
118 .write_end = reiser4_write_end_careful,
119 .bmap = reiser4_bmap_careful,
120 .invalidatepage = reiser4_invalidatepage,
121 .releasepage = reiser4_releasepage
124 /* VFS methods for symlink files */
125 static struct inode_operations symlink_file_i_ops = {
126 .readlink = generic_readlink,
127 .follow_link = reiser4_follow_link_common,
128 .permission = reiser4_permission_common,
129 .setattr = reiser4_setattr_common,
130 .getattr = reiser4_getattr_common
133 /* VFS methods for special files */
134 static struct inode_operations special_file_i_ops = {
135 .permission = reiser4_permission_common,
136 .setattr = reiser4_setattr_common,
137 .getattr = reiser4_getattr_common
140 /* VFS methods for directories */
141 static struct inode_operations directory_i_ops = {
142 .create = reiser4_create_common,
143 .lookup = reiser4_lookup_common,
144 .link = reiser4_link_common,
145 .unlink = reiser4_unlink_common,
146 .symlink = reiser4_symlink_common,
147 .mkdir = reiser4_mkdir_common,
148 .rmdir = reiser4_unlink_common,
149 .mknod = reiser4_mknod_common,
150 .rename = reiser4_rename_common,
151 .permission = reiser4_permission_common,
152 .setattr = reiser4_setattr_common,
153 .getattr = reiser4_getattr_common
155 static struct file_operations directory_f_ops = {
156 .llseek = reiser4_llseek_dir_common,
157 .read = generic_read_dir,
158 .readdir = reiser4_readdir_common,
159 .release = reiser4_release_dir_common,
160 .fsync = reiser4_sync_common
162 static struct address_space_operations directory_a_ops = {
163 .writepage = bugop,
164 .sync_page = bugop,
165 .writepages = dummyop,
166 .set_page_dirty = bugop,
167 .readpages = bugop,
168 .write_begin = bugop,
169 .write_end = bugop,
170 .bmap = bugop,
171 .invalidatepage = bugop,
172 .releasepage = bugop
176 * Definitions of object plugins.
179 file_plugin file_plugins[LAST_FILE_PLUGIN_ID] = {
180 [UNIX_FILE_PLUGIN_ID] = {
181 .h = {
182 .type_id = REISER4_FILE_PLUGIN_TYPE,
183 .id = UNIX_FILE_PLUGIN_ID,
184 .groups = (1 << REISER4_REGULAR_FILE),
185 .pops = &file_plugin_ops,
186 .label = "reg",
187 .desc = "regular file",
188 .linkage = {NULL, NULL},
191 * invariant vfs ops
193 .inode_ops = &regular_file_i_ops,
194 .file_ops = &regular_file_f_ops,
195 .as_ops = &regular_file_a_ops,
197 * private i_ops
199 .setattr = setattr_unix_file,
200 .open = open_unix_file,
201 .read = read_unix_file,
202 .write = write_unix_file,
203 .ioctl = ioctl_unix_file,
204 .mmap = mmap_unix_file,
205 .release = release_unix_file,
207 * private f_ops
209 .readpage = readpage_unix_file,
210 .readpages = readpages_unix_file,
211 .writepages = writepages_unix_file,
212 .write_begin = write_begin_unix_file,
213 .write_end = write_end_unix_file,
215 * private a_ops
217 .bmap = bmap_unix_file,
219 * other private methods
221 .write_sd_by_inode = write_sd_by_inode_common,
222 .flow_by_inode = flow_by_inode_unix_file,
223 .key_by_inode = key_by_inode_and_offset_common,
224 .set_plug_in_inode = set_plug_in_inode_common,
225 .adjust_to_parent = adjust_to_parent_common,
226 .create_object = reiser4_create_object_common,
227 .delete_object = delete_object_unix_file,
228 .add_link = reiser4_add_link_common,
229 .rem_link = reiser4_rem_link_common,
230 .owns_item = owns_item_unix_file,
231 .can_add_link = can_add_link_common,
232 .detach = dummyop,
233 .bind = dummyop,
234 .safelink = safelink_common,
235 .estimate = {
236 .create = estimate_create_common,
237 .update = estimate_update_common,
238 .unlink = estimate_unlink_common
240 .init_inode_data = init_inode_data_unix_file,
241 .cut_tree_worker = cut_tree_worker_common,
242 .wire = {
243 .write = wire_write_common,
244 .read = wire_read_common,
245 .get = wire_get_common,
246 .size = wire_size_common,
247 .done = wire_done_common
250 [DIRECTORY_FILE_PLUGIN_ID] = {
251 .h = {
252 .type_id = REISER4_FILE_PLUGIN_TYPE,
253 .id = DIRECTORY_FILE_PLUGIN_ID,
254 .groups = (1 << REISER4_DIRECTORY_FILE),
255 .pops = &file_plugin_ops,
256 .label = "dir",
257 .desc = "directory",
258 .linkage = {NULL, NULL}
260 .inode_ops = &null_i_ops,
261 .file_ops = &null_f_ops,
262 .as_ops = &null_a_ops,
264 .write_sd_by_inode = write_sd_by_inode_common,
265 .flow_by_inode = bugop,
266 .key_by_inode = bugop,
267 .set_plug_in_inode = set_plug_in_inode_common,
268 .adjust_to_parent = adjust_to_parent_common_dir,
269 .create_object = reiser4_create_object_common,
270 .delete_object = reiser4_delete_dir_common,
271 .add_link = reiser4_add_link_common,
272 .rem_link = rem_link_common_dir,
273 .owns_item = owns_item_common_dir,
274 .can_add_link = can_add_link_common,
275 .can_rem_link = can_rem_link_common_dir,
276 .detach = reiser4_detach_common_dir,
277 .bind = reiser4_bind_common_dir,
278 .safelink = safelink_common,
279 .estimate = {
280 .create = estimate_create_common_dir,
281 .update = estimate_update_common,
282 .unlink = estimate_unlink_common_dir
284 .wire = {
285 .write = wire_write_common,
286 .read = wire_read_common,
287 .get = wire_get_common,
288 .size = wire_size_common,
289 .done = wire_done_common
291 .init_inode_data = init_inode_ordering,
292 .cut_tree_worker = cut_tree_worker_common,
294 [SYMLINK_FILE_PLUGIN_ID] = {
295 .h = {
296 .type_id = REISER4_FILE_PLUGIN_TYPE,
297 .id = SYMLINK_FILE_PLUGIN_ID,
298 .groups = (1 << REISER4_SYMLINK_FILE),
299 .pops = &file_plugin_ops,
300 .label = "symlink",
301 .desc = "symbolic link",
302 .linkage = {NULL, NULL}
304 .inode_ops = &symlink_file_i_ops,
305 /* inode->i_fop of symlink is initialized by NULL in
306 * setup_inode_ops */
307 .file_ops = &null_f_ops,
308 .as_ops = &null_a_ops,
310 .write_sd_by_inode = write_sd_by_inode_common,
311 .set_plug_in_inode = set_plug_in_inode_common,
312 .adjust_to_parent = adjust_to_parent_common,
313 .create_object = reiser4_create_symlink,
314 .delete_object = reiser4_delete_object_common,
315 .add_link = reiser4_add_link_common,
316 .rem_link = reiser4_rem_link_common,
317 .can_add_link = can_add_link_common,
318 .detach = dummyop,
319 .bind = dummyop,
320 .safelink = safelink_common,
321 .estimate = {
322 .create = estimate_create_common,
323 .update = estimate_update_common,
324 .unlink = estimate_unlink_common
326 .init_inode_data = init_inode_ordering,
327 .cut_tree_worker = cut_tree_worker_common,
328 .destroy_inode = destroy_inode_symlink,
329 .wire = {
330 .write = wire_write_common,
331 .read = wire_read_common,
332 .get = wire_get_common,
333 .size = wire_size_common,
334 .done = wire_done_common
337 [SPECIAL_FILE_PLUGIN_ID] = {
338 .h = {
339 .type_id = REISER4_FILE_PLUGIN_TYPE,
340 .id = SPECIAL_FILE_PLUGIN_ID,
341 .groups = (1 << REISER4_SPECIAL_FILE),
342 .pops = &file_plugin_ops,
343 .label = "special",
344 .desc =
345 "special: fifo, device or socket",
346 .linkage = {NULL, NULL}
348 .inode_ops = &special_file_i_ops,
349 /* file_ops of special files (sockets, block, char, fifo) are
350 initialized by init_special_inode. */
351 .file_ops = &null_f_ops,
352 .as_ops = &null_a_ops,
354 .write_sd_by_inode = write_sd_by_inode_common,
355 .set_plug_in_inode = set_plug_in_inode_common,
356 .adjust_to_parent = adjust_to_parent_common,
357 .create_object = reiser4_create_object_common,
358 .delete_object = reiser4_delete_object_common,
359 .add_link = reiser4_add_link_common,
360 .rem_link = reiser4_rem_link_common,
361 .owns_item = owns_item_common,
362 .can_add_link = can_add_link_common,
363 .detach = dummyop,
364 .bind = dummyop,
365 .safelink = safelink_common,
366 .estimate = {
367 .create = estimate_create_common,
368 .update = estimate_update_common,
369 .unlink = estimate_unlink_common
371 .init_inode_data = init_inode_ordering,
372 .cut_tree_worker = cut_tree_worker_common,
373 .wire = {
374 .write = wire_write_common,
375 .read = wire_read_common,
376 .get = wire_get_common,
377 .size = wire_size_common,
378 .done = wire_done_common
381 [CRYPTCOMPRESS_FILE_PLUGIN_ID] = {
382 .h = {
383 .type_id = REISER4_FILE_PLUGIN_TYPE,
384 .id = CRYPTCOMPRESS_FILE_PLUGIN_ID,
385 .groups = (1 << REISER4_REGULAR_FILE),
386 .pops = &file_plugin_ops,
387 .label = "cryptcompress",
388 .desc = "cryptcompress file",
389 .linkage = {NULL, NULL}
391 .inode_ops = &regular_file_i_ops,
392 .file_ops = &regular_file_f_ops,
393 .as_ops = &regular_file_a_ops,
395 .setattr = setattr_cryptcompress,
396 .open = open_cryptcompress,
397 .read = read_cryptcompress,
398 .write = write_cryptcompress,
399 .ioctl = ioctl_cryptcompress,
400 .mmap = mmap_cryptcompress,
401 .release = release_cryptcompress,
403 .readpage = readpage_cryptcompress,
404 .readpages = readpages_cryptcompress,
405 .writepages = writepages_cryptcompress,
406 .write_begin = write_begin_cryptcompress,
407 .write_end = write_end_cryptcompress,
409 .bmap = bmap_cryptcompress,
411 .write_sd_by_inode = write_sd_by_inode_common,
412 .flow_by_inode = flow_by_inode_cryptcompress,
413 .key_by_inode = key_by_inode_cryptcompress,
414 .set_plug_in_inode = set_plug_in_inode_common,
415 .adjust_to_parent = adjust_to_parent_cryptcompress,
416 .create_object = create_object_cryptcompress,
417 .delete_object = delete_object_cryptcompress,
418 .add_link = reiser4_add_link_common,
419 .rem_link = reiser4_rem_link_common,
420 .owns_item = owns_item_common,
421 .can_add_link = can_add_link_common,
422 .detach = dummyop,
423 .bind = dummyop,
424 .safelink = safelink_common,
425 .estimate = {
426 .create = estimate_create_common,
427 .update = estimate_update_common,
428 .unlink = estimate_unlink_common
430 .init_inode_data = init_inode_data_cryptcompress,
431 .cut_tree_worker = cut_tree_worker_cryptcompress,
432 .destroy_inode = destroy_inode_cryptcompress,
433 .wire = {
434 .write = wire_write_common,
435 .read = wire_read_common,
436 .get = wire_get_common,
437 .size = wire_size_common,
438 .done = wire_done_common
443 static int change_dir(struct inode *inode,
444 reiser4_plugin * plugin,
445 pset_member memb)
447 /* cannot change dir plugin of already existing object */
448 return RETERR(-EINVAL);
451 static reiser4_plugin_ops dir_plugin_ops = {
452 .change = change_dir
456 * definition of directory plugins
459 dir_plugin dir_plugins[LAST_DIR_ID] = {
460 /* standard hashed directory plugin */
461 [HASHED_DIR_PLUGIN_ID] = {
462 .h = {
463 .type_id = REISER4_DIR_PLUGIN_TYPE,
464 .id = HASHED_DIR_PLUGIN_ID,
465 .pops = &dir_plugin_ops,
466 .label = "dir",
467 .desc = "hashed directory",
468 .linkage = {NULL, NULL}
470 .inode_ops = &directory_i_ops,
471 .file_ops = &directory_f_ops,
472 .as_ops = &directory_a_ops,
474 .get_parent = get_parent_common,
475 .is_name_acceptable = is_name_acceptable_common,
476 .build_entry_key = build_entry_key_hashed,
477 .build_readdir_key = build_readdir_key_common,
478 .add_entry = reiser4_add_entry_common,
479 .rem_entry = reiser4_rem_entry_common,
480 .init = reiser4_dir_init_common,
481 .done = reiser4_dir_done_common,
482 .attach = reiser4_attach_common,
483 .detach = reiser4_detach_common,
484 .estimate = {
485 .add_entry = estimate_add_entry_common,
486 .rem_entry = estimate_rem_entry_common,
487 .unlink = dir_estimate_unlink_common
490 /* hashed directory for which seekdir/telldir are guaranteed to
491 * work. Brain-damage. */
492 [SEEKABLE_HASHED_DIR_PLUGIN_ID] = {
493 .h = {
494 .type_id = REISER4_DIR_PLUGIN_TYPE,
495 .id = SEEKABLE_HASHED_DIR_PLUGIN_ID,
496 .pops = &dir_plugin_ops,
497 .label = "dir32",
498 .desc = "directory hashed with 31 bit hash",
499 .linkage = {NULL, NULL}
501 .inode_ops = &directory_i_ops,
502 .file_ops = &directory_f_ops,
503 .as_ops = &directory_a_ops,
505 .get_parent = get_parent_common,
506 .is_name_acceptable = is_name_acceptable_common,
507 .build_entry_key = build_entry_key_seekable,
508 .build_readdir_key = build_readdir_key_common,
509 .add_entry = reiser4_add_entry_common,
510 .rem_entry = reiser4_rem_entry_common,
511 .init = reiser4_dir_init_common,
512 .done = reiser4_dir_done_common,
513 .attach = reiser4_attach_common,
514 .detach = reiser4_detach_common,
515 .estimate = {
516 .add_entry = estimate_add_entry_common,
517 .rem_entry = estimate_rem_entry_common,
518 .unlink = dir_estimate_unlink_common
523 /* Make Linus happy.
524 Local variables:
525 c-indentation-style: "K&R"
526 mode-name: "LC"
527 c-basic-offset: 8
528 tab-width: 8
529 fill-column: 120
530 End: