1. 18 Apr, 2008 16 commits
    • Joel Becker's avatar
      ocfs2: Remove CANCELGRANT from the view of dlmglue. · de551246
      Joel Becker authored
      o2dlm has the non-standard behavior of providing a cancel callback
      (unlock_ast) even when the cancel has failed (the locking operation
      succeeded without canceling).  This is called CANCELGRANT after the
      status code sent to the callback.  fs/dlm does not provide this
      callback, so dlmglue must be changed to live without it.
      o2dlm_unlock_ast_wrapper() in stackglue now ignores CANCELGRANT calls.
      
      Because dlmglue no longer sees CANCELGRANT, ocfs2_unlock_ast() no longer
      needs to check for it.  ocfs2_locking_ast() must catch that a cancel was
      tried and clear the cancel state.
      
      Making these changes opens up a locking race.  dlmglue uses the the
      OCFS2_LOCK_BUSY flag to ensure only one thread is calling the dlm at any
      one time.  But dlmglue must unlock the lockres before calling into the
      dlm.  In the small window of time between unlocking the lockres and
      calling the dlm, the downconvert thread can try to cancel the lock.  The
      downconvert thread is checking the OCFS2_LOCK_BUSY flag - it doesn't
      know that ocfs2_dlm_lock() has not yet been called.
      
      Because ocfs2_dlm_lock() has not yet been called, the cancel operation
      will just be a no-op.  There's nothing to cancel.  With CANCELGRANT,
      dlmglue uses the CANCELGRANT callback to clear up the cancel state.
      When it comes around again, it will retry the cancel.  Eventually, the
      first thread will have called into ocfs2_dlm_lock(), and either the
      lock or the cancel will succeed.  The downconvert thread can then do its
      downconvert.
      
      Without CANCELGRANT, there is nothing to clean up the cancellation
      state.  The downconvert thread does not know to retry its operations.
      More importantly, the original lock may be blocking on the other node
      that is trying to cancel us.  With neither able to make progress, the
      ast is never called and the cancellation state is never cleaned up that
      way.  dlmglue is deadlocked.
      
      The OCFS2_LOCK_PENDING flag is introduced to remedy this window.  It is
      set at the same time OCFS2_LOCK_BUSY is.  Thus, the downconvert thread
      can check whether the lock is cancelable.  If not, it just loops around
      to try again.  Once ocfs2_dlm_lock() is called, the thread then clears
      OCFS2_LOCK_PENDING and wakes the downconvert thread.  Now, if the
      downconvert thread finds the lock BUSY, it can safely try to cancel it.
      Whether the cancel works or not, the state will be properly set and the
      lock processing can continue.
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      de551246
    • Mark Fasheh's avatar
      ocfs2: Fill node number during cluster stack init · 0abd6d18
      Mark Fasheh authored
      It doesn't make sense to query for a node number before connecting to the
      cluster stack. This should be safe to do because node_num is only just
      printed,
      and we're actually only moving the setting of node num a small amount
      further in the mount process.
      
      [ Disconnect when node query fails -- Joel ]
      Reviewed-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      0abd6d18
    • Joel Becker's avatar
      ocfs2: Move o2hb functionality into the stack glue. · 6953b4c0
      Joel Becker authored
      The last bit of classic stack used directly in ocfs2 code is o2hb.
      Specifically, the check for heartbeat during mount and the call to
      ocfs2_hb_ctl during unmount.
      
      We create an extra API, ocfs2_cluster_hangup(), to encapsulate the call
      to ocfs2_hb_ctl.  Other stacks will just leave hangup() empty.
      
      The check for heartbeat is moved into ocfs2_cluster_connect().  It will
      be matched by a similar check for other stacks.
      
      With this change, only stackglue.c includes cluster/ headers.
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      6953b4c0
    • Joel Becker's avatar
      ocfs2: Abstract out node number queries. · 19fdb624
      Joel Becker authored
      ocfs2 asks the cluster stack for the local node's node number for two
      reasons; to fill the slot map and to print it. While the slot map isn't
      necessary for userspace cluster stacks, the printing is very nice for
      debugging. Thus we add ocfs2_cluster_this_node() as a generic API to get
      this value. It is anticipated that the slot map will not be used under a
      userspace cluster stack, so validity checks of the node num only need to
      exist in the slot map code. Otherwise, it just gets used and printed as an
      opaque value.
      
      [ Fixed up some "int" versus "unsigned int" issues and made osb->node_num
        truly opaque. --Mark ]
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      19fdb624
    • Joel Becker's avatar
      ocfs2: Introduce the new ocfs2_cluster_connect/disconnect() API. · 4670c46d
      Joel Becker authored
      This step introduces a cluster stack agnostic API for initializing and
      exiting.  fs/ocfs2/dlmglue.c no longer uses o2cb/o2dlm knowledge to
      connect to the stack.  It is all handled in stackglue.c.
      
      heartbeat.c no longer needs to know how it gets called.
      ocfs2_do_node_down() is now a clean recovery trigger.
      
      The big gotcha is the ordering of initializations and de-initializations done
      underneath ocfs2_cluster_connect().  ocfs2_dlm_init() used to do all
      o2dlm initialization in one block.  Thus, the o2dlm functionality of
      ocfs2_cluster_connect() is very straightforward.  ocfs2_dlm_shutdown(),
      however, did a few things between de-registration of the eviction
      callback and actually shutting down the domain.  Now de-registration and
      shutdown of the domain are wrapped within the single
      ocfs2_cluster_disconnect() call.  I've checked the code paths to make
      sure we can safely tear down things in ocfs2_dlm_shutdown() before
      calling ocfs2_cluster_disconnect().  The filesystem has already set
      itself to ignore the callback.
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      4670c46d
    • Joel Becker's avatar
      ocfs2: Create the lock status block union. · 8f2c9c1b
      Joel Becker authored
      Wrap the lock status block (lksb) in a union.  Later we will add a union
      element for the fs/dlm lksb.  Create accessors for the status and lvb
      fields.
      
      Other than a debugging function, dlmglue.c does not directly reference
      the o2dlm locking path anymore.
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      8f2c9c1b
    • Joel Becker's avatar
      ocfs2: Use -errno instead of dlm_status for ocfs2_dlm_lock/unlock() API. · 7431cd7e
      Joel Becker authored
      Change the ocfs2_dlm_lock/unlock() functions to return -errno values.
      This is the first step towards elminiating dlm_status in
      fs/ocfs2/dlmglue.c.  The change also passes -errno values to
      ->unlock_ast().
      
      [ Fix a return code in dlmglue.c and change the error translation table into
        an array of ints. --Mark ]
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      7431cd7e
    • Joel Becker's avatar
      ocfs2: Use global DLM_ constants in generic code. · bd3e7610
      Joel Becker authored
      The ocfs2 generic code should use the values in <linux/dlmconstants.h>.
      stackglue.c will convert them to o2dlm values.
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      bd3e7610
    • Joel Becker's avatar
      ocfs2: Separate out dlm lock functions. · 24ef1815
      Joel Becker authored
      This is the first in a series of patches to isolate ocfs2 from the
      underlying cluster stack. Here we wrap the dlm locking functions with
      ocfs2-specific calls. Because ocfs2 always uses the same dlm lock status
      callbacks, we can eliminate the callbacks from the filesystem visible
      functions.
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      24ef1815
    • Joel Becker's avatar
      ocfs2: New slot map format · 386a2ef8
      Joel Becker authored
      The old slot map had a few limitations:
      
      - It was limited to one block, so the maximum slot count was 255.
      - Each slot was signed 16bits, limiting node numbers to INT16_MAX.
      - An empty slot was marked by the magic 0xFFFF (-1).
      
      The new slot map format provides 32bit node numbers (UINT32_MAX), a
      separate space to mark a slot in use, and extra room to grow.  The slot
      map is now bounded by i_size, not a block.
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      386a2ef8
    • Joel Becker's avatar
      ocfs2: Define the contents of the slot_map file. · fb86b1f0
      Joel Becker authored
      The slot map file is merely an array of __le16.  Wrap it in a structure for
      cleaner reference.
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      fb86b1f0
    • Joel Becker's avatar
      ocfs2: De-magic the in-memory slot map. · fc881fa0
      Joel Becker authored
      The in-memory slot map uses the same magic as the on-disk one.  There is
      a special value to mark a slot as invalid.  It relies on the size of
      certain types and so on.
      
      Write a new in-memory map that keeps validity as a separate field.  Outside
      of the I/O functions, OCFS2_INVALID_SLOT now means what it is supposed to.
      It also is no longer tied to the type size.
      
      This also means that only the I/O functions refer to 16bit quantities.
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      fc881fa0
    • Joel Becker's avatar
      ocfs2: slot_map I/O based on max_slots. · 1c8d9a6a
      Joel Becker authored
      The slot map code assumed a slot_map file has one block allocated.
      This changes the code to I/O as many blocks as will cover max_slots.
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      1c8d9a6a
    • Joel Becker's avatar
      ocfs2: Change the recovery map to an array of node numbers. · 553abd04
      Joel Becker authored
      The old recovery map was a bitmap of node numbers.  This was sufficient
      for the maximum node number of 254.  Going forward, we want node numbers
      to be UINT32.  Thus, we need a new recovery map.
      
      Note that we can't keep track of slots here.  We must write down the
      node number to recovery *before* we get the locks needed to convert a
      node number into a slot number.
      
      The recovery map is now an array of unsigned ints, max_slots in size.
      It moves to journal.c with the rest of recovery.
      
      Because it needs to be initialized, we move all of recovery initialization
      into a new function, ocfs2_recovery_init().  This actually cleans up
      ocfs2_initialize_super() a little as well.  Following on, recovery cleaup
      becomes part of ocfs2_recovery_exit().
      
      A number of node map functions are rendered obsolete and are removed.
      
      Finally, waiting on recovery is wrapped in a function rather than naked
      checks on the recovery_event.  This is a cleanup from Mark.
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      553abd04
    • Joel Becker's avatar
      ocfs2: Make ocfs2_slot_info private. · d85b20e4
      Joel Becker authored
      Just use osb_lock around the ocfs2_slot_info data.  This allows us to
      take the ocfs2_slot_info structure private in slot_info.c.  All access
      is now via accessors.
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      d85b20e4
    • Mark Fasheh's avatar
      ocfs2: Move slot map access into slot_map.c · 8e8a4603
      Mark Fasheh authored
      journal.c and dlmglue.c would refresh the slot map by hand.  Instead, have
      the update and clear functions do the work inside slot_map.c.  The eventual
      result is to make ocfs2_slot_info defined privately in slot_map.c
      Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
      Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
      8e8a4603
  2. 17 Apr, 2008 2 commits
  3. 16 Apr, 2008 22 commits