]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/ocfs2/stackglue.c
ocfs2: Use -errno instead of dlm_status for ocfs2_dlm_lock/unlock() API.
[linux-2.6-omap-h63xx.git] / fs / ocfs2 / stackglue.c
index 99538043fc17194d6d6e183354eae924cf7ec00d..0aec2fcf21758ed40a15434b846050128f3051ba 100644 (file)
@@ -18,6 +18,7 @@
  * General Public License for more details.
  */
 
+#include "cluster/masklog.h"
 #include "stackglue.h"
 
 static struct ocfs2_locking_protocol *lproto;
@@ -77,7 +78,126 @@ static int flags_to_o2dlm(u32 flags)
 }
 #undef map_flag
 
-enum dlm_status ocfs2_dlm_lock(struct dlm_ctxt *dlm,
+/*
+ * Map an o2dlm status to standard errno values.
+ *
+ * o2dlm only uses a handful of these, and returns even fewer to the
+ * caller. Still, we try to assign sane values to each error.
+ *
+ * The following value pairs have special meanings to dlmglue, thus
+ * the right hand side needs to stay unique - never duplicate the
+ * mapping elsewhere in the table!
+ *
+ * DLM_NORMAL:         0
+ * DLM_NOTQUEUED:      -EAGAIN
+ * DLM_CANCELGRANT:    -DLM_ECANCEL
+ * DLM_CANCEL:         -DLM_EUNLOCK
+ */
+/* Keep in sync with dlmapi.h */
+static int status_map[] = {
+       [DLM_NORMAL]                    = 0,            /* Success */
+       [DLM_GRANTED]                   = -EINVAL,
+       [DLM_DENIED]                    = -EACCES,
+       [DLM_DENIED_NOLOCKS]            = -EACCES,
+       [DLM_WORKING]                   = -EBUSY,
+       [DLM_BLOCKED]                   = -EINVAL,
+       [DLM_BLOCKED_ORPHAN]            = -EINVAL,
+       [DLM_DENIED_GRACE_PERIOD]       = -EACCES,
+       [DLM_SYSERR]                    = -ENOMEM,      /* It is what it is */
+       [DLM_NOSUPPORT]                 = -EPROTO,
+       [DLM_CANCELGRANT]               = -DLM_ECANCEL, /* Cancel after grant */
+       [DLM_IVLOCKID]                  = -EINVAL,
+       [DLM_SYNC]                      = -EINVAL,
+       [DLM_BADTYPE]                   = -EINVAL,
+       [DLM_BADRESOURCE]               = -EINVAL,
+       [DLM_MAXHANDLES]                = -ENOMEM,
+       [DLM_NOCLINFO]                  = -EINVAL,
+       [DLM_NOLOCKMGR]                 = -EINVAL,
+       [DLM_NOPURGED]                  = -EINVAL,
+       [DLM_BADARGS]                   = -EINVAL,
+       [DLM_VOID]                      = -EINVAL,
+       [DLM_NOTQUEUED]                 = -EAGAIN,      /* Trylock failed */
+       [DLM_IVBUFLEN]                  = -EINVAL,
+       [DLM_CVTUNGRANT]                = -EPERM,
+       [DLM_BADPARAM]                  = -EINVAL,
+       [DLM_VALNOTVALID]               = -EINVAL,
+       [DLM_REJECTED]                  = -EPERM,
+       [DLM_ABORT]                     = -EINVAL,
+       [DLM_CANCEL]                    = -DLM_EUNLOCK, /* Successful cancel */
+       [DLM_IVRESHANDLE]               = -EINVAL,
+       [DLM_DEADLOCK]                  = -EDEADLK,
+       [DLM_DENIED_NOASTS]             = -EINVAL,
+       [DLM_FORWARD]                   = -EINVAL,
+       [DLM_TIMEOUT]                   = -ETIMEDOUT,
+       [DLM_IVGROUPID]                 = -EINVAL,
+       [DLM_VERS_CONFLICT]             = -EOPNOTSUPP,
+       [DLM_BAD_DEVICE_PATH]           = -ENOENT,
+       [DLM_NO_DEVICE_PERMISSION]      = -EPERM,
+       [DLM_NO_CONTROL_DEVICE]         = -ENOENT,
+       [DLM_RECOVERING]                = -ENOTCONN,
+       [DLM_MIGRATING]                 = -ERESTART,
+       [DLM_MAXSTATS]                  = -EINVAL,
+};
+static int dlm_status_to_errno(enum dlm_status status)
+{
+       BUG_ON(status > (sizeof(status_map) / sizeof(status_map[0])));
+
+       return status_map[status];
+}
+
+static void o2dlm_lock_ast_wrapper(void *astarg)
+{
+       BUG_ON(lproto == NULL);
+
+       lproto->lp_lock_ast(astarg);
+}
+
+static void o2dlm_blocking_ast_wrapper(void *astarg, int level)
+{
+       BUG_ON(lproto == NULL);
+
+       lproto->lp_blocking_ast(astarg, level);
+}
+
+static void o2dlm_unlock_ast_wrapper(void *astarg, enum dlm_status status)
+{
+       int error;
+
+       BUG_ON(lproto == NULL);
+
+       /*
+        * XXX: CANCEL values are sketchy.
+        *
+        * Currently we have preserved the o2dlm paradigm.  You can get
+        * unlock_ast() whether the cancel succeded or not.
+        *
+        * First, we're going to pass DLM_EUNLOCK just like fs/dlm does for
+        * successful unlocks.  That is a clean behavior.
+        *
+        * In o2dlm, you can get both the lock_ast() for the lock being
+        * granted and the unlock_ast() for the CANCEL failing.  A
+        * successful cancel sends DLM_NORMAL here.  If the
+        * lock grant happened before the cancel arrived, you get
+        * DLM_CANCELGRANT.  For now, we'll use DLM_ECANCEL to signify
+        * CANCELGRANT - the CANCEL was supposed to happen but didn't.  We
+        * can then use DLM_EUNLOCK to signify a successful CANCEL -
+        * effectively, the CANCEL caused the lock to roll back.
+        *
+        * In the future, we will likely move the o2dlm to send only one
+        * ast - either unlock_ast() for a successful CANCEL or lock_ast()
+        * when the grant succeeds.  At that point, we'll send DLM_ECANCEL
+        * for all cancel results (CANCELGRANT will no longer exist).
+        */
+       error = dlm_status_to_errno(status);
+
+       /* Successful unlock is DLM_EUNLOCK */
+       if (!error)
+               error = -DLM_EUNLOCK;
+
+       lproto->lp_unlock_ast(astarg, error);
+}
+
+int ocfs2_dlm_lock(struct dlm_ctxt *dlm,
                   int mode,
                   struct dlm_lockstatus *lksb,
                   u32 flags,
@@ -85,27 +205,35 @@ enum dlm_status ocfs2_dlm_lock(struct dlm_ctxt *dlm,
                   unsigned int namelen,
                   void *astarg)
 {
+       enum dlm_status status;
        int o2dlm_mode = mode_to_o2dlm(mode);
        int o2dlm_flags = flags_to_o2dlm(flags);
+       int ret;
 
        BUG_ON(lproto == NULL);
 
-       return dlmlock(dlm, o2dlm_mode, lksb, o2dlm_flags, name, namelen,
-                      lproto->lp_lock_ast, astarg,
-                      lproto->lp_blocking_ast);
+       status = dlmlock(dlm, o2dlm_mode, lksb, o2dlm_flags, name, namelen,
+                      o2dlm_lock_ast_wrapper, astarg,
+                      o2dlm_blocking_ast_wrapper);
+       ret = dlm_status_to_errno(status);
+       return ret;
 }
 
-enum dlm_status ocfs2_dlm_unlock(struct dlm_ctxt *dlm,
+int ocfs2_dlm_unlock(struct dlm_ctxt *dlm,
                     struct dlm_lockstatus *lksb,
                     u32 flags,
                     void *astarg)
 {
+       enum dlm_status status;
        int o2dlm_flags = flags_to_o2dlm(flags);
+       int ret;
 
        BUG_ON(lproto == NULL);
 
-       return dlmunlock(dlm, lksb, o2dlm_flags,
-                        lproto->lp_unlock_ast, astarg);
+       status = dlmunlock(dlm, lksb, o2dlm_flags,
+                        o2dlm_unlock_ast_wrapper, astarg);
+       ret = dlm_status_to_errno(status);
+       return ret;
 }