diff -u --recursive --new-file linux-2.4.10-rdplus/fs/lockd/clntlock.c linux-2.4.10-reclaim/fs/lockd/clntlock.c --- linux-2.4.10-rdplus/fs/lockd/clntlock.c Mon Sep 24 00:33:20 2001 +++ linux-2.4.10-reclaim/fs/lockd/clntlock.c Wed Sep 26 16:28:13 2001 @@ -8,6 +8,7 @@ #define __KERNEL_SYSCALLS__ +#include #include #include #include @@ -17,7 +18,7 @@ #include #include -#define NLMDBG_FACILITY NLMDBG_CIENT +#define NLMDBG_FACILITY NLMDBG_CLIENT /* * Local function prototypes @@ -131,29 +132,63 @@ */ /* + * Mark the locks for reclaiming. + * FIXME: In 2.5 we don't want to iterate through any global file_lock_list. + * Maintain NLM lock reclaiming lists in the nlm_host instead. + */ +static +void nlmclnt_mark_reclaim(struct nlm_host *host) +{ + struct file_lock *fl; + struct inode *inode; + struct list_head *tmp; + + list_for_each(tmp, &file_lock_list) { + fl = list_entry(tmp, struct file_lock, fl_link); + + inode = fl->fl_file->f_dentry->d_inode; + if (inode->i_sb->s_magic != NFS_SUPER_MAGIC) + continue; + if (fl->fl_u.nfs_fl.host != host) + continue; + if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_GRANTED)) + continue; + fl->fl_u.nfs_fl.flags |= NFS_LCK_RECLAIM; + } +} + +/* + * Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number, + * that we mark locks for reclaiming, and that we bump the pseudo NSM state. + */ +static inline +void nlmclnt_prepare_reclaim(struct nlm_host *host, u32 newstate) +{ + host->h_monitored = 0; + host->h_nsmstate = newstate; + host->h_state++; + host->h_nextrebind = 0; + nlm_rebind_host(host); + nlmclnt_mark_reclaim(host); + dprintk("NLM: reclaiming locks for host %s", host->h_name); +} + +/* * Reclaim all locks on server host. We do this by spawning a separate * reclaimer thread. - * FIXME: should bump MOD_USE_COUNT while reclaiming */ void nlmclnt_recovery(struct nlm_host *host, u32 newstate) { - if (!host->h_reclaiming++) { + if (host->h_reclaiming++) { if (host->h_nsmstate == newstate) return; - printk(KERN_WARNING - "lockd: Uh-oh! Interfering reclaims for host %s", - host->h_name); - host->h_monitored = 0; - host->h_nsmstate = newstate; - host->h_state++; - nlm_release_host(host); + nlmclnt_prepare_reclaim(host, newstate); } else { - host->h_monitored = 0; - host->h_nsmstate = newstate; - host->h_state++; + nlmclnt_prepare_reclaim(host, newstate); nlm_get_host(host); - kernel_thread(reclaimer, host, 0); + MOD_INC_USE_COUNT; + kernel_thread(reclaimer, host, CLONE_SIGNAL); } } @@ -163,32 +198,38 @@ struct nlm_host *host = (struct nlm_host *) ptr; struct nlm_wait *block; struct list_head *tmp; + struct file_lock *fl; + struct inode *inode; + daemonize(); reparent_to_init(); snprintf(current->comm, sizeof(current->comm), "%s-reclaim", host->h_name); - + /* This one ensures that our parent doesn't terminate while the * reclaim is in progress */ lock_kernel(); lockd_up(); - /* First, reclaim all locks that have been granted previously. */ + /* First, reclaim all locks that have been marked. */ restart: - tmp = file_lock_list.next; - while (tmp != &file_lock_list) { - struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link); - struct inode *inode = fl->fl_file->f_dentry->d_inode; - if (inode->i_sb->s_magic == NFS_SUPER_MAGIC && - nlm_cmp_addr(NFS_ADDR(inode), &host->h_addr) && - fl->fl_u.nfs_fl.state != host->h_state && - (fl->fl_u.nfs_fl.flags & NFS_LCK_GRANTED)) { - fl->fl_u.nfs_fl.flags &= ~ NFS_LCK_GRANTED; - nlmclnt_reclaim(host, fl); /* This sleeps */ - goto restart; - } - tmp = tmp->next; + list_for_each(tmp, &file_lock_list) { + fl = list_entry(tmp, struct file_lock, fl_link); + + inode = fl->fl_file->f_dentry->d_inode; + if (inode->i_sb->s_magic != NFS_SUPER_MAGIC) + continue; + if (fl->fl_u.nfs_fl.host != host) + continue; + if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_RECLAIM)) + continue; + + fl->fl_u.nfs_fl.flags &= ~NFS_LCK_RECLAIM; + nlmclnt_reclaim(host, fl); + if (signalled()) + break; + goto restart; } host->h_reclaiming = 0; @@ -206,6 +247,7 @@ nlm_release_host(host); lockd_down(); unlock_kernel(); + MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file linux-2.4.10-rdplus/fs/lockd/host.c linux-2.4.10-reclaim/fs/lockd/host.c --- linux-2.4.10-rdplus/fs/lockd/host.c Fri Feb 9 20:29:44 2001 +++ linux-2.4.10-reclaim/fs/lockd/host.c Mon Sep 24 22:31:22 2001 @@ -51,7 +51,8 @@ struct nlm_host * nlmsvc_lookup_host(struct svc_rqst *rqstp) { - return nlm_lookup_host(rqstp->rq_client, &rqstp->rq_addr, 0, 0); + return nlm_lookup_host(rqstp->rq_client, &rqstp->rq_addr, + rqstp->rq_prot, rqstp->rq_vers); } /* @@ -97,7 +98,9 @@ nlm_gc_hosts(); for (hp = &nlm_hosts[hash]; (host = *hp); hp = &host->h_next) { - if (host->h_version != version || host->h_proto != proto) + if (proto && host->h_proto != proto) + continue; + if (version && host->h_version != version) continue; if (nlm_match_host(host, clnt, sin)) { @@ -325,7 +328,8 @@ } dprintk("lockd: delete host %s\n", host->h_name); *q = host->h_next; - if (host->h_monitored) + /* Don't unmonitor hosts that have been invalidated */ + if (host->h_monitored && !host->h_killed) nsm_unmonitor(host); if ((clnt = host->h_rpcclnt) != NULL) { if (atomic_read(&clnt->cl_users)) { diff -u --recursive --new-file linux-2.4.10-rdplus/fs/lockd/lockd_syms.c linux-2.4.10-reclaim/fs/lockd/lockd_syms.c --- linux-2.4.10-rdplus/fs/lockd/lockd_syms.c Thu Mar 9 15:57:08 2000 +++ linux-2.4.10-reclaim/fs/lockd/lockd_syms.c Tue Sep 25 11:51:15 2001 @@ -35,8 +35,4 @@ EXPORT_SYMBOL(nlmsvc_invalidate_client); EXPORT_SYMBOL(nlmsvc_ops); -/* Configuration at insmod time */ -EXPORT_SYMBOL(nlmsvc_grace_period); -EXPORT_SYMBOL(nlmsvc_timeout); - #endif /* CONFIG_MODULES */ diff -u --recursive --new-file linux-2.4.10-rdplus/fs/lockd/mon.c linux-2.4.10-reclaim/fs/lockd/mon.c --- linux-2.4.10-rdplus/fs/lockd/mon.c Tue Jun 12 04:15:27 2001 +++ linux-2.4.10-reclaim/fs/lockd/mon.c Mon Sep 24 00:37:22 2001 @@ -43,7 +43,7 @@ args.addr = host->h_addr.sin_addr.s_addr; args.prog = NLM_PROGRAM; - args.vers = 1; + args.vers = host->h_version; args.proc = NLMPROC_NSM_NOTIFY; memset(res, 0, sizeof(*res)); diff -u --recursive --new-file linux-2.4.10-rdplus/fs/lockd/svc.c linux-2.4.10-reclaim/fs/lockd/svc.c --- linux-2.4.10-rdplus/fs/lockd/svc.c Mon Sep 24 00:33:20 2001 +++ linux-2.4.10-reclaim/fs/lockd/svc.c Thu Sep 27 01:29:34 2001 @@ -43,7 +43,7 @@ static DECLARE_MUTEX(nlmsvc_sema); static unsigned int nlmsvc_users; static pid_t nlmsvc_pid; -unsigned long nlmsvc_grace_period; +int nlmsvc_grace_period; unsigned long nlmsvc_timeout; static DECLARE_MUTEX_LOCKED(lockd_start); @@ -56,6 +56,25 @@ unsigned long nlm_grace_period; unsigned long nlm_timeout = LOCKD_DFLT_TIMEO; +static unsigned long set_grace_period(void) +{ + unsigned long grace_period; + + /* Note: nlm_timeout should always be nonzero */ + if (nlm_grace_period) + grace_period = ((nlm_grace_period + nlm_timeout - 1) + / nlm_timeout) * nlm_timeout * HZ; + else + grace_period = nlm_timeout * 5 * HZ; + nlmsvc_grace_period = 1; + return grace_period + jiffies; +} + +static inline void clear_grace_period(void) +{ + nlmsvc_grace_period = 0; +} + /* * This is the lockd kernel thread */ @@ -84,7 +103,7 @@ spin_lock_irq(¤t->sigmask_lock); siginitsetinv(¤t->blocked, sigmask(SIGKILL)); recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sigmask_lock); /* kick rpciod */ rpciod_up(); @@ -93,21 +112,10 @@ if (!nlm_timeout) nlm_timeout = LOCKD_DFLT_TIMEO; - -#ifdef RPC_DEBUG - nlmsvc_grace_period = 10 * HZ; -#else - if (nlm_grace_period) { - nlmsvc_grace_period += (1 + nlm_grace_period / nlm_timeout) - * nlm_timeout * HZ; - } else { - nlmsvc_grace_period += 5 * nlm_timeout * HZ; - } -#endif - - grace_period_expire = nlmsvc_grace_period + jiffies; nlmsvc_timeout = nlm_timeout * HZ; + grace_period_expire = set_grace_period(); + /* * The main request loop. We don't terminate until the last * NFS mount or NFS daemon has gone away, and we've been sent a @@ -122,13 +130,7 @@ spin_unlock_irq(¤t->sigmask_lock); if (nlmsvc_ops) { nlmsvc_ops->detach(); -#ifdef RPC_DEBUG - nlmsvc_grace_period = 10 * HZ; -#else - nlmsvc_grace_period += 5 * nlm_timeout * HZ; - -#endif - grace_period_expire = nlmsvc_grace_period + jiffies; + grace_period_expire = set_grace_period(); } } @@ -140,16 +142,15 @@ */ if (!nlmsvc_grace_period) { timeout = nlmsvc_retry_blocked(); - } else if (time_before(nlmsvc_grace_period, jiffies)) - nlmsvc_grace_period = 0; + } else if (time_before(grace_period_expire, jiffies)) + clear_grace_period(); /* * Find a socket with data available and call its * recvfrom routine. */ - if ((err = svc_recv(serv, rqstp, timeout)) == -EAGAIN - || err == -EINTR - ) + err = svc_recv(serv, rqstp, timeout); + if (err == -EAGAIN || err == -EINTR) continue; if (err < 0) { printk(KERN_WARNING @@ -345,7 +346,7 @@ * Define NLM program and procedures */ static struct svc_version nlmsvc_version1 = { - 1, 16, nlmsvc_procedures, NULL + 1, 17, nlmsvc_procedures, NULL }; static struct svc_version nlmsvc_version3 = { 3, 24, nlmsvc_procedures, NULL diff -u --recursive --new-file linux-2.4.10-rdplus/fs/lockd/svc4proc.c linux-2.4.10-reclaim/fs/lockd/svc4proc.c --- linux-2.4.10-rdplus/fs/lockd/svc4proc.c Fri Feb 9 20:29:44 2001 +++ linux-2.4.10-reclaim/fs/lockd/svc4proc.c Thu Sep 27 01:23:33 2001 @@ -420,6 +420,8 @@ void *resp) { struct sockaddr_in saddr = rqstp->rq_addr; + int vers = rqstp->rq_vers; + int prot = rqstp->rq_prot; struct nlm_host *host; dprintk("lockd: SM_NOTIFY called\n"); @@ -435,8 +437,8 @@ /* Obtain the host pointer for this NFS server and try to * reclaim all locks we hold on this server. */ - saddr.sin_addr.s_addr = argp->addr; - if ((host = nlm_lookup_host(NULL, &saddr, IPPROTO_UDP, 1)) != NULL) { + saddr.sin_addr.s_addr = argp->addr; + if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) { nlmclnt_recovery(host, argp->state); nlm_release_host(host); } @@ -444,7 +446,7 @@ /* If we run on an NFS server, delete all locks held by the client */ if (nlmsvc_ops != NULL) { struct svc_client *clnt; - saddr.sin_addr.s_addr = argp->addr; + saddr.sin_addr.s_addr = argp->addr; if ((clnt = nlmsvc_ops->exp_getclient(&saddr)) != NULL && (host = nlm_lookup_host(clnt, &saddr, 0, 0)) != NULL) { nlmsvc_free_host_resources(host); @@ -549,7 +551,8 @@ PROC(cancel_res, cancelres, norep, res, void), PROC(unlock_res, unlockres, norep, res, void), PROC(granted_res, grantedres, norep, res, void), - PROC(none, void, void, void, void), + /* statd callback */ + PROC(sm_notify, reboot, void, reboot, void), PROC(none, void, void, void, void), PROC(none, void, void, void, void), PROC(none, void, void, void, void), @@ -558,6 +561,4 @@ PROC(nm_lock, lockargs, res, args, res), PROC(free_all, notify, void, args, void), - /* statd callback */ - PROC(sm_notify, reboot, void, reboot, void), }; diff -u --recursive --new-file linux-2.4.10-rdplus/fs/lockd/svcproc.c linux-2.4.10-reclaim/fs/lockd/svcproc.c --- linux-2.4.10-rdplus/fs/lockd/svcproc.c Fri Feb 9 20:29:44 2001 +++ linux-2.4.10-reclaim/fs/lockd/svcproc.c Thu Sep 27 01:24:20 2001 @@ -445,6 +445,8 @@ void *resp) { struct sockaddr_in saddr = rqstp->rq_addr; + int vers = rqstp->rq_vers; + int prot = rqstp->rq_prot; struct nlm_host *host; dprintk("lockd: SM_NOTIFY called\n"); @@ -460,8 +462,8 @@ /* Obtain the host pointer for this NFS server and try to * reclaim all locks we hold on this server. */ - saddr.sin_addr.s_addr = argp->addr; - if ((host = nlm_lookup_host(NULL, &saddr, IPPROTO_UDP, 1)) != NULL) { + saddr.sin_addr.s_addr = argp->addr; + if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) { nlmclnt_recovery(host, argp->state); nlm_release_host(host); } @@ -574,7 +576,8 @@ PROC(cancel_res, cancelres, norep, res, void), PROC(unlock_res, unlockres, norep, res, void), PROC(granted_res, grantedres, norep, res, void), - PROC(none, void, void, void, void), + /* statd callback */ + PROC(sm_notify, reboot, void, reboot, void), PROC(none, void, void, void, void), PROC(none, void, void, void, void), PROC(none, void, void, void, void), @@ -583,6 +586,4 @@ PROC(nm_lock, lockargs, res, args, res), PROC(free_all, notify, void, args, void), - /* statd callback */ - PROC(sm_notify, reboot, void, reboot, void), }; diff -u --recursive --new-file linux-2.4.10-rdplus/fs/lockd/svcsubs.c linux-2.4.10-reclaim/fs/lockd/svcsubs.c --- linux-2.4.10-rdplus/fs/lockd/svcsubs.c Sat Jun 24 06:12:53 2000 +++ linux-2.4.10-reclaim/fs/lockd/svcsubs.c Mon Sep 24 22:13:59 2001 @@ -305,6 +305,7 @@ dprintk("lockd: invalidating client for %s\n", host->h_name); nlmsvc_free_host_resources(host); host->h_expires = 0; + host->h_killed = 1; nlm_release_host(host); } } diff -u --recursive --new-file linux-2.4.10-rdplus/fs/lockd/xdr.c linux-2.4.10-reclaim/fs/lockd/xdr.c --- linux-2.4.10-rdplus/fs/lockd/xdr.c Mon Sep 24 00:33:20 2001 +++ linux-2.4.10-reclaim/fs/lockd/xdr.c Tue Sep 25 10:27:31 2001 @@ -367,7 +367,8 @@ if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) return 0; argp->state = ntohl(*p++); - argp->addr = ntohl(*p++); + /* Preserve the address in network byte order */ + argp->addr = *p++; return xdr_argsize_check(rqstp, p); } diff -u --recursive --new-file linux-2.4.10-rdplus/fs/lockd/xdr4.c linux-2.4.10-reclaim/fs/lockd/xdr4.c --- linux-2.4.10-rdplus/fs/lockd/xdr4.c Mon Sep 24 00:33:20 2001 +++ linux-2.4.10-reclaim/fs/lockd/xdr4.c Tue Sep 25 11:03:10 2001 @@ -373,7 +373,8 @@ if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) return 0; argp->state = ntohl(*p++); - argp->addr = ntohl(*p++); + /* Preserve the address in network byte order */ + argp->addr = *p++; return xdr_argsize_check(rqstp, p); } diff -u --recursive --new-file linux-2.4.10-rdplus/include/linux/lockd/lockd.h linux-2.4.10-reclaim/include/linux/lockd/lockd.h --- linux-2.4.10-rdplus/include/linux/lockd/lockd.h Mon Sep 24 20:25:26 2001 +++ linux-2.4.10-reclaim/include/linux/lockd/lockd.h Thu Sep 27 01:38:36 2001 @@ -47,6 +47,7 @@ unsigned short h_authflavor; /* RPC authentication type */ unsigned short h_reclaiming : 1, h_inuse : 1, + h_killed : 1, h_monitored : 1; wait_queue_head_t h_gracewait; /* wait while reclaiming */ u32 h_state; /* pseudo-state counter */ @@ -120,7 +121,7 @@ #ifdef CONFIG_LOCKD_V4 extern struct svc_procedure nlmsvc_procedures4[]; #endif -extern unsigned long nlmsvc_grace_period; +extern int nlmsvc_grace_period; extern unsigned long nlmsvc_timeout; /* diff -u --recursive --new-file linux-2.4.10-rdplus/include/linux/lockd/nlm.h linux-2.4.10-reclaim/include/linux/lockd/nlm.h --- linux-2.4.10-rdplus/include/linux/lockd/nlm.h Mon Aug 13 21:28:01 2001 +++ linux-2.4.10-reclaim/include/linux/lockd/nlm.h Mon Sep 24 00:51:01 2001 @@ -49,10 +49,10 @@ #define NLMPROC_CANCEL_RES 13 #define NLMPROC_UNLOCK_RES 14 #define NLMPROC_GRANTED_RES 15 +#define NLMPROC_NSM_NOTIFY 16 /* statd callback */ #define NLMPROC_SHARE 20 #define NLMPROC_UNSHARE 21 #define NLMPROC_NM_LOCK 22 #define NLMPROC_FREE_ALL 23 -#define NLMPROC_NSM_NOTIFY 24 /* statd callback */ #endif /* LINUX_LOCKD_NLM_H */ diff -u --recursive --new-file linux-2.4.10-rdplus/include/linux/nfs_fs_i.h linux-2.4.10-reclaim/include/linux/nfs_fs_i.h --- linux-2.4.10-rdplus/include/linux/nfs_fs_i.h Mon Sep 24 00:44:12 2001 +++ linux-2.4.10-reclaim/include/linux/nfs_fs_i.h Wed Sep 26 15:16:25 2001 @@ -99,5 +99,6 @@ * Lock flag values */ #define NFS_LCK_GRANTED 0x0001 /* lock has been granted */ +#define NFS_LCK_RECLAIM 0x0002 /* lock marked for reclaiming */ #endif