Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 147717 Details for
Bug 227945
GFS2: Final notes on the state of GFS2 and GFS2_KP
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
bring gfs2_kp up to current kernel and cluster infrastructure
ken2tot (text/plain), 130.45 KB, created by
Russell Cattelan
on 2007-02-09 00:37:30 UTC
(
hide
)
Description:
bring gfs2_kp up to current kernel and cluster infrastructure
Filename:
MIME Type:
Creator:
Russell Cattelan
Created:
2007-02-09 00:37:30 UTC
Size:
130.45 KB
patch
obsolete
>Index: gfs2_kp/fs/gfs2/acl.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/acl.c 2007-02-07 16:04:02.395952421 -0600 >+++ gfs2_kp/fs/gfs2/acl.c 2007-02-07 16:04:05.783989874 -0600 >@@ -20,7 +20,8 @@ > #include <linux/buffer_head.h> > #include <linux/posix_acl.h> > #include <linux/posix_acl_xattr.h> >-#include <linux/xattr_acl.h> >+#include <gfs2_ondisk.h> >+#include <linux/lm_interface.h> > > #include "gfs2.h" > #include "acl.h" >Index: gfs2_kp/fs/gfs2/diaper.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/diaper.c 2007-02-07 16:04:02.899957991 -0600 >+++ gfs2_kp/fs/gfs2/diaper.c 2007-02-07 16:04:05.867990803 -0600 >@@ -50,7 +50,7 @@ static int diaper_major = 0; > static LIST_HEAD(diaper_list); > static spinlock_t diaper_lock; > static DEFINE_IDR(diaper_idr); >-kmem_cache_t *diaper_slab; >+struct kmem_cache *diaper_slab; > > /** > * diaper_open - >@@ -382,7 +382,7 @@ diaper_get(struct block_device *real, in > if (!diaper) > goto fail_remove; > >- down(&diaper->bd_sem); >+ mutex_lock(&diaper->bd_mutex); > if (!diaper->bd_openers) { > diaper->bd_disk = gd; > diaper->bd_contains = diaper; >@@ -391,7 +391,7 @@ diaper_get(struct block_device *real, in > } else > printk("GFS2: diaper: reopening\n"); > diaper->bd_openers++; >- up(&diaper->bd_sem); >+ mutex_unlock(&diaper->bd_mutex); > > dh->dh_mempool = mempool_create(512, > mempool_alloc_slab, mempool_free_slab, >@@ -414,14 +414,14 @@ diaper_get(struct block_device *real, in > mempool_destroy(dh->dh_mempool); > > fail_bdput: >- down(&diaper->bd_sem); >+ mutex_lock(&diaper->bd_mutex); > if (!--diaper->bd_openers) { > invalidate_bdev(diaper, 1); > diaper->bd_contains = NULL; > diaper->bd_disk = NULL; > } else > printk("GFS2: diaper: not closed\n"); >- up(&diaper->bd_sem); >+ mutex_unlock(&diaper->bd_mutex); > bdput(diaper); > > fail_remove: >@@ -457,14 +457,14 @@ diaper_put(struct diaper_holder *dh) > > mempool_destroy(dh->dh_mempool); > >- down(&diaper->bd_sem); >+ mutex_lock(&diaper->bd_mutex); > if (!--diaper->bd_openers) { > invalidate_bdev(diaper, 1); > diaper->bd_contains = NULL; > diaper->bd_disk = NULL; > } else > printk("GFS2: diaper: not closed\n"); >- up(&diaper->bd_sem); >+ mutex_unlock(&diaper->bd_mutex); > > bdput(diaper); > del_gendisk(gd); >Index: gfs2_kp/fs/gfs2/eaops.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/eaops.c 2007-02-07 16:04:02.951958565 -0600 >+++ gfs2_kp/fs/gfs2/eaops.c 2007-02-07 16:04:05.867990803 -0600 >@@ -20,7 +20,6 @@ > #include <linux/buffer_head.h> > #include <asm/uaccess.h> > #include <linux/xattr.h> >-#include <linux/xattr_acl.h> > > #include "gfs2.h" > #include "acl.h" >Index: gfs2_kp/fs/gfs2/eattr.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/eattr.c 2007-02-07 16:04:02.979958875 -0600 >+++ gfs2_kp/fs/gfs2/eattr.c 2007-02-07 16:04:05.867990803 -0600 >@@ -20,7 +20,6 @@ > #include <linux/buffer_head.h> > #include <asm/uaccess.h> > #include <linux/xattr.h> >-#include <linux/xattr_acl.h> > > #include "gfs2.h" > #include "acl.h" >@@ -1685,7 +1684,7 @@ gfs2_ea_acl_chmod(struct gfs2_inode *ip, > > error = gfs2_meta_inode_buffer(ip, &dibh); > if (!error) { >- inode_setattr(ip->i_vnode, attr); >+ error = inode_setattr(ip->i_vnode, attr); > gfs2_inode_attr_out(ip); > gfs2_trans_add_bh(ip->i_gl, dibh); > gfs2_dinode_out(&ip->i_di, dibh->b_data); >Index: gfs2_kp/fs/gfs2/gfs2.h >=================================================================== >--- gfs2_kp.orig/fs/gfs2/gfs2.h 2007-02-07 16:04:03.003959140 -0600 >+++ gfs2_kp/fs/gfs2/gfs2.h 2007-02-07 16:04:05.911991289 -0600 >@@ -17,7 +17,7 @@ > #define GFS2_RELEASE_NAME "<CVS>" > > #include <linux/lm_interface.h> >-#include <linux/gfs2_ondisk.h> >+#include <gfs2_ondisk.h> > > #include "fixed_div64.h" > #include "lvb.h" >@@ -74,8 +74,8 @@ > > #define get_v2sdp(sb) ((struct gfs2_sbd *)(sb)->s_fs_info) > #define set_v2sdp(sb, sdp) (sb)->s_fs_info = (sdp) >-#define get_v2ip(inode) ((struct gfs2_inode *)(inode)->u.generic_ip) >-#define set_v2ip(inode, ip) (inode)->u.generic_ip = (ip) >+#define get_v2ip(inode) ((struct gfs2_inode *)(inode)->i_private) >+#define set_v2ip(inode, ip) (inode)->i_private = (ip) > #define get_v2fp(file) ((struct gfs2_file *)(file)->private_data) > #define set_v2fp(file, fp) (file)->private_data = (fp) > #define get_v2bd(bh) ((struct gfs2_bufdata *)(bh)->b_private) >Index: gfs2_kp/fs/gfs2/glock.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/glock.c 2007-02-07 16:04:03.027959405 -0600 >+++ gfs2_kp/fs/gfs2/glock.c 2007-02-07 16:04:05.919991378 -0600 >@@ -18,6 +18,7 @@ > #include <asm/semaphore.h> > #include <linux/completion.h> > #include <linux/buffer_head.h> >+#include <linux/delay.h> > #include <asm/uaccess.h> > > #include "gfs2.h" >@@ -38,7 +39,7 @@ struct glock_plug { > > struct greedy { > struct gfs2_holder gr_gh; >- struct work_struct gr_work; >+ struct delayed_work gr_work; > }; > > typedef void (*glock_examiner) (struct gfs2_glock * gl); >@@ -1781,10 +1782,11 @@ gfs2_glock_force_drop(struct gfs2_glock > */ > > static void >-greedy_work(void *data) >+greedy_work(struct work_struct *work) > { > ENTER(G2FN_GREEDY_WORK) >- struct greedy *gr = (struct greedy *)data; >+ >+ struct greedy *gr = container_of(work, struct greedy, gr_work.work); > struct gfs2_holder *gh = &gr->gr_gh; > struct gfs2_glock *gl = gh->gh_gl; > struct gfs2_glock_operations *glops = gl->gl_ops; >@@ -1841,7 +1843,7 @@ gfs2_glock_be_greedy(struct gfs2_glock * > > gfs2_holder_init(gl, 0, GL_NEVER_RECURSE, gh); > set_bit(HIF_GREEDY, &gh->gh_iflags); >- INIT_WORK(&gr->gr_work, greedy_work, gr); >+ INIT_DELAYED_WORK(&gr->gr_work, greedy_work); > > set_bit(GLF_SKIP_WAITERS2, &gl->gl_flags); > schedule_delayed_work(&gr->gr_work, time); >@@ -2272,7 +2274,7 @@ blocking_cb(struct gfs2_sbd *sdp, struct > */ > > void >-gfs2_glock_cb(lm_fsdata_t *fsdata, unsigned int type, void *data) >+gfs2_glock_cb(void *fsdata, unsigned int type, void *data) > { > ENTER(G2FN_GLOCK_CB) > struct gfs2_sbd *sdp = (struct gfs2_sbd *)fsdata; >Index: gfs2_kp/fs/gfs2/glock.h >=================================================================== >--- gfs2_kp.orig/fs/gfs2/glock.h 2007-02-07 16:04:03.027959405 -0600 >+++ gfs2_kp/fs/gfs2/glock.h 2007-02-07 16:04:05.919991378 -0600 >@@ -140,7 +140,7 @@ int gfs2_lvb_hold(struct gfs2_glock *gl) > void gfs2_lvb_unhold(struct gfs2_glock *gl); > void gfs2_lvb_sync(struct gfs2_glock *gl); > >-void gfs2_glock_cb(lm_fsdata_t *fsdata, unsigned int type, void *data); >+void gfs2_glock_cb(void *fsdata, unsigned int type, void *data); > > void gfs2_try_toss_inode(struct gfs2_sbd *sdp, struct gfs2_inum *inum); > void gfs2_iopen_go_callback(struct gfs2_glock *gl, unsigned int state); >Index: gfs2_kp/fs/gfs2/incore.h >=================================================================== >--- gfs2_kp.orig/fs/gfs2/incore.h 2007-02-07 16:04:03.047959626 -0600 >+++ gfs2_kp/fs/gfs2/incore.h 2007-02-07 16:04:05.967991909 -0600 >@@ -30,7 +30,7 @@ > #define DIO_DATA (0x00000040) /* Process glock's protected filedata */ > #define DIO_RELEASE (0x00000080) /* Releasing glock */ > #define DIO_ALL (0x00000100) /* Flush all AIL transactions to disk */ >- >+#define GFS2_FSNAME_LEN 256 > /* Structure prototypes */ > > struct gfs2_log_operations; >@@ -424,7 +424,7 @@ struct gfs2_glock { > struct gfs2_holder *gl_req_gh; /* Holder for request being serviced */ > gfs2_glop_bh_t gl_req_bh; /* The bottom half to execute */ > >- lm_lock_t *gl_lock; /* Lock module's private lock data */ >+ void *gl_lock; /* Lock module's private lock data */ > char *gl_lvb; /* Lock Value Block */ > atomic_t gl_lvb_count; /* LVB recursive usage (hold/unhold) count */ > >@@ -785,6 +785,7 @@ struct gfs2_sbd { > struct super_block *sd_vfs; /* Linux VFS device independent sb */ > > unsigned long sd_flags; /* SDF_... see above */ >+ struct kobject sd_kobj; > struct gfs2_sb sd_sb; /* GFS2 on-disk Super Block image */ > > /* Constants computed on mount */ >@@ -1047,13 +1048,17 @@ struct gfs2_sbd { > atomic_t sd_ops_super; > atomic_t sd_ops_vm; > >- char sd_fsname[256]; >+ char sd_fsname[GFS2_FSNAME_LEN]; >+ char sd_table_name[GFS2_FSNAME_LEN]; >+ char sd_proto_name[GFS2_FSNAME_LEN]; > > /* Debugging crud */ > > unsigned long sd_last_warning; > > struct list_head sd_list; >+ >+ struct vfsmount *sd_gfs2mnt; > }; > > #endif /* __INCORE_DOT_H__ */ >Index: gfs2_kp/fs/gfs2/inode.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/inode.c 2007-02-07 16:04:03.051959671 -0600 >+++ gfs2_kp/fs/gfs2/inode.c 2007-02-07 16:04:05.967991909 -0600 >@@ -71,7 +71,7 @@ inode_attr_in(struct gfs2_inode *ip, str > inode->i_mtime.tv_sec = ip->i_di.di_mtime; > inode->i_ctime.tv_sec = ip->i_di.di_ctime; > inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0; >- inode->i_blksize = PAGE_SIZE; >+// inode->i_blksize = PAGE_SIZE; > inode->i_blocks = ip->i_di.di_blocks << > (ip->i_sbd->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT); > >@@ -1942,7 +1942,7 @@ gfs2_setattr_simple(struct gfs2_inode *i > > error = gfs2_meta_inode_buffer(ip, &dibh); > if (!error) { >- inode_setattr(ip->i_vnode, attr); >+ error = inode_setattr(ip->i_vnode, attr); > gfs2_inode_attr_out(ip); > > gfs2_trans_add_bh(ip->i_gl, dibh); >Index: gfs2_kp/fs/gfs2/Kconfig >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ gfs2_kp/fs/gfs2/Kconfig 2007-02-07 16:04:05.967991909 -0600 >@@ -0,0 +1,43 @@ >+config GFS2_FS >+ tristate "GFS2 file system support" >+ depends on EXPERIMENTAL >+ select FS_POSIX_ACL >+ help >+ A cluster filesystem. >+ >+ Allows a cluster of computers to simultaneously use a block device >+ that is shared between them (with FC, iSCSI, NBD, etc...). GFS reads >+ and writes to the block device like a local filesystem, but also uses >+ a lock module to allow the computers coordinate their I/O so >+ filesystem consistency is maintained. One of the nifty features of >+ GFS is perfect consistency -- changes made to the filesystem on one >+ machine show up immediately on all other machines in the cluster. >+ >+ To use the GFS2 filesystem, you will need to enable one or more of >+ the below locking modules. Documentation and utilities for GFS2 can >+ be found here: http://sources.redhat.com/cluster >+ >+config GFS2_FS_LOCKING_NOLOCK >+ tristate "GFS2 \"nolock\" locking module" >+ depends on GFS2_FS >+ help >+ Single node locking module for GFS2. >+ >+ Use this module if you want to use GFS2 on a single node without >+ its clustering features. You can still take advantage of the >+ large file support, and upgrade to running a full cluster later on >+ if required. >+ >+ If you will only be using GFS2 in cluster mode, you do not need this >+ module. >+ >+config GFS2_FS_LOCKING_DLM >+ tristate "GFS2 DLM locking module" >+ depends on GFS2_FS >+ help >+ Multiple node locking module for GFS2 >+ >+ Most users of GFS2 will require this module. It provides the locking >+ interface between GFS2 and the DLM, which is required to use GFS2 >+ in a cluster environment. >+ >Index: gfs2_kp/fs/gfs2/lm.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/lm.c 2007-02-07 16:04:03.191961218 -0600 >+++ gfs2_kp/fs/gfs2/lm.c 2007-02-07 16:04:06.147993900 -0600 >@@ -87,10 +87,10 @@ gfs2_lm_mount(struct gfs2_sbd *sdp, int > printk("GFS2: Trying to join cluster \"%s\", \"%s\"\n", > proto, table); > >- error = lm_mount(proto, table, sdp->sd_args.ar_hostdata, >- gfs2_glock_cb, sdp, >- GFS2_MIN_LVB_SIZE, flags, >- &sdp->sd_lockstruct); >+ error = gfs2_mount_lockproto(proto, table, sdp->sd_args.ar_hostdata, >+ gfs2_glock_cb, sdp, >+ GFS2_MIN_LVB_SIZE, flags, >+ &sdp->sd_lockstruct, &sdp->sd_kobj); > if (error) { > printk("GFS2: can't mount proto = %s, table = %s, hostdata = %s\n", > proto, table, sdp->sd_args.ar_hostdata); >@@ -99,8 +99,9 @@ gfs2_lm_mount(struct gfs2_sbd *sdp, int > > if (gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lockspace) || > gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_ops) || >- gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >= GFS2_MIN_LVB_SIZE)) { >- lm_unmount(&sdp->sd_lockstruct); >+ gfs2_assert_warn(sdp, sdp->sd_lockstruct.ls_lvb_size >= >+ GFS2_MIN_LVB_SIZE)) { >+ gfs2_unmount_lockproto(&sdp->sd_lockstruct); > goto out; > } > >@@ -159,7 +160,7 @@ gfs2_lm_unmount(struct gfs2_sbd *sdp) > { > ENTER(G2FN_LM_UNMOUNT) > if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) >- lm_unmount(&sdp->sd_lockstruct); >+ gfs2_unmount_lockproto(&sdp->sd_lockstruct); > RET(G2FN_LM_UNMOUNT); > } > >@@ -198,7 +199,9 @@ gfs2_lm_withdraw(struct gfs2_sbd *sdp, c > > printk("GFS2: fsid=%s: telling LM to withdraw\n", > sdp->sd_fsname); >- lm_withdraw(&sdp->sd_lockstruct); >+ >+// lm_withdraw(&sdp->sd_lockstruct); >+ > printk("GFS2: fsid=%s: withdrawn\n", > sdp->sd_fsname); > >@@ -216,7 +219,7 @@ gfs2_lm_withdraw(struct gfs2_sbd *sdp, c > > int > gfs2_lm_get_lock(struct gfs2_sbd *sdp, >- struct lm_lockname *name, lm_lock_t **lockp) >+ struct lm_lockname *name, void **lockp) > { > ENTER(G2FN_LM_GET_LOCK) > int error; >@@ -236,7 +239,7 @@ gfs2_lm_get_lock(struct gfs2_sbd *sdp, > */ > > void >-gfs2_lm_put_lock(struct gfs2_sbd *sdp, lm_lock_t *lock) >+gfs2_lm_put_lock(struct gfs2_sbd *sdp, void *lock) > { > ENTER(G2FN_LM_PUT_LOCK) > if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) >@@ -256,7 +259,7 @@ gfs2_lm_put_lock(struct gfs2_sbd *sdp, l > */ > > unsigned int >-gfs2_lm_lock(struct gfs2_sbd *sdp, lm_lock_t *lock, >+gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock, > unsigned int cur_state, unsigned int req_state, > unsigned int flags) > { >@@ -281,7 +284,7 @@ gfs2_lm_lock(struct gfs2_sbd *sdp, lm_lo > */ > > unsigned int >-gfs2_lm_unlock(struct gfs2_sbd *sdp, lm_lock_t *lock, >+gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock, > unsigned int cur_state) > { > ENTER(G2FN_LM_UNLOCK) >@@ -301,7 +304,7 @@ gfs2_lm_unlock(struct gfs2_sbd *sdp, lm_ > */ > > void >-gfs2_lm_cancel(struct gfs2_sbd *sdp, lm_lock_t *lock) >+gfs2_lm_cancel(struct gfs2_sbd *sdp, void *lock) > { > ENTER(G2FN_LM_CANCEL) > if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) >@@ -319,7 +322,7 @@ gfs2_lm_cancel(struct gfs2_sbd *sdp, lm_ > */ > > int >-gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, lm_lock_t *lock, char **lvbp) >+gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp) > { > ENTER(G2FN_LM_HOLD_LVB) > int error; >@@ -339,7 +342,7 @@ gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, l > */ > > void >-gfs2_lm_unhold_lvb(struct gfs2_sbd *sdp, lm_lock_t *lock, char *lvb) >+gfs2_lm_unhold_lvb(struct gfs2_sbd *sdp, void *lock, char *lvb) > { > ENTER(G2FN_LM_UNHOLD_LVB) > if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) >@@ -356,12 +359,15 @@ gfs2_lm_unhold_lvb(struct gfs2_sbd *sdp, > */ > > void >-gfs2_lm_sync_lvb(struct gfs2_sbd *sdp, lm_lock_t *lock, char *lvb) >+gfs2_lm_sync_lvb(struct gfs2_sbd *sdp, void *lock, char *lvb) > { >+ >+#if 0 > ENTER(G2FN_LM_SYNC_LVB) > if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) > sdp->sd_lockstruct.ls_ops->lm_sync_lvb(lock, lvb); > RET(G2FN_LM_SYNC_LVB); >+#endif > } > > /** >Index: gfs2_kp/fs/gfs2/lm.h >=================================================================== >--- gfs2_kp.orig/fs/gfs2/lm.h 2007-02-07 16:04:03.191961218 -0600 >+++ gfs2_kp/fs/gfs2/lm.h 2007-02-07 16:04:06.147993900 -0600 >@@ -20,17 +20,17 @@ void gfs2_lm_unmount(struct gfs2_sbd *sd > int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...) > __attribute__ ((format(printf, 2, 3))); > int gfs2_lm_get_lock(struct gfs2_sbd *sdp, >- struct lm_lockname *name, lm_lock_t **lockp); >-void gfs2_lm_put_lock(struct gfs2_sbd *sdp, lm_lock_t *lock); >-unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, lm_lock_t *lock, >+ struct lm_lockname *name, void **lockp); >+void gfs2_lm_put_lock(struct gfs2_sbd *sdp, void *lock); >+unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock, > unsigned int cur_state, unsigned int req_state, > unsigned int flags); >-unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, lm_lock_t *lock, >+unsigned int gfs2_lm_unlock(struct gfs2_sbd *sdp, void *lock, > unsigned int cur_state); >-void gfs2_lm_cancel(struct gfs2_sbd *sdp, lm_lock_t *lock); >-int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, lm_lock_t *lock, char **lvbp); >-void gfs2_lm_unhold_lvb(struct gfs2_sbd *sdp, lm_lock_t *lock, char *lvb); >-void gfs2_lm_sync_lvb(struct gfs2_sbd *sdp, lm_lock_t *lock, char *lvb); >+void gfs2_lm_cancel(struct gfs2_sbd *sdp, void *lock); >+int gfs2_lm_hold_lvb(struct gfs2_sbd *sdp, void *lock, char **lvbp); >+void gfs2_lm_unhold_lvb(struct gfs2_sbd *sdp, void *lock, char *lvb); >+void gfs2_lm_sync_lvb(struct gfs2_sbd *sdp, void *lock, char *lvb); > int gfs2_lm_plock_get(struct gfs2_sbd *sdp, > struct lm_lockname *name, > struct file *file, struct file_lock *fl); >Index: gfs2_kp/fs/gfs2/locking.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ gfs2_kp/fs/gfs2/locking.c 2007-02-07 16:04:06.147993900 -0600 >@@ -0,0 +1,188 @@ >+/* >+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. >+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. >+ * >+ * This copyrighted material is made available to anyone wishing to use, >+ * modify, copy, or redistribute it subject to the terms and conditions >+ * of the GNU General Public License version 2. >+ */ >+ >+#include <linux/module.h> >+#include <linux/init.h> >+#include <linux/string.h> >+#include <linux/slab.h> >+#include <linux/wait.h> >+#include <linux/sched.h> >+#include <linux/kmod.h> >+#include <linux/fs.h> >+#include <linux/delay.h> >+#include <linux/lm_interface.h> >+ >+struct lmh_wrapper { >+ struct list_head lw_list; >+ const struct lm_lockops *lw_ops; >+}; >+ >+/* List of registered low-level locking protocols. A file system selects one >+ of them by name at mount time, e.g. lock_nolock, lock_dlm. */ >+ >+static LIST_HEAD(lmh_list); >+static DEFINE_MUTEX(lmh_lock); >+ >+/** >+ * gfs2_register_lockproto - Register a low-level locking protocol >+ * @proto: the protocol definition >+ * >+ * Returns: 0 on success, -EXXX on failure >+ */ >+ >+int gfs2_register_lockproto(const struct lm_lockops *proto) >+{ >+ struct lmh_wrapper *lw; >+ >+ printk(KERN_INFO "GFS2: gfs2_register_lockproto %s\n", proto->lm_proto_name); >+ >+ mutex_lock(&lmh_lock); >+ >+ list_for_each_entry(lw, &lmh_list, lw_list) { >+ if (!strcmp(lw->lw_ops->lm_proto_name, proto->lm_proto_name)) { >+ mutex_unlock(&lmh_lock); >+ printk(KERN_INFO "GFS2: protocol %s already exists\n", >+ proto->lm_proto_name); >+ return -EEXIST; >+ } >+ } >+ >+ lw = kzalloc(sizeof(struct lmh_wrapper), GFP_KERNEL); >+ if (!lw) { >+ mutex_unlock(&lmh_lock); >+ return -ENOMEM; >+ } >+ >+ lw->lw_ops = proto; >+ list_add(&lw->lw_list, &lmh_list); >+ >+ mutex_unlock(&lmh_lock); >+ >+ return 0; >+} >+ >+/** >+ * gfs2_unregister_lockproto - Unregister a low-level locking protocol >+ * @proto: the protocol definition >+ * >+ */ >+ >+void gfs2_unregister_lockproto(const struct lm_lockops *proto) >+{ >+ struct lmh_wrapper *lw; >+ >+ mutex_lock(&lmh_lock); >+ >+ list_for_each_entry(lw, &lmh_list, lw_list) { >+ if (!strcmp(lw->lw_ops->lm_proto_name, proto->lm_proto_name)) { >+ list_del(&lw->lw_list); >+ mutex_unlock(&lmh_lock); >+ kfree(lw); >+ return; >+ } >+ } >+ >+ mutex_unlock(&lmh_lock); >+ >+ printk(KERN_WARNING "GFS2: can't unregister lock protocol %s\n", >+ proto->lm_proto_name); >+} >+ >+/** >+ * gfs2_mount_lockproto - Mount a lock protocol >+ * @proto_name - the name of the protocol >+ * @table_name - the name of the lock space >+ * @host_data - data specific to this host >+ * @cb - the callback to the code using the lock module >+ * @sdp - The GFS2 superblock >+ * @min_lvb_size - the mininum LVB size that the caller can deal with >+ * @flags - LM_MFLAG_* >+ * @lockstruct - a structure returned describing the mount >+ * >+ * Returns: 0 on success, -EXXX on failure >+ */ >+ >+int gfs2_mount_lockproto(char *proto_name, char *table_name, char *host_data, >+ lm_callback_t cb, void *cb_data, >+ unsigned int min_lvb_size, int flags, >+ struct lm_lockstruct *lockstruct, >+ struct kobject *fskobj) >+{ >+ struct lmh_wrapper *lw = NULL; >+ int try = 0; >+ int error, found; >+ >+ printk("gfs2_mount_lockproto: 0\n"); >+retry: >+ mutex_lock(&lmh_lock); >+ >+ found = 0; >+ list_for_each_entry(lw, &lmh_list, lw_list) { >+ if (!strcmp(lw->lw_ops->lm_proto_name, proto_name)) { >+ found = 1; >+ break; >+ } >+ } >+ >+ if (!found) { >+ if (!try && capable(CAP_SYS_MODULE)) { >+ try = 1; >+ mutex_unlock(&lmh_lock); >+ request_module(proto_name); >+ goto retry; >+ } >+ printk(KERN_INFO "GFS2: can't find protocol %s\n", proto_name); >+ error = -ENOENT; >+ goto out; >+ } >+ >+ if (!try_module_get(lw->lw_ops->lm_owner)) { >+ try = 0; >+ mutex_unlock(&lmh_lock); >+ msleep(1000); >+ goto retry; >+ } >+ >+ error = lw->lw_ops->lm_mount(table_name, host_data, cb, cb_data, >+ min_lvb_size, flags, lockstruct, fskobj); >+ if (error) >+ module_put(lw->lw_ops->lm_owner); >+out: >+ mutex_unlock(&lmh_lock); >+ printk("gfs2_mount_lockproto: error %d\n",error); >+ return error; >+} >+ >+void gfs2_unmount_lockproto(struct lm_lockstruct *lockstruct) >+{ >+ mutex_lock(&lmh_lock); >+ lockstruct->ls_ops->lm_unmount(lockstruct->ls_lockspace); >+ if (lockstruct->ls_ops->lm_owner) >+ module_put(lockstruct->ls_ops->lm_owner); >+ mutex_unlock(&lmh_lock); >+} >+ >+/** >+ * gfs2_withdraw_lockproto - abnormally unmount a lock module >+ * @lockstruct: the lockstruct passed into mount >+ * >+ */ >+ >+void gfs2_withdraw_lockproto(struct lm_lockstruct *lockstruct) >+{ >+ mutex_lock(&lmh_lock); >+ lockstruct->ls_ops->lm_withdraw(lockstruct->ls_lockspace); >+ if (lockstruct->ls_ops->lm_owner) >+ module_put(lockstruct->ls_ops->lm_owner); >+ mutex_unlock(&lmh_lock); >+} >+ >+EXPORT_SYMBOL_GPL(gfs2_register_lockproto); >+EXPORT_SYMBOL_GPL(gfs2_unregister_lockproto); >+ >Index: gfs2_kp/fs/gfs2/Makefile >=================================================================== >--- gfs2_kp.orig/fs/gfs2/Makefile 2007-02-07 16:04:03.515964799 -0600 >+++ gfs2_kp/fs/gfs2/Makefile 2007-02-07 16:04:06.187994342 -0600 >@@ -11,21 +11,8 @@ > ############################################################################### > ############################################################################### > >-top_srcdir = ../.. >-ifndef USING_KBUILD >-include ${top_srcdir}/make/defines.mk >-UNINSTALL=${top_srcdir}/scripts/uninstall.pl >-endif >- >-linux_orig = ${top_srcdir}/src/linux-orig >-linux_patched = ${top_srcdir}/src/linux-patched >- >-TARGET = gfs2.patch >- >-PWD := $(shell pwd) >- >-obj-m := gfs2.o >-gfs2-objs := \ >+obj-$(CONFIG_GFS2_FS) += gfs2.o >+gfs2-y := \ > acl.o \ > bits.o \ > bmap.o \ >@@ -41,6 +28,7 @@ gfs2-objs := \ > ioctl.o \ > jdata.o \ > lm.o \ >+ locking.o \ > log.o \ > lops.o \ > lvb.o \ >@@ -65,7 +53,12 @@ gfs2-objs := \ > super.o \ > trans.o \ > unlinked.o \ >- util.o >+ util.o \ >+ sys.o >+ >+obj-$(CONFIG_GFS2_FS_LOCKING_NOLOCK) += locking/nolock/ >+obj-$(CONFIG_GFS2_FS_LOCKING_DLM) += locking/dlm/ >+ > > EXTRA_CFLAGS += -I$(obj) > >@@ -75,43 +68,4 @@ EXTRA_CFLAGS += -I$(obj) > #EXTRA_CFLAGS += -DGFS2_MEMORY_BRUTE > #EXTRA_CFLAGS += -DGFS2_KDBL > >-all: >- ${top_srcdir}/../kdbl/scripts/build_debug gfs2 *.[ch] > gfs2_debug_const.h >- rm -f linux lm_interface.h >- ln -s . linux >- ln -s ${top_srcdir}/../gfs-kernel/src/harness/lm_interface.h . >- ${MAKE} -C ${KERNEL_SRC} M=${PWD} modules USING_KBUILD=yes >- >-install: all >- install -d ${module_dir}/fs/gfs2 >- install gfs2.ko ${module_dir}/fs/gfs2 >- install -d ${incdir}/linux >- install gfs2_ondisk.h gfs2_ioctl.h ${incdir}/linux >- >-uninstall: >- ${UNINSTALL} gfs2.ko ${module_dir}/fs/gfs2 >- ${UNINSTALL} gfs2_ondisk.h gfs2_ioctl.h ${incdir}/linux >- >-clean: >- rm -rf linux *.o .*.o.cmd .gfs2.ko.cmd lm_interface.h \ >- gfs2.ko gfs2.mod.c .tmp_versions *~ gfs2_debug_const.h >- >- >-patches: pre add post >- >-pre: >- @if [ ! -d ${linux_orig} ] ; then \ >- echo "No linux source directory (${linux_orig})" ; \ >- exit 1; \ >- fi >- mkdir -p ${linux_patched} >- rsync -a --delete ${linux_orig}/ ${linux_patched}/ >- >-post: >- ( cd ${top_srcdir}/src ; diff -urN linux-orig linux-patched > ${TARGET} ; exit 0 ) >- >-add: >- mkdir -p ${linux_patched}/fs/gfs2 >- cp *.[ch] ${linux_patched}/fs/gfs2 >- mv ${linux_patched}/fs/gfs2/gfs2_*.h ${linux_patched}/include/linux > >Index: gfs2_kp/fs/gfs2/meta_io.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/meta_io.c 2007-02-07 16:04:03.515964799 -0600 >+++ gfs2_kp/fs/gfs2/meta_io.c 2007-02-07 16:04:06.187994342 -0600 >@@ -146,7 +146,7 @@ stuck_releasepage(struct buffer_head *bh > */ > > static int >-gfs2_aspace_releasepage(struct page *page, int gfp_mask) >+gfs2_aspace_releasepage(struct page *page, gfp_t gfp_mask) > { > ENTER(G2FN_ASPACE_RELEASEPAGE) > struct inode *aspace = page->mapping->host; >@@ -229,7 +229,8 @@ gfs2_aspace_get(struct gfs2_sbd *sdp) > mapping_set_gfp_mask(aspace->i_mapping, GFP_KERNEL); > aspace->i_mapping->a_ops = &aspace_aops; > aspace->i_size = ~0ULL; >- get_v2ip(aspace) = NULL; >+ //get_v2ip(aspace) = NULL; >+ aspace->i_private = NULL; > insert_inode_hash(aspace); > } > >Index: gfs2_kp/fs/gfs2/ops_address.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/ops_address.c 2007-02-07 16:04:03.551965197 -0600 >+++ gfs2_kp/fs/gfs2/ops_address.c 2007-02-07 16:04:06.191994386 -0600 >@@ -111,7 +111,6 @@ get_block_noalloc(struct inode *inode, s > > static int > get_blocks(struct inode *inode, sector_t lblock, >- unsigned long max_blocks, > struct buffer_head *bh_result, int create) > { > ENTER(G2FN_GET_BLOCKS) >@@ -132,8 +131,10 @@ get_blocks(struct inode *inode, sector_t > if (new) > set_buffer_new(bh_result); > >+#if 0 > if (extlen > max_blocks) > extlen = max_blocks; >+#endif > bh_result->b_size = extlen << inode->i_blkbits; > > RETURN(G2FN_GET_BLOCKS, 0); >@@ -152,7 +153,6 @@ get_blocks(struct inode *inode, sector_t > > static int > get_blocks_noalloc(struct inode *inode, sector_t lblock, >- unsigned long max_blocks, > struct buffer_head *bh_result, int create) > { > ENTER(G2FN_GET_BLOCKS_NOALLOC) >@@ -168,8 +168,10 @@ get_blocks_noalloc(struct inode *inode, > > if (dblock) { > map_bh(bh_result, inode->i_sb, dblock); >+#if 0 > if (extlen > max_blocks) > extlen = max_blocks; >+#endif > bh_result->b_size = extlen << inode->i_blkbits; > } else if (gfs2_assert_withdraw(ip->i_sbd, !create)) > error = -EIO; >@@ -506,18 +508,18 @@ discard_buffer(struct gfs2_sbd *sdp, str > RET(G2FN_DISCARD_BUFFER); > } > >-int >+void > gfs2_invalidatepage(struct page *page, unsigned long offset) > { > ENTER(G2FN_INVALIDATEPAGE) > struct gfs2_sbd *sdp = get_v2sdp(page->mapping->host->i_sb); > struct buffer_head *head, *bh, *next; > unsigned int curr_off = 0; >- int ret = 1; >+ int ret = 0; > > BUG_ON(!PageLocked(page)); > if (!page_has_buffers(page)) >- RETURN(G2FN_INVALIDATEPAGE, 1); >+ RET(G2FN_INVALIDATEPAGE); > > bh = head = page_buffers(page); > do { >@@ -534,7 +536,7 @@ gfs2_invalidatepage(struct page *page, u > if (!offset) > ret = try_to_release_page(page, 0); > >- RETURN(G2FN_INVALIDATEPAGE, ret); >+ RET(G2FN_INVALIDATEPAGE); > } > > /** >@@ -557,7 +559,7 @@ gfs2_direct_IO(int rw, struct kiocb *ioc > struct inode *inode = file->f_mapping->host; > struct gfs2_inode *ip = get_v2ip(inode); > struct gfs2_sbd *sdp = ip->i_sbd; >- get_blocks_t *gb = get_blocks; >+ get_block_t *gb = get_blocks; > > atomic_inc(&sdp->sd_ops_address); > >Index: gfs2_kp/fs/gfs2/ops_file.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/ops_file.c 2007-02-07 16:04:03.607965816 -0600 >+++ gfs2_kp/fs/gfs2/ops_file.c 2007-02-07 16:04:06.191994386 -0600 >@@ -24,7 +24,8 @@ > #include <linux/blkdev.h> > #include <linux/mm.h> > #include <asm/uaccess.h> >-#include <linux/gfs2_ioctl.h> >+ >+#include "gfs2_ioctl.h" > > #include "gfs2.h" > #include "bmap.h" >@@ -334,8 +335,11 @@ do_read_direct(struct file *file, char * > goto out_gunlock; > > count = do_jdata_read(file, buf, size & ~mask, offset); >- } else >- count = generic_file_read(file, buf, size, offset); >+ } else { >+ // count = generic_file_read(file, buf, size, offset); >+ printk("do_read_direct: broken\n"); >+ do_sync_read(file, buf, size, offset); >+ } > > error = 0; > >@@ -380,8 +384,11 @@ do_read_buf(struct file *file, char *buf > if (gfs2_is_jdata(ip) || > (gfs2_is_stuffed(ip) && !test_bit(GIF_PAGED, &ip->i_flags))) > count = do_jdata_read(file, buf, size, offset); >- else >- count = generic_file_read(file, buf, size, offset); >+ else { >+ //count = generic_file_read(file, buf, size, offset); >+ count = do_sync_read(file, buf, size, offset); >+ } >+ > > gfs2_glock_dq_m(num_gh + 1, ghs); > >@@ -469,11 +476,16 @@ do_write_direct_alloc(struct file *file, > struct gfs2_sbd *sdp = ip->i_sbd; > struct gfs2_alloc *al = NULL; > struct iovec local_iov = { .iov_base = buf, .iov_len = size }; >+ struct kiocb kiocb; > struct buffer_head *dibh; > unsigned int data_blocks, ind_blocks; > ssize_t count; > int error; > >+ init_sync_kiocb(&kiocb, file); >+ kiocb.ki_pos = *offset; >+ kiocb.ki_left = size; >+ > gfs2_write_calc_reserv(ip, size, &data_blocks, &ind_blocks); > > al = gfs2_alloc_get(ip); >@@ -517,7 +529,7 @@ do_write_direct_alloc(struct file *file, > goto fail_end_trans; > } > >- count = generic_file_write_nolock(file, &local_iov, 1, offset); >+ count = generic_file_aio_write_nolock(&kiocb, &local_iov, 1, kiocb.ki_pos); > if (count < 0) { > error = count; > goto fail_end_trans; >@@ -665,6 +677,11 @@ do_write_direct(struct file *file, char > } else { > struct iovec local_iov = { .iov_base = buf, .iov_len = size }; > struct gfs2_holder t_gh; >+ struct kiocb kiocb; >+ >+ init_sync_kiocb(&kiocb, file); >+ kiocb.ki_pos = *offset; >+ kiocb.ki_left = size; > > clear_bit(GFF_DID_DIRECT_ALLOC, &fp->f_flags); > >@@ -672,7 +689,8 @@ do_write_direct(struct file *file, char > if (error) > goto out_gunlock; > >- count = generic_file_write_nolock(file, &local_iov, 1, offset); >+ count = generic_file_aio_write_nolock(&kiocb, &local_iov, 1, kiocb.ki_pos); >+ > > gfs2_glock_dq_uninit(&t_gh); > } >@@ -777,9 +795,14 @@ do_do_write_buf(struct file *file, char > > *offset += count; > } else { >- struct iovec local_iov = { .iov_base = buf, .iov_len = size }; >+ struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = size }; >+ struct kiocb kiocb; >+ init_sync_kiocb(&kiocb, file); >+ kiocb.ki_pos = *offset; >+ kiocb.ki_left = 1; >+ >+ count = generic_file_aio_write_nolock(&kiocb, &local_iov, 1, kiocb.ki_pos); > >- count = generic_file_write_nolock(file, &local_iov, 1, offset); > if (count < 0) { > error = count; > goto fail_end_trans; >@@ -932,12 +955,12 @@ gfs2_write(struct file *file, const char > if (!access_ok(VERIFY_READ, buf, size)) > RETURN(G2FN_WRITE, -EFAULT); > >- down(&inode->i_sem); >+ mutex_lock(&inode->i_mutex); > if (file->f_flags & O_DIRECT) > count = walk_vm(file, (char *)buf, size, offset, do_write_direct); > else > count = walk_vm(file, (char *)buf, size, offset, do_write_buf); >- up(&inode->i_sem); >+ mutex_unlock(&inode->i_mutex); > > RETURN(G2FN_WRITE, count); > } >@@ -1413,19 +1436,16 @@ gfs2_lock(struct file *file, int cmd, st > > if (sdp->sd_args.ar_localflocks) { > if (IS_GETLK(cmd)) { >- struct file_lock *tmp; >- lock_kernel(); >- tmp = posix_test_lock(file, fl); >+ struct file_lock tmp; >+ int ret; >+ ret = posix_test_lock(file, fl, &tmp); > fl->fl_type = F_UNLCK; >- if (tmp) >- memcpy(fl, tmp, sizeof(struct file_lock)); >- unlock_kernel(); >+ if (ret) >+ memcpy(fl, &tmp, sizeof(struct file_lock)); > RETURN(G2FN_LOCK, 0); > } else { > int error; >- lock_kernel(); > error = posix_lock_file_wait(file, fl); >- unlock_kernel(); > RETURN(G2FN_LOCK, error); > } > } >@@ -1603,6 +1623,8 @@ struct file_operations gfs2_file_fops = > .llseek = gfs2_llseek, > .read = gfs2_read, > .write = gfs2_write, >+ .aio_read = generic_file_aio_read, >+ .aio_write = generic_file_aio_write, > .ioctl = gfs2_ioctl, > .mmap = gfs2_mmap, > .open = gfs2_open, >Index: gfs2_kp/fs/gfs2/ops_fstype.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/ops_fstype.c 2007-02-07 16:04:03.635966126 -0600 >+++ gfs2_kp/fs/gfs2/ops_fstype.c 2007-02-07 16:04:06.639999341 -0600 >@@ -20,6 +20,10 @@ > #include <linux/buffer_head.h> > #include <linux/vmalloc.h> > #include <linux/blkdev.h> >+#include <linux/kthread.h> >+#include <linux/namei.h> >+#include <linux/mount.h> >+#include <linux/lm_interface.h> > > #include "gfs2.h" > #include "daemon.h" >@@ -37,11 +41,13 @@ > #include "rgrp.h" > #include "super.h" > #include "unlinked.h" >+#include "sys.h" >+#include "util.h" > > #define DO FALSE > #define UNDO TRUE > >-#undef NO_DIAPER >+#define NO_DIAPER > > static __inline__ int > do_thread(struct gfs2_sbd *sdp, >@@ -160,6 +166,50 @@ init_vfs(struct gfs2_sbd *sdp) > RET(G2FN_INIT_VFS); > } > >+ >+static int >+init_names(struct gfs2_sbd *sdp, int silent) >+{ >+ struct page *page; >+ char *proto, *table; >+ int error = 0; >+ >+ proto = sdp->sd_args.ar_lockproto; >+ table = sdp->sd_args.ar_locktable; >+ >+ /* Try to autodetect */ >+ >+ if (!proto[0] || !table[0]) { >+ struct gfs2_sb *sb; >+ page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); >+ if (!page) >+ return -ENOBUFS; >+ sb = kmap(page); >+ gfs2_sb_in(&sdp->sd_sb, sb); >+ kunmap(page); >+ __free_page(page); >+ >+ error = gfs2_check_sb(sdp, &sdp->sd_sb, silent); >+ if (error) >+ goto out; >+ >+ if (!proto[0]) >+ proto = sdp->sd_sb.sb_lockproto; >+ if (!table[0]) >+ table = sdp->sd_sb.sb_locktable; >+ } >+ >+ if (!table[0]) >+ table = sdp->sd_vfs->s_id; >+ >+ snprintf(sdp->sd_proto_name, GFS2_FSNAME_LEN, "%s", proto); >+ snprintf(sdp->sd_table_name, GFS2_FSNAME_LEN, "%s", table); >+ >+out: >+ return error; >+} >+ >+ > static int > init_locking(struct gfs2_sbd *sdp, struct gfs2_holder *mount_gh, int undo) > { >@@ -820,10 +870,26 @@ fill_super(struct super_block *sb, void > > init_vfs(sdp); > >+ /* Set up the buffer cache and fill in some fake block size values >+ to allow us to read-in the on-disk superblock. */ >+ sdp->sd_sb.sb_bsize = sb_min_blocksize(sb, GFS2_BASIC_BLOCK); >+ sdp->sd_sb.sb_bsize_shift = sb->s_blocksize_bits; >+ sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift - >+ GFS2_BASIC_BLOCK_SHIFT; >+ sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift; >+ >+ error = init_names(sdp, silent); >+ if (error) >+ goto fail; >+ >+ error = gfs2_sys_fs_add(sdp); >+ if (error) >+ goto fail; >+ > /* Mount an inter-node lock module, check for local optimizations */ > error = gfs2_lm_mount(sdp, silent); > if (error) >- goto fail; >+ goto fail_sys; > > error = init_locking(sdp, &mount_gh, DO); > if (error) >@@ -897,6 +963,8 @@ fill_super(struct super_block *sb, void > while (invalidate_inodes(sb)) > yield(); > >+ fail_sys: >+ gfs2_sys_fs_del(sdp); > fail: > vfree(sdp); > set_v2sdp(sb, NULL); >@@ -936,12 +1004,23 @@ gfs2_set_bdev_super(struct super_block * > } > > #ifdef NO_DIAPER >-struct super_block * >+ >+static int > gfs2_get_sb(struct file_system_type *fs_type, int flags, >- const char *dev_name, void *data) >+ const char *dev_name, void *data, struct vfsmount *mnt) > { >- return get_sb_bdev(fs_type, flags, dev_name, data, fill_super); >+ struct super_block *sb; >+ struct gfs2_sbd *sdp; >+ int error = get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt); >+ if (error) >+ goto out; >+ sb = mnt->mnt_sb; >+ sdp = sb->s_fs_info; >+ sdp->sd_gfs2mnt = mnt; >+out: >+ return error; > } >+ > #else > /** > * gfs2_get_sb - >@@ -955,6 +1034,9 @@ gfs2_get_sb(struct file_system_type *fs_ > * Returns: the new superblock > */ > >+static int gfs2_get_sb(struct file_system_type *fs_type, int flags, >+ const char *dev_name, void *data, struct vfsmount *mnt) >+ > struct super_block * > gfs2_get_sb(struct file_system_type *fs_type, int flags, > const char *dev_name, void *data) >@@ -974,9 +1056,9 @@ gfs2_get_sb(struct file_system_type *fs_ > RETURN(G2FN_GET_SB, (struct super_block *)diaper); > } > >- down(&diaper->bd_mount_sem); >+ mutex_lock(&diaper->bd_mount_mutex); > sb = sget(fs_type, gfs2_test_bdev_super, gfs2_set_bdev_super, diaper); >- up(&diaper->bd_mount_sem); >+ mutex_unlock(&diaper->bd_mount_mutex); > if (IS_ERR(sb)) > goto out; > >@@ -992,9 +1074,11 @@ gfs2_get_sb(struct file_system_type *fs_ > > sb->s_flags = flags; > strlcpy(sb->s_id, bdevname(real, buf), sizeof(sb->s_id)); >+#if 0 > sb->s_old_blocksize = block_size(real); > sb_set_blocksize(sb, sb->s_old_blocksize); > set_blocksize(real, sb->s_old_blocksize); >+#endif > error = fill_super(sb, data, (flags & MS_VERBOSE) ? 1 : 0); > if (error) { > up_write(&sb->s_umount); >@@ -1026,7 +1110,7 @@ gfs2_kill_sb(struct super_block *sb) > ENTER(G2FN_KILL_SB) > struct block_device *diaper = sb->s_bdev; > struct block_device *real = gfs2_diaper_2real(diaper); >- unsigned long bsize = sb->s_old_blocksize; >+ unsigned long bsize = 4096; /* = sb->s_old_blocksize */; > > generic_shutdown_super(sb); > set_blocksize(diaper, bsize); >Index: gfs2_kp/fs/gfs2/ops_inode.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/ops_inode.c 2007-02-07 16:04:03.639966170 -0600 >+++ gfs2_kp/fs/gfs2/ops_inode.c 2007-02-07 16:04:06.643999386 -0600 >@@ -131,17 +131,17 @@ lookup_cdpn_sub_at(struct gfs2_sbd *sdp, > parent = dget_parent(dentry); > > if (gfs2_filecmp(&dentry->d_name, "@hostname", 9)) >- new = lookup_one_len(system_utsname.nodename, >+ new = lookup_one_len(init_uts_ns.name.nodename, > parent, >- strlen(system_utsname.nodename)); >+ strlen(init_uts_ns.name.nodename)); > else if (gfs2_filecmp(&dentry->d_name, "@mach", 5)) >- new = lookup_one_len(system_utsname.machine, >+ new = lookup_one_len(init_uts_ns.name.machine, > parent, >- strlen(system_utsname.machine)); >+ strlen(init_uts_ns.name.machine)); > else if (gfs2_filecmp(&dentry->d_name, "@os", 3)) >- new = lookup_one_len(system_utsname.sysname, >+ new = lookup_one_len(init_uts_ns.name.sysname, > parent, >- strlen(system_utsname.sysname)); >+ strlen(init_uts_ns.name.sysname)); > else if (gfs2_filecmp(&dentry->d_name, "@uid", 4)) > new = lookup_one_len(buf, > parent, >@@ -154,8 +154,8 @@ lookup_cdpn_sub_at(struct gfs2_sbd *sdp, > new = lookup_one_len(buf, > parent, > sprintf(buf, "%s_%s", >- system_utsname.machine, >- system_utsname.sysname)); >+ init_uts_ns.name.machine, >+ init_uts_ns.name.sysname)); > else if (gfs2_filecmp(&dentry->d_name, "@jid", 4)) > new = lookup_one_len(buf, > parent, >@@ -191,17 +191,17 @@ lookup_cdpn_sub_brace(struct gfs2_sbd *s > parent = dget_parent(dentry); > > if (gfs2_filecmp(&dentry->d_name, "{hostname}", 10)) >- new = lookup_one_len(system_utsname.nodename, >+ new = lookup_one_len(init_uts_ns.name.nodename, > parent, >- strlen(system_utsname.nodename)); >+ strlen(init_uts_ns.name.nodename)); > else if (gfs2_filecmp(&dentry->d_name, "{mach}", 6)) >- new = lookup_one_len(system_utsname.machine, >+ new = lookup_one_len(init_uts_ns.name.machine, > parent, >- strlen(system_utsname.machine)); >+ strlen(init_uts_ns.name.machine)); > else if (gfs2_filecmp(&dentry->d_name, "{os}", 4)) >- new = lookup_one_len(system_utsname.sysname, >+ new = lookup_one_len(init_uts_ns.name.sysname, > parent, >- strlen(system_utsname.sysname)); >+ strlen(init_uts_ns.name.sysname)); > else if (gfs2_filecmp(&dentry->d_name, "{uid}", 5)) > new = lookup_one_len(buf, > parent, >@@ -214,8 +214,8 @@ lookup_cdpn_sub_brace(struct gfs2_sbd *s > new = lookup_one_len(buf, > parent, > sprintf(buf, "%s_%s", >- system_utsname.machine, >- system_utsname.sysname)); >+ init_uts_ns.name.machine, >+ init_uts_ns.name.sysname)); > else if (gfs2_filecmp(&dentry->d_name, "{jid}", 5)) > new = lookup_one_len(buf, > parent, >@@ -1080,7 +1080,7 @@ gfs2_readlink(struct dentry *dentry, cha > * Returns: 0 on success or error code > */ > >-static int >+static void * > gfs2_follow_link(struct dentry *dentry, struct nameidata *nd) > { > ENTER(G2FN_FOLLOW_LINK) >@@ -1098,7 +1098,7 @@ gfs2_follow_link(struct dentry *dentry, > kfree(buf); > } > >- RETURN(G2FN_FOLLOW_LINK, error); >+ RETURN(G2FN_FOLLOW_LINK,ERR_PTR(error)); > } > > /** >@@ -1199,7 +1199,7 @@ setattr_chown(struct inode *inode, struc > if (error) > goto out_end_trans; > >- inode_setattr(inode, attr); >+ error = inode_setattr(inode, attr); > gfs2_inode_attr_out(ip); > > gfs2_trans_add_bh(ip->i_gl, dibh); >Index: gfs2_kp/include/linux/gfs2_ondisk.h >=================================================================== >--- gfs2_kp.orig/include/linux/gfs2_ondisk.h 2007-02-07 16:04:03.919969265 -0600 >+++ /dev/null 1970-01-01 00:00:00.000000000 +0000 >@@ -1,443 +0,0 @@ >-/* >- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. >- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. >- * >- * This copyrighted material is made available to anyone wishing to use, >- * modify, copy, or redistribute it subject to the terms and conditions >- * of the GNU General Public License v.2. >- */ >- >-#ifndef __GFS2_ONDISK_DOT_H__ >-#define __GFS2_ONDISK_DOT_H__ >- >-#define GFS2_MAGIC 0x01161970 >-#define GFS2_BASIC_BLOCK 512 >-#define GFS2_BASIC_BLOCK_SHIFT 9 >- >-/* Lock numbers of the LM_TYPE_NONDISK type */ >- >-#define GFS2_MOUNT_LOCK 0 >-#define GFS2_LIVE_LOCK 1 >-#define GFS2_TRANS_LOCK 2 >-#define GFS2_RENAME_LOCK 3 >- >-/* Format numbers for various metadata types */ >- >-#define GFS2_FORMAT_NONE 0 >-#define GFS2_FORMAT_SB 100 >-#define GFS2_FORMAT_RG 200 >-#define GFS2_FORMAT_RB 300 >-#define GFS2_FORMAT_DI 400 >-#define GFS2_FORMAT_IN 500 >-#define GFS2_FORMAT_LF 600 >-#define GFS2_FORMAT_JD 700 >-#define GFS2_FORMAT_LH 800 >-#define GFS2_FORMAT_LD 900 >-#define GFS2_FORMAT_LB 1000 >-#define GFS2_FORMAT_EA 1600 >-#define GFS2_FORMAT_ED 1700 >-#define GFS2_FORMAT_QC 1400 >-/* These are format numbers for entities contained in files */ >-#define GFS2_FORMAT_RI 1100 >-#define GFS2_FORMAT_DE 1200 >-#define GFS2_FORMAT_QU 1500 >-/* These are part of the superblock */ >-#define GFS2_FORMAT_FS 1801 >-#define GFS2_FORMAT_MULTI 1900 >- >-/* >- * An on-disk inode number >- */ >- >-struct gfs2_inum { >- __be64 no_formal_ino; >- __be64 no_addr; >-}; >- >-static inline int gfs2_inum_equal(const struct gfs2_inum *ino1, >- const struct gfs2_inum *ino2) >-{ >- return ino1->no_formal_ino == ino2->no_formal_ino && >- ino1->no_addr == ino2->no_addr; >-} >- >-/* >- * Generic metadata head structure >- * Every inplace buffer logged in the journal must start with this. >- */ >- >-#define GFS2_METATYPE_NONE 0 >-#define GFS2_METATYPE_SB 1 >-#define GFS2_METATYPE_RG 2 >-#define GFS2_METATYPE_RB 3 >-#define GFS2_METATYPE_DI 4 >-#define GFS2_METATYPE_IN 5 >-#define GFS2_METATYPE_LF 6 >-#define GFS2_METATYPE_JD 7 >-#define GFS2_METATYPE_LH 8 >-#define GFS2_METATYPE_LD 9 >-#define GFS2_METATYPE_LB 12 >-#define GFS2_METATYPE_EA 10 >-#define GFS2_METATYPE_ED 11 >-#define GFS2_METATYPE_QC 14 >- >-struct gfs2_meta_header { >- __be32 mh_magic; >- __be32 mh_type; >- __be64 __pad0; /* Was generation number in gfs1 */ >- __be32 mh_format; >- __be32 __pad1; /* Was incarnation number in gfs1 */ >-}; >- >-/* >- * super-block structure >- * >- * It's probably good if SIZEOF_SB <= GFS2_BASIC_BLOCK (512 bytes) >- * >- * Order is important, need to be able to read old superblocks to do on-disk >- * version upgrades. >- */ >- >-/* Address of superblock in GFS2 basic blocks */ >-#define GFS2_SB_ADDR 128 >- >-/* The lock number for the superblock (must be zero) */ >-#define GFS2_SB_LOCK 0 >- >-/* Requirement: GFS2_LOCKNAME_LEN % 8 == 0 >- Includes: the fencing zero at the end */ >-#define GFS2_LOCKNAME_LEN 64 >- >-struct gfs2_sb { >- struct gfs2_meta_header sb_header; >- >- __be32 sb_fs_format; >- __be32 sb_multihost_format; >- __u32 __pad0; /* Was superblock flags in gfs1 */ >- >- __be32 sb_bsize; >- __be32 sb_bsize_shift; >- __u32 __pad1; /* Was journal segment size in gfs1 */ >- >- struct gfs2_inum sb_master_dir; /* Was jindex dinode in gfs1 */ >- struct gfs2_inum __pad2; /* Was rindex dinode in gfs1 */ >- struct gfs2_inum sb_root_dir; >- >- char sb_lockproto[GFS2_LOCKNAME_LEN]; >- char sb_locktable[GFS2_LOCKNAME_LEN]; >- /* In gfs1, quota and license dinodes followed */ >-}; >- >-/* >- * resource index structure >- */ >- >-struct gfs2_rindex { >- __be64 ri_addr; /* grp block disk address */ >- __be32 ri_length; /* length of rgrp header in fs blocks */ >- __u32 __pad; >- >- __be64 ri_data0; /* first data location */ >- __be32 ri_data; /* num of data blocks in rgrp */ >- >- __be32 ri_bitbytes; /* number of bytes in data bitmaps */ >- >- __u8 ri_reserved[64]; >-}; >- >-/* >- * resource group header structure >- */ >- >-/* Number of blocks per byte in rgrp */ >-#define GFS2_NBBY 4 >-#define GFS2_BIT_SIZE 2 >-#define GFS2_BIT_MASK 0x00000003 >- >-#define GFS2_BLKST_FREE 0 >-#define GFS2_BLKST_USED 1 >-#define GFS2_BLKST_UNLINKED 2 >-#define GFS2_BLKST_DINODE 3 >- >-#define GFS2_RGF_JOURNAL 0x00000001 >-#define GFS2_RGF_METAONLY 0x00000002 >-#define GFS2_RGF_DATAONLY 0x00000004 >-#define GFS2_RGF_NOALLOC 0x00000008 >- >-struct gfs2_rgrp { >- struct gfs2_meta_header rg_header; >- >- __be32 rg_flags; >- __be32 rg_free; >- __be32 rg_dinodes; >- __be32 __pad; >- __be64 rg_igeneration; >- >- __u8 rg_reserved[80]; /* Several fields from gfs1 now reserved */ >-}; >- >-/* >- * quota structure >- */ >- >-struct gfs2_quota { >- __be64 qu_limit; >- __be64 qu_warn; >- __be64 qu_value; >- __u8 qu_reserved[64]; >-}; >- >-/* >- * dinode structure >- */ >- >-#define GFS2_MAX_META_HEIGHT 10 >-#define GFS2_DIR_MAX_DEPTH 17 >- >-#define DT2IF(dt) (((dt) << 12) & S_IFMT) >-#define IF2DT(sif) (((sif) & S_IFMT) >> 12) >- >-enum { >- gfs2fl_Jdata = 0, >- gfs2fl_ExHash = 1, >- gfs2fl_Unused = 2, >- gfs2fl_EaIndirect = 3, >- gfs2fl_Directio = 4, >- gfs2fl_Immutable = 5, >- gfs2fl_AppendOnly = 6, >- gfs2fl_NoAtime = 7, >- gfs2fl_Sync = 8, >- gfs2fl_System = 9, >- gfs2fl_TruncInProg = 29, >- gfs2fl_InheritDirectio = 30, >- gfs2fl_InheritJdata = 31, >-}; >- >-/* Dinode flags */ >-#define GFS2_DIF_JDATA 0x00000001 >-#define GFS2_DIF_EXHASH 0x00000002 >-#define GFS2_DIF_UNUSED 0x00000004 /* only in gfs1 */ >-#define GFS2_DIF_EA_INDIRECT 0x00000008 >-#define GFS2_DIF_DIRECTIO 0x00000010 >-#define GFS2_DIF_IMMUTABLE 0x00000020 >-#define GFS2_DIF_APPENDONLY 0x00000040 >-#define GFS2_DIF_NOATIME 0x00000080 >-#define GFS2_DIF_SYNC 0x00000100 >-#define GFS2_DIF_SYSTEM 0x00000200 /* New in gfs2 */ >-#define GFS2_DIF_TRUNC_IN_PROG 0x20000000 /* New in gfs2 */ >-#define GFS2_DIF_INHERIT_DIRECTIO 0x40000000 >-#define GFS2_DIF_INHERIT_JDATA 0x80000000 >- >-struct gfs2_dinode { >- struct gfs2_meta_header di_header; >- >- struct gfs2_inum di_num; >- >- __be32 di_mode; /* mode of file */ >- __be32 di_uid; /* owner's user id */ >- __be32 di_gid; /* owner's group id */ >- __be32 di_nlink; /* number of links to this file */ >- __be64 di_size; /* number of bytes in file */ >- __be64 di_blocks; /* number of blocks in file */ >- __be64 di_atime; /* time last accessed */ >- __be64 di_mtime; /* time last modified */ >- __be64 di_ctime; /* time last changed */ >- __be32 di_major; /* device major number */ >- __be32 di_minor; /* device minor number */ >- >- /* This section varies from gfs1. Padding added to align with >- * remainder of dinode >- */ >- __be64 di_goal_meta; /* rgrp to alloc from next */ >- __be64 di_goal_data; /* data block goal */ >- __be64 di_generation; /* generation number for NFS */ >- >- __be32 di_flags; /* GFS2_DIF_... */ >- __be32 di_payload_format; /* GFS2_FORMAT_... */ >- __u16 __pad1; /* Was ditype in gfs1 */ >- __be16 di_height; /* height of metadata */ >- __u32 __pad2; /* Unused incarnation number from gfs1 */ >- >- /* These only apply to directories */ >- __u16 __pad3; /* Padding */ >- __be16 di_depth; /* Number of bits in the table */ >- __be32 di_entries; /* The number of entries in the directory */ >- >- struct gfs2_inum __pad4; /* Unused even in current gfs1 */ >- >- __be64 di_eattr; /* extended attribute block number */ >- >- __u8 di_reserved[56]; >-}; >- >-/* >- * directory structure - many of these per directory file >- */ >- >-#define GFS2_FNAMESIZE 255 >-#define GFS2_DIRENT_SIZE(name_len) ((sizeof(struct gfs2_dirent) + (name_len) + 7) & ~7) >- >-struct gfs2_dirent { >- struct gfs2_inum de_inum; >- __be32 de_hash; >- __be16 de_rec_len; >- __be16 de_name_len; >- __be16 de_type; >- __u8 __pad[14]; >-}; >- >-/* >- * Header of leaf directory nodes >- */ >- >-struct gfs2_leaf { >- struct gfs2_meta_header lf_header; >- >- __be16 lf_depth; /* Depth of leaf */ >- __be16 lf_entries; /* Number of dirents in leaf */ >- __be32 lf_dirent_format; /* Format of the dirents */ >- __be64 lf_next; /* Next leaf, if overflow */ >- >- __u8 lf_reserved[64]; >-}; >- >-/* >- * Extended attribute header format >- */ >- >-#define GFS2_EA_MAX_NAME_LEN 255 >-#define GFS2_EA_MAX_DATA_LEN 65536 >- >-#define GFS2_EATYPE_UNUSED 0 >-#define GFS2_EATYPE_USR 1 >-#define GFS2_EATYPE_SYS 2 >-#define GFS2_EATYPE_SECURITY 3 >- >-#define GFS2_EATYPE_LAST 3 >-#define GFS2_EATYPE_VALID(x) ((x) <= GFS2_EATYPE_LAST) >- >-#define GFS2_EAFLAG_LAST 0x01 /* last ea in block */ >- >-struct gfs2_ea_header { >- __be32 ea_rec_len; >- __be32 ea_data_len; >- __u8 ea_name_len; /* no NULL pointer after the string */ >- __u8 ea_type; /* GFS2_EATYPE_... */ >- __u8 ea_flags; /* GFS2_EAFLAG_... */ >- __u8 ea_num_ptrs; >- __u32 __pad; >-}; >- >-/* >- * Log header structure >- */ >- >-#define GFS2_LOG_HEAD_UNMOUNT 0x00000001 /* log is clean */ >- >-struct gfs2_log_header { >- struct gfs2_meta_header lh_header; >- >- __be64 lh_sequence; /* Sequence number of this transaction */ >- __be32 lh_flags; /* GFS2_LOG_HEAD_... */ >- __be32 lh_tail; /* Block number of log tail */ >- __be32 lh_blkno; >- __be32 lh_hash; >-}; >- >-/* >- * Log type descriptor >- */ >- >-#define GFS2_LOG_DESC_METADATA 300 >-/* ld_data1 is the number of metadata blocks in the descriptor. >- ld_data2 is unused. */ >- >-#define GFS2_LOG_DESC_REVOKE 301 >-/* ld_data1 is the number of revoke blocks in the descriptor. >- ld_data2 is unused. */ >- >-#define GFS2_LOG_DESC_JDATA 302 >-/* ld_data1 is the number of data blocks in the descriptor. >- ld_data2 is unused. */ >- >-struct gfs2_log_descriptor { >- struct gfs2_meta_header ld_header; >- >- __be32 ld_type; /* GFS2_LOG_DESC_... */ >- __be32 ld_length; /* Number of buffers in this chunk */ >- __be32 ld_data1; /* descriptor-specific field */ >- __be32 ld_data2; /* descriptor-specific field */ >- >- __u8 ld_reserved[32]; >-}; >- >-/* >- * Inum Range >- * Describe a range of formal inode numbers allocated to >- * one machine to assign to inodes. >- */ >- >-#define GFS2_INUM_QUANTUM 1048576 >- >-struct gfs2_inum_range { >- __be64 ir_start; >- __be64 ir_length; >-}; >- >-/* >- * Statfs change >- * Describes an change to the pool of free and allocated >- * blocks. >- */ >- >-struct gfs2_statfs_change { >- __be64 sc_total; >- __be64 sc_free; >- __be64 sc_dinodes; >-}; >- >-/* >- * Quota change >- * Describes an allocation change for a particular >- * user or group. >- */ >- >-#define GFS2_QCF_USER 0x00000001 >- >-struct gfs2_quota_change { >- __be64 qc_change; >- __be32 qc_flags; /* GFS2_QCF_... */ >- __be32 qc_id; >-}; >- >-#ifdef __KERNEL__ >-/* Translation functions */ >- >-extern void gfs2_inum_in(struct gfs2_inum *no, const void *buf); >-extern void gfs2_inum_out(const struct gfs2_inum *no, void *buf); >-extern void gfs2_sb_in(struct gfs2_sb *sb, const void *buf); >-extern void gfs2_rindex_in(struct gfs2_rindex *ri, const void *buf); >-extern void gfs2_rindex_out(const struct gfs2_rindex *ri, void *buf); >-extern void gfs2_rgrp_in(struct gfs2_rgrp *rg, const void *buf); >-extern void gfs2_rgrp_out(const struct gfs2_rgrp *rg, void *buf); >-extern void gfs2_quota_in(struct gfs2_quota *qu, const void *buf); >-extern void gfs2_quota_out(const struct gfs2_quota *qu, void *buf); >-extern void gfs2_dinode_in(struct gfs2_dinode *di, const void *buf); >-extern void gfs2_dinode_out(const struct gfs2_dinode *di, void *buf); >-extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf); >-extern void gfs2_ea_header_out(const struct gfs2_ea_header *ea, void *buf); >-extern void gfs2_log_header_in(struct gfs2_log_header *lh, const void *buf); >-extern void gfs2_inum_range_in(struct gfs2_inum_range *ir, const void *buf); >-extern void gfs2_inum_range_out(const struct gfs2_inum_range *ir, void *buf); >-extern void gfs2_statfs_change_in(struct gfs2_statfs_change *sc, const void *buf); >-extern void gfs2_statfs_change_out(const struct gfs2_statfs_change *sc, void *buf); >-extern void gfs2_quota_change_in(struct gfs2_quota_change *qc, const void *buf); >- >-/* Printing functions */ >- >-extern void gfs2_rindex_print(const struct gfs2_rindex *ri); >-extern void gfs2_dinode_print(const struct gfs2_dinode *di); >- >-#endif /* __KERNEL__ */ >- >-#endif /* __GFS2_ONDISK_DOT_H__ */ >Index: gfs2_kp/fs/gfs2/locking/nolock/Makefile >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ gfs2_kp/fs/gfs2/locking/nolock/Makefile 2007-02-07 16:04:06.643999386 -0600 >@@ -0,0 +1,3 @@ >+obj-$(CONFIG_GFS2_FS_LOCKING_NOLOCK) += lock_nolock.o >+lock_nolock-y := main.o >+ >Index: gfs2_kp/fs/gfs2/locking/nolock/main.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ gfs2_kp/fs/gfs2/locking/nolock/main.c 2007-02-07 16:04:06.647999430 -0600 >@@ -0,0 +1,246 @@ >+/* >+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. >+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. >+ * >+ * This copyrighted material is made available to anyone wishing to use, >+ * modify, copy, or redistribute it subject to the terms and conditions >+ * of the GNU General Public License version 2. >+ */ >+ >+#include <linux/module.h> >+#include <linux/slab.h> >+#include <linux/module.h> >+#include <linux/init.h> >+#include <linux/types.h> >+#include <linux/fs.h> >+#include <linux/smp_lock.h> >+#include <linux/lm_interface.h> >+ >+struct nolock_lockspace { >+ unsigned int nl_lvb_size; >+}; >+ >+static const struct lm_lockops nolock_ops; >+ >+static int nolock_mount(char *table_name, char *host_data, >+ lm_callback_t cb, void *cb_data, >+ unsigned int min_lvb_size, int flags, >+ struct lm_lockstruct *lockstruct, >+ struct kobject *fskobj) >+{ >+ char *c; >+ unsigned int jid; >+ struct nolock_lockspace *nl; >+ >+ c = strstr(host_data, "jid="); >+ if (!c) >+ jid = 0; >+ else { >+ c += 4; >+ sscanf(c, "%u", &jid); >+ } >+ >+ nl = kzalloc(sizeof(struct nolock_lockspace), GFP_KERNEL); >+ if (!nl) >+ return -ENOMEM; >+ >+ nl->nl_lvb_size = min_lvb_size; >+ >+ lockstruct->ls_jid = jid; >+ lockstruct->ls_first = 1; >+ lockstruct->ls_lvb_size = min_lvb_size; >+ lockstruct->ls_lockspace = nl; >+ lockstruct->ls_ops = &nolock_ops; >+ lockstruct->ls_flags = LM_LSFLAG_LOCAL; >+ >+ return 0; >+} >+ >+static void nolock_others_may_mount(void *lockspace) >+{ >+} >+ >+static void nolock_unmount(void *lockspace) >+{ >+ struct nolock_lockspace *nl = lockspace; >+ kfree(nl); >+} >+ >+static void nolock_withdraw(void *lockspace) >+{ >+} >+ >+/** >+ * nolock_get_lock - get a lm_lock_t given a descripton of the lock >+ * @lockspace: the lockspace the lock lives in >+ * @name: the name of the lock >+ * @lockp: return the lm_lock_t here >+ * >+ * Returns: 0 on success, -EXXX on failure >+ */ >+ >+static int nolock_get_lock(void *lockspace, struct lm_lockname *name, >+ void **lockp) >+{ >+ *lockp = lockspace; >+ return 0; >+} >+ >+/** >+ * nolock_put_lock - get rid of a lock structure >+ * @lock: the lock to throw away >+ * >+ */ >+ >+static void nolock_put_lock(void *lock) >+{ >+} >+ >+/** >+ * nolock_lock - acquire a lock >+ * @lock: the lock to manipulate >+ * @cur_state: the current state >+ * @req_state: the requested state >+ * @flags: modifier flags >+ * >+ * Returns: A bitmap of LM_OUT_* >+ */ >+ >+static unsigned int nolock_lock(void *lock, unsigned int cur_state, >+ unsigned int req_state, unsigned int flags) >+{ >+ return req_state | LM_OUT_CACHEABLE; >+} >+ >+/** >+ * nolock_unlock - unlock a lock >+ * @lock: the lock to manipulate >+ * @cur_state: the current state >+ * >+ * Returns: 0 >+ */ >+ >+static unsigned int nolock_unlock(void *lock, unsigned int cur_state) >+{ >+ return 0; >+} >+ >+static void nolock_cancel(void *lock) >+{ >+} >+ >+/** >+ * nolock_hold_lvb - hold on to a lock value block >+ * @lock: the lock the LVB is associated with >+ * @lvbp: return the lm_lvb_t here >+ * >+ * Returns: 0 on success, -EXXX on failure >+ */ >+ >+static int nolock_hold_lvb(void *lock, char **lvbp) >+{ >+ struct nolock_lockspace *nl = lock; >+ int error = 0; >+ >+ *lvbp = kzalloc(nl->nl_lvb_size, GFP_KERNEL); >+ if (!*lvbp) >+ error = -ENOMEM; >+ >+ return error; >+} >+ >+/** >+ * nolock_unhold_lvb - release a LVB >+ * @lock: the lock the LVB is associated with >+ * @lvb: the lock value block >+ * >+ */ >+ >+static void nolock_unhold_lvb(void *lock, char *lvb) >+{ >+ kfree(lvb); >+} >+ >+static int nolock_plock_get(void *lockspace, struct lm_lockname *name, >+ struct file *file, struct file_lock *fl) >+{ >+ struct file_lock tmp; >+ int ret; >+ >+ ret = posix_test_lock(file, fl, &tmp); >+ fl->fl_type = F_UNLCK; >+ if (ret) >+ memcpy(fl, &tmp, sizeof(struct file_lock)); >+ >+ return 0; >+} >+ >+static int nolock_plock(void *lockspace, struct lm_lockname *name, >+ struct file *file, int cmd, struct file_lock *fl) >+{ >+ int error; >+ error = posix_lock_file_wait(file, fl); >+ return error; >+} >+ >+static int nolock_punlock(void *lockspace, struct lm_lockname *name, >+ struct file *file, struct file_lock *fl) >+{ >+ int error; >+ error = posix_lock_file_wait(file, fl); >+ return error; >+} >+ >+static void nolock_recovery_done(void *lockspace, unsigned int jid, >+ unsigned int message) >+{ >+} >+ >+static const struct lm_lockops nolock_ops = { >+ .lm_proto_name = "lock_nolock", >+ .lm_mount = nolock_mount, >+ .lm_others_may_mount = nolock_others_may_mount, >+ .lm_unmount = nolock_unmount, >+ .lm_withdraw = nolock_withdraw, >+ .lm_get_lock = nolock_get_lock, >+ .lm_put_lock = nolock_put_lock, >+ .lm_lock = nolock_lock, >+ .lm_unlock = nolock_unlock, >+ .lm_cancel = nolock_cancel, >+ .lm_hold_lvb = nolock_hold_lvb, >+ .lm_unhold_lvb = nolock_unhold_lvb, >+ .lm_plock_get = nolock_plock_get, >+ .lm_plock = nolock_plock, >+ .lm_punlock = nolock_punlock, >+ .lm_recovery_done = nolock_recovery_done, >+ .lm_owner = THIS_MODULE, >+}; >+ >+static int __init init_nolock(void) >+{ >+ int error; >+ >+ error = gfs2_register_lockproto(&nolock_ops); >+ if (error) { >+ printk(KERN_WARNING >+ "lock_nolock: can't register protocol: %d\n", error); >+ return error; >+ } >+ >+ printk(KERN_INFO >+ "Lock_Nolock (built %s %s) installed\n", __DATE__, __TIME__); >+ return 0; >+} >+ >+static void __exit exit_nolock(void) >+{ >+ gfs2_unregister_lockproto(&nolock_ops); >+} >+ >+module_init(init_nolock); >+module_exit(exit_nolock); >+ >+MODULE_DESCRIPTION("GFS Nolock Locking Module"); >+MODULE_AUTHOR("Red Hat, Inc."); >+MODULE_LICENSE("GPL"); >+ >Index: gfs2_kp/fs/gfs2/ops_super.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/ops_super.c 2007-02-07 16:04:03.671966523 -0600 >+++ gfs2_kp/fs/gfs2/ops_super.c 2007-02-07 16:04:06.736000403 -0600 >@@ -273,9 +273,10 @@ gfs2_unlockfs(struct super_block *sb) > */ > > static int >-gfs2_statfs(struct super_block *sb, struct kstatfs *buf) >+gfs2_statfs(struct dentry *dentry, struct kstatfs *buf) > { > ENTER(G2FN_STATFS) >+ struct super_block *sb = dentry->d_inode->i_sb; > struct gfs2_sbd *sdp = get_v2sdp(sb); > struct gfs2_statfs_change sc; > int error; >Index: gfs2_kp/fs/gfs2/ioctl.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/ioctl.c 2007-02-07 16:04:03.055959715 -0600 >+++ gfs2_kp/fs/gfs2/ioctl.c 2007-02-07 16:04:07.024003589 -0600 >@@ -19,7 +19,8 @@ > #include <linux/completion.h> > #include <linux/buffer_head.h> > #include <asm/uaccess.h> >-#include <linux/gfs2_ioctl.h> >+ >+#include "gfs2_ioctl.h" > > #include "gfs2.h" > #include "bmap.h" >Index: gfs2_kp/fs/gfs2/util.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/util.c 2007-02-07 16:04:03.867968690 -0600 >+++ gfs2_kp/fs/gfs2/util.c 2007-02-07 16:04:07.028003633 -0600 >@@ -28,9 +28,9 @@ uint32_t gfs2_random_number; > > unsigned long gfs2_malloc_warning = 0; > >-kmem_cache_t *gfs2_glock_cachep = NULL; >-kmem_cache_t *gfs2_inode_cachep = NULL; >-kmem_cache_t *gfs2_bufdata_cachep = NULL; >+struct kmem_cache *gfs2_glock_cachep = NULL; >+struct kmem_cache *gfs2_inode_cachep = NULL; >+struct kmem_cache *gfs2_bufdata_cachep = NULL; > > /** > * gfs2_random - Generate a random 32-bit number >Index: gfs2_kp/fs/gfs2/util.h >=================================================================== >--- gfs2_kp.orig/fs/gfs2/util.h 2007-02-07 16:04:03.879968822 -0600 >+++ gfs2_kp/fs/gfs2/util.h 2007-02-07 16:04:07.028003633 -0600 >@@ -14,6 +14,14 @@ > #ifndef __UTIL_DOT_H__ > #define __UTIL_DOT_H__ > >+#define fs_printk(level, fs, fmt, arg...) \ >+ printk(level "GFS2: fsid=%s: " fmt , (fs)->sd_fsname , ## arg) >+ >+#define fs_warn(fs, fmt, arg...) \ >+ fs_printk(KERN_WARNING , fs , fmt , ## arg) >+ >+#define fs_err(fs, fmt, arg...) \ >+ fs_printk(KERN_ERR, fs , fmt , ## arg) > > /* Utility functions */ > >@@ -291,9 +299,9 @@ for (;;) { \ > yield(); \ > } > >-extern kmem_cache_t *gfs2_glock_cachep; >-extern kmem_cache_t *gfs2_inode_cachep; >-extern kmem_cache_t *gfs2_bufdata_cachep; >+extern struct kmem_cache *gfs2_glock_cachep; >+extern struct kmem_cache *gfs2_inode_cachep; >+extern struct kmem_cache *gfs2_bufdata_cachep; > > > struct gfs2_user_buffer { >Index: gfs2_kp/fs/gfs2/locking/dlm/lock.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ gfs2_kp/fs/gfs2/locking/dlm/lock.c 2007-02-07 16:04:07.028003633 -0600 >@@ -0,0 +1,524 @@ >+/* >+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. >+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. >+ * >+ * This copyrighted material is made available to anyone wishing to use, >+ * modify, copy, or redistribute it subject to the terms and conditions >+ * of the GNU General Public License version 2. >+ */ >+ >+#include "lock_dlm.h" >+ >+static char junk_lvb[GDLM_LVB_SIZE]; >+ >+static void queue_complete(struct gdlm_lock *lp) >+{ >+ struct gdlm_ls *ls = lp->ls; >+ >+ clear_bit(LFL_ACTIVE, &lp->flags); >+ >+ spin_lock(&ls->async_lock); >+ list_add_tail(&lp->clist, &ls->complete); >+ spin_unlock(&ls->async_lock); >+ wake_up(&ls->thread_wait); >+} >+ >+static inline void gdlm_ast(void *astarg) >+{ >+ queue_complete(astarg); >+} >+ >+static inline void gdlm_bast(void *astarg, int mode) >+{ >+ struct gdlm_lock *lp = astarg; >+ struct gdlm_ls *ls = lp->ls; >+ >+ if (!mode) { >+ printk(KERN_INFO "lock_dlm: bast mode zero %x,%llx\n", >+ lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number); >+ return; >+ } >+ >+ spin_lock(&ls->async_lock); >+ if (!lp->bast_mode) { >+ list_add_tail(&lp->blist, &ls->blocking); >+ lp->bast_mode = mode; >+ } else if (lp->bast_mode < mode) >+ lp->bast_mode = mode; >+ spin_unlock(&ls->async_lock); >+ wake_up(&ls->thread_wait); >+} >+ >+void gdlm_queue_delayed(struct gdlm_lock *lp) >+{ >+ struct gdlm_ls *ls = lp->ls; >+ >+ spin_lock(&ls->async_lock); >+ list_add_tail(&lp->delay_list, &ls->delayed); >+ spin_unlock(&ls->async_lock); >+} >+ >+/* convert gfs lock-state to dlm lock-mode */ >+ >+static s16 make_mode(s16 lmstate) >+{ >+ switch (lmstate) { >+ case LM_ST_UNLOCKED: >+ return DLM_LOCK_NL; >+ case LM_ST_EXCLUSIVE: >+ return DLM_LOCK_EX; >+ case LM_ST_DEFERRED: >+ return DLM_LOCK_CW; >+ case LM_ST_SHARED: >+ return DLM_LOCK_PR; >+ } >+ gdlm_assert(0, "unknown LM state %d", lmstate); >+ return -1; >+} >+ >+/* convert dlm lock-mode to gfs lock-state */ >+ >+s16 gdlm_make_lmstate(s16 dlmmode) >+{ >+ switch (dlmmode) { >+ case DLM_LOCK_IV: >+ case DLM_LOCK_NL: >+ return LM_ST_UNLOCKED; >+ case DLM_LOCK_EX: >+ return LM_ST_EXCLUSIVE; >+ case DLM_LOCK_CW: >+ return LM_ST_DEFERRED; >+ case DLM_LOCK_PR: >+ return LM_ST_SHARED; >+ } >+ gdlm_assert(0, "unknown DLM mode %d", dlmmode); >+ return -1; >+} >+ >+/* verify agreement with GFS on the current lock state, NB: DLM_LOCK_NL and >+ DLM_LOCK_IV are both considered LM_ST_UNLOCKED by GFS. */ >+ >+static void check_cur_state(struct gdlm_lock *lp, unsigned int cur_state) >+{ >+ s16 cur = make_mode(cur_state); >+ if (lp->cur != DLM_LOCK_IV) >+ gdlm_assert(lp->cur == cur, "%d, %d", lp->cur, cur); >+} >+ >+static inline unsigned int make_flags(struct gdlm_lock *lp, >+ unsigned int gfs_flags, >+ s16 cur, s16 req) >+{ >+ unsigned int lkf = 0; >+ >+ if (gfs_flags & LM_FLAG_TRY) >+ lkf |= DLM_LKF_NOQUEUE; >+ >+ if (gfs_flags & LM_FLAG_TRY_1CB) { >+ lkf |= DLM_LKF_NOQUEUE; >+ lkf |= DLM_LKF_NOQUEUEBAST; >+ } >+ >+ if (gfs_flags & LM_FLAG_PRIORITY) { >+ lkf |= DLM_LKF_NOORDER; >+ lkf |= DLM_LKF_HEADQUE; >+ } >+ >+ if (gfs_flags & LM_FLAG_ANY) { >+ if (req == DLM_LOCK_PR) >+ lkf |= DLM_LKF_ALTCW; >+ else if (req == DLM_LOCK_CW) >+ lkf |= DLM_LKF_ALTPR; >+ } >+ >+ if (lp->lksb.sb_lkid != 0) { >+ lkf |= DLM_LKF_CONVERT; >+ >+ /* Conversion deadlock avoidance by DLM */ >+ >+ if (!test_bit(LFL_FORCE_PROMOTE, &lp->flags) && >+ !(lkf & DLM_LKF_NOQUEUE) && >+ cur > DLM_LOCK_NL && req > DLM_LOCK_NL && cur != req) >+ lkf |= DLM_LKF_CONVDEADLK; >+ } >+ >+ if (lp->lvb) >+ lkf |= DLM_LKF_VALBLK; >+ >+ return lkf; >+} >+ >+/* make_strname - convert GFS lock numbers to a string */ >+ >+static inline void make_strname(struct lm_lockname *lockname, >+ struct gdlm_strname *str) >+{ >+ sprintf(str->name, "%8x%16llx", lockname->ln_type, >+ (unsigned long long)lockname->ln_number); >+ str->namelen = GDLM_STRNAME_BYTES; >+} >+ >+static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name, >+ struct gdlm_lock **lpp) >+{ >+ struct gdlm_lock *lp; >+ >+ lp = kzalloc(sizeof(struct gdlm_lock), GFP_KERNEL); >+ if (!lp) >+ return -ENOMEM; >+ >+ lp->lockname = *name; >+ lp->ls = ls; >+ lp->cur = DLM_LOCK_IV; >+ lp->lvb = NULL; >+ lp->hold_null = NULL; >+ init_completion(&lp->ast_wait); >+ INIT_LIST_HEAD(&lp->clist); >+ INIT_LIST_HEAD(&lp->blist); >+ INIT_LIST_HEAD(&lp->delay_list); >+ >+ spin_lock(&ls->async_lock); >+ list_add(&lp->all_list, &ls->all_locks); >+ ls->all_locks_count++; >+ spin_unlock(&ls->async_lock); >+ >+ *lpp = lp; >+ return 0; >+} >+ >+void gdlm_delete_lp(struct gdlm_lock *lp) >+{ >+ struct gdlm_ls *ls = lp->ls; >+ >+ spin_lock(&ls->async_lock); >+ if (!list_empty(&lp->clist)) >+ list_del_init(&lp->clist); >+ if (!list_empty(&lp->blist)) >+ list_del_init(&lp->blist); >+ if (!list_empty(&lp->delay_list)) >+ list_del_init(&lp->delay_list); >+ gdlm_assert(!list_empty(&lp->all_list), "%x,%llx", lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number); >+ list_del_init(&lp->all_list); >+ ls->all_locks_count--; >+ spin_unlock(&ls->async_lock); >+ >+ kfree(lp); >+} >+ >+int gdlm_get_lock(void *lockspace, struct lm_lockname *name, >+ void **lockp) >+{ >+ struct gdlm_lock *lp; >+ int error; >+ >+ error = gdlm_create_lp(lockspace, name, &lp); >+ >+ *lockp = lp; >+ return error; >+} >+ >+void gdlm_put_lock(void *lock) >+{ >+ gdlm_delete_lp(lock); >+} >+ >+unsigned int gdlm_do_lock(struct gdlm_lock *lp) >+{ >+ struct gdlm_ls *ls = lp->ls; >+ struct gdlm_strname str; >+ int error, bast = 1; >+ >+ /* >+ * When recovery is in progress, delay lock requests for submission >+ * once recovery is done. Requests for recovery (NOEXP) and unlocks >+ * can pass. >+ */ >+ >+ if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) && >+ !test_bit(LFL_NOBLOCK, &lp->flags) && lp->req != DLM_LOCK_NL) { >+ gdlm_queue_delayed(lp); >+ return LM_OUT_ASYNC; >+ } >+ >+ /* >+ * Submit the actual lock request. >+ */ >+ >+ if (test_bit(LFL_NOBAST, &lp->flags)) >+ bast = 0; >+ >+ make_strname(&lp->lockname, &str); >+ >+ set_bit(LFL_ACTIVE, &lp->flags); >+ >+ log_debug("lk %x,%llx id %x %d,%d %x", lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number, lp->lksb.sb_lkid, >+ lp->cur, lp->req, lp->lkf); >+ >+ error = dlm_lock(ls->dlm_lockspace, lp->req, &lp->lksb, lp->lkf, >+ str.name, str.namelen, 0, gdlm_ast, lp, >+ bast ? gdlm_bast : NULL); >+ >+ if ((error == -EAGAIN) && (lp->lkf & DLM_LKF_NOQUEUE)) { >+ lp->lksb.sb_status = -EAGAIN; >+ queue_complete(lp); >+ error = 0; >+ } >+ >+ if (error) { >+ log_debug("%s: gdlm_lock %x,%llx err=%d cur=%d req=%d lkf=%x " >+ "flags=%lx", ls->fsname, lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number, error, >+ lp->cur, lp->req, lp->lkf, lp->flags); >+ return LM_OUT_ERROR; >+ } >+ return LM_OUT_ASYNC; >+} >+ >+static unsigned int gdlm_do_unlock(struct gdlm_lock *lp) >+{ >+ struct gdlm_ls *ls = lp->ls; >+ unsigned int lkf = 0; >+ int error; >+ >+ set_bit(LFL_DLM_UNLOCK, &lp->flags); >+ set_bit(LFL_ACTIVE, &lp->flags); >+ >+ if (lp->lvb) >+ lkf = DLM_LKF_VALBLK; >+ >+ log_debug("un %x,%llx %x %d %x", lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number, >+ lp->lksb.sb_lkid, lp->cur, lkf); >+ >+ error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, lkf, NULL, lp); >+ >+ if (error) { >+ log_debug("%s: gdlm_unlock %x,%llx err=%d cur=%d req=%d lkf=%x " >+ "flags=%lx", ls->fsname, lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number, error, >+ lp->cur, lp->req, lp->lkf, lp->flags); >+ return LM_OUT_ERROR; >+ } >+ return LM_OUT_ASYNC; >+} >+ >+unsigned int gdlm_lock(void *lock, unsigned int cur_state, >+ unsigned int req_state, unsigned int flags) >+{ >+ struct gdlm_lock *lp = lock; >+ >+ clear_bit(LFL_DLM_CANCEL, &lp->flags); >+ if (flags & LM_FLAG_NOEXP) >+ set_bit(LFL_NOBLOCK, &lp->flags); >+ >+ check_cur_state(lp, cur_state); >+ lp->req = make_mode(req_state); >+ lp->lkf = make_flags(lp, flags, lp->cur, lp->req); >+ >+ return gdlm_do_lock(lp); >+} >+ >+unsigned int gdlm_unlock(void *lock, unsigned int cur_state) >+{ >+ struct gdlm_lock *lp = lock; >+ >+ clear_bit(LFL_DLM_CANCEL, &lp->flags); >+ if (lp->cur == DLM_LOCK_IV) >+ return 0; >+ return gdlm_do_unlock(lp); >+} >+ >+void gdlm_cancel(void *lock) >+{ >+ struct gdlm_lock *lp = lock; >+ struct gdlm_ls *ls = lp->ls; >+ int error, delay_list = 0; >+ >+ if (test_bit(LFL_DLM_CANCEL, &lp->flags)) >+ return; >+ >+ log_info("gdlm_cancel %x,%llx flags %lx", lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number, lp->flags); >+ >+ spin_lock(&ls->async_lock); >+ if (!list_empty(&lp->delay_list)) { >+ list_del_init(&lp->delay_list); >+ delay_list = 1; >+ } >+ spin_unlock(&ls->async_lock); >+ >+ if (delay_list) { >+ set_bit(LFL_CANCEL, &lp->flags); >+ set_bit(LFL_ACTIVE, &lp->flags); >+ queue_complete(lp); >+ return; >+ } >+ >+ if (!test_bit(LFL_ACTIVE, &lp->flags) || >+ test_bit(LFL_DLM_UNLOCK, &lp->flags)) { >+ log_info("gdlm_cancel skip %x,%llx flags %lx", >+ lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number, lp->flags); >+ return; >+ } >+ >+ /* the lock is blocked in the dlm */ >+ >+ set_bit(LFL_DLM_CANCEL, &lp->flags); >+ set_bit(LFL_ACTIVE, &lp->flags); >+ >+ error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, DLM_LKF_CANCEL, >+ NULL, lp); >+ >+ log_info("gdlm_cancel rv %d %x,%llx flags %lx", error, >+ lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number, lp->flags); >+ >+ if (error == -EBUSY) >+ clear_bit(LFL_DLM_CANCEL, &lp->flags); >+} >+ >+static int gdlm_add_lvb(struct gdlm_lock *lp) >+{ >+ char *lvb; >+ >+ lvb = kzalloc(GDLM_LVB_SIZE, GFP_KERNEL); >+ if (!lvb) >+ return -ENOMEM; >+ >+ lp->lksb.sb_lvbptr = lvb; >+ lp->lvb = lvb; >+ return 0; >+} >+ >+static void gdlm_del_lvb(struct gdlm_lock *lp) >+{ >+ kfree(lp->lvb); >+ lp->lvb = NULL; >+ lp->lksb.sb_lvbptr = NULL; >+} >+ >+/* This can do a synchronous dlm request (requiring a lock_dlm thread to get >+ the completion) because gfs won't call hold_lvb() during a callback (from >+ the context of a lock_dlm thread). */ >+ >+static int hold_null_lock(struct gdlm_lock *lp) >+{ >+ struct gdlm_lock *lpn = NULL; >+ int error; >+ >+ if (lp->hold_null) { >+ printk(KERN_INFO "lock_dlm: lvb already held\n"); >+ return 0; >+ } >+ >+ error = gdlm_create_lp(lp->ls, &lp->lockname, &lpn); >+ if (error) >+ goto out; >+ >+ lpn->lksb.sb_lvbptr = junk_lvb; >+ lpn->lvb = junk_lvb; >+ >+ lpn->req = DLM_LOCK_NL; >+ lpn->lkf = DLM_LKF_VALBLK | DLM_LKF_EXPEDITE; >+ set_bit(LFL_NOBAST, &lpn->flags); >+ set_bit(LFL_INLOCK, &lpn->flags); >+ >+ init_completion(&lpn->ast_wait); >+ gdlm_do_lock(lpn); >+ wait_for_completion(&lpn->ast_wait); >+ error = lpn->lksb.sb_status; >+ if (error) { >+ printk(KERN_INFO "lock_dlm: hold_null_lock dlm error %d\n", >+ error); >+ gdlm_delete_lp(lpn); >+ lpn = NULL; >+ } >+out: >+ lp->hold_null = lpn; >+ return error; >+} >+ >+/* This cannot do a synchronous dlm request (requiring a lock_dlm thread to get >+ the completion) because gfs may call unhold_lvb() during a callback (from >+ the context of a lock_dlm thread) which could cause a deadlock since the >+ other lock_dlm thread could be engaged in recovery. */ >+ >+static void unhold_null_lock(struct gdlm_lock *lp) >+{ >+ struct gdlm_lock *lpn = lp->hold_null; >+ >+ gdlm_assert(lpn, "%x,%llx", lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number); >+ lpn->lksb.sb_lvbptr = NULL; >+ lpn->lvb = NULL; >+ set_bit(LFL_UNLOCK_DELETE, &lpn->flags); >+ gdlm_do_unlock(lpn); >+ lp->hold_null = NULL; >+} >+ >+/* Acquire a NL lock because gfs requires the value block to remain >+ intact on the resource while the lvb is "held" even if it's holding no locks >+ on the resource. */ >+ >+int gdlm_hold_lvb(void *lock, char **lvbp) >+{ >+ struct gdlm_lock *lp = lock; >+ int error; >+ >+ error = gdlm_add_lvb(lp); >+ if (error) >+ return error; >+ >+ *lvbp = lp->lvb; >+ >+ error = hold_null_lock(lp); >+ if (error) >+ gdlm_del_lvb(lp); >+ >+ return error; >+} >+ >+void gdlm_unhold_lvb(void *lock, char *lvb) >+{ >+ struct gdlm_lock *lp = lock; >+ >+ unhold_null_lock(lp); >+ gdlm_del_lvb(lp); >+} >+ >+void gdlm_submit_delayed(struct gdlm_ls *ls) >+{ >+ struct gdlm_lock *lp, *safe; >+ >+ spin_lock(&ls->async_lock); >+ list_for_each_entry_safe(lp, safe, &ls->delayed, delay_list) { >+ list_del_init(&lp->delay_list); >+ list_add_tail(&lp->delay_list, &ls->submit); >+ } >+ spin_unlock(&ls->async_lock); >+ wake_up(&ls->thread_wait); >+} >+ >+int gdlm_release_all_locks(struct gdlm_ls *ls) >+{ >+ struct gdlm_lock *lp, *safe; >+ int count = 0; >+ >+ spin_lock(&ls->async_lock); >+ list_for_each_entry_safe(lp, safe, &ls->all_locks, all_list) { >+ list_del_init(&lp->all_list); >+ >+ if (lp->lvb && lp->lvb != junk_lvb) >+ kfree(lp->lvb); >+ kfree(lp); >+ count++; >+ } >+ spin_unlock(&ls->async_lock); >+ >+ return count; >+} >+ >Index: gfs2_kp/fs/gfs2/locking/dlm/lock_dlm.h >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ gfs2_kp/fs/gfs2/locking/dlm/lock_dlm.h 2007-02-07 16:04:07.032003677 -0600 >@@ -0,0 +1,187 @@ >+/* >+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. >+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. >+ * >+ * This copyrighted material is made available to anyone wishing to use, >+ * modify, copy, or redistribute it subject to the terms and conditions >+ * of the GNU General Public License version 2. >+ */ >+ >+#ifndef LOCK_DLM_DOT_H >+#define LOCK_DLM_DOT_H >+ >+#include <linux/module.h> >+#include <linux/slab.h> >+#include <linux/spinlock.h> >+#include <linux/module.h> >+#include <linux/types.h> >+#include <linux/string.h> >+#include <linux/list.h> >+#include <linux/socket.h> >+#include <linux/delay.h> >+#include <linux/kthread.h> >+#include <linux/kobject.h> >+#include <linux/fcntl.h> >+#include <linux/wait.h> >+#include <net/sock.h> >+ >+#include <linux/dlm.h> >+#include <linux/lm_interface.h> >+ >+/* >+ * Internally, we prefix things with gdlm_ and GDLM_ (for gfs-dlm) since a >+ * prefix of lock_dlm_ gets awkward. Externally, GFS refers to this module >+ * as "lock_dlm". >+ */ >+ >+#define GDLM_STRNAME_BYTES 24 >+#define GDLM_LVB_SIZE 32 >+#define GDLM_DROP_COUNT 200000 >+#define GDLM_DROP_PERIOD 60 >+#define GDLM_NAME_LEN 128 >+ >+/* GFS uses 12 bytes to identify a resource (32 bit type + 64 bit number). >+ We sprintf these numbers into a 24 byte string of hex values to make them >+ human-readable (to make debugging simpler.) */ >+ >+struct gdlm_strname { >+ unsigned char name[GDLM_STRNAME_BYTES]; >+ unsigned short namelen; >+}; >+ >+enum { >+ DFL_BLOCK_LOCKS = 0, >+ DFL_SPECTATOR = 1, >+ DFL_WITHDRAW = 2, >+}; >+ >+struct gdlm_ls { >+ u32 id; >+ int jid; >+ int first; >+ int first_done; >+ unsigned long flags; >+ struct kobject kobj; >+ char clustername[GDLM_NAME_LEN]; >+ char fsname[GDLM_NAME_LEN]; >+ int fsflags; >+ dlm_lockspace_t *dlm_lockspace; >+ lm_callback_t fscb; >+ struct gfs2_sbd *sdp; >+ int recover_jid; >+ int recover_jid_done; >+ int recover_jid_status; >+ spinlock_t async_lock; >+ struct list_head complete; >+ struct list_head blocking; >+ struct list_head delayed; >+ struct list_head submit; >+ struct list_head all_locks; >+ u32 all_locks_count; >+ wait_queue_head_t wait_control; >+ struct task_struct *thread1; >+ struct task_struct *thread2; >+ wait_queue_head_t thread_wait; >+ unsigned long drop_time; >+ int drop_locks_count; >+ int drop_locks_period; >+}; >+ >+enum { >+ LFL_NOBLOCK = 0, >+ LFL_NOCACHE = 1, >+ LFL_DLM_UNLOCK = 2, >+ LFL_DLM_CANCEL = 3, >+ LFL_SYNC_LVB = 4, >+ LFL_FORCE_PROMOTE = 5, >+ LFL_REREQUEST = 6, >+ LFL_ACTIVE = 7, >+ LFL_INLOCK = 8, >+ LFL_CANCEL = 9, >+ LFL_NOBAST = 10, >+ LFL_HEADQUE = 11, >+ LFL_UNLOCK_DELETE = 12, >+}; >+ >+struct gdlm_lock { >+ struct gdlm_ls *ls; >+ struct lm_lockname lockname; >+ char *lvb; >+ struct dlm_lksb lksb; >+ >+ s16 cur; >+ s16 req; >+ s16 prev_req; >+ u32 lkf; /* dlm flags DLM_LKF_ */ >+ unsigned long flags; /* lock_dlm flags LFL_ */ >+ >+ int bast_mode; /* protected by async_lock */ >+ struct completion ast_wait; >+ >+ struct list_head clist; /* complete */ >+ struct list_head blist; /* blocking */ >+ struct list_head delay_list; /* delayed */ >+ struct list_head all_list; /* all locks for the fs */ >+ struct gdlm_lock *hold_null; /* NL lock for hold_lvb */ >+}; >+ >+#define gdlm_assert(assertion, fmt, args...) \ >+do { \ >+ if (unlikely(!(assertion))) { \ >+ printk(KERN_EMERG "lock_dlm: fatal assertion failed \"%s\"\n" \ >+ "lock_dlm: " fmt "\n", \ >+ #assertion, ##args); \ >+ BUG(); \ >+ } \ >+} while (0) >+ >+#define log_print(lev, fmt, arg...) printk(lev "lock_dlm: " fmt "\n" , ## arg) >+#define log_info(fmt, arg...) log_print(KERN_INFO , fmt , ## arg) >+#define log_error(fmt, arg...) log_print(KERN_ERR , fmt , ## arg) >+#ifdef LOCK_DLM_LOG_DEBUG >+#define log_debug(fmt, arg...) log_print(KERN_DEBUG , fmt , ## arg) >+#else >+#define log_debug(fmt, arg...) >+#endif >+ >+/* sysfs.c */ >+ >+int gdlm_sysfs_init(void); >+void gdlm_sysfs_exit(void); >+int gdlm_kobject_setup(struct gdlm_ls *, struct kobject *); >+void gdlm_kobject_release(struct gdlm_ls *); >+ >+/* thread.c */ >+ >+int gdlm_init_threads(struct gdlm_ls *); >+void gdlm_release_threads(struct gdlm_ls *); >+ >+/* lock.c */ >+ >+s16 gdlm_make_lmstate(s16); >+void gdlm_queue_delayed(struct gdlm_lock *); >+void gdlm_submit_delayed(struct gdlm_ls *); >+int gdlm_release_all_locks(struct gdlm_ls *); >+void gdlm_delete_lp(struct gdlm_lock *); >+unsigned int gdlm_do_lock(struct gdlm_lock *); >+ >+int gdlm_get_lock(void *, struct lm_lockname *, void **); >+void gdlm_put_lock(void *); >+unsigned int gdlm_lock(void *, unsigned int, unsigned int, unsigned int); >+unsigned int gdlm_unlock(void *, unsigned int); >+void gdlm_cancel(void *); >+int gdlm_hold_lvb(void *, char **); >+void gdlm_unhold_lvb(void *, char *); >+ >+/* plock.c */ >+ >+int gdlm_plock_init(void); >+void gdlm_plock_exit(void); >+int gdlm_plock(void *, struct lm_lockname *, struct file *, int, >+ struct file_lock *); >+int gdlm_plock_get(void *, struct lm_lockname *, struct file *, >+ struct file_lock *); >+int gdlm_punlock(void *, struct lm_lockname *, struct file *, >+ struct file_lock *); >+#endif >+ >Index: gfs2_kp/fs/gfs2/locking/dlm/main.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ gfs2_kp/fs/gfs2/locking/dlm/main.c 2007-02-07 16:04:07.056003943 -0600 >@@ -0,0 +1,58 @@ >+/* >+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. >+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. >+ * >+ * This copyrighted material is made available to anyone wishing to use, >+ * modify, copy, or redistribute it subject to the terms and conditions >+ * of the GNU General Public License version 2. >+ */ >+ >+#include <linux/init.h> >+ >+#include "lock_dlm.h" >+ >+extern struct lm_lockops gdlm_ops; >+ >+static int __init init_lock_dlm(void) >+{ >+ int error; >+ >+ error = gfs2_register_lockproto(&gdlm_ops); >+ if (error) { >+ printk(KERN_WARNING "lock_dlm: can't register protocol: %d\n", >+ error); >+ return error; >+ } >+ >+ error = gdlm_sysfs_init(); >+ if (error) { >+ gfs2_unregister_lockproto(&gdlm_ops); >+ return error; >+ } >+ >+ error = gdlm_plock_init(); >+ if (error) { >+ gdlm_sysfs_exit(); >+ gfs2_unregister_lockproto(&gdlm_ops); >+ return error; >+ } >+ >+ printk(KERN_INFO >+ "Lock_DLM (built %s %s) installed\n", __DATE__, __TIME__); >+ return 0; >+} >+ >+static void __exit exit_lock_dlm(void) >+{ >+ gdlm_plock_exit(); >+ gdlm_sysfs_exit(); >+ gfs2_unregister_lockproto(&gdlm_ops); >+} >+ >+module_init(init_lock_dlm); >+module_exit(exit_lock_dlm); >+ >+MODULE_DESCRIPTION("GFS DLM Locking Module"); >+MODULE_AUTHOR("Red Hat, Inc."); >+MODULE_LICENSE("GPL"); >+ >Index: gfs2_kp/fs/gfs2/locking/dlm/Makefile >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ gfs2_kp/fs/gfs2/locking/dlm/Makefile 2007-02-07 16:04:07.056003943 -0600 >@@ -0,0 +1,3 @@ >+obj-$(CONFIG_GFS2_FS_LOCKING_DLM) += lock_dlm.o >+lock_dlm-y := lock.o main.o mount.o sysfs.o thread.o plock.o >+ >Index: gfs2_kp/fs/gfs2/locking/dlm/mount.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ gfs2_kp/fs/gfs2/locking/dlm/mount.c 2007-02-07 16:04:07.060003987 -0600 >@@ -0,0 +1,259 @@ >+/* >+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. >+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. >+ * >+ * This copyrighted material is made available to anyone wishing to use, >+ * modify, copy, or redistribute it subject to the terms and conditions >+ * of the GNU General Public License version 2. >+ */ >+ >+#include "lock_dlm.h" >+ >+const struct lm_lockops gdlm_ops; >+ >+ >+static struct gdlm_ls *init_gdlm(lm_callback_t cb, struct gfs2_sbd *sdp, >+ int flags, char *table_name) >+{ >+ struct gdlm_ls *ls; >+ char buf[256], *p; >+ >+ ls = kzalloc(sizeof(struct gdlm_ls), GFP_KERNEL); >+ if (!ls) >+ return NULL; >+ >+ ls->drop_locks_count = GDLM_DROP_COUNT; >+ ls->drop_locks_period = GDLM_DROP_PERIOD; >+ ls->fscb = cb; >+ ls->sdp = sdp; >+ ls->fsflags = flags; >+ spin_lock_init(&ls->async_lock); >+ INIT_LIST_HEAD(&ls->complete); >+ INIT_LIST_HEAD(&ls->blocking); >+ INIT_LIST_HEAD(&ls->delayed); >+ INIT_LIST_HEAD(&ls->submit); >+ INIT_LIST_HEAD(&ls->all_locks); >+ init_waitqueue_head(&ls->thread_wait); >+ init_waitqueue_head(&ls->wait_control); >+ ls->thread1 = NULL; >+ ls->thread2 = NULL; >+ ls->drop_time = jiffies; >+ ls->jid = -1; >+ >+ strncpy(buf, table_name, 256); >+ buf[255] = '\0'; >+ >+ p = strchr(buf, ':'); >+ if (!p) { >+ log_info("invalid table_name \"%s\"", table_name); >+ kfree(ls); >+ return NULL; >+ } >+ *p = '\0'; >+ p++; >+ >+ strncpy(ls->clustername, buf, GDLM_NAME_LEN); >+ strncpy(ls->fsname, p, GDLM_NAME_LEN); >+ >+ return ls; >+} >+ >+static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir) >+{ >+ char data[256]; >+ char *options, *x, *y; >+ int error = 0; >+ >+ memset(data, 0, 256); >+ strncpy(data, data_arg, 255); >+ >+ for (options = data; (x = strsep(&options, ":")); ) { >+ if (!*x) >+ continue; >+ >+ y = strchr(x, '='); >+ if (y) >+ *y++ = 0; >+ >+ if (!strcmp(x, "jid")) { >+ if (!y) { >+ log_error("need argument to jid"); >+ error = -EINVAL; >+ break; >+ } >+ sscanf(y, "%u", &ls->jid); >+ >+ } else if (!strcmp(x, "first")) { >+ if (!y) { >+ log_error("need argument to first"); >+ error = -EINVAL; >+ break; >+ } >+ sscanf(y, "%u", &ls->first); >+ >+ } else if (!strcmp(x, "id")) { >+ if (!y) { >+ log_error("need argument to id"); >+ error = -EINVAL; >+ break; >+ } >+ sscanf(y, "%u", &ls->id); >+ >+ } else if (!strcmp(x, "nodir")) { >+ if (!y) { >+ log_error("need argument to nodir"); >+ error = -EINVAL; >+ break; >+ } >+ sscanf(y, "%u", nodir); >+ >+ } else { >+ log_error("unkonwn option: %s", x); >+ error = -EINVAL; >+ break; >+ } >+ } >+ >+ return error; >+} >+ >+static int gdlm_mount(char *table_name, char *host_data, >+ lm_callback_t cb, void *cb_data, >+ unsigned int min_lvb_size, int flags, >+ struct lm_lockstruct *lockstruct, >+ struct kobject *fskobj) >+{ >+ struct gdlm_ls *ls; >+ int i; >+ int error = -ENOMEM, nodir = 0; >+ >+ if (min_lvb_size > GDLM_LVB_SIZE) >+ goto out; >+ >+ ls = init_gdlm(cb, cb_data, flags, table_name); >+ if (!ls) >+ goto out; >+ >+ printk("gdlm_mount %d\n",i++); >+ error = make_args(ls, host_data, &nodir); >+ if (error) >+ goto out; >+ >+ printk("gdlm_mount %d\n",i++); >+ error = gdlm_init_threads(ls); >+ if (error) >+ goto out_free; >+ >+ printk("gdlm_mount %d\n",i++); >+ error = gdlm_kobject_setup(ls, fskobj); >+ if (error) >+ goto out_thread; >+ >+ printk("gdlm_mount %d\n",i++); >+ error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname), >+ &ls->dlm_lockspace, >+ nodir ? DLM_LSFL_NODIR : 0, >+ GDLM_LVB_SIZE); >+ if (error) { >+ log_error("dlm_new_lockspace error %d", error); >+ goto out_kobj; >+ } >+ >+ lockstruct->ls_jid = ls->jid; >+ lockstruct->ls_first = ls->first; >+ lockstruct->ls_lockspace = ls; >+ lockstruct->ls_ops = &gdlm_ops; >+ lockstruct->ls_flags = 0; >+ lockstruct->ls_lvb_size = GDLM_LVB_SIZE; >+ return 0; >+ >+out_kobj: >+ gdlm_kobject_release(ls); >+out_thread: >+ gdlm_release_threads(ls); >+out_free: >+ kfree(ls); >+out: >+ printk("gldm_mount error %d\n",error); >+ return error; >+} >+ >+static void gdlm_unmount(void *lockspace) >+{ >+ struct gdlm_ls *ls = lockspace; >+ int rv; >+ >+ log_debug("unmount flags %lx", ls->flags); >+ >+ /* FIXME: serialize unmount and withdraw in case they >+ happen at once. Also, if unmount follows withdraw, >+ wait for withdraw to finish. */ >+ >+ if (test_bit(DFL_WITHDRAW, &ls->flags)) >+ goto out; >+ >+ gdlm_kobject_release(ls); >+ dlm_release_lockspace(ls->dlm_lockspace, 2); >+ gdlm_release_threads(ls); >+ rv = gdlm_release_all_locks(ls); >+ if (rv) >+ log_info("gdlm_unmount: %d stray locks freed", rv); >+out: >+ kfree(ls); >+} >+ >+static void gdlm_recovery_done(void *lockspace, unsigned int jid, >+ unsigned int message) >+{ >+ struct gdlm_ls *ls = lockspace; >+ ls->recover_jid_done = jid; >+ ls->recover_jid_status = message; >+ kobject_uevent(&ls->kobj, KOBJ_CHANGE); >+} >+ >+static void gdlm_others_may_mount(void *lockspace) >+{ >+ struct gdlm_ls *ls = lockspace; >+ ls->first_done = 1; >+ kobject_uevent(&ls->kobj, KOBJ_CHANGE); >+} >+ >+/* Userspace gets the offline uevent, blocks new gfs locks on >+ other mounters, and lets us know (sets WITHDRAW flag). Then, >+ userspace leaves the mount group while we leave the lockspace. */ >+ >+static void gdlm_withdraw(void *lockspace) >+{ >+ struct gdlm_ls *ls = lockspace; >+ >+ kobject_uevent(&ls->kobj, KOBJ_OFFLINE); >+ >+ wait_event_interruptible(ls->wait_control, >+ test_bit(DFL_WITHDRAW, &ls->flags)); >+ >+ dlm_release_lockspace(ls->dlm_lockspace, 2); >+ gdlm_release_threads(ls); >+ gdlm_release_all_locks(ls); >+ gdlm_kobject_release(ls); >+} >+ >+const struct lm_lockops gdlm_ops = { >+ .lm_proto_name = "lock_dlm", >+ .lm_mount = gdlm_mount, >+ .lm_others_may_mount = gdlm_others_may_mount, >+ .lm_unmount = gdlm_unmount, >+ .lm_withdraw = gdlm_withdraw, >+ .lm_get_lock = gdlm_get_lock, >+ .lm_put_lock = gdlm_put_lock, >+ .lm_lock = gdlm_lock, >+ .lm_unlock = gdlm_unlock, >+ .lm_plock = gdlm_plock, >+ .lm_punlock = gdlm_punlock, >+ .lm_plock_get = gdlm_plock_get, >+ .lm_cancel = gdlm_cancel, >+ .lm_hold_lvb = gdlm_hold_lvb, >+ .lm_unhold_lvb = gdlm_unhold_lvb, >+ .lm_recovery_done = gdlm_recovery_done, >+ .lm_owner = THIS_MODULE, >+}; >+ >Index: gfs2_kp/fs/gfs2/locking/dlm/plock.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ gfs2_kp/fs/gfs2/locking/dlm/plock.c 2007-02-07 16:04:07.060003987 -0600 >@@ -0,0 +1,302 @@ >+/* >+ * Copyright (C) 2005 Red Hat, Inc. All rights reserved. >+ * >+ * This copyrighted material is made available to anyone wishing to use, >+ * modify, copy, or redistribute it subject to the terms and conditions >+ * of the GNU General Public License version 2. >+ */ >+ >+#include <linux/miscdevice.h> >+#include <linux/lock_dlm_plock.h> >+#include <linux/poll.h> >+ >+#include "lock_dlm.h" >+ >+ >+static spinlock_t ops_lock; >+static struct list_head send_list; >+static struct list_head recv_list; >+static wait_queue_head_t send_wq; >+static wait_queue_head_t recv_wq; >+ >+struct plock_op { >+ struct list_head list; >+ int done; >+ struct gdlm_plock_info info; >+}; >+ >+static inline void set_version(struct gdlm_plock_info *info) >+{ >+ info->version[0] = GDLM_PLOCK_VERSION_MAJOR; >+ info->version[1] = GDLM_PLOCK_VERSION_MINOR; >+ info->version[2] = GDLM_PLOCK_VERSION_PATCH; >+} >+ >+static int check_version(struct gdlm_plock_info *info) >+{ >+ if ((GDLM_PLOCK_VERSION_MAJOR != info->version[0]) || >+ (GDLM_PLOCK_VERSION_MINOR < info->version[1])) { >+ log_error("plock device version mismatch: " >+ "kernel (%u.%u.%u), user (%u.%u.%u)", >+ GDLM_PLOCK_VERSION_MAJOR, >+ GDLM_PLOCK_VERSION_MINOR, >+ GDLM_PLOCK_VERSION_PATCH, >+ info->version[0], >+ info->version[1], >+ info->version[2]); >+ return -EINVAL; >+ } >+ return 0; >+} >+ >+static void send_op(struct plock_op *op) >+{ >+ set_version(&op->info); >+ INIT_LIST_HEAD(&op->list); >+ spin_lock(&ops_lock); >+ list_add_tail(&op->list, &send_list); >+ spin_unlock(&ops_lock); >+ wake_up(&send_wq); >+} >+ >+int gdlm_plock(void *lockspace, struct lm_lockname *name, >+ struct file *file, int cmd, struct file_lock *fl) >+{ >+ struct gdlm_ls *ls = lockspace; >+ struct plock_op *op; >+ int rv; >+ >+ op = kzalloc(sizeof(*op), GFP_KERNEL); >+ if (!op) >+ return -ENOMEM; >+ >+ op->info.optype = GDLM_PLOCK_OP_LOCK; >+ op->info.pid = fl->fl_pid; >+ op->info.ex = (fl->fl_type == F_WRLCK); >+ op->info.wait = IS_SETLKW(cmd); >+ op->info.fsid = ls->id; >+ op->info.number = name->ln_number; >+ op->info.start = fl->fl_start; >+ op->info.end = fl->fl_end; >+ op->info.owner = (__u64)(long) fl->fl_owner; >+ >+ send_op(op); >+ wait_event(recv_wq, (op->done != 0)); >+ >+ spin_lock(&ops_lock); >+ if (!list_empty(&op->list)) { >+ printk(KERN_INFO "plock op on list\n"); >+ list_del(&op->list); >+ } >+ spin_unlock(&ops_lock); >+ >+ rv = op->info.rv; >+ >+ if (!rv) { >+ if (posix_lock_file_wait(file, fl) < 0) >+ log_error("gdlm_plock: vfs lock error %x,%llx", >+ name->ln_type, >+ (unsigned long long)name->ln_number); >+ } >+ >+ kfree(op); >+ return rv; >+} >+ >+int gdlm_punlock(void *lockspace, struct lm_lockname *name, >+ struct file *file, struct file_lock *fl) >+{ >+ struct gdlm_ls *ls = lockspace; >+ struct plock_op *op; >+ int rv; >+ >+ op = kzalloc(sizeof(*op), GFP_KERNEL); >+ if (!op) >+ return -ENOMEM; >+ >+ if (posix_lock_file_wait(file, fl) < 0) >+ log_error("gdlm_punlock: vfs unlock error %x,%llx", >+ name->ln_type, (unsigned long long)name->ln_number); >+ >+ op->info.optype = GDLM_PLOCK_OP_UNLOCK; >+ op->info.pid = fl->fl_pid; >+ op->info.fsid = ls->id; >+ op->info.number = name->ln_number; >+ op->info.start = fl->fl_start; >+ op->info.end = fl->fl_end; >+ op->info.owner = (__u64)(long) fl->fl_owner; >+ >+ send_op(op); >+ wait_event(recv_wq, (op->done != 0)); >+ >+ spin_lock(&ops_lock); >+ if (!list_empty(&op->list)) { >+ printk(KERN_INFO "punlock op on list\n"); >+ list_del(&op->list); >+ } >+ spin_unlock(&ops_lock); >+ >+ rv = op->info.rv; >+ >+ kfree(op); >+ return rv; >+} >+ >+int gdlm_plock_get(void *lockspace, struct lm_lockname *name, >+ struct file *file, struct file_lock *fl) >+{ >+ struct gdlm_ls *ls = lockspace; >+ struct plock_op *op; >+ int rv; >+ >+ op = kzalloc(sizeof(*op), GFP_KERNEL); >+ if (!op) >+ return -ENOMEM; >+ >+ op->info.optype = GDLM_PLOCK_OP_GET; >+ op->info.pid = fl->fl_pid; >+ op->info.ex = (fl->fl_type == F_WRLCK); >+ op->info.fsid = ls->id; >+ op->info.number = name->ln_number; >+ op->info.start = fl->fl_start; >+ op->info.end = fl->fl_end; >+ >+ send_op(op); >+ wait_event(recv_wq, (op->done != 0)); >+ >+ spin_lock(&ops_lock); >+ if (!list_empty(&op->list)) { >+ printk(KERN_INFO "plock_get op on list\n"); >+ list_del(&op->list); >+ } >+ spin_unlock(&ops_lock); >+ >+ rv = op->info.rv; >+ >+ if (rv == 0) >+ fl->fl_type = F_UNLCK; >+ else if (rv > 0) { >+ fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK; >+ fl->fl_pid = op->info.pid; >+ fl->fl_start = op->info.start; >+ fl->fl_end = op->info.end; >+ } >+ >+ kfree(op); >+ return rv; >+} >+ >+/* a read copies out one plock request from the send list */ >+static ssize_t dev_read(struct file *file, char __user *u, size_t count, >+ loff_t *ppos) >+{ >+ struct gdlm_plock_info info; >+ struct plock_op *op = NULL; >+ >+ if (count < sizeof(info)) >+ return -EINVAL; >+ >+ spin_lock(&ops_lock); >+ if (!list_empty(&send_list)) { >+ op = list_entry(send_list.next, struct plock_op, list); >+ list_move(&op->list, &recv_list); >+ memcpy(&info, &op->info, sizeof(info)); >+ } >+ spin_unlock(&ops_lock); >+ >+ if (!op) >+ return -EAGAIN; >+ >+ if (copy_to_user(u, &info, sizeof(info))) >+ return -EFAULT; >+ return sizeof(info); >+} >+ >+/* a write copies in one plock result that should match a plock_op >+ on the recv list */ >+static ssize_t dev_write(struct file *file, const char __user *u, size_t count, >+ loff_t *ppos) >+{ >+ struct gdlm_plock_info info; >+ struct plock_op *op; >+ int found = 0; >+ >+ if (count != sizeof(info)) >+ return -EINVAL; >+ >+ if (copy_from_user(&info, u, sizeof(info))) >+ return -EFAULT; >+ >+ if (check_version(&info)) >+ return -EINVAL; >+ >+ spin_lock(&ops_lock); >+ list_for_each_entry(op, &recv_list, list) { >+ if (op->info.fsid == info.fsid && op->info.number == info.number && >+ op->info.owner == info.owner) { >+ list_del_init(&op->list); >+ found = 1; >+ op->done = 1; >+ memcpy(&op->info, &info, sizeof(info)); >+ break; >+ } >+ } >+ spin_unlock(&ops_lock); >+ >+ if (found) >+ wake_up(&recv_wq); >+ else >+ printk(KERN_INFO "gdlm dev_write no op %x %llx\n", info.fsid, >+ (unsigned long long)info.number); >+ return count; >+} >+ >+static unsigned int dev_poll(struct file *file, poll_table *wait) >+{ >+ poll_wait(file, &send_wq, wait); >+ >+ spin_lock(&ops_lock); >+ if (!list_empty(&send_list)) { >+ spin_unlock(&ops_lock); >+ return POLLIN | POLLRDNORM; >+ } >+ spin_unlock(&ops_lock); >+ return 0; >+} >+ >+static struct file_operations dev_fops = { >+ .read = dev_read, >+ .write = dev_write, >+ .poll = dev_poll, >+ .owner = THIS_MODULE >+}; >+ >+static struct miscdevice plock_dev_misc = { >+ .minor = MISC_DYNAMIC_MINOR, >+ .name = GDLM_PLOCK_MISC_NAME, >+ .fops = &dev_fops >+}; >+ >+int gdlm_plock_init(void) >+{ >+ int rv; >+ >+ spin_lock_init(&ops_lock); >+ INIT_LIST_HEAD(&send_list); >+ INIT_LIST_HEAD(&recv_list); >+ init_waitqueue_head(&send_wq); >+ init_waitqueue_head(&recv_wq); >+ >+ rv = misc_register(&plock_dev_misc); >+ if (rv) >+ printk(KERN_INFO "gdlm_plock_init: misc_register failed %d", >+ rv); >+ return rv; >+} >+ >+void gdlm_plock_exit(void) >+{ >+ if (misc_deregister(&plock_dev_misc) < 0) >+ printk(KERN_INFO "gdlm_plock_exit: misc_deregister failed"); >+} >+ >Index: gfs2_kp/fs/gfs2/locking/dlm/sysfs.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ gfs2_kp/fs/gfs2/locking/dlm/sysfs.c 2007-02-07 16:04:07.100004429 -0600 >@@ -0,0 +1,239 @@ >+/* >+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. >+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. >+ * >+ * This copyrighted material is made available to anyone wishing to use, >+ * modify, copy, or redistribute it subject to the terms and conditions >+ * of the GNU General Public License version 2. >+ */ >+ >+#include <linux/ctype.h> >+#include <linux/stat.h> >+ >+#include "lock_dlm.h" >+ >+extern struct lm_lockops gdlm_ops; >+ >+static ssize_t proto_name_show(struct gdlm_ls *ls, char *buf) >+{ >+ return sprintf(buf, "%s\n", gdlm_ops.lm_proto_name); >+} >+ >+static ssize_t block_show(struct gdlm_ls *ls, char *buf) >+{ >+ ssize_t ret; >+ int val = 0; >+ >+ if (test_bit(DFL_BLOCK_LOCKS, &ls->flags)) >+ val = 1; >+ ret = sprintf(buf, "%d\n", val); >+ return ret; >+} >+ >+static ssize_t block_store(struct gdlm_ls *ls, const char *buf, size_t len) >+{ >+ ssize_t ret = len; >+ int val; >+ >+ val = simple_strtol(buf, NULL, 0); >+ >+ if (val == 1) >+ set_bit(DFL_BLOCK_LOCKS, &ls->flags); >+ else if (val == 0) { >+ clear_bit(DFL_BLOCK_LOCKS, &ls->flags); >+ gdlm_submit_delayed(ls); >+ } else { >+ ret = -EINVAL; >+ } >+ return ret; >+} >+ >+static ssize_t withdraw_show(struct gdlm_ls *ls, char *buf) >+{ >+ ssize_t ret; >+ int val = 0; >+ >+ if (test_bit(DFL_WITHDRAW, &ls->flags)) >+ val = 1; >+ ret = sprintf(buf, "%d\n", val); >+ return ret; >+} >+ >+static ssize_t withdraw_store(struct gdlm_ls *ls, const char *buf, size_t len) >+{ >+ ssize_t ret = len; >+ int val; >+ >+ val = simple_strtol(buf, NULL, 0); >+ >+ if (val == 1) >+ set_bit(DFL_WITHDRAW, &ls->flags); >+ else >+ ret = -EINVAL; >+ wake_up(&ls->wait_control); >+ return ret; >+} >+ >+static ssize_t id_show(struct gdlm_ls *ls, char *buf) >+{ >+ return sprintf(buf, "%u\n", ls->id); >+} >+ >+static ssize_t jid_show(struct gdlm_ls *ls, char *buf) >+{ >+ return sprintf(buf, "%d\n", ls->jid); >+} >+ >+static ssize_t first_show(struct gdlm_ls *ls, char *buf) >+{ >+ return sprintf(buf, "%d\n", ls->first); >+} >+ >+static ssize_t first_done_show(struct gdlm_ls *ls, char *buf) >+{ >+ return sprintf(buf, "%d\n", ls->first_done); >+} >+ >+static ssize_t recover_show(struct gdlm_ls *ls, char *buf) >+{ >+ return sprintf(buf, "%d\n", ls->recover_jid); >+} >+ >+static ssize_t recover_store(struct gdlm_ls *ls, const char *buf, size_t len) >+{ >+ ls->recover_jid = simple_strtol(buf, NULL, 0); >+ ls->fscb(ls->sdp, LM_CB_NEED_RECOVERY, &ls->recover_jid); >+ return len; >+} >+ >+static ssize_t recover_done_show(struct gdlm_ls *ls, char *buf) >+{ >+ return sprintf(buf, "%d\n", ls->recover_jid_done); >+} >+ >+static ssize_t recover_status_show(struct gdlm_ls *ls, char *buf) >+{ >+ return sprintf(buf, "%d\n", ls->recover_jid_status); >+} >+ >+static ssize_t drop_count_show(struct gdlm_ls *ls, char *buf) >+{ >+ return sprintf(buf, "%d\n", ls->drop_locks_count); >+} >+ >+static ssize_t drop_count_store(struct gdlm_ls *ls, const char *buf, size_t len) >+{ >+ ls->drop_locks_count = simple_strtol(buf, NULL, 0); >+ return len; >+} >+ >+struct gdlm_attr { >+ struct attribute attr; >+ ssize_t (*show)(struct gdlm_ls *, char *); >+ ssize_t (*store)(struct gdlm_ls *, const char *, size_t); >+}; >+ >+#define GDLM_ATTR(_name,_mode,_show,_store) \ >+static struct gdlm_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store) >+ >+GDLM_ATTR(proto_name, 0444, proto_name_show, NULL); >+GDLM_ATTR(block, 0644, block_show, block_store); >+GDLM_ATTR(withdraw, 0644, withdraw_show, withdraw_store); >+GDLM_ATTR(id, 0444, id_show, NULL); >+GDLM_ATTR(jid, 0444, jid_show, NULL); >+GDLM_ATTR(first, 0444, first_show, NULL); >+GDLM_ATTR(first_done, 0444, first_done_show, NULL); >+GDLM_ATTR(recover, 0644, recover_show, recover_store); >+GDLM_ATTR(recover_done, 0444, recover_done_show, NULL); >+GDLM_ATTR(recover_status, 0444, recover_status_show, NULL); >+GDLM_ATTR(drop_count, 0644, drop_count_show, drop_count_store); >+ >+static struct attribute *gdlm_attrs[] = { >+ &gdlm_attr_proto_name.attr, >+ &gdlm_attr_block.attr, >+ &gdlm_attr_withdraw.attr, >+ &gdlm_attr_id.attr, >+ &gdlm_attr_jid.attr, >+ &gdlm_attr_first.attr, >+ &gdlm_attr_first_done.attr, >+ &gdlm_attr_recover.attr, >+ &gdlm_attr_recover_done.attr, >+ &gdlm_attr_recover_status.attr, >+ &gdlm_attr_drop_count.attr, >+ NULL, >+}; >+ >+static ssize_t gdlm_attr_show(struct kobject *kobj, struct attribute *attr, >+ char *buf) >+{ >+ struct gdlm_ls *ls = container_of(kobj, struct gdlm_ls, kobj); >+ struct gdlm_attr *a = container_of(attr, struct gdlm_attr, attr); >+ return a->show ? a->show(ls, buf) : 0; >+} >+ >+static ssize_t gdlm_attr_store(struct kobject *kobj, struct attribute *attr, >+ const char *buf, size_t len) >+{ >+ struct gdlm_ls *ls = container_of(kobj, struct gdlm_ls, kobj); >+ struct gdlm_attr *a = container_of(attr, struct gdlm_attr, attr); >+ return a->store ? a->store(ls, buf, len) : len; >+} >+ >+static struct sysfs_ops gdlm_attr_ops = { >+ .show = gdlm_attr_show, >+ .store = gdlm_attr_store, >+}; >+ >+static struct kobj_type gdlm_ktype = { >+ .default_attrs = gdlm_attrs, >+ .sysfs_ops = &gdlm_attr_ops, >+}; >+ >+static struct kset gdlm_kset = { >+ .subsys = &kernel_subsys, >+ .kobj = {.name = "lock_dlm",}, >+ .ktype = &gdlm_ktype, >+}; >+ >+int gdlm_kobject_setup(struct gdlm_ls *ls, struct kobject *fskobj) >+{ >+ int error; >+ >+ error = kobject_set_name(&ls->kobj, "%s", "lock_module"); >+ if (error) { >+ log_error("can't set kobj name %d", error); >+ return error; >+ } >+ >+ ls->kobj.kset = &gdlm_kset; >+ ls->kobj.ktype = &gdlm_ktype; >+ ls->kobj.parent = fskobj; >+ >+ error = kobject_register(&ls->kobj); >+ if (error) >+ log_error("can't register kobj %d", error); >+ >+ return error; >+} >+ >+void gdlm_kobject_release(struct gdlm_ls *ls) >+{ >+ kobject_unregister(&ls->kobj); >+} >+ >+int gdlm_sysfs_init(void) >+{ >+ int error; >+ >+ error = kset_register(&gdlm_kset); >+ if (error) >+ printk("lock_dlm: cannot register kset %d\n", error); >+ >+ return error; >+} >+ >+void gdlm_sysfs_exit(void) >+{ >+ kset_unregister(&gdlm_kset); >+} >+ >Index: gfs2_kp/fs/gfs2/locking/dlm/thread.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ gfs2_kp/fs/gfs2/locking/dlm/thread.c 2007-02-07 16:04:07.104004474 -0600 >@@ -0,0 +1,359 @@ >+/* >+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. >+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. >+ * >+ * This copyrighted material is made available to anyone wishing to use, >+ * modify, copy, or redistribute it subject to the terms and conditions >+ * of the GNU General Public License version 2. >+ */ >+ >+#include "lock_dlm.h" >+ >+/* A lock placed on this queue is re-submitted to DLM as soon as the lock_dlm >+ thread gets to it. */ >+ >+static void queue_submit(struct gdlm_lock *lp) >+{ >+ struct gdlm_ls *ls = lp->ls; >+ >+ spin_lock(&ls->async_lock); >+ list_add_tail(&lp->delay_list, &ls->submit); >+ spin_unlock(&ls->async_lock); >+ wake_up(&ls->thread_wait); >+} >+ >+static void process_blocking(struct gdlm_lock *lp, int bast_mode) >+{ >+ struct gdlm_ls *ls = lp->ls; >+ unsigned int cb = 0; >+ >+ switch (gdlm_make_lmstate(bast_mode)) { >+ case LM_ST_EXCLUSIVE: >+ cb = LM_CB_NEED_E; >+ break; >+ case LM_ST_DEFERRED: >+ cb = LM_CB_NEED_D; >+ break; >+ case LM_ST_SHARED: >+ cb = LM_CB_NEED_S; >+ break; >+ default: >+ gdlm_assert(0, "unknown bast mode %u", lp->bast_mode); >+ } >+ >+ ls->fscb(ls->sdp, cb, &lp->lockname); >+} >+ >+static void process_complete(struct gdlm_lock *lp) >+{ >+ struct gdlm_ls *ls = lp->ls; >+ struct lm_async_cb acb; >+ s16 prev_mode = lp->cur; >+ >+ memset(&acb, 0, sizeof(acb)); >+ >+ if (lp->lksb.sb_status == -DLM_ECANCEL) { >+ log_info("complete dlm cancel %x,%llx flags %lx", >+ lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number, >+ lp->flags); >+ >+ lp->req = lp->cur; >+ acb.lc_ret |= LM_OUT_CANCELED; >+ if (lp->cur == DLM_LOCK_IV) >+ lp->lksb.sb_lkid = 0; >+ goto out; >+ } >+ >+ if (test_and_clear_bit(LFL_DLM_UNLOCK, &lp->flags)) { >+ if (lp->lksb.sb_status != -DLM_EUNLOCK) { >+ log_info("unlock sb_status %d %x,%llx flags %lx", >+ lp->lksb.sb_status, lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number, >+ lp->flags); >+ return; >+ } >+ >+ lp->cur = DLM_LOCK_IV; >+ lp->req = DLM_LOCK_IV; >+ lp->lksb.sb_lkid = 0; >+ >+ if (test_and_clear_bit(LFL_UNLOCK_DELETE, &lp->flags)) { >+ gdlm_delete_lp(lp); >+ return; >+ } >+ goto out; >+ } >+ >+ if (lp->lksb.sb_flags & DLM_SBF_VALNOTVALID) >+ memset(lp->lksb.sb_lvbptr, 0, GDLM_LVB_SIZE); >+ >+ if (lp->lksb.sb_flags & DLM_SBF_ALTMODE) { >+ if (lp->req == DLM_LOCK_PR) >+ lp->req = DLM_LOCK_CW; >+ else if (lp->req == DLM_LOCK_CW) >+ lp->req = DLM_LOCK_PR; >+ } >+ >+ /* >+ * A canceled lock request. The lock was just taken off the delayed >+ * list and was never even submitted to dlm. >+ */ >+ >+ if (test_and_clear_bit(LFL_CANCEL, &lp->flags)) { >+ log_info("complete internal cancel %x,%llx", >+ lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number); >+ lp->req = lp->cur; >+ acb.lc_ret |= LM_OUT_CANCELED; >+ goto out; >+ } >+ >+ /* >+ * An error occured. >+ */ >+ >+ if (lp->lksb.sb_status) { >+ /* a "normal" error */ >+ if ((lp->lksb.sb_status == -EAGAIN) && >+ (lp->lkf & DLM_LKF_NOQUEUE)) { >+ lp->req = lp->cur; >+ if (lp->cur == DLM_LOCK_IV) >+ lp->lksb.sb_lkid = 0; >+ goto out; >+ } >+ >+ /* this could only happen with cancels I think */ >+ log_info("ast sb_status %d %x,%llx flags %lx", >+ lp->lksb.sb_status, lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number, >+ lp->flags); >+ return; >+ } >+ >+ /* >+ * This is an AST for an EX->EX conversion for sync_lvb from GFS. >+ */ >+ >+ if (test_and_clear_bit(LFL_SYNC_LVB, &lp->flags)) { >+ complete(&lp->ast_wait); >+ return; >+ } >+ >+ /* >+ * A lock has been demoted to NL because it initially completed during >+ * BLOCK_LOCKS. Now it must be requested in the originally requested >+ * mode. >+ */ >+ >+ if (test_and_clear_bit(LFL_REREQUEST, &lp->flags)) { >+ gdlm_assert(lp->req == DLM_LOCK_NL, "%x,%llx", >+ lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number); >+ gdlm_assert(lp->prev_req > DLM_LOCK_NL, "%x,%llx", >+ lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number); >+ >+ lp->cur = DLM_LOCK_NL; >+ lp->req = lp->prev_req; >+ lp->prev_req = DLM_LOCK_IV; >+ lp->lkf &= ~DLM_LKF_CONVDEADLK; >+ >+ set_bit(LFL_NOCACHE, &lp->flags); >+ >+ if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) && >+ !test_bit(LFL_NOBLOCK, &lp->flags)) >+ gdlm_queue_delayed(lp); >+ else >+ queue_submit(lp); >+ return; >+ } >+ >+ /* >+ * A request is granted during dlm recovery. It may be granted >+ * because the locks of a failed node were cleared. In that case, >+ * there may be inconsistent data beneath this lock and we must wait >+ * for recovery to complete to use it. When gfs recovery is done this >+ * granted lock will be converted to NL and then reacquired in this >+ * granted state. >+ */ >+ >+ if (test_bit(DFL_BLOCK_LOCKS, &ls->flags) && >+ !test_bit(LFL_NOBLOCK, &lp->flags) && >+ lp->req != DLM_LOCK_NL) { >+ >+ lp->cur = lp->req; >+ lp->prev_req = lp->req; >+ lp->req = DLM_LOCK_NL; >+ lp->lkf |= DLM_LKF_CONVERT; >+ lp->lkf &= ~DLM_LKF_CONVDEADLK; >+ >+ log_debug("rereq %x,%llx id %x %d,%d", >+ lp->lockname.ln_type, >+ (unsigned long long)lp->lockname.ln_number, >+ lp->lksb.sb_lkid, lp->cur, lp->req); >+ >+ set_bit(LFL_REREQUEST, &lp->flags); >+ queue_submit(lp); >+ return; >+ } >+ >+ /* >+ * DLM demoted the lock to NL before it was granted so GFS must be >+ * told it cannot cache data for this lock. >+ */ >+ >+ if (lp->lksb.sb_flags & DLM_SBF_DEMOTED) >+ set_bit(LFL_NOCACHE, &lp->flags); >+ >+out: >+ /* >+ * This is an internal lock_dlm lock >+ */ >+ >+ if (test_bit(LFL_INLOCK, &lp->flags)) { >+ clear_bit(LFL_NOBLOCK, &lp->flags); >+ lp->cur = lp->req; >+ complete(&lp->ast_wait); >+ return; >+ } >+ >+ /* >+ * Normal completion of a lock request. Tell GFS it now has the lock. >+ */ >+ >+ clear_bit(LFL_NOBLOCK, &lp->flags); >+ lp->cur = lp->req; >+ >+ acb.lc_name = lp->lockname; >+ acb.lc_ret |= gdlm_make_lmstate(lp->cur); >+ >+ if (!test_and_clear_bit(LFL_NOCACHE, &lp->flags) && >+ (lp->cur > DLM_LOCK_NL) && (prev_mode > DLM_LOCK_NL)) >+ acb.lc_ret |= LM_OUT_CACHEABLE; >+ >+ ls->fscb(ls->sdp, LM_CB_ASYNC, &acb); >+} >+ >+static inline int no_work(struct gdlm_ls *ls, int blocking) >+{ >+ int ret; >+ >+ spin_lock(&ls->async_lock); >+ ret = list_empty(&ls->complete) && list_empty(&ls->submit); >+ if (ret && blocking) >+ ret = list_empty(&ls->blocking); >+ spin_unlock(&ls->async_lock); >+ >+ return ret; >+} >+ >+static inline int check_drop(struct gdlm_ls *ls) >+{ >+ if (!ls->drop_locks_count) >+ return 0; >+ >+ if (time_after(jiffies, ls->drop_time + ls->drop_locks_period * HZ)) { >+ ls->drop_time = jiffies; >+ if (ls->all_locks_count >= ls->drop_locks_count) >+ return 1; >+ } >+ return 0; >+} >+ >+static int gdlm_thread(void *data) >+{ >+ struct gdlm_ls *ls = (struct gdlm_ls *) data; >+ struct gdlm_lock *lp = NULL; >+ int blist = 0; >+ uint8_t complete, blocking, submit, drop; >+ DECLARE_WAITQUEUE(wait, current); >+ >+ /* Only thread1 is allowed to do blocking callbacks since gfs >+ may wait for a completion callback within a blocking cb. */ >+ >+ if (current == ls->thread1) >+ blist = 1; >+ >+ while (!kthread_should_stop()) { >+ set_current_state(TASK_INTERRUPTIBLE); >+ add_wait_queue(&ls->thread_wait, &wait); >+ if (no_work(ls, blist)) >+ schedule(); >+ remove_wait_queue(&ls->thread_wait, &wait); >+ set_current_state(TASK_RUNNING); >+ >+ complete = blocking = submit = drop = 0; >+ >+ spin_lock(&ls->async_lock); >+ >+ if (blist && !list_empty(&ls->blocking)) { >+ lp = list_entry(ls->blocking.next, struct gdlm_lock, >+ blist); >+ list_del_init(&lp->blist); >+ blocking = lp->bast_mode; >+ lp->bast_mode = 0; >+ } else if (!list_empty(&ls->complete)) { >+ lp = list_entry(ls->complete.next, struct gdlm_lock, >+ clist); >+ list_del_init(&lp->clist); >+ complete = 1; >+ } else if (!list_empty(&ls->submit)) { >+ lp = list_entry(ls->submit.next, struct gdlm_lock, >+ delay_list); >+ list_del_init(&lp->delay_list); >+ submit = 1; >+ } >+ >+ drop = check_drop(ls); >+ spin_unlock(&ls->async_lock); >+ >+ if (complete) >+ process_complete(lp); >+ >+ else if (blocking) >+ process_blocking(lp, blocking); >+ >+ else if (submit) >+ gdlm_do_lock(lp); >+ >+ if (drop) >+ ls->fscb(ls->sdp, LM_CB_DROPLOCKS, NULL); >+ >+ schedule(); >+ } >+ >+ return 0; >+} >+ >+int gdlm_init_threads(struct gdlm_ls *ls) >+{ >+ struct task_struct *p; >+ int error; >+ >+ p = kthread_run(gdlm_thread, ls, "lock_dlm1"); >+ error = IS_ERR(p); >+ if (error) { >+ log_error("can't start lock_dlm1 thread %d", error); >+ return error; >+ } >+ ls->thread1 = p; >+ >+ p = kthread_run(gdlm_thread, ls, "lock_dlm2"); >+ error = IS_ERR(p); >+ if (error) { >+ log_error("can't start lock_dlm2 thread %d", error); >+ kthread_stop(ls->thread1); >+ return error; >+ } >+ ls->thread2 = p; >+ >+ return 0; >+} >+ >+void gdlm_release_threads(struct gdlm_ls *ls) >+{ >+ kthread_stop(ls->thread1); >+ kthread_stop(ls->thread2); >+} >+ >Index: gfs2_kp/fs/gfs2/main.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/main.c 2007-02-07 16:04:03.515964799 -0600 >+++ gfs2_kp/fs/gfs2/main.c 2007-02-07 16:04:07.104004474 -0600 >@@ -26,6 +26,7 @@ > #include "diaper.h" > #include "ops_fstype.h" > #include "proc.h" >+#include "sys.h" > > /** > * init_gfs2_fs - Register GFS2 as a filesystem >@@ -38,6 +39,10 @@ init_gfs2_fs(void) > { > int error; > >+ error = gfs2_sys_init(); >+ if (error) >+ return error; >+ > gfs2_random_number = xtime.tv_nsec; > > error = gfs2_trace_init(); >@@ -98,6 +103,8 @@ init_gfs2_fs(void) > kmem_cache_destroy(gfs2_glock_cachep); > > gfs2_diaper_uninit(); >+ >+ gfs2_sys_uninit(); > > fail_proc: > gfs2_proc_uninit(); >@@ -124,6 +131,7 @@ exit_gfs2_fs(void) > kmem_cache_destroy(gfs2_inode_cachep); > kmem_cache_destroy(gfs2_glock_cachep); > >+ gfs2_sys_uninit(); > gfs2_diaper_uninit(); > gfs2_proc_uninit(); > >Index: gfs2_kp/fs/gfs2/super.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/super.c 2007-02-07 16:04:03.767967585 -0600 >+++ gfs2_kp/fs/gfs2/super.c 2007-02-07 16:04:07.104004474 -0600 >@@ -18,6 +18,7 @@ > #include <asm/semaphore.h> > #include <linux/completion.h> > #include <linux/buffer_head.h> >+#include <linux/bio.h> > > #include "gfs2.h" > #include "bmap.h" >@@ -156,6 +157,75 @@ gfs2_check_sb(struct gfs2_sbd *sdp, stru > RETURN(G2FN_CHECK_SB, 0); > } > >+ >+static int >+end_bio_io_page(struct bio *bio, unsigned int bytes_done, int error) >+{ >+ struct page *page = bio->bi_private; >+ if (bio->bi_size) >+ return 1; >+ >+ if (!error) >+ SetPageUptodate(page); >+ else >+ printk(KERN_WARNING "gfs2: error %d reading superblock\n", error); >+ unlock_page(page); >+ return 0; >+} >+ >+/** >+ * gfs2_read_super - Read the gfs2 super block from disk >+ * @sb: The VFS super block >+ * @sector: The location of the super block >+ * >+ * This uses the bio functions to read the super block from disk >+ * because we want to be 100% sure that we never read cached data. >+ * A super block is read twice only during each GFS2 mount and is >+ * never written to by the filesystem. The first time its read no >+ * locks are held, and the only details which are looked at are those >+ * relating to the locking protocol. Once locking is up and working, >+ * the sb is read again under the lock to establish the location of >+ * the master directory (contains pointers to journals etc) and the >+ * root directory. >+ * >+ * Returns: A page containing the sb or NULL >+ */ >+ >+struct page *gfs2_read_super(struct super_block *sb, sector_t sector) >+{ >+ struct page *page; >+ struct bio *bio; >+ >+ page = alloc_page(GFP_KERNEL); >+ if (unlikely(!page)) >+ return NULL; >+ >+ ClearPageUptodate(page); >+ ClearPageDirty(page); >+ lock_page(page); >+ >+ bio = bio_alloc(GFP_KERNEL, 1); >+ if (unlikely(!bio)) { >+ __free_page(page); >+ return NULL; >+ } >+ >+ bio->bi_sector = sector * (sb->s_blocksize >> 9); >+ bio->bi_bdev = sb->s_bdev; >+ bio_add_page(bio, page, PAGE_SIZE, 0); >+ >+ bio->bi_end_io = end_bio_io_page; >+ bio->bi_private = page; >+ submit_bio(READ_SYNC | (1 << BIO_RW_META), bio); >+ wait_on_page_locked(page); >+ bio_put(bio); >+ if (!PageUptodate(page)) { >+ __free_page(page); >+ return NULL; >+ } >+ return page; >+} >+ > /** > * gfs2_read_sb - Read super block > * @sdp: The GFS2 superblock >Index: gfs2_kp/fs/gfs2/super.h >=================================================================== >--- gfs2_kp.orig/fs/gfs2/super.h 2007-02-07 16:04:03.767967585 -0600 >+++ gfs2_kp/fs/gfs2/super.h 2007-02-07 16:04:07.116004606 -0600 >@@ -19,6 +19,8 @@ void gfs2_tune_init(struct gfs2_tune *gt > int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb *sb, int silent); > int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent); > int gfs2_do_upgrade(struct gfs2_sbd *sdp, struct gfs2_glock *gl_sb); >+struct page *gfs2_read_super(struct super_block *sb, sector_t sector); >+ > > static __inline__ unsigned int > gfs2_jindex_size(struct gfs2_sbd *sdp) >Index: gfs2_kp/fs/gfs2/sys.c >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ gfs2_kp/fs/gfs2/sys.c 2007-02-07 16:04:07.120004651 -0600 >@@ -0,0 +1,571 @@ >+/* >+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. >+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. >+ * >+ * This copyrighted material is made available to anyone wishing to use, >+ * modify, copy, or redistribute it subject to the terms and conditions >+ * of the GNU General Public License version 2. >+ */ >+ >+#include <linux/sched.h> >+#include <linux/slab.h> >+#include <linux/spinlock.h> >+#include <linux/completion.h> >+#include <linux/buffer_head.h> >+#include <linux/module.h> >+#include <linux/kobject.h> >+#include <gfs2_ondisk.h> >+#include <linux/lm_interface.h> >+#include <asm/uaccess.h> >+ >+#include "gfs2.h" >+#include "incore.h" >+#include "lm.h" >+#include "sys.h" >+#include "super.h" >+#include "glock.h" >+#include "quota.h" >+#include "util.h" >+ >+char *gfs2_sys_margs; >+spinlock_t gfs2_sys_margs_lock; >+ >+static ssize_t id_show(struct gfs2_sbd *sdp, char *buf) >+{ >+ return snprintf(buf, PAGE_SIZE, "%s\n", sdp->sd_vfs->s_id); >+} >+ >+static ssize_t fsname_show(struct gfs2_sbd *sdp, char *buf) >+{ >+ return snprintf(buf, PAGE_SIZE, "%s\n", sdp->sd_fsname); >+} >+ >+static ssize_t freeze_show(struct gfs2_sbd *sdp, char *buf) >+{ >+ unsigned int count; >+ >+ down(&sdp->sd_freeze_lock); >+ count = sdp->sd_freeze_count; >+ up(&sdp->sd_freeze_lock); >+ >+ return snprintf(buf, PAGE_SIZE, "%u\n", count); >+} >+ >+static ssize_t freeze_store(struct gfs2_sbd *sdp, const char *buf, size_t len) >+{ >+ ssize_t ret = len; >+ int error = 0; >+ int n = simple_strtol(buf, NULL, 0); >+ >+ if (!capable(CAP_SYS_ADMIN)) >+ return -EACCES; >+ >+ switch (n) { >+ case 0: >+ gfs2_unfreeze_fs(sdp); >+ break; >+ case 1: >+ error = gfs2_freeze_fs(sdp); >+ break; >+ default: >+ ret = -EINVAL; >+ } >+ >+ if (error) >+ fs_warn(sdp, "freeze %d error %d", n, error); >+ >+ return ret; >+} >+ >+static ssize_t withdraw_show(struct gfs2_sbd *sdp, char *buf) >+{ >+ unsigned int b = test_bit(SDF_SHUTDOWN, &sdp->sd_flags); >+ return snprintf(buf, PAGE_SIZE, "%u\n", b); >+} >+ >+static ssize_t withdraw_store(struct gfs2_sbd *sdp, const char *buf, size_t len) >+{ >+ if (!capable(CAP_SYS_ADMIN)) >+ return -EACCES; >+ >+ if (simple_strtol(buf, NULL, 0) != 1) >+ return -EINVAL; >+ >+ gfs2_lm_withdraw(sdp, >+ "GFS2: fsid=%s: withdrawing from cluster at user's request\n", >+ sdp->sd_fsname); >+ return len; >+} >+ >+static ssize_t statfs_sync_store(struct gfs2_sbd *sdp, const char *buf, >+ size_t len) >+{ >+ if (!capable(CAP_SYS_ADMIN)) >+ return -EACCES; >+ >+ if (simple_strtol(buf, NULL, 0) != 1) >+ return -EINVAL; >+ >+ gfs2_statfs_sync(sdp); >+ return len; >+} >+ >+static ssize_t shrink_store(struct gfs2_sbd *sdp, const char *buf, size_t len) >+{ >+ if (!capable(CAP_SYS_ADMIN)) >+ return -EACCES; >+ >+ if (simple_strtol(buf, NULL, 0) != 1) >+ return -EINVAL; >+ >+ gfs2_gl_hash_clear(sdp, NO_WAIT); >+ return len; >+} >+ >+static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf, >+ size_t len) >+{ >+ if (!capable(CAP_SYS_ADMIN)) >+ return -EACCES; >+ >+ if (simple_strtol(buf, NULL, 0) != 1) >+ return -EINVAL; >+ >+ gfs2_quota_sync(sdp); >+ return len; >+} >+ >+static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf, >+ size_t len) >+{ >+ u32 id; >+ >+ if (!capable(CAP_SYS_ADMIN)) >+ return -EACCES; >+ >+ id = simple_strtoul(buf, NULL, 0); >+ >+ gfs2_quota_refresh(sdp, 1, id); >+ return len; >+} >+ >+static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf, >+ size_t len) >+{ >+ u32 id; >+ >+ if (!capable(CAP_SYS_ADMIN)) >+ return -EACCES; >+ >+ id = simple_strtoul(buf, NULL, 0); >+ >+ gfs2_quota_refresh(sdp, 0, id); >+ return len; >+} >+ >+struct gfs2_attr { >+ struct attribute attr; >+ ssize_t (*show)(struct gfs2_sbd *, char *); >+ ssize_t (*store)(struct gfs2_sbd *, const char *, size_t); >+}; >+ >+#define GFS2_ATTR(name, mode, show, store) \ >+static struct gfs2_attr gfs2_attr_##name = __ATTR(name, mode, show, store) >+ >+GFS2_ATTR(id, 0444, id_show, NULL); >+GFS2_ATTR(fsname, 0444, fsname_show, NULL); >+GFS2_ATTR(freeze, 0644, freeze_show, freeze_store); >+GFS2_ATTR(shrink, 0200, NULL, shrink_store); >+GFS2_ATTR(withdraw, 0644, withdraw_show, withdraw_store); >+GFS2_ATTR(statfs_sync, 0200, NULL, statfs_sync_store); >+GFS2_ATTR(quota_sync, 0200, NULL, quota_sync_store); >+GFS2_ATTR(quota_refresh_user, 0200, NULL, quota_refresh_user_store); >+GFS2_ATTR(quota_refresh_group, 0200, NULL, quota_refresh_group_store); >+ >+static struct attribute *gfs2_attrs[] = { >+ &gfs2_attr_id.attr, >+ &gfs2_attr_fsname.attr, >+ &gfs2_attr_freeze.attr, >+ &gfs2_attr_shrink.attr, >+ &gfs2_attr_withdraw.attr, >+ &gfs2_attr_statfs_sync.attr, >+ &gfs2_attr_quota_sync.attr, >+ &gfs2_attr_quota_refresh_user.attr, >+ &gfs2_attr_quota_refresh_group.attr, >+ NULL, >+}; >+ >+static ssize_t gfs2_attr_show(struct kobject *kobj, struct attribute *attr, >+ char *buf) >+{ >+ struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj); >+ struct gfs2_attr *a = container_of(attr, struct gfs2_attr, attr); >+ return a->show ? a->show(sdp, buf) : 0; >+} >+ >+static ssize_t gfs2_attr_store(struct kobject *kobj, struct attribute *attr, >+ const char *buf, size_t len) >+{ >+ struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj); >+ struct gfs2_attr *a = container_of(attr, struct gfs2_attr, attr); >+ return a->store ? a->store(sdp, buf, len) : len; >+} >+ >+static struct sysfs_ops gfs2_attr_ops = { >+ .show = gfs2_attr_show, >+ .store = gfs2_attr_store, >+}; >+ >+static struct kobj_type gfs2_ktype = { >+ .default_attrs = gfs2_attrs, >+ .sysfs_ops = &gfs2_attr_ops, >+}; >+ >+static struct kset gfs2_kset = { >+ .subsys = &fs_subsys, >+ .kobj = {.name = "gfs2"}, >+ .ktype = &gfs2_ktype, >+}; >+ >+/* >+ * display struct lm_lockstruct fields >+ */ >+ >+struct lockstruct_attr { >+ struct attribute attr; >+ ssize_t (*show)(struct gfs2_sbd *, char *); >+}; >+ >+#define LOCKSTRUCT_ATTR(name, fmt) \ >+static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf) \ >+{ \ >+ return snprintf(buf, PAGE_SIZE, fmt, sdp->sd_lockstruct.ls_##name); \ >+} \ >+static struct lockstruct_attr lockstruct_attr_##name = __ATTR_RO(name) >+ >+LOCKSTRUCT_ATTR(jid, "%u\n"); >+LOCKSTRUCT_ATTR(first, "%u\n"); >+LOCKSTRUCT_ATTR(lvb_size, "%u\n"); >+LOCKSTRUCT_ATTR(flags, "%d\n"); >+ >+static struct attribute *lockstruct_attrs[] = { >+ &lockstruct_attr_jid.attr, >+ &lockstruct_attr_first.attr, >+ &lockstruct_attr_lvb_size.attr, >+ &lockstruct_attr_flags.attr, >+ NULL, >+}; >+ >+/* >+ * display struct gfs2_args fields >+ */ >+ >+struct args_attr { >+ struct attribute attr; >+ ssize_t (*show)(struct gfs2_sbd *, char *); >+}; >+ >+#define ARGS_ATTR(name, fmt) \ >+static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf) \ >+{ \ >+ return snprintf(buf, PAGE_SIZE, fmt, sdp->sd_args.ar_##name); \ >+} \ >+static struct args_attr args_attr_##name = __ATTR_RO(name) >+ >+ARGS_ATTR(lockproto, "%s\n"); >+ARGS_ATTR(locktable, "%s\n"); >+ARGS_ATTR(hostdata, "%s\n"); >+ARGS_ATTR(spectator, "%d\n"); >+ARGS_ATTR(ignore_local_fs, "%d\n"); >+ARGS_ATTR(localcaching, "%d\n"); >+ARGS_ATTR(localflocks, "%d\n"); >+ARGS_ATTR(debug, "%d\n"); >+ARGS_ATTR(upgrade, "%d\n"); >+ARGS_ATTR(num_glockd, "%u\n"); >+ARGS_ATTR(posix_acl, "%d\n"); >+ARGS_ATTR(quota, "%u\n"); >+ARGS_ATTR(suiddir, "%d\n"); >+ARGS_ATTR(data, "%d\n"); >+ >+/* one oddball doesn't fit the macro mold */ >+static ssize_t noatime_show(struct gfs2_sbd *sdp, char *buf) >+{ >+ return snprintf(buf, PAGE_SIZE, "%d\n", >+ !!test_bit(SDF_NOATIME, &sdp->sd_flags)); >+} >+static struct args_attr args_attr_noatime = __ATTR_RO(noatime); >+ >+static struct attribute *args_attrs[] = { >+ &args_attr_lockproto.attr, >+ &args_attr_locktable.attr, >+ &args_attr_hostdata.attr, >+ &args_attr_spectator.attr, >+ &args_attr_ignore_local_fs.attr, >+ &args_attr_localcaching.attr, >+ &args_attr_localflocks.attr, >+ &args_attr_debug.attr, >+ &args_attr_upgrade.attr, >+ &args_attr_num_glockd.attr, >+ &args_attr_posix_acl.attr, >+ &args_attr_quota.attr, >+ &args_attr_suiddir.attr, >+ &args_attr_data.attr, >+ &args_attr_noatime.attr, >+ NULL, >+}; >+ >+/* >+ * display counters from superblock >+ */ >+ >+struct counters_attr { >+ struct attribute attr; >+ ssize_t (*show)(struct gfs2_sbd *, char *); >+}; >+ >+#define COUNTERS_ATTR(name, fmt) \ >+static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf) \ >+{ \ >+ return snprintf(buf, PAGE_SIZE, fmt, \ >+ (unsigned int)atomic_read(&sdp->sd_##name)); \ >+} \ >+static struct counters_attr counters_attr_##name = __ATTR_RO(name) >+ >+COUNTERS_ATTR(glock_count, "%u\n"); >+COUNTERS_ATTR(glock_held_count, "%u\n"); >+COUNTERS_ATTR(inode_count, "%u\n"); >+COUNTERS_ATTR(reclaimed, "%u\n"); >+ >+static struct attribute *counters_attrs[] = { >+ &counters_attr_glock_count.attr, >+ &counters_attr_glock_held_count.attr, >+ &counters_attr_inode_count.attr, >+ &counters_attr_reclaimed.attr, >+ NULL, >+}; >+ >+/* >+ * get and set struct gfs2_tune fields >+ */ >+ >+static ssize_t quota_scale_show(struct gfs2_sbd *sdp, char *buf) >+{ >+ return snprintf(buf, PAGE_SIZE, "%u %u\n", >+ sdp->sd_tune.gt_quota_scale_num, >+ sdp->sd_tune.gt_quota_scale_den); >+} >+ >+static ssize_t quota_scale_store(struct gfs2_sbd *sdp, const char *buf, >+ size_t len) >+{ >+ struct gfs2_tune *gt = &sdp->sd_tune; >+ unsigned int x, y; >+ >+ if (!capable(CAP_SYS_ADMIN)) >+ return -EACCES; >+ >+ if (sscanf(buf, "%u %u", &x, &y) != 2 || !y) >+ return -EINVAL; >+ >+ spin_lock(>->gt_spin); >+ gt->gt_quota_scale_num = x; >+ gt->gt_quota_scale_den = y; >+ spin_unlock(>->gt_spin); >+ return len; >+} >+ >+static ssize_t tune_set(struct gfs2_sbd *sdp, unsigned int *field, >+ int check_zero, const char *buf, size_t len) >+{ >+ struct gfs2_tune *gt = &sdp->sd_tune; >+ unsigned int x; >+ >+ if (!capable(CAP_SYS_ADMIN)) >+ return -EACCES; >+ >+ x = simple_strtoul(buf, NULL, 0); >+ >+ if (check_zero && !x) >+ return -EINVAL; >+ >+ spin_lock(>->gt_spin); >+ *field = x; >+ spin_unlock(>->gt_spin); >+ return len; >+} >+ >+struct tune_attr { >+ struct attribute attr; >+ ssize_t (*show)(struct gfs2_sbd *, char *); >+ ssize_t (*store)(struct gfs2_sbd *, const char *, size_t); >+}; >+ >+#define TUNE_ATTR_3(name, show, store) \ >+static struct tune_attr tune_attr_##name = __ATTR(name, 0644, show, store) >+ >+#define TUNE_ATTR_2(name, store) \ >+static ssize_t name##_show(struct gfs2_sbd *sdp, char *buf) \ >+{ \ >+ return snprintf(buf, PAGE_SIZE, "%u\n", sdp->sd_tune.gt_##name); \ >+} \ >+TUNE_ATTR_3(name, name##_show, store) >+ >+#define TUNE_ATTR(name, check_zero) \ >+static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\ >+{ \ >+ return tune_set(sdp, &sdp->sd_tune.gt_##name, check_zero, buf, len); \ >+} \ >+TUNE_ATTR_2(name, name##_store) >+ >+#define TUNE_ATTR_DAEMON(name, process) \ >+static ssize_t name##_store(struct gfs2_sbd *sdp, const char *buf, size_t len)\ >+{ \ >+ ssize_t r = tune_set(sdp, &sdp->sd_tune.gt_##name, 1, buf, len); \ >+ wake_up_process(sdp->sd_##process); \ >+ return r; \ >+} \ >+TUNE_ATTR_2(name, name##_store) >+ >+TUNE_ATTR(demote_secs, 0); >+TUNE_ATTR(incore_log_blocks, 0); >+TUNE_ATTR(log_flush_secs, 0); >+TUNE_ATTR(jindex_refresh_secs, 0); >+TUNE_ATTR(quota_warn_period, 0); >+TUNE_ATTR(quota_quantum, 0); >+TUNE_ATTR(atime_quantum, 0); >+TUNE_ATTR(max_readahead, 0); >+TUNE_ATTR(complain_secs, 0); >+TUNE_ATTR(reclaim_limit, 0); >+TUNE_ATTR(statfs_slow, 0); >+TUNE_ATTR(new_files_jdata, 0); >+TUNE_ATTR(new_files_directio, 0); >+TUNE_ATTR(quota_simul_sync, 1); >+TUNE_ATTR(quota_cache_secs, 1); >+TUNE_ATTR(stall_secs, 1); >+TUNE_ATTR(greedy_default, 1); >+TUNE_ATTR(greedy_quantum, 1); >+TUNE_ATTR(greedy_max, 1); >+TUNE_ATTR(statfs_quantum, 1); >+TUNE_ATTR_DAEMON(scand_secs, scand_process); >+TUNE_ATTR_DAEMON(recoverd_secs, recoverd_process); >+TUNE_ATTR_DAEMON(logd_secs, logd_process); >+TUNE_ATTR_DAEMON(quotad_secs, quotad_process); >+TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store); >+ >+static struct attribute *tune_attrs[] = { >+ &tune_attr_demote_secs.attr, >+ &tune_attr_incore_log_blocks.attr, >+ &tune_attr_log_flush_secs.attr, >+ &tune_attr_jindex_refresh_secs.attr, >+ &tune_attr_quota_warn_period.attr, >+ &tune_attr_quota_quantum.attr, >+ &tune_attr_atime_quantum.attr, >+ &tune_attr_max_readahead.attr, >+ &tune_attr_complain_secs.attr, >+ &tune_attr_reclaim_limit.attr, >+ &tune_attr_statfs_slow.attr, >+ &tune_attr_quota_simul_sync.attr, >+ &tune_attr_quota_cache_secs.attr, >+ &tune_attr_stall_secs.attr, >+ &tune_attr_greedy_default.attr, >+ &tune_attr_greedy_quantum.attr, >+ &tune_attr_greedy_max.attr, >+ &tune_attr_statfs_quantum.attr, >+ &tune_attr_scand_secs.attr, >+ &tune_attr_recoverd_secs.attr, >+ &tune_attr_logd_secs.attr, >+ &tune_attr_quotad_secs.attr, >+ &tune_attr_quota_scale.attr, >+ &tune_attr_new_files_jdata.attr, >+ &tune_attr_new_files_directio.attr, >+ NULL, >+}; >+ >+static struct attribute_group lockstruct_group = { >+ .name = "lockstruct", >+ .attrs = lockstruct_attrs, >+}; >+ >+static struct attribute_group counters_group = { >+ .name = "counters", >+ .attrs = counters_attrs, >+}; >+ >+static struct attribute_group args_group = { >+ .name = "args", >+ .attrs = args_attrs, >+}; >+ >+static struct attribute_group tune_group = { >+ .name = "tune", >+ .attrs = tune_attrs, >+}; >+ >+int gfs2_sys_fs_add(struct gfs2_sbd *sdp) >+{ >+ int error; >+ >+ sdp->sd_kobj.kset = &gfs2_kset; >+ sdp->sd_kobj.ktype = &gfs2_ktype; >+ >+ error = kobject_set_name(&sdp->sd_kobj, "%s", sdp->sd_table_name); >+ if (error) >+ goto fail; >+ >+ error = kobject_register(&sdp->sd_kobj); >+ if (error) >+ goto fail; >+ >+ error = sysfs_create_group(&sdp->sd_kobj, &lockstruct_group); >+ if (error) >+ goto fail_reg; >+ >+ error = sysfs_create_group(&sdp->sd_kobj, &counters_group); >+ if (error) >+ goto fail_lockstruct; >+ >+ error = sysfs_create_group(&sdp->sd_kobj, &args_group); >+ if (error) >+ goto fail_counters; >+ >+ error = sysfs_create_group(&sdp->sd_kobj, &tune_group); >+ if (error) >+ goto fail_args; >+ >+ return 0; >+ >+fail_args: >+ sysfs_remove_group(&sdp->sd_kobj, &args_group); >+fail_counters: >+ sysfs_remove_group(&sdp->sd_kobj, &counters_group); >+fail_lockstruct: >+ sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group); >+fail_reg: >+ kobject_unregister(&sdp->sd_kobj); >+fail: >+ fs_err(sdp, "error %d adding sysfs files", error); >+ return error; >+} >+ >+void gfs2_sys_fs_del(struct gfs2_sbd *sdp) >+{ >+ sysfs_remove_group(&sdp->sd_kobj, &tune_group); >+ sysfs_remove_group(&sdp->sd_kobj, &args_group); >+ sysfs_remove_group(&sdp->sd_kobj, &counters_group); >+ sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group); >+ kobject_unregister(&sdp->sd_kobj); >+} >+ >+int gfs2_sys_init(void) >+{ >+ gfs2_sys_margs = NULL; >+ spin_lock_init(&gfs2_sys_margs_lock); >+ return kset_register(&gfs2_kset); >+} >+ >+void gfs2_sys_uninit(void) >+{ >+ kfree(gfs2_sys_margs); >+ kset_unregister(&gfs2_kset); >+} >+ >Index: gfs2_kp/fs/gfs2/sys.h >=================================================================== >--- /dev/null 1970-01-01 00:00:00.000000000 +0000 >+++ gfs2_kp/fs/gfs2/sys.h 2007-02-07 16:04:07.120004651 -0600 >@@ -0,0 +1,27 @@ >+/* >+ * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. >+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. >+ * >+ * This copyrighted material is made available to anyone wishing to use, >+ * modify, copy, or redistribute it subject to the terms and conditions >+ * of the GNU General Public License version 2. >+ */ >+ >+#ifndef __SYS_DOT_H__ >+#define __SYS_DOT_H__ >+ >+#include <linux/spinlock.h> >+struct gfs2_sbd; >+ >+/* Allow args to be passed to GFS2 when using an initial ram disk */ >+extern char *gfs2_sys_margs; >+extern spinlock_t gfs2_sys_margs_lock; >+ >+int gfs2_sys_fs_add(struct gfs2_sbd *sdp); >+void gfs2_sys_fs_del(struct gfs2_sbd *sdp); >+ >+int gfs2_sys_init(void); >+void gfs2_sys_uninit(void); >+ >+#endif /* __SYS_DOT_H__ */ >+ >Index: gfs2_kp/fs/gfs2/gfs2_ondisk.h >=================================================================== >--- gfs2_kp.orig/fs/gfs2/gfs2_ondisk.h 2007-02-07 16:04:03.007959184 -0600 >+++ gfs2_kp/fs/gfs2/gfs2_ondisk.h 2007-02-07 16:05:52.809187296 -0600 >@@ -84,7 +84,7 @@ > #ifndef __GFS2_ONDISK_DOT_H__ > #define __GFS2_ONDISK_DOT_H__ > >-#define GFS2_MAGIC (0x07131974) /* for all on-disk headers */ >+#define GFS2_MAGIC (0x01161970) /* for all on-disk headers */ > #define GFS2_BASIC_BLOCK (512) /* "basic block" = "sector" = 512B */ > #define GFS2_BASIC_BLOCK_SHIFT (9) > >@@ -559,7 +559,7 @@ struct gfs2_quota_change { > > /* Endian functions */ > >-#undef GFS2_ENDIAN_BIG >+#define GFS2_ENDIAN_BIG > > #ifdef GFS2_ENDIAN_BIG > >@@ -573,6 +573,7 @@ struct gfs2_quota_change { > > #else /* GFS2_ENDIAN_BIG */ > >+#warning GFS2_ENDIAN_LITTLE > #define gfs2_16_to_cpu le16_to_cpu > #define gfs2_32_to_cpu le32_to_cpu > #define gfs2_64_to_cpu le64_to_cpu >Index: gfs2_kp/fs/gfs2/ondisk.c >=================================================================== >--- gfs2_kp.orig/fs/gfs2/ondisk.c 2007-02-07 16:04:03.523964888 -0600 >+++ gfs2_kp/fs/gfs2/ondisk.c 2007-02-07 16:04:07.192005447 -0600 >@@ -24,7 +24,7 @@ > #define pv(struct, member, fmt) printk(" "#member" = "fmt"\n", struct->member); > > #define WANT_GFS2_CONVERSION_FUNCTIONS >-#include <linux/gfs2_ondisk.h> >+#include <gfs2_ondisk.h> > > #ifdef GFS2_ENDIAN_BIG > #warning Big endian is set.
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 227945
: 147717 |
147805