From: Christoph Hellwig Date: Thu, 30 Aug 2007 07:20:39 +0000 (+1000) Subject: [XFS] call common xfs vfs-level helpers directly and remove vfs operations X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=745f691912b700ac98607b525f3c892204c7f12f;p=GitHub%2FLineageOS%2FG12%2Fandroid_kernel_amlogic_linux-4.9.git [XFS] call common xfs vfs-level helpers directly and remove vfs operations Also remove the now dead behavior code. SGI-PV: 969608 SGI-Modid: xfs-linux-melb:xfs-kern:29505a Signed-off-by: Christoph Hellwig Signed-off-by: David Chinner Signed-off-by: Tim Shimmin --- diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6 index 0e474785ebae..85b0de65bd9b 100644 --- a/fs/xfs/Makefile-linux-2.6 +++ b/fs/xfs/Makefile-linux-2.6 @@ -49,7 +49,6 @@ xfs-y += xfs_alloc.o \ xfs_alloc_btree.o \ xfs_attr.o \ xfs_attr_leaf.o \ - xfs_behavior.o \ xfs_bit.o \ xfs_bmap.o \ xfs_bmap_btree.o \ @@ -88,7 +87,6 @@ xfs-y += xfs_alloc.o \ xfs_trans_item.o \ xfs_utils.o \ xfs_vfsops.o \ - xfs_vfsops_bhv.o \ xfs_vnodeops.o \ xfs_rw.o \ xfs_dmops.o \ diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index 0919021d56c4..4ed28a6767bb 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c @@ -28,6 +28,7 @@ #include "xfs_vnodeops.h" #include "xfs_bmap_btree.h" #include "xfs_inode.h" +#include "xfs_vfsops.h" static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, }; @@ -143,10 +144,9 @@ xfs_fs_get_dentry( bhv_vnode_t *vp; struct inode *inode; struct dentry *result; - bhv_vfs_t *vfsp = vfs_from_sb(sb); int error; - error = bhv_vfs_vget(vfsp, &vp, (fid_t *)data); + error = xfs_vget(XFS_M(sb), &vp, (fid_t *)data); if (error || vp == NULL) return ERR_PTR(-ESTALE) ; diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index ab634a775d23..dc3752de22da 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -83,7 +83,6 @@ #include #include -#include #include #include #include diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h index 4cd85c3360f5..4b7747a828d9 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.h +++ b/fs/xfs/linux-2.6/xfs_lrw.h @@ -18,7 +18,6 @@ #ifndef __XFS_LRW_H__ #define __XFS_LRW_H__ -struct bhv_desc; struct xfs_mount; struct xfs_iocore; struct xfs_inode; diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 0cb149ad65cc..24bc0afb003c 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -47,6 +47,7 @@ #include "xfs_buf_item.h" #include "xfs_utils.h" #include "xfs_vnodeops.h" +#include "xfs_vfsops.h" #include "xfs_version.h" #include @@ -204,8 +205,7 @@ void xfs_initialize_vnode( struct xfs_mount *mp, bhv_vnode_t *vp, - struct xfs_inode *ip, - int unlock) + struct xfs_inode *ip) { struct inode *inode = vn_to_inode(vp); @@ -221,7 +221,7 @@ xfs_initialize_vnode( * second time once the inode is properly set up, and then we can * finish our work. */ - if (ip->i_d.di_mode != 0 && unlock && (inode->i_state & I_NEW)) { + if (ip->i_d.di_mode != 0 && (inode->i_state & I_NEW)) { xfs_revalidate_inode(mp, vp, ip); xfs_set_inodeops(inode); @@ -535,9 +535,8 @@ vfs_sync_worker( int error; if (!(vfsp->vfs_flag & VFS_RDONLY)) - error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \ - SYNC_ATTR | SYNC_REFCACHE | SYNC_SUPER, - NULL); + error = xfs_sync(XFS_VFSTOM(vfsp), SYNC_FSDATA | SYNC_BDFLUSH | \ + SYNC_ATTR | SYNC_REFCACHE | SYNC_SUPER); vfsp->vfs_sync_seq++; wake_up(&vfsp->vfs_wait_single_sync_task); } @@ -614,11 +613,12 @@ xfs_fs_put_super( struct super_block *sb) { bhv_vfs_t *vfsp = vfs_from_sb(sb); + struct xfs_mount *mp = XFS_M(sb); int error; xfs_fs_stop_syncd(vfsp); - bhv_vfs_sync(vfsp, SYNC_ATTR | SYNC_DELWRI, NULL); - error = bhv_vfs_unmount(vfsp, 0, NULL); + xfs_sync(mp, SYNC_ATTR | SYNC_DELWRI); + error = xfs_unmount(mp, 0, NULL); if (error) { printk("XFS: unmount got error=%d\n", error); printk("%s: vfs=0x%p left dangling!\n", __FUNCTION__, vfsp); @@ -632,7 +632,7 @@ xfs_fs_write_super( struct super_block *sb) { if (!(sb->s_flags & MS_RDONLY)) - bhv_vfs_sync(vfs_from_sb(sb), SYNC_FSDATA, NULL); + xfs_sync(XFS_M(sb), SYNC_FSDATA); sb->s_dirt = 0; } @@ -642,6 +642,7 @@ xfs_fs_sync_super( int wait) { bhv_vfs_t *vfsp = vfs_from_sb(sb); + struct xfs_mount *mp = XFS_M(sb); int error; int flags; @@ -658,7 +659,7 @@ xfs_fs_sync_super( } else flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0); - error = bhv_vfs_sync(vfsp, flags, NULL); + error = xfs_sync(mp, flags); sb->s_dirt = 0; if (unlikely(laptop_mode)) { @@ -688,7 +689,7 @@ xfs_fs_statfs( struct dentry *dentry, struct kstatfs *statp) { - return -bhv_vfs_statvfs(vfs_from_sb(dentry->d_sb), statp, + return -xfs_statvfs(XFS_M(dentry->d_sb), statp, vn_from_inode(dentry->d_inode)); } @@ -698,13 +699,13 @@ xfs_fs_remount( int *flags, char *options) { - bhv_vfs_t *vfsp = vfs_from_sb(sb); + struct xfs_mount *mp = XFS_M(sb); struct xfs_mount_args *args = xfs_args_allocate(sb, 0); int error; - error = bhv_vfs_parseargs(vfsp, options, args, 1); + error = xfs_parseargs(mp, options, args, 1); if (!error) - error = bhv_vfs_mntupdate(vfsp, flags, args); + error = xfs_mntupdate(mp, flags, args); kmem_free(args, sizeof(*args)); return -error; } @@ -713,7 +714,7 @@ STATIC void xfs_fs_lockfs( struct super_block *sb) { - bhv_vfs_freeze(vfs_from_sb(sb)); + xfs_freeze(XFS_M(sb)); } STATIC int @@ -721,7 +722,7 @@ xfs_fs_show_options( struct seq_file *m, struct vfsmount *mnt) { - return -bhv_vfs_showargs(vfs_from_sb(mnt->mnt_sb), m); + return -xfs_showargs(XFS_M(mnt->mnt_sb), m); } STATIC int @@ -783,30 +784,29 @@ xfs_fs_fill_super( { struct inode *rootvp; struct bhv_vfs *vfsp = vfs_allocate(sb); + struct xfs_mount *mp = NULL; struct xfs_mount_args *args = xfs_args_allocate(sb, silent); struct kstatfs statvfs; int error; - bhv_insert_all_vfsops(vfsp); + mp = xfs_mount_init(); + mp->m_vfsp = vfsp; + vfsp->vfs_mount = mp; - error = bhv_vfs_parseargs(vfsp, (char *)data, args, 0); - if (error) { - bhv_remove_all_vfsops(vfsp, 1); + error = xfs_parseargs(mp, (char *)data, args, 0); + if (error) goto fail_vfsop; - } sb_min_blocksize(sb, BBSIZE); sb->s_export_op = &xfs_export_operations; sb->s_qcop = &xfs_quotactl_operations; sb->s_op = &xfs_super_operations; - error = bhv_vfs_mount(vfsp, args, NULL); - if (error) { - bhv_remove_all_vfsops(vfsp, 1); + error = xfs_mount(mp, args, NULL); + if (error) goto fail_vfsop; - } - error = bhv_vfs_statvfs(vfsp, &statvfs, NULL); + error = xfs_statvfs(mp, &statvfs, NULL); if (error) goto fail_unmount; @@ -818,7 +818,7 @@ xfs_fs_fill_super( sb->s_time_gran = 1; set_posix_acl_flag(sb); - error = bhv_vfs_root(vfsp, &rootvp); + error = xfs_root(mp, &rootvp); if (error) goto fail_unmount; @@ -848,7 +848,7 @@ fail_vnrele: } fail_unmount: - bhv_vfs_unmount(vfsp, 0, NULL); + xfs_unmount(mp, 0, NULL); fail_vfsop: vfs_deallocate(vfsp); diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h index dba6f1cc348a..529ada86f2c9 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/linux-2.6/xfs_super.h @@ -107,6 +107,9 @@ struct block_device; extern __uint64_t xfs_max_file_offset(unsigned int); +extern void xfs_initialize_vnode(struct xfs_mount *mp, bhv_vnode_t *vp, + struct xfs_inode *ip); + extern void xfs_flush_inode(struct xfs_inode *); extern void xfs_flush_device(struct xfs_inode *); diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c index 5f616ccaea8d..573e52a24072 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.c +++ b/fs/xfs/linux-2.6/xfs_vfs.c @@ -204,7 +204,6 @@ vfs_allocate( struct bhv_vfs *vfsp; vfsp = kmem_zalloc(sizeof(bhv_vfs_t), KM_SLEEP); - bhv_head_init(VFS_BHVHEAD(vfsp), "vfs"); INIT_LIST_HEAD(&vfsp->vfs_sync_list); spin_lock_init(&vfsp->vfs_sync_lock); init_waitqueue_head(&vfsp->vfs_wait_single_sync_task); @@ -229,71 +228,5 @@ void vfs_deallocate( struct bhv_vfs *vfsp) { - bhv_head_destroy(VFS_BHVHEAD(vfsp)); kmem_free(vfsp, sizeof(bhv_vfs_t)); } - -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, - struct bhv_vfsops *vfsops, - void *mount) -{ - bhv_desc_init(bdp, mount, vfsp, vfsops); - bhv_insert_initial(&vfsp->vfs_bh, bdp); -} - -void -bhv_remove_vfsops( - struct bhv_vfs *vfsp, - int pos) -{ - 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)); -} - -void -bhv_remove_all_vfsops( - struct bhv_vfs *vfsp, - int freebase) -{ - struct xfs_mount *mp; - - bhv_remove_vfsops(vfsp, VFS_POSITION_QM); - if (!freebase) - return; - mp = XFS_VFSTOM(vfsp); - VFS_REMOVEBHV(vfsp, &mp->m_bhv); - xfs_mount_free(mp, 0); - kmem_free(mp, sizeof(xfs_mount_t)); -} - -void -bhv_insert_all_vfsops( - struct bhv_vfs *vfsp) -{ - struct xfs_mount *mp; - - mp = xfs_mount_init(); - vfs_insertbhv(vfsp, &mp->m_bhv, &xfs_vfsops, mp); - vfs_insertdmapi(vfsp); - vfs_insertquota(vfsp); -} diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h index e63b2d012f0c..04303cb911c7 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.h +++ b/fs/xfs/linux-2.6/xfs_vfs.h @@ -29,6 +29,7 @@ struct cred; struct seq_file; struct super_block; struct xfs_inode; +struct xfs_mount; struct xfs_mount_args; typedef struct kstatfs bhv_statvfs_t; @@ -41,10 +42,10 @@ typedef struct bhv_vfs_sync_work { } bhv_vfs_sync_work_t; typedef struct bhv_vfs { + struct xfs_mount *vfs_mount; u_int vfs_flag; /* flags */ xfs_fsid_t vfs_fsid; /* file system ID */ xfs_fsid_t *vfs_altfsid; /* An ID fixed for life of FS */ - bhv_head_t vfs_bh; /* head of vfs behavior chain */ struct super_block *vfs_super; /* generic superblock pointer */ struct task_struct *vfs_sync_task; /* generalised sync thread */ bhv_vfs_sync_work_t vfs_sync_work; /* work item for VFS_SYNC */ @@ -54,27 +55,6 @@ typedef struct bhv_vfs { wait_queue_head_t vfs_wait_single_sync_task; } bhv_vfs_t; -#define bhvtovfs(bdp) ( (struct bhv_vfs *)BHV_VOBJ(bdp) ) -#define bhvtovfsops(bdp) ( (struct bhv_vfsops *)BHV_OPS(bdp) ) -#define VFS_BHVHEAD(vfs) ( &(vfs)->vfs_bh ) -#define VFS_REMOVEBHV(vfs, bdp) ( bhv_remove(VFS_BHVHEAD(vfs), bdp) ) - -#define VFS_POSITION_BASE BHV_POSITION_BASE /* chain bottom */ -#define VFS_POSITION_TOP BHV_POSITION_TOP /* chain top */ -#define VFS_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */ - -typedef enum { - VFS_BHV_UNKNOWN, /* not specified */ - VFS_BHV_XFS, /* xfs */ - VFS_BHV_QM, /* quota manager */ - VFS_BHV_IO, /* IO path */ - VFS_BHV_END /* housekeeping end-of-range */ -} bhv_vfs_type_t; - -#define VFS_POSITION_XFS (BHV_POSITION_BASE) -#define VFS_POSITION_QM (VFS_POSITION_BASE+20) -#define VFS_POSITION_IO (VFS_POSITION_BASE+30) - #define VFS_RDONLY 0x0001 /* read-only vfs */ #define VFS_GRPID 0x0002 /* group-ID assigned from directory */ #define VFS_DMI 0x0004 /* filesystem has the DMI enabled */ @@ -114,108 +94,11 @@ typedef enum { #define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */ #define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */ -typedef int (*vfs_mount_t)(bhv_desc_t *, - struct xfs_mount_args *, struct cred *); -typedef int (*vfs_parseargs_t)(bhv_desc_t *, char *, - struct xfs_mount_args *, int); -typedef int (*vfs_showargs_t)(bhv_desc_t *, struct seq_file *); -typedef int (*vfs_unmount_t)(bhv_desc_t *, int, struct cred *); -typedef int (*vfs_mntupdate_t)(bhv_desc_t *, int *, - struct xfs_mount_args *); -typedef int (*vfs_root_t)(bhv_desc_t *, struct inode **); -typedef int (*vfs_statvfs_t)(bhv_desc_t *, bhv_statvfs_t *, - struct inode *); -typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *); -typedef int (*vfs_vget_t)(bhv_desc_t *, struct inode **, struct fid *); -typedef void (*vfs_init_vnode_t)(bhv_desc_t *, - struct inode *, struct xfs_inode *, int); -typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int); -typedef void (*vfs_freeze_t)(bhv_desc_t *); - -typedef struct bhv_vfsops { - bhv_position_t vf_position; /* behavior chain position */ - vfs_mount_t vfs_mount; /* mount file system */ - vfs_parseargs_t vfs_parseargs; /* parse mount options */ - vfs_showargs_t vfs_showargs; /* unparse mount options */ - vfs_unmount_t vfs_unmount; /* unmount file system */ - vfs_mntupdate_t vfs_mntupdate; /* update file system options */ - vfs_root_t vfs_root; /* get root vnode */ - vfs_statvfs_t vfs_statvfs; /* file system statistics */ - vfs_sync_t vfs_sync; /* flush files */ - vfs_vget_t vfs_vget; /* get vnode from fid */ - vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */ - vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */ - vfs_freeze_t vfs_freeze; /* freeze fs for snapshot */ -} bhv_vfsops_t; - -/* - * Virtual filesystem operations, operating from head bhv. - */ -#define VFSHEAD(v) ((v)->vfs_bh.bh_first) -#define bhv_vfs_mount(v, ma,cr) vfs_mount(VFSHEAD(v), ma,cr) -#define bhv_vfs_parseargs(v, o,ma,f) vfs_parseargs(VFSHEAD(v), o,ma,f) -#define bhv_vfs_showargs(v, m) vfs_showargs(VFSHEAD(v), m) -#define bhv_vfs_unmount(v, f,cr) vfs_unmount(VFSHEAD(v), f,cr) -#define bhv_vfs_mntupdate(v, fl,args) vfs_mntupdate(VFSHEAD(v), fl,args) -#define bhv_vfs_root(v, vpp) vfs_root(VFSHEAD(v), vpp) -#define bhv_vfs_statvfs(v, sp,vp) vfs_statvfs(VFSHEAD(v), sp,vp) -#define bhv_vfs_sync(v, flag,cr) vfs_sync(VFSHEAD(v), flag,cr) -#define bhv_vfs_vget(v, vpp,fidp) vfs_vget(VFSHEAD(v), vpp,fidp) -#define bhv_vfs_init_vnode(v, vp,b,ul) vfs_init_vnode(VFSHEAD(v), vp,b,ul) -#define bhv_vfs_force_shutdown(v,u,f,l) vfs_force_shutdown(VFSHEAD(v), u,f,l) -#define bhv_vfs_freeze(v) vfs_freeze(VFSHEAD(v)) - -/* - * Virtual filesystem operations, operating from next bhv. - */ -#define bhv_next_vfs_mount(b, ma,cr) vfs_mount(b, ma,cr) -#define bhv_next_vfs_parseargs(b, o,ma,f) vfs_parseargs(b, o,ma,f) -#define bhv_next_vfs_showargs(b, m) vfs_showargs(b, m) -#define bhv_next_vfs_unmount(b, f,cr) vfs_unmount(b, f,cr) -#define bhv_next_vfs_mntupdate(b, fl,args) vfs_mntupdate(b, fl, args) -#define bhv_next_vfs_root(b, vpp) vfs_root(b, vpp) -#define bhv_next_vfs_statvfs(b, sp,vp) vfs_statvfs(b, sp,vp) -#define bhv_next_vfs_sync(b, flag,cr) vfs_sync(b, flag,cr) -#define bhv_next_vfs_vget(b, vpp,fidp) vfs_vget(b, vpp,fidp) -#define bhv_next_vfs_init_vnode(b, vp,b2,ul) vfs_init_vnode(b, vp,b2,ul) -#define bhv_next_force_shutdown(b, fl,f,l) vfs_force_shutdown(b, fl,f,l) -#define bhv_next_vfs_freeze(b) vfs_freeze(b) - -extern int vfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *); -extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int); -extern int vfs_showargs(bhv_desc_t *, struct seq_file *); -extern int vfs_unmount(bhv_desc_t *, int, struct cred *); -extern int vfs_mntupdate(bhv_desc_t *, int *, struct xfs_mount_args *); -extern int vfs_root(bhv_desc_t *, struct inode **); -extern int vfs_statvfs(bhv_desc_t *, bhv_statvfs_t *, struct inode *); -extern int vfs_sync(bhv_desc_t *, int, struct cred *); -extern int vfs_vget(bhv_desc_t *, struct inode **, struct fid *); -extern void vfs_init_vnode(bhv_desc_t *, struct inode *, struct xfs_inode *, int); -extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int); -extern void vfs_freeze(bhv_desc_t *); - #define vfs_test_for_freeze(vfs) ((vfs)->vfs_super->s_frozen) #define vfs_wait_for_freeze(vfs,l) vfs_check_frozen((vfs)->vfs_super, (l)) -typedef struct bhv_module_vfsops { - struct bhv_vfsops bhv_common; - void * bhv_custom; -} bhv_module_vfsops_t; - -#define vfs_bhv_lookup(v, id) (bhv_lookup_range(&(v)->vfs_bh, (id), (id))) -#define vfs_bhv_custom(b) (((bhv_module_vfsops_t*)BHV_OPS(b))->bhv_custom) -#define vfs_bhv_set_custom(b,o) ((b)->bhv_custom = (void *)(o)) -#define vfs_bhv_clr_custom(b) ((b)->bhv_custom = NULL) - extern bhv_vfs_t *vfs_allocate(struct super_block *); extern bhv_vfs_t *vfs_from_sb(struct super_block *); extern void vfs_deallocate(bhv_vfs_t *); -extern void vfs_insertbhv(bhv_vfs_t *, bhv_desc_t *, bhv_vfsops_t *, void *); - -extern void vfs_insertops(bhv_vfs_t *, bhv_module_vfsops_t *); - -extern void bhv_insert_all_vfsops(struct bhv_vfs *); -extern void bhv_remove_all_vfsops(struct bhv_vfs *, int); -extern void bhv_remove_vfsops(struct bhv_vfs *, int); #endif /* __XFS_VFS_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index b7ff26780a0c..814169fd7e1e 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -78,10 +78,8 @@ vn_ioerror( char *f, int l) { - bhv_vfs_t *vfsp = XFS_MTOVFS(ip->i_mount); - if (unlikely(error == -ENODEV)) - bhv_vfs_force_shutdown(vfsp, SHUTDOWN_DEVICE_REQ, f, l); + xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, f, l); } bhv_vnode_t * diff --git a/fs/xfs/xfs_behavior.c b/fs/xfs/xfs_behavior.c deleted file mode 100644 index 0dc17219d412..000000000000 --- a/fs/xfs/xfs_behavior.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include "xfs.h" - -/* - * Source file used to associate/disassociate behaviors with virtualized - * objects. See xfs_behavior.h for more information about behaviors, etc. - * - * The implementation is split between functions in this file and macros - * in xfs_behavior.h. - */ - -/* - * Insert a new behavior descriptor into a behavior chain. - * - * The behavior chain is ordered based on the 'position' number which - * lives in the first field of the ops vector (higher numbers first). - * - * Attempts to insert duplicate ops result in an EINVAL return code. - * Otherwise, return 0 to indicate success. - */ -int -bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp) -{ - bhv_desc_t *curdesc, *prev; - int position; - - /* - * Validate the position value of the new behavior. - */ - position = BHV_POSITION(bdp); - ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP); - - /* - * Find location to insert behavior. Check for duplicates. - */ - prev = NULL; - for (curdesc = bhp->bh_first; - curdesc != NULL; - curdesc = curdesc->bd_next) { - - /* Check for duplication. */ - if (curdesc->bd_ops == bdp->bd_ops) { - ASSERT(0); - return EINVAL; - } - - /* Find correct position */ - if (position >= BHV_POSITION(curdesc)) { - ASSERT(position != BHV_POSITION(curdesc)); - break; /* found it */ - } - - prev = curdesc; - } - - if (prev == NULL) { - /* insert at front of chain */ - bdp->bd_next = bhp->bh_first; - bhp->bh_first = bdp; - } else { - /* insert after prev */ - bdp->bd_next = prev->bd_next; - prev->bd_next = bdp; - } - - return 0; -} - -/* - * Remove a behavior descriptor from a position in a behavior chain; - * the position is guaranteed not to be the first position. - * Should only be called by the bhv_remove() macro. - */ -void -bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp) -{ - bhv_desc_t *curdesc, *prev; - - ASSERT(bhp->bh_first != NULL); - ASSERT(bhp->bh_first->bd_next != NULL); - - prev = bhp->bh_first; - for (curdesc = bhp->bh_first->bd_next; - curdesc != NULL; - curdesc = curdesc->bd_next) { - - if (curdesc == bdp) - break; /* found it */ - prev = curdesc; - } - - ASSERT(curdesc == bdp); - prev->bd_next = bdp->bd_next; /* remove from after prev */ -} - -/* - * Looks for the first behavior within a specified range of positions. - * Return the associated behavior descriptor. Or NULL, if none found. - */ -bhv_desc_t * -bhv_lookup_range(bhv_head_t *bhp, int low, int high) -{ - bhv_desc_t *curdesc; - - for (curdesc = bhp->bh_first; - curdesc != NULL; - curdesc = curdesc->bd_next) { - - int position = BHV_POSITION(curdesc); - - if (position <= high) { - if (position >= low) - return curdesc; - return NULL; - } - } - - return NULL; -} - -/* - * Return the base behavior in the chain, or NULL if the chain - * is empty. - * - * The caller has not read locked the behavior chain, so acquire the - * lock before traversing the chain. - */ -bhv_desc_t * -bhv_base(bhv_head_t *bhp) -{ - bhv_desc_t *curdesc; - - for (curdesc = bhp->bh_first; - curdesc != NULL; - curdesc = curdesc->bd_next) { - - if (curdesc->bd_next == NULL) { - return curdesc; - } - } - - return NULL; -} - -void -bhv_head_init( - bhv_head_t *bhp, - char *name) -{ - bhp->bh_first = NULL; -} - -void -bhv_insert_initial( - bhv_head_t *bhp, - bhv_desc_t *bdp) -{ - ASSERT(bhp->bh_first == NULL); - (bhp)->bh_first = bdp; -} - -void -bhv_head_destroy( - bhv_head_t *bhp) -{ - ASSERT(bhp->bh_first == NULL); -} diff --git a/fs/xfs/xfs_behavior.h b/fs/xfs/xfs_behavior.h deleted file mode 100644 index e7ca1fed955a..000000000000 --- a/fs/xfs/xfs_behavior.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#ifndef __XFS_BEHAVIOR_H__ -#define __XFS_BEHAVIOR_H__ - -/* - * Header file used to associate behaviors with virtualized objects. - * - * A virtualized object is an internal, virtualized representation of - * OS entities such as persistent files, processes, or sockets. Examples - * of virtualized objects include vnodes, vprocs, and vsockets. Often - * a virtualized object is referred to simply as an "object." - * - * A behavior is essentially an implementation layer associated with - * an object. Multiple behaviors for an object are chained together, - * the order of chaining determining the order of invocation. Each - * behavior of a given object implements the same set of interfaces - * (e.g., the VOP interfaces). - * - * Behaviors may be dynamically inserted into an object's behavior chain, - * such that the addition is transparent to consumers that already have - * references to the object. Typically, a given behavior will be inserted - * at a particular location in the behavior chain. Insertion of new - * behaviors is synchronized with operations-in-progress (oip's) so that - * the oip's always see a consistent view of the chain. - * - * The term "interposition" is used to refer to the act of inserting - * a behavior such that it interposes on (i.e., is inserted in front - * of) a particular other behavior. A key example of this is when a - * system implementing distributed single system image wishes to - * interpose a distribution layer (providing distributed coherency) - * in front of an object that is otherwise only accessed locally. - * - * Note that the traditional vnode/inode combination is simply a virtualized - * object that has exactly one associated behavior. - * - * Behavior synchronization is logic which is necessary under certain - * circumstances that there is no conflict between ongoing operations - * traversing the behavior chain and those dynamically modifying the - * behavior chain. Because behavior synchronization adds extra overhead - * to virtual operation invocation, we want to restrict, as much as - * we can, the requirement for this extra code, to those situations - * in which it is truly necessary. - * - * Behavior synchronization is needed whenever there's at least one class - * of object in the system for which: - * 1) multiple behaviors for a given object are supported, - * -- AND -- - * 2a) insertion of a new behavior can happen dynamically at any time during - * the life of an active object, - * -- AND -- - * 3a) insertion of a new behavior needs to synchronize with existing - * ops-in-progress. - * -- OR -- - * 3b) multiple different behaviors can be dynamically inserted at - * any time during the life of an active object - * -- OR -- - * 3c) removal of a behavior can occur at any time during the life of - * an active object. - * -- OR -- - * 2b) removal of a behavior can occur at any time during the life of an - * active object - * - */ - -/* - * Behavior head. Head of the chain of behaviors. - * Contained within each virtualized object data structure. - */ -typedef struct bhv_head { - struct bhv_desc *bh_first; /* first behavior in chain */ -} bhv_head_t; - -/* - * Behavior descriptor. Descriptor associated with each behavior. - * Contained within the behavior's private data structure. - */ -typedef struct bhv_desc { - void *bd_pdata; /* private data for this behavior */ - void *bd_vobj; /* virtual object associated with */ - void *bd_ops; /* ops for this behavior */ - struct bhv_desc *bd_next; /* next behavior in chain */ -} bhv_desc_t; - -/* - * Behavior identity field. A behavior's identity determines the position - * where it lives within a behavior chain, and it's always the first field - * of the behavior's ops vector. The optional id field further identifies the - * subsystem responsible for the behavior. - */ -typedef struct bhv_identity { - __u16 bi_id; /* owning subsystem id */ - __u16 bi_position; /* position in chain */ -} bhv_identity_t; - -typedef bhv_identity_t bhv_position_t; - -#define BHV_IDENTITY_INIT(id,pos) {id, pos} -#define BHV_IDENTITY_INIT_POSITION(pos) BHV_IDENTITY_INIT(0, pos) - -/* - * Define boundaries of position values. - */ -#define BHV_POSITION_INVALID 0 /* invalid position number */ -#define BHV_POSITION_BASE 1 /* base (last) implementation layer */ -#define BHV_POSITION_TOP 63 /* top (first) implementation layer */ - -/* - * Plumbing macros. - */ -#define BHV_HEAD_FIRST(bhp) (ASSERT((bhp)->bh_first), (bhp)->bh_first) -#define BHV_NEXT(bdp) (ASSERT((bdp)->bd_next), (bdp)->bd_next) -#define BHV_NEXTNULL(bdp) ((bdp)->bd_next) -#define BHV_VOBJ(bdp) (ASSERT((bdp)->bd_vobj), (bdp)->bd_vobj) -#define BHV_VOBJNULL(bdp) ((bdp)->bd_vobj) -#define BHV_PDATA(bdp) (bdp)->bd_pdata -#define BHV_OPS(bdp) (bdp)->bd_ops -#define BHV_IDENTITY(bdp) ((bhv_identity_t *)(bdp)->bd_ops) -#define BHV_POSITION(bdp) (BHV_IDENTITY(bdp)->bi_position) - -extern void bhv_head_init(bhv_head_t *, char *); -extern void bhv_head_destroy(bhv_head_t *); -extern int bhv_insert(bhv_head_t *, bhv_desc_t *); -extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *); - -/* - * Initialize a new behavior descriptor. - * Arguments: - * bdp - pointer to behavior descriptor - * pdata - pointer to behavior's private data - * vobj - pointer to associated virtual object - * ops - pointer to ops for this behavior - */ -#define bhv_desc_init(bdp, pdata, vobj, ops) \ - { \ - (bdp)->bd_pdata = pdata; \ - (bdp)->bd_vobj = vobj; \ - (bdp)->bd_ops = ops; \ - (bdp)->bd_next = NULL; \ - } - -/* - * Remove a behavior descriptor from a behavior chain. - */ -#define bhv_remove(bhp, bdp) \ - { \ - if ((bhp)->bh_first == (bdp)) { \ - /* \ - * Remove from front of chain. \ - * Atomic wrt oip's. \ - */ \ - (bhp)->bh_first = (bdp)->bd_next; \ - } else { \ - /* remove from non-front of chain */ \ - bhv_remove_not_first(bhp, bdp); \ - } \ - (bdp)->bd_vobj = NULL; \ - } - -/* - * Behavior module prototypes. - */ -extern void bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp); -extern bhv_desc_t * bhv_lookup_range(bhv_head_t *bhp, int low, int high); -extern bhv_desc_t * bhv_base(bhv_head_t *bhp); - -/* No bhv locking on Linux */ -#define bhv_base_unlocked bhv_base - -#endif /* __XFS_BEHAVIOR_H__ */ diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 03f32c68731f..772bbc7a8ac9 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -343,8 +343,7 @@ finish_inode: * If we have a real type for an on-disk inode, we can set ops(&unlock) * now. If it's a new inode being created, xfs_ialloc will handle it. */ - bhv_vfs_init_vnode(XFS_MTOVFS(mp), vp, ip, 1); - + xfs_initialize_vnode(mp, vp, ip); return 0; } @@ -370,7 +369,8 @@ xfs_iget( XFS_STATS_INC(xs_ig_attempts); retry: - if ((inode = iget_locked(XFS_MTOVFS(mp)->vfs_super, ino))) { + inode = iget_locked(XFS_MTOVFS(mp)->vfs_super, ino); + if (inode) { xfs_inode_t *ip; vp = vn_from_inode(inode); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index b82f4e43ef3e..0c376bd9e173 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1272,7 +1272,7 @@ xfs_ialloc( xfs_trans_log_inode(tp, ip, flags); /* now that we have an i_mode we can setup inode ops and unlock */ - bhv_vfs_init_vnode(XFS_MTOVFS(tp->t_mountp), vp, ip, 1); + xfs_initialize_vnode(tp->t_mountp, vp, ip); *ipp = ip; return 0; diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 3e948f58ab82..4f3488a7dc06 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -157,8 +157,7 @@ xfs_mount_init(void) */ void xfs_mount_free( - xfs_mount_t *mp, - int remove_bhv) + xfs_mount_t *mp) { if (mp->m_perag) { int agno; @@ -186,13 +185,6 @@ xfs_mount_free( if (mp->m_logname != NULL) kmem_free(mp->m_logname, strlen(mp->m_logname) + 1); - if (remove_bhv) { - struct bhv_vfs *vfsp = XFS_MTOVFS(mp); - - bhv_remove_all_vfsops(vfsp, 0); - VFS_REMOVEBHV(vfsp, &mp->m_bhv); - } - xfs_icsb_destroy_counters(mp); } @@ -1287,7 +1279,7 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) xfs_errortag_clearall_umount(fsid, mp->m_fsname, 0); #endif XFS_IODONE(vfsp); - xfs_mount_free(mp, 1); + xfs_mount_free(mp); return 0; } diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 68d712574b81..8fefad022ae6 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -64,8 +64,6 @@ struct xfs_extdelta; struct xfs_swapext; struct xfs_mru_cache; -extern struct bhv_vfsops xfs_vfsops; - #define AIL_LOCK_T lock_t #define AIL_LOCKINIT(x,y) spinlock_init(x,y) #define AIL_LOCK_DESTROY(x) spinlock_destroy(x) @@ -330,7 +328,7 @@ extern void xfs_icsb_sync_counters_flags(struct xfs_mount *, int); #endif typedef struct xfs_mount { - bhv_desc_t m_bhv; /* vfs xfs behavior */ + struct bhv_vfs *m_vfsp; xfs_tid_t m_tid; /* next unused tid for fs */ AIL_LOCK_T m_ail_lock; /* fs AIL mutex */ xfs_ail_entry_t m_ail; /* fs active log item list */ @@ -527,8 +525,10 @@ xfs_preferred_iosize(xfs_mount_t *mp) #define XFS_LAST_UNMOUNT_WAS_CLEAN(mp) \ ((mp)->m_flags & XFS_MOUNT_WAS_CLEAN) #define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN) +void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname, + int lnnum); #define xfs_force_shutdown(m,f) \ - bhv_vfs_force_shutdown((XFS_MTOVFS(m)), f, __FILE__, __LINE__) + xfs_do_force_shutdown(m, f, __FILE__, __LINE__) /* * Flags for xfs_mountfs @@ -548,20 +548,13 @@ xfs_preferred_iosize(xfs_mount_t *mp) #define XFS_MTOVFS(mp) xfs_mtovfs(mp) static inline struct bhv_vfs *xfs_mtovfs(xfs_mount_t *mp) { - return bhvtovfs(&mp->m_bhv); -} - -#define XFS_BHVTOM(bdp) xfs_bhvtom(bdp) -static inline xfs_mount_t *xfs_bhvtom(bhv_desc_t *bdp) -{ - return (xfs_mount_t *)BHV_PDATA(bdp); + return mp->m_vfsp; } #define XFS_VFSTOM(vfs) xfs_vfstom(vfs) static inline xfs_mount_t *xfs_vfstom(bhv_vfs_t *vfs) { - return XFS_BHVTOM(bhv_lookup_range(VFS_BHVHEAD(vfs), - VFS_POSITION_XFS, VFS_POSITION_XFS)); + return vfs->vfs_mount; } #define XFS_DADDR_TO_AGNO(mp,d) xfs_daddr_to_agno(mp,d) @@ -633,7 +626,7 @@ typedef struct xfs_mod_sb { extern xfs_mount_t *xfs_mount_init(void); extern void xfs_mod_sb(xfs_trans_t *, __int64_t); extern int xfs_log_sbcount(xfs_mount_t *, uint); -extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv); +extern void xfs_mount_free(xfs_mount_t *mp); extern int xfs_mountfs(struct bhv_vfs *, xfs_mount_t *mp, int); extern void xfs_mountfs_check_barriers(xfs_mount_t *mp); diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 2d672f317110..593e6e2b3921 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -439,7 +439,6 @@ xfs_mount( cred_t *credp) { struct bhv_vfs *vfsp = XFS_MTOVFS(mp); - struct bhv_desc *p; struct block_device *ddev, *logdev, *rtdev; int flags = 0, error; @@ -453,11 +452,7 @@ xfs_mount( if (error) return error; - /* - * Setup xfs_mount function vectors from available behaviors - */ - p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO); - mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs; + mp->m_io_ops = xfs_iocore_xfs; if (args->flags & XFSMNT_QUIET) flags |= XFS_MFSI_QUIET; @@ -741,7 +736,7 @@ xfs_mntupdate( } } else if (!(vfsp->vfs_flag & VFS_RDONLY)) { /* rw -> ro */ xfs_filestream_flush(mp); - bhv_vfs_sync(vfsp, SYNC_DATA_QUIESCE, NULL); + xfs_sync(mp, SYNC_DATA_QUIESCE); xfs_attr_quiesce(mp); vfsp->vfs_flag |= VFS_RDONLY; } diff --git a/fs/xfs/xfs_vfsops.h b/fs/xfs/xfs_vfsops.h index 994502eac19a..bc99e3eb7dbb 100644 --- a/fs/xfs/xfs_vfsops.h +++ b/fs/xfs/xfs_vfsops.h @@ -24,8 +24,5 @@ int xfs_showargs(struct xfs_mount *mp, struct seq_file *m); void xfs_freeze(struct xfs_mount *mp); void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname, int lnnum); -struct inode *xfs_get_inode(struct xfs_mount *mp, xfs_ino_t ino, int flags); -void xfs_initialize_vnode(struct xfs_mount *mp, bhv_vnode_t *vp, - struct xfs_inode *ip, int unlock); #endif /* _XFS_VFSOPS_H */ diff --git a/fs/xfs/xfs_vfsops_bhv.c b/fs/xfs/xfs_vfsops_bhv.c deleted file mode 100644 index 764b2aefb6bc..000000000000 --- a/fs/xfs/xfs_vfsops_bhv.c +++ /dev/null @@ -1,145 +0,0 @@ - -#include "xfs_linux.h" -#include "xfs_vfsops.h" - -#include "xfs_inum.h" -#include "xfs_dmapi.h" -#include "xfs_sb.h" -#include "xfs_log.h" -#include "xfs_trans.h" -#include "xfs_ag.h" -#include "xfs_mount.h" - - -STATIC int -xfs_bhv_mount( - struct bhv_desc *bhvp, - struct xfs_mount_args *args, - cred_t *credp) -{ - return xfs_mount(XFS_BHVTOM(bhvp), args, credp); -} - -STATIC int -xfs_bhv_unmount( - bhv_desc_t *bdp, - int flags, - cred_t *credp) -{ - return xfs_unmount(XFS_BHVTOM(bdp), flags, credp); -} - -STATIC int -xfs_bhv_mntupdate( - bhv_desc_t *bdp, - int *flags, - struct xfs_mount_args *args) -{ - return xfs_mntupdate(XFS_BHVTOM(bdp), flags, args); -} - -STATIC int -xfs_bhv_root( - bhv_desc_t *bdp, - bhv_vnode_t **vpp) -{ - return xfs_root(XFS_BHVTOM(bdp), vpp); -} - -STATIC int -xfs_bhv_statvfs( - bhv_desc_t *bdp, - bhv_statvfs_t *statp, - bhv_vnode_t *vp) -{ - return xfs_statvfs(XFS_BHVTOM(bdp), statp, vp); -} - -STATIC int -xfs_bhv_sync( - bhv_desc_t *bdp, - int flags, - cred_t *credp) -{ - return xfs_sync(XFS_BHVTOM(bdp), flags); -} - -STATIC int -xfs_bhv_vget( - bhv_desc_t *bdp, - bhv_vnode_t **vpp, - fid_t *fidp) -{ - return xfs_vget(XFS_BHVTOM(bdp), vpp, fidp); -} - -STATIC int -xfs_bhv_parseargs( - struct bhv_desc *bhv, - char *options, - struct xfs_mount_args *args, - int update) -{ - return xfs_parseargs(XFS_BHVTOM(bhv), options, args, update); -} - -STATIC int -xfs_bhv_showargs( - struct bhv_desc *bhv, - struct seq_file *m) -{ - return xfs_showargs(XFS_BHVTOM(bhv), m); -} - -STATIC void -xfs_bhv_freeze( - bhv_desc_t *bdp) -{ - return xfs_freeze(XFS_BHVTOM(bdp)); -} - -STATIC void -xfs_bhv_force_shutdown( - bhv_desc_t *bdp, - int flags, - char *fname, - int lnnum) -{ - return xfs_do_force_shutdown(XFS_BHVTOM(bdp), flags, fname, lnnum); -} - -STATIC struct inode * -xfs_bhv_get_inode( - bhv_desc_t *bdp, - xfs_ino_t ino, - int flags) -{ - return xfs_get_inode(XFS_BHVTOM(bdp), ino, flags); -} - -STATIC void -xfs_bhv_initialize_vnode( - bhv_desc_t *bdp, - bhv_vnode_t *vp, - struct xfs_inode *ip, - int unlock) -{ - return xfs_initialize_vnode(XFS_BHVTOM(bdp), vp, ip, unlock); -} - -bhv_vfsops_t xfs_vfsops = { - BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS), - .vfs_parseargs = xfs_bhv_parseargs, - .vfs_showargs = xfs_bhv_showargs, - .vfs_mount = xfs_bhv_mount, - .vfs_unmount = xfs_bhv_unmount, - .vfs_mntupdate = xfs_bhv_mntupdate, - .vfs_root = xfs_bhv_root, - .vfs_statvfs = xfs_bhv_statvfs, - .vfs_sync = xfs_bhv_sync, - .vfs_vget = xfs_bhv_vget, - .vfs_get_inode = xfs_bhv_get_inode, - .vfs_init_vnode = xfs_bhv_initialize_vnode, - .vfs_force_shutdown = xfs_bhv_force_shutdown, - .vfs_freeze = xfs_bhv_freeze, -};