[PATCH/RFC 00/19] Support loop-back NFS mounts

NeilBrown
2014-04-16T04:17:49Z

Loop-back NFS mounts are when the NFS client and server run on the
same host.

The use-case for this is a high availability cluster with shared
storage. The shared filesystem is mounted on any one machine and
NFS-mounted on the others.
If the nfs server fails, some other node will take over that service,
and then it will have a loop-back NFS mount which needs to keep
working.

This patch set addresses the "keep working" bit and specifically
addresses deadlocks and livelocks.
Allowing the fail-over itself to be deadlock free is a separate
challenge for another day.

The short description of how this works is:

deadlocks:
- Elevate PF_FSTRANS to apply globally instead of just in NFS and XFS.
PF_FSTRANS disables __GFP_NS in the same way that PF_MEMALLOC_NOIO
disables __GFP_IO.
- Set PF_FSTRANS in nfsd when handling requests related to
memory reclaim, or requests which could block requests related
to memory reclaim.
- Use lockdep to find all consequent deadlocks from some other
thread allocating memory while holding a lock that nfsd might
want.
- Fix those other deadlocks by setting PF_FSTRANS or using GFP_NOFS
as appropriate.

livelocks:
- identify throttling during reclaim and bypass it when
PF_LESS_THROTTLE is set
- only set PF_LESS_THROTTLE for nfsd when handling write requests
from the local host.

The last 12 patches address various deadlocks due to locking chains.
11 were found by lockdep, 2 by testing. There is a reasonable chance
that there are more, I just need to exercise more code while
testing....

There is one issue that lockdep reports which I haven't fixed (I've
just hacked the code out for my testing). That issue relates to
freeze_super().
I may not be interpreting the lockdep reports perfectly, but I think
they are basically saying that if I were to freeze a filesystem that
was exported to the local host, then we could end up deadlocking.
This is to be expected. The NFS filesystem would need to be frozen
first. I don't know how to tell lockdep that I know that is a problem
and I don't want to be warned about it. Suggestions welcome.
Until this is addressed I cannot really ask others to test the code
with lockdep enabled.

There are more subsidiary places that I needed to add PF_FSTRANS than
I would have liked. The thought keeps crossing my mind that maybe we
can get rid of __GFP_FS and require that memory reclaim never ever
block on a filesystem. Then most of these patches go away.

Now that writeback doesn't happen from reclaim (but from kswapd) much
of the calls from reclaim to FS are gone.
The ->releasepage call is the only one that I *know* causes me
problems so I'd like to just say that that must never block. I don't
really understand the consequences of that though.
There are a couple of other places where __GFP_FS is used and I'd need
to carefully analyze those. But if someone just said "no, that is
impossible", I could be happy and stick with the current approach....

I've cc:ed Peter Zijlstra and Ingo Molnar only on the lockdep-related
patches, Ming Lei only on the PF_MEMALLOC_NOIO related patches,
and net-dev only on the network-related patches.
There are probably other people I should CC. Apologies if I missed you.
I'll ensure better coverage if the nfs/mm/xfs people are reasonably happy.

Comments, criticisms, etc most welcome.

Thanks,
NeilBrown

---

NeilBrown (19):
Promote current_{set,restore}_flags_nested from xfs to global.
lockdep: lockdep_set_current_reclaim_state should save old value
lockdep: improve scenario messages for RECLAIM_FS errors.
Make effect of PF_FSTRANS to disable __GFP_FS universal.
SUNRPC: track whether a request is coming from a loop-back interface.
nfsd: set PF_FSTRANS for nfsd threads.
nfsd and VM: use PF_LESS_THROTTLE to avoid throttle in shrink_inactive_list.
Set PF_FSTRANS while write_cache_pages calls ->writepage
XFS: ensure xfs_file_*_read cannot deadlock in memory allocation.
NET: set PF_FSTRANS while holding sk_lock
FS: set PF_FSTRANS while holding mmap_sem in exec.c
NET: set PF_FSTRANS while holding rtnl_lock
MM: set PF_FSTRANS while allocating per-cpu memory to avoid deadlock.
driver core: set PF_FSTRANS while holding gdp_mutex
nfsd: set PF_FSTRANS when client_mutex is held.
VFS: use GFP_NOFS rather than GFP_KERNEL in __d_alloc.
VFS: set PF_FSTRANS while namespace_sem is held.
nfsd: set PF_FSTRANS during nfsd4_do_callback_rpc.
XFS: set PF_FSTRANS while ilock is held in xfs_free_eofblocks

drivers/base/core.c | 3 ++
drivers/base/power/runtime.c | 6 ++---
drivers/block/nbd.c | 6 ++---
drivers/md/dm-bufio.c | 6 ++---
drivers/md/dm-ioctl.c | 6 ++---
drivers/mtd/nand/nandsim.c | 28 ++++++---------------
drivers/scsi/iscsi_tcp.c | 6 ++---
drivers/usb/core/hub.c | 6 ++---
fs/dcache.c | 4 ++-
fs/exec.c | 6 +++++
fs/fs-writeback.c | 5 ++--
fs/namespace.c | 4 +++
fs/nfs/file.c | 3 +-
fs/nfsd/nfs4callback.c | 5 ++++
fs/nfsd/nfs4state.c | 3 ++
fs/nfsd/nfssvc.c | 24 ++++++++++++++----
fs/nfsd/vfs.c | 6 +++++
fs/xfs/kmem.h | 2 --
fs/xfs/xfs_aops.c | 7 -----
fs/xfs/xfs_bmap_util.c | 4 +++
fs/xfs/xfs_file.c | 12 +++++++++
fs/xfs/xfs_linux.h | 7 -----
include/linux/lockdep.h | 8 +++---
include/linux/sched.h | 32 +++++++++---------------
include/linux/sunrpc/svc.h | 2 ++
include/linux/sunrpc/svc_xprt.h | 1 +
include/net/sock.h | 1 +
kernel/locking/lockdep.c | 51 ++++++++++++++++++++++++++++-----------
kernel/softirq.c | 6 ++---
mm/migrate.c | 9 +++----
mm/page-writeback.c | 3 ++
mm/page_alloc.c | 18 ++++++++------
mm/percpu.c | 4 +++
mm/slab.c | 2 ++
mm/slob.c | 2 ++
mm/slub.c | 1 +
mm/vmscan.c | 31 +++++++++++++++---------
net/core/dev.c | 6 ++---
net/core/rtnetlink.c | 9 ++++++-
net/core/sock.c | 8 ++++--
net/sunrpc/sched.c | 5 ++--
net/sunrpc/svc.c | 6 +++++
net/sunrpc/svcsock.c | 10 ++++++++
net/sunrpc/xprtrdma/transport.c | 5 ++--
net/sunrpc/xprtsock.c | 17 ++++++++-----
45 files changed, 247 insertions(+), 149 deletions(-)

--
Signature