Skip to content
  • Chuck Lever's avatar
    lockd: Update NSM state from SM_MON replies · 6c9dc425
    Chuck Lever authored
    
    
    When rpc.statd starts up in user space at boot time, it attempts to
    write the latest NSM local state number into
    /proc/sys/fs/nfs/nsm_local_state.
    
    If lockd.ko isn't loaded yet (as is the case in most configurations),
    that file doesn't exist, thus the kernel's NSM state remains set to
    its initial value of zero during lockd operation.
    
    This is a problem because rpc.statd and lockd use the NSM state number
    to prevent repeated lock recovery on rebooted hosts.  If lockd sends
    a zero NSM state, but then a delayed SM_NOTIFY with a real NSM state
    number is received, there is no way for lockd or rpc.statd to
    distinguish that stale SM_NOTIFY from an actual reboot.  Thus lock
    recovery could be performed after the rebooted host has already
    started reclaiming locks, and those locks will be lost.
    
    We could change /etc/init.d/nfslock so it always modprobes lockd.ko
    before starting rpc.statd.  However, if lockd.ko is ever unloaded
    and reloaded, we are back at square one, since the NSM state is not
    preserved across an unload/reload cycle.  This may happen frequently
    on clients that use automounter.  A period of NFS inactivity causes
    lockd.ko to be unloaded, and the kernel loses its NSM state setting.
    
    Instead, let's use the fact that rpc.statd plants the local system's
    NSM state in every SM_MON (and SM_UNMON) reply.  lockd performs a
    synchronous SM_MON upcall to the local rpc.statd _before_ sending its
    first NLM request to a new remote.  This would permit rpc.statd to
    provide the current NSM state to lockd, even after lockd.ko had been
    unloaded and reloaded.
    
    Note that NLMPROC_LOCK arguments are constructed before the
    nsm_monitor() call, so we have to rearrange argument construction very
    slightly to make this all work out.
    
    And, the kernel appears to treat NSM state as a u32 (see struct
    nlm_args and nsm_res).  Make nsm_local_state a u32 as well, to ensure
    we don't get bogus comparison results.
    
    Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
    Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
    6c9dc425