Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
  3  * Copyright (C) 2004-2009 Red Hat, Inc.  All rights reserved.
  4  *
  5  * This copyrighted material is made available to anyone wishing to use,
  6  * modify, copy, or redistribute it subject to the terms and conditions
  7  * of the GNU General Public License version 2.
  8  */
  9 
 10 #include <linux/fs.h>
 11 #include <linux/dlm.h>
 12 #include <linux/types.h>
 13 #include <linux/gfs2_ondisk.h>
 14 
 15 #include "incore.h"
 16 #include "glock.h"
 17 #include "util.h"
 18 
 19 
 20 static void gdlm_ast(void *arg)
 21 {
 22         struct gfs2_glock *gl = arg;
 23         unsigned ret = gl->gl_state;
 24 
 25         BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED);
 26 
 27         if (gl->gl_lksb.sb_flags & DLM_SBF_VALNOTVALID)
 28                 memset(gl->gl_lvb, 0, GDLM_LVB_SIZE);
 29 
 30         switch (gl->gl_lksb.sb_status) {
 31         case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */
 32                 kmem_cache_free(gfs2_glock_cachep, gl);
 33                 return;
 34         case -DLM_ECANCEL: /* Cancel while getting lock */
 35                 ret |= LM_OUT_CANCELED;
 36                 goto out;
 37         case -EAGAIN: /* Try lock fails */
 38                 goto out;
 39         case -EINVAL: /* Invalid */
 40         case -ENOMEM: /* Out of memory */
 41                 ret |= LM_OUT_ERROR;
 42                 goto out;
 43         case 0: /* Success */
 44                 break;
 45         default: /* Something unexpected */
 46                 BUG();
 47         }
 48 
 49         ret = gl->gl_req;
 50         if (gl->gl_lksb.sb_flags & DLM_SBF_ALTMODE) {
 51                 if (gl->gl_req == LM_ST_SHARED)
 52                         ret = LM_ST_DEFERRED;
 53                 else if (gl->gl_req == LM_ST_DEFERRED)
 54                         ret = LM_ST_SHARED;
 55                 else
 56                         BUG();
 57         }
 58 
 59         set_bit(GLF_INITIAL, &gl->gl_flags);
 60         gfs2_glock_complete(gl, ret);
 61         return;
 62 out:
 63         if (!test_bit(GLF_INITIAL, &gl->gl_flags))
 64                 gl->gl_lksb.sb_lkid = 0;
 65         gfs2_glock_complete(gl, ret);
 66 }
 67 
 68 static void gdlm_bast(void *arg, int mode)
 69 {
 70         struct gfs2_glock *gl = arg;
 71 
 72         switch (mode) {
 73         case DLM_LOCK_EX:
 74                 gfs2_glock_cb(gl, LM_ST_UNLOCKED);
 75                 break;
 76         case DLM_LOCK_CW:
 77                 gfs2_glock_cb(gl, LM_ST_DEFERRED);
 78                 break;
 79         case DLM_LOCK_PR:
 80                 gfs2_glock_cb(gl, LM_ST_SHARED);
 81                 break;
 82         default:
 83                 printk(KERN_ERR "unknown bast mode %d", mode);
 84                 BUG();
 85         }
 86 }
 87 
 88 /* convert gfs lock-state to dlm lock-mode */
 89 
 90 static int make_mode(const unsigned int lmstate)
 91 {
 92         switch (lmstate) {
 93         case LM_ST_UNLOCKED:
 94                 return DLM_LOCK_NL;
 95         case LM_ST_EXCLUSIVE:
 96                 return DLM_LOCK_EX;
 97         case LM_ST_DEFERRED:
 98                 return DLM_LOCK_CW;
 99         case LM_ST_SHARED:
100                 return DLM_LOCK_PR;
101         }
102         printk(KERN_ERR "unknown LM state %d", lmstate);
103         BUG();
104         return -1;
105 }
106 
107 static u32 make_flags(const u32 lkid, const unsigned int gfs_flags,
108                       const int req)
109 {
110         u32 lkf = 0;
111 
112         if (gfs_flags & LM_FLAG_TRY)
113                 lkf |= DLM_LKF_NOQUEUE;
114 
115         if (gfs_flags & LM_FLAG_TRY_1CB) {
116                 lkf |= DLM_LKF_NOQUEUE;
117                 lkf |= DLM_LKF_NOQUEUEBAST;
118         }
119 
120         if (gfs_flags & LM_FLAG_PRIORITY) {
121                 lkf |= DLM_LKF_NOORDER;
122                 lkf |= DLM_LKF_HEADQUE;
123         }
124 
125         if (gfs_flags & LM_FLAG_ANY) {
126                 if (req == DLM_LOCK_PR)
127                         lkf |= DLM_LKF_ALTCW;
128                 else if (req == DLM_LOCK_CW)
129                         lkf |= DLM_LKF_ALTPR;
130                 else
131                         BUG();
132         }
133 
134         if (lkid != 0) 
135                 lkf |= DLM_LKF_CONVERT;
136 
137         lkf |= DLM_LKF_VALBLK;
138 
139         return lkf;
140 }
141 
142 static unsigned int gdlm_lock(struct gfs2_glock *gl,
143                               unsigned int req_state, unsigned int flags)
144 {
145         struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
146         int error;
147         int req;
148         u32 lkf;
149 
150         gl->gl_req = req_state;
151         req = make_mode(req_state);
152         lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req);
153 
154         /*
155          * Submit the actual lock request.
156          */
157 
158         error = dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, gl->gl_strname,
159                          GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast);
160         if (error == -EAGAIN)
161                 return 0;
162         if (error)
163                 return LM_OUT_ERROR;
164         return LM_OUT_ASYNC;
165 }
166 
167 static void gdlm_put_lock(struct kmem_cache *cachep, void *ptr)
168 {
169         struct gfs2_glock *gl = ptr;
170         struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
171         int error;
172 
173         if (gl->gl_lksb.sb_lkid == 0) {
174                 kmem_cache_free(cachep, gl);
175                 return;
176         }
177 
178         error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK,
179                            NULL, gl);
180         if (error) {
181                 printk(KERN_ERR "gdlm_unlock %x,%llx err=%d\n",
182                        gl->gl_name.ln_type,
183                        (unsigned long long)gl->gl_name.ln_number, error);
184                 return;
185         }
186 }
187 
188 static void gdlm_cancel(struct gfs2_glock *gl)
189 {
190         struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
191         dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_CANCEL, NULL, gl);
192 }
193 
194 static int gdlm_mount(struct gfs2_sbd *sdp, const char *fsname)
195 {
196         struct lm_lockstruct *ls = &sdp->sd_lockstruct;
197         int error;
198 
199         if (fsname == NULL) {
200                 fs_info(sdp, "no fsname found\n");
201                 return -EINVAL;
202         }
203 
204         error = dlm_new_lockspace(fsname, strlen(fsname), &ls->ls_dlm,
205                                   DLM_LSFL_FS | DLM_LSFL_NEWEXCL |
206                                   (ls->ls_nodir ? DLM_LSFL_NODIR : 0),
207                                   GDLM_LVB_SIZE);
208         if (error)
209                 printk(KERN_ERR "dlm_new_lockspace error %d", error);
210 
211         return error;
212 }
213 
214 static void gdlm_unmount(struct gfs2_sbd *sdp)
215 {
216         struct lm_lockstruct *ls = &sdp->sd_lockstruct;
217 
218         if (ls->ls_dlm) {
219                 dlm_release_lockspace(ls->ls_dlm, 2);
220                 ls->ls_dlm = NULL;
221         }
222 }
223 
224 static const match_table_t dlm_tokens = {
225         { Opt_jid, "jid=%d"},
226         { Opt_id, "id=%d"},
227         { Opt_first, "first=%d"},
228         { Opt_nodir, "nodir=%d"},
229         { Opt_err, NULL },
230 };
231 
232 const struct lm_lockops gfs2_dlm_ops = {
233         .lm_proto_name = "lock_dlm",
234         .lm_mount = gdlm_mount,
235         .lm_unmount = gdlm_unmount,
236         .lm_put_lock = gdlm_put_lock,
237         .lm_lock = gdlm_lock,
238         .lm_cancel = gdlm_cancel,
239         .lm_tokens = &dlm_tokens,
240 };
241 
242 
  This page was automatically generated by the LXR engine.