fs/nfsd/nfssvc.c

Source file repositories/reference/linux-study-clean/fs/nfsd/nfssvc.c

File Facts

System
Linux kernel
Corpus path
fs/nfsd/nfssvc.c
Extension
.c
Size
27448 bytes
Lines
1079
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (nn->lockd_up) {
			lockd_down(net);
			nn->lockd_up = false;
		}
		wait_for_completion(&nn->nfsd_net_free_done);
	}

	percpu_ref_exit(&nn->nfsd_net_ref);

	if (nn->nfsd_net_up)
		nfsd_shutdown_generic();
	nn->nfsd_net_up = false;
}

static DEFINE_SPINLOCK(nfsd_notifier_lock);
static int nfsd_inetaddr_event(struct notifier_block *this, unsigned long event,
	void *ptr)
{
	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
	struct net_device *dev = ifa->ifa_dev->dev;
	struct net *net = dev_net(dev);
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
	struct sockaddr_in sin;

	if (event != NETDEV_DOWN || !nn->nfsd_serv)
		goto out;

	spin_lock(&nfsd_notifier_lock);
	if (nn->nfsd_serv) {
		dprintk("nfsd_inetaddr_event: removed %pI4\n", &ifa->ifa_local);
		sin.sin_family = AF_INET;
		sin.sin_addr.s_addr = ifa->ifa_local;
		svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin);
	}
	spin_unlock(&nfsd_notifier_lock);

out:
	return NOTIFY_DONE;
}

static struct notifier_block nfsd_inetaddr_notifier = {
	.notifier_call = nfsd_inetaddr_event,
};

#if IS_ENABLED(CONFIG_IPV6)
static int nfsd_inet6addr_event(struct notifier_block *this,
	unsigned long event, void *ptr)
{
	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
	struct net_device *dev = ifa->idev->dev;
	struct net *net = dev_net(dev);
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
	struct sockaddr_in6 sin6;

	if (event != NETDEV_DOWN || !nn->nfsd_serv)
		goto out;

	spin_lock(&nfsd_notifier_lock);
	if (nn->nfsd_serv) {
		dprintk("nfsd_inet6addr_event: removed %pI6\n", &ifa->addr);
		sin6.sin6_family = AF_INET6;
		sin6.sin6_addr = ifa->addr;
		if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
			sin6.sin6_scope_id = ifa->idev->dev->ifindex;
		svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin6);
	}
	spin_unlock(&nfsd_notifier_lock);

out:
	return NOTIFY_DONE;
}

static struct notifier_block nfsd_inet6addr_notifier = {
	.notifier_call = nfsd_inet6addr_event,
};
#endif

/* Only used under nfsd_mutex, so this atomic may be overkill: */
static atomic_t nfsd_notifier_refcount = ATOMIC_INIT(0);

/**
 * nfsd_destroy_serv - tear down NFSD's svc_serv for a namespace
 * @net: network namespace the NFS service is associated with
 */
void nfsd_destroy_serv(struct net *net)
{
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
	struct svc_serv *serv = nn->nfsd_serv;

	lockdep_assert_held(&nfsd_mutex);

Annotation

Implementation Notes