|
|
| version 1.2, 2007/01/16 14:53:53 | version 1.3, 2007/01/16 14:56:58 |
|---|---|
| Line 0 | Line 1 |
| Definition of vfs_get_inode for ioops module. | |
| Add behaviour module support. | |
| --- /tmp/diff_prompt.12865.update_only 2006-12-15 22:49:16.949849328 +1100 | |
| +++ linux-2.6/xfs_vfs.c 2006-12-15 17:48:29.000000000 +1100 | |
| @@ -183,6 +183,19 @@ | |
| return ((*bhvtovfsops(next)->vfs_quotactl)(next, cmd, id, addr)); | |
| } | |
| +struct inode * | |
| +vfs_get_inode( | |
| + struct bhv_desc *bdp, | |
| + xfs_ino_t ino, | |
| + int fl) | |
| +{ | |
| + struct bhv_desc *next = bdp; | |
| + | |
| + while (! (bhvtovfsops(next))->vfs_get_inode) | |
| + next = BHV_NEXTNULL(next); | |
| + return ((*bhvtovfsops(next)->vfs_get_inode)(next, ino, fl)); | |
| +} | |
| + | |
| void | |
| vfs_init_vnode( | |
| struct bhv_desc *bdp, | |
| @@ -262,18 +275,6 @@ | |
| } | |
| void | |
| -vfs_insertops( | |
| - struct bhv_vfs *vfsp, | |
| - struct bhv_module_vfsops *vfsops) | |
| -{ | |
| - struct bhv_desc *bdp; | |
| - | |
| - bdp = kmem_alloc(sizeof(struct bhv_desc), KM_SLEEP); | |
| - bhv_desc_init(bdp, NULL, vfsp, vfsops); | |
| - bhv_insert(&vfsp->vfs_bh, bdp); | |
| -} | |
| - | |
| -void | |
| vfs_insertbhv( | |
| struct bhv_vfs *vfsp, | |
| struct bhv_desc *bdp, | |
| @@ -284,6 +285,99 @@ | |
| bhv_insert_initial(&vfsp->vfs_bh, bdp); | |
| } | |
| +/* | |
| + * Implementation for behaviours-as-modules | |
| + */ | |
| + | |
| +typedef struct bhv_module_list { | |
| + struct list_head bm_list; | |
| + struct module * bm_module; | |
| + const char * bm_name; | |
| + void * bm_ops; | |
| +} bhv_module_list_t; | |
| + | |
| +static DEFINE_SPINLOCK(bhv_lock); | |
| +static struct list_head bhv_list = LIST_HEAD_INIT(bhv_list); | |
| + | |
| +void | |
| +bhv_module_init( | |
| + const char *name, | |
| + struct module *module, | |
| + const void *ops) | |
| +{ | |
| + bhv_module_list_t *bm, *entry, *n; | |
| + | |
| + bm = kmem_alloc(sizeof(struct bhv_module_list), KM_SLEEP); | |
| + INIT_LIST_HEAD(&bm->bm_list); | |
| + bm->bm_module = module; | |
| + bm->bm_name = name; | |
| + bm->bm_ops = (void *)ops; | |
| + | |
| + spin_lock(&bhv_lock); | |
| + list_for_each_entry_safe(entry, n, &bhv_list, bm_list) | |
| + BUG_ON(strcmp(entry->bm_name, name) == 0); | |
| + list_add(&bm->bm_list, &bhv_list); | |
| + spin_unlock(&bhv_lock); | |
| +} | |
| + | |
| +void | |
| +bhv_module_exit( | |
| + const char *name) | |
| +{ | |
| + bhv_module_list_t *entry, *n; | |
| + | |
| + spin_lock(&bhv_lock); | |
| + list_for_each_entry_safe(entry, n, &bhv_list, bm_list) | |
| + if (strcmp(entry->bm_name, name) == 0) | |
| + list_del(&entry->bm_list); | |
| + spin_unlock(&bhv_lock); | |
| +} | |
| + | |
| +STATIC void * | |
| +bhv_insert_module( | |
| + const char *name, | |
| + const char *modname) | |
| +{ | |
| + bhv_module_list_t *entry, *n; | |
| + void *ops = NULL; | |
| + | |
| + spin_lock(&bhv_lock); | |
| + list_for_each_entry_safe(entry, n, &bhv_list, bm_list) | |
| + if (strcmp(entry->bm_name, name) == 0 && | |
| + try_module_get(entry->bm_module)) | |
| + ops = entry->bm_ops; | |
| + spin_unlock(&bhv_lock); | |
| + return ops; | |
| +} | |
| + | |
| +STATIC void | |
| +bhv_remove_module( | |
| + const char *name) | |
| +{ | |
| + bhv_module_list_t *entry, *n; | |
| + | |
| + spin_lock(&bhv_lock); | |
| + list_for_each_entry_safe(entry, n, &bhv_list, bm_list) | |
| + if (strcmp(entry->bm_name, name) == 0) | |
| + module_put(entry->bm_module); | |
| + spin_unlock(&bhv_lock); | |
| +} | |
| + | |
| +STATIC void * | |
| +bhv_lookup_module( | |
| + const char *name, | |
| + const char *module) | |
| +{ | |
| + void *ops; | |
| + | |
| + ops = bhv_insert_module(name, module); | |
| + if (!ops && module) { | |
| + request_module("%s", module); | |
| + ops = bhv_insert_module(name, module); | |
| + } | |
| + return ops; | |
| +} | |
| + | |
| void | |
| bhv_remove_vfsops( | |
| struct bhv_vfs *vfsp, | |
| @@ -292,10 +386,14 @@ | |
| struct bhv_desc *bhv; | |
| bhv = bhv_lookup_range(&vfsp->vfs_bh, pos, pos); | |
| - if (!bhv) | |
| - return; | |
| - bhv_remove(&vfsp->vfs_bh, bhv); | |
| - kmem_free(bhv, sizeof(*bhv)); | |
| + if (bhv) { | |
| + struct bhv_module *bm; | |
| + | |
| + bm = (bhv_module_t *) BHV_PDATA(bhv); | |
| + bhv_remove(&vfsp->vfs_bh, bhv); | |
| + bhv_remove_module(bm->bm_name); | |
| + kmem_free(bhv, sizeof(*bhv)); | |
| + } | |
| } | |
| void | |
| @@ -307,6 +405,7 @@ | |
| bhv_remove_vfsops(vfsp, VFS_POSITION_QM); | |
| bhv_remove_vfsops(vfsp, VFS_POSITION_DM); | |
| + bhv_remove_vfsops(vfsp, VFS_POSITION_IO); | |
| if (!freebase) | |
| return; | |
| mp = XFS_VFSTOM(vfsp); | |
| @@ -315,6 +414,25 @@ | |
| } | |
| void | |
| +bhv_get_vfsops( | |
| + struct bhv_vfs *vfsp, | |
| + const char *name, | |
| + const char *module) | |
| +{ | |
| + struct bhv_vfsops *ops; | |
| + | |
| + ops = (struct bhv_vfsops *) bhv_lookup_module(name, module); | |
| + if (ops) { | |
| + struct bhv_module *bm; | |
| + | |
| + bm = kmem_alloc(sizeof(struct bhv_module), KM_SLEEP); | |
| + bm->bm_name = name; | |
| + bhv_desc_init(&bm->bm_desc, bm, vfsp, ops); | |
| + bhv_insert(&vfsp->vfs_bh, &bm->bm_desc); | |
| + } | |
| +} | |
| + | |
| +void | |
| bhv_insert_all_vfsops( | |
| struct bhv_vfs *vfsp) | |
| { | |
| @@ -322,6 +440,10 @@ | |
| mp = xfs_mount_init(); | |
| vfs_insertbhv(vfsp, &mp->m_bhv, &xfs_vfsops, mp); | |
| - vfs_insertdmapi(vfsp); | |
| - vfs_insertquota(vfsp); | |
| + bhv_get_vfsops(vfsp, XFS_DMOPS, | |
| + xfs_probe_dmapi ? XFS_DM_MODULE : NULL); | |
| + bhv_get_vfsops(vfsp, XFS_QMOPS, | |
| + xfs_probe_quota ? XFS_QM_MODULE : NULL); | |
| + bhv_get_vfsops(vfsp, XFS_IOOPS, | |
| + xfs_probe_ioops ? XFS_IO_MODULE : NULL); | |
| } |