1 /* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by
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
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
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.
56 static int _bugop(void)
62 #define bugop ((void *)_bugop)
64 static int _dummyop(void)
69 #define dummyop ((void *)_dummyop)
71 static int change_file(struct inode
*inode
,
72 reiser4_plugin
* plugin
,
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
= {
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
= {
165 .writepages
= dummyop
,
166 .set_page_dirty
= bugop
,
168 .write_begin
= bugop
,
171 .invalidatepage
= bugop
,
176 * Definitions of object plugins.
179 file_plugin file_plugins
[LAST_FILE_PLUGIN_ID
] = {
180 [UNIX_FILE_PLUGIN_ID
] = {
182 .type_id
= REISER4_FILE_PLUGIN_TYPE
,
183 .id
= UNIX_FILE_PLUGIN_ID
,
184 .groups
= (1 << REISER4_REGULAR_FILE
),
185 .pops
= &file_plugin_ops
,
187 .desc
= "regular file",
188 .linkage
= {NULL
, NULL
},
193 .inode_ops
= ®ular_file_i_ops
,
194 .file_ops
= ®ular_file_f_ops
,
195 .as_ops
= ®ular_file_a_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
,
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
,
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
,
234 .safelink
= safelink_common
,
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
,
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
] = {
252 .type_id
= REISER4_FILE_PLUGIN_TYPE
,
253 .id
= DIRECTORY_FILE_PLUGIN_ID
,
254 .groups
= (1 << REISER4_DIRECTORY_FILE
),
255 .pops
= &file_plugin_ops
,
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
,
280 .create
= estimate_create_common_dir
,
281 .update
= estimate_update_common
,
282 .unlink
= estimate_unlink_common_dir
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
] = {
296 .type_id
= REISER4_FILE_PLUGIN_TYPE
,
297 .id
= SYMLINK_FILE_PLUGIN_ID
,
298 .groups
= (1 << REISER4_SYMLINK_FILE
),
299 .pops
= &file_plugin_ops
,
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
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
,
320 .safelink
= safelink_common
,
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
,
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
] = {
339 .type_id
= REISER4_FILE_PLUGIN_TYPE
,
340 .id
= SPECIAL_FILE_PLUGIN_ID
,
341 .groups
= (1 << REISER4_SPECIAL_FILE
),
342 .pops
= &file_plugin_ops
,
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
,
365 .safelink
= safelink_common
,
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
,
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
] = {
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
= ®ular_file_i_ops
,
392 .file_ops
= ®ular_file_f_ops
,
393 .as_ops
= ®ular_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
,
424 .safelink
= safelink_common
,
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
,
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
,
447 /* cannot change dir plugin of already existing object */
448 return RETERR(-EINVAL
);
451 static reiser4_plugin_ops dir_plugin_ops
= {
456 * definition of directory plugins
459 dir_plugin dir_plugins
[LAST_DIR_ID
] = {
460 /* standard hashed directory plugin */
461 [HASHED_DIR_PLUGIN_ID
] = {
463 .type_id
= REISER4_DIR_PLUGIN_TYPE
,
464 .id
= HASHED_DIR_PLUGIN_ID
,
465 .pops
= &dir_plugin_ops
,
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
,
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
] = {
494 .type_id
= REISER4_DIR_PLUGIN_TYPE
,
495 .id
= SEEKABLE_HASHED_DIR_PLUGIN_ID
,
496 .pops
= &dir_plugin_ops
,
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
,
516 .add_entry
= estimate_add_entry_common
,
517 .rem_entry
= estimate_rem_entry_common
,
518 .unlink
= dir_estimate_unlink_common
525 c-indentation-style: "K&R"