Commit 26bcbf965f857c710adafd16cf424f043006b5dd

Authored by Christoph Hellwig
Committed by Trond Myklebust
1 parent 04266473ec

lockd: stop abusing file_lock_list

Currently lockd directly access the file_lock_list from fs/locks.c.
It does so to mark locks granted or reclaimable.  This is very
suboptimal, because a) lockd needs to poke into locks.c internals, and
b) it needs to iterate over all locks in the system for marking locks
granted or reclaimable.

This patch adds lists for granted and reclaimable locks to the nlm_host
structure instead, and adds locks to those.

nlmclnt_lock:
	now adds the lock to h_granted instead of setting the
	NFS_LCK_GRANTED, still O(1)

nlmclnt_mark_reclaim:
	goes away completely, replaced by a list_splice_init.
	Complexity reduced from O(locks in the system) to O(1)

reclaimer:
	iterates over h_reclaim now, complexity reduced from
	O(locks in the system) to O(locks per nlm_host)

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

Showing 7 changed files with 21 additions and 63 deletions Side-by-side Diff

... ... @@ -155,34 +155,6 @@
155 155 */
156 156  
157 157 /*
158   - * Mark the locks for reclaiming.
159   - * FIXME: In 2.5 we don't want to iterate through any global file_lock_list.
160   - * Maintain NLM lock reclaiming lists in the nlm_host instead.
161   - */
162   -static
163   -void nlmclnt_mark_reclaim(struct nlm_host *host)
164   -{
165   - struct file_lock *fl;
166   - struct inode *inode;
167   - struct list_head *tmp;
168   -
169   - list_for_each(tmp, &file_lock_list) {
170   - fl = list_entry(tmp, struct file_lock, fl_link);
171   -
172   - inode = fl->fl_file->f_dentry->d_inode;
173   - if (inode->i_sb->s_magic != NFS_SUPER_MAGIC)
174   - continue;
175   - if (fl->fl_u.nfs_fl.owner == NULL)
176   - continue;
177   - if (fl->fl_u.nfs_fl.owner->host != host)
178   - continue;
179   - if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_GRANTED))
180   - continue;
181   - fl->fl_u.nfs_fl.flags |= NFS_LCK_RECLAIM;
182   - }
183   -}
184   -
185   -/*
186 158 * Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number,
187 159 * that we mark locks for reclaiming, and that we bump the pseudo NSM state.
188 160 */
... ... @@ -194,7 +166,12 @@
194 166 host->h_state++;
195 167 host->h_nextrebind = 0;
196 168 nlm_rebind_host(host);
197   - nlmclnt_mark_reclaim(host);
  169 +
  170 + /*
  171 + * Mark the locks for reclaiming.
  172 + */
  173 + list_splice_init(&host->h_granted, &host->h_reclaim);
  174 +
198 175 dprintk("NLM: reclaiming locks for host %s", host->h_name);
199 176 }
200 177  
... ... @@ -223,9 +200,7 @@
223 200 {
224 201 struct nlm_host *host = (struct nlm_host *) ptr;
225 202 struct nlm_wait *block;
226   - struct list_head *tmp;
227   - struct file_lock *fl;
228   - struct inode *inode;
  203 + struct file_lock *fl, *next;
229 204  
230 205 daemonize("%s-reclaim", host->h_name);
231 206 allow_signal(SIGKILL);
232 207  
... ... @@ -237,20 +212,9 @@
237 212  
238 213 /* First, reclaim all locks that have been marked. */
239 214 restart:
240   - list_for_each(tmp, &file_lock_list) {
241   - fl = list_entry(tmp, struct file_lock, fl_link);
  215 + list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) {
  216 + list_del(&fl->fl_u.nfs_fl.list);
242 217  
243   - inode = fl->fl_file->f_dentry->d_inode;
244   - if (inode->i_sb->s_magic != NFS_SUPER_MAGIC)
245   - continue;
246   - if (fl->fl_u.nfs_fl.owner == NULL)
247   - continue;
248   - if (fl->fl_u.nfs_fl.owner->host != host)
249   - continue;
250   - if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_RECLAIM))
251   - continue;
252   -
253   - fl->fl_u.nfs_fl.flags &= ~NFS_LCK_RECLAIM;
254 218 nlmclnt_reclaim(host, fl);
255 219 if (signalled())
256 220 break;
... ... @@ -465,7 +465,6 @@
465 465 {
466 466 BUG_ON(fl->fl_ops != NULL);
467 467 fl->fl_u.nfs_fl.state = 0;
468   - fl->fl_u.nfs_fl.flags = 0;
469 468 fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner);
470 469 fl->fl_ops = &nlmclnt_lock_ops;
471 470 }
472 471  
... ... @@ -552,8 +551,8 @@
552 551  
553 552 if (resp->status == NLM_LCK_GRANTED) {
554 553 fl->fl_u.nfs_fl.state = host->h_state;
555   - fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
556 554 fl->fl_flags |= FL_SLEEP;
  555 + list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted);
557 556 do_vfs_lock(fl);
558 557 }
559 558 status = nlm_stat_to_errno(resp->status);
... ... @@ -619,9 +618,11 @@
619 618 struct nlm_res *resp = &req->a_res;
620 619 int status;
621 620  
622   - /* Clean the GRANTED flag now so the lock doesn't get
623   - * reclaimed while we're stuck in the unlock call. */
624   - fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED;
  621 + /*
  622 + * Remove from the granted list now so the lock doesn't get
  623 + * reclaimed while we're stuck in the unlock call.
  624 + */
  625 + list_del(&fl->fl_u.nfs_fl.list);
625 626  
626 627 /*
627 628 * Note: the server is supposed to either grant us the unlock
... ... @@ -123,6 +123,8 @@
123 123 nlm_hosts[hash] = host;
124 124 INIT_LIST_HEAD(&host->h_lockowners);
125 125 spin_lock_init(&host->h_lock);
  126 + INIT_LIST_HEAD(&host->h_granted);
  127 + INIT_LIST_HEAD(&host->h_reclaim);
126 128  
127 129 if (++nrhosts > NLM_HOST_MAX)
128 130 next_gc = 0;
... ... @@ -139,10 +139,7 @@
139 139 #define for_each_lock(inode, lockp) \
140 140 for (lockp = &inode->i_flock; *lockp != NULL; lockp = &(*lockp)->fl_next)
141 141  
142   -LIST_HEAD(file_lock_list);
143   -
144   -EXPORT_SYMBOL(file_lock_list);
145   -
  142 +static LIST_HEAD(file_lock_list);
146 143 static LIST_HEAD(blocked_list);
147 144  
148 145 static kmem_cache_t *filelock_cache;
... ... @@ -730,8 +730,6 @@
730 730 #define OFFT_OFFSET_MAX INT_LIMIT(off_t)
731 731 #endif
732 732  
733   -extern struct list_head file_lock_list;
734   -
735 733 #include <linux/fcntl.h>
736 734  
737 735 extern int fcntl_getlk(struct file *, struct flock __user *);
include/linux/lockd/lockd.h
... ... @@ -59,6 +59,8 @@
59 59 unsigned long h_expires; /* eligible for GC */
60 60 struct list_head h_lockowners; /* Lockowners for the client */
61 61 spinlock_t h_lock;
  62 + struct list_head h_granted; /* Locks in GRANTED state */
  63 + struct list_head h_reclaim; /* Locks in RECLAIM state */
62 64 };
63 65  
64 66 /*
include/linux/nfs_fs_i.h
... ... @@ -12,20 +12,14 @@
12 12 */
13 13 struct nfs_lock_info {
14 14 u32 state;
15   - u32 flags;
16 15 struct nlm_lockowner *owner;
  16 + struct list_head list;
17 17 };
18 18  
19 19 struct nfs4_lock_state;
20 20 struct nfs4_lock_info {
21 21 struct nfs4_lock_state *owner;
22 22 };
23   -
24   -/*
25   - * Lock flag values
26   - */
27   -#define NFS_LCK_GRANTED 0x0001 /* lock has been granted */
28   -#define NFS_LCK_RECLAIM 0x0002 /* lock marked for reclaiming */
29 23  
30 24 #endif