aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2006-03-20 13:44:40 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:40 -0500
commit26bcbf965f857c710adafd16cf424f043006b5dd (patch)
treefa3c1e4ba07ab3d1e4e61b27c7579c57fd2d5c65
parent04266473ecf5cdca242201d9f1ed890afe070fb6 (diff)
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>
-rw-r--r--fs/lockd/clntlock.c54
-rw-r--r--fs/lockd/clntproc.c11
-rw-r--r--fs/lockd/host.c2
-rw-r--r--fs/locks.c5
-rw-r--r--include/linux/fs.h2
-rw-r--r--include/linux/lockd/lockd.h2
-rw-r--r--include/linux/nfs_fs_i.h8
7 files changed, 21 insertions, 63 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 8ae79ae4b998..0fc0ee267b04 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -155,34 +155,6 @@ u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock)
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 */
162static
163void 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 * Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number, 158 * Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number,
187 * that we mark locks for reclaiming, and that we bump the pseudo NSM state. 159 * that we mark locks for reclaiming, and that we bump the pseudo NSM state.
188 */ 160 */
@@ -194,7 +166,12 @@ void nlmclnt_prepare_reclaim(struct nlm_host *host, u32 newstate)
194 host->h_state++; 166 host->h_state++;
195 host->h_nextrebind = 0; 167 host->h_nextrebind = 0;
196 nlm_rebind_host(host); 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 dprintk("NLM: reclaiming locks for host %s", host->h_name); 175 dprintk("NLM: reclaiming locks for host %s", host->h_name);
199} 176}
200 177
@@ -223,9 +200,7 @@ reclaimer(void *ptr)
223{ 200{
224 struct nlm_host *host = (struct nlm_host *) ptr; 201 struct nlm_host *host = (struct nlm_host *) ptr;
225 struct nlm_wait *block; 202 struct nlm_wait *block;
226 struct list_head *tmp; 203 struct file_lock *fl, *next;
227 struct file_lock *fl;
228 struct inode *inode;
229 204
230 daemonize("%s-reclaim", host->h_name); 205 daemonize("%s-reclaim", host->h_name);
231 allow_signal(SIGKILL); 206 allow_signal(SIGKILL);
@@ -237,20 +212,9 @@ reclaimer(void *ptr)
237 212
238 /* First, reclaim all locks that have been marked. */ 213 /* First, reclaim all locks that have been marked. */
239restart: 214restart:
240 list_for_each(tmp, &file_lock_list) { 215 list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) {
241 fl = list_entry(tmp, struct file_lock, fl_link); 216 list_del(&fl->fl_u.nfs_fl.list);
242
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 217
253 fl->fl_u.nfs_fl.flags &= ~NFS_LCK_RECLAIM;
254 nlmclnt_reclaim(host, fl); 218 nlmclnt_reclaim(host, fl);
255 if (signalled()) 219 if (signalled())
256 break; 220 break;
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 80ae3127699f..cb469431bd1d 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -465,7 +465,6 @@ static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *ho
465{ 465{
466 BUG_ON(fl->fl_ops != NULL); 466 BUG_ON(fl->fl_ops != NULL);
467 fl->fl_u.nfs_fl.state = 0; 467 fl->fl_u.nfs_fl.state = 0;
468 fl->fl_u.nfs_fl.flags = 0;
469 fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner); 468 fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner);
470 fl->fl_ops = &nlmclnt_lock_ops; 469 fl->fl_ops = &nlmclnt_lock_ops;
471} 470}
@@ -552,8 +551,8 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
552 551
553 if (resp->status == NLM_LCK_GRANTED) { 552 if (resp->status == NLM_LCK_GRANTED) {
554 fl->fl_u.nfs_fl.state = host->h_state; 553 fl->fl_u.nfs_fl.state = host->h_state;
555 fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
556 fl->fl_flags |= FL_SLEEP; 554 fl->fl_flags |= FL_SLEEP;
555 list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted);
557 do_vfs_lock(fl); 556 do_vfs_lock(fl);
558 } 557 }
559 status = nlm_stat_to_errno(resp->status); 558 status = nlm_stat_to_errno(resp->status);
@@ -619,9 +618,11 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
619 struct nlm_res *resp = &req->a_res; 618 struct nlm_res *resp = &req->a_res;
620 int status; 619 int status;
621 620
622 /* Clean the GRANTED flag now so the lock doesn't get 621 /*
623 * reclaimed while we're stuck in the unlock call. */ 622 * Remove from the granted list now so the lock doesn't get
624 fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED; 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 * Note: the server is supposed to either grant us the unlock 628 * Note: the server is supposed to either grant us the unlock
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 100e78229700..f456f8ed9acd 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -123,6 +123,8 @@ nlm_lookup_host(int server, struct sockaddr_in *sin,
123 nlm_hosts[hash] = host; 123 nlm_hosts[hash] = host;
124 INIT_LIST_HEAD(&host->h_lockowners); 124 INIT_LIST_HEAD(&host->h_lockowners);
125 spin_lock_init(&host->h_lock); 125 spin_lock_init(&host->h_lock);
126 INIT_LIST_HEAD(&host->h_granted);
127 INIT_LIST_HEAD(&host->h_reclaim);
126 128
127 if (++nrhosts > NLM_HOST_MAX) 129 if (++nrhosts > NLM_HOST_MAX)
128 next_gc = 0; 130 next_gc = 0;
diff --git a/fs/locks.c b/fs/locks.c
index c83b5dbe0ed9..56f996e98bbc 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -139,10 +139,7 @@ int lease_break_time = 45;
139#define for_each_lock(inode, lockp) \ 139#define for_each_lock(inode, lockp) \
140 for (lockp = &inode->i_flock; *lockp != NULL; lockp = &(*lockp)->fl_next) 140 for (lockp = &inode->i_flock; *lockp != NULL; lockp = &(*lockp)->fl_next)
141 141
142LIST_HEAD(file_lock_list); 142static LIST_HEAD(file_lock_list);
143
144EXPORT_SYMBOL(file_lock_list);
145
146static LIST_HEAD(blocked_list); 143static LIST_HEAD(blocked_list);
147 144
148static kmem_cache_t *filelock_cache; 145static kmem_cache_t *filelock_cache;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d2cffee8fc11..5dc0fa288a4c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -730,8 +730,6 @@ struct file_lock {
730#define OFFT_OFFSET_MAX INT_LIMIT(off_t) 730#define OFFT_OFFSET_MAX INT_LIMIT(off_t)
731#endif 731#endif
732 732
733extern struct list_head file_lock_list;
734
735#include <linux/fcntl.h> 733#include <linux/fcntl.h>
736 734
737extern int fcntl_getlk(struct file *, struct flock __user *); 735extern int fcntl_getlk(struct file *, struct flock __user *);
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 860a93f6ce6d..b0f63b6ab0d4 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -59,6 +59,8 @@ struct nlm_host {
59 unsigned long h_expires; /* eligible for GC */ 59 unsigned long h_expires; /* eligible for GC */
60 struct list_head h_lockowners; /* Lockowners for the client */ 60 struct list_head h_lockowners; /* Lockowners for the client */
61 spinlock_t h_lock; 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/*
diff --git a/include/linux/nfs_fs_i.h b/include/linux/nfs_fs_i.h
index e2c18dabff86..861730275ba0 100644
--- a/include/linux/nfs_fs_i.h
+++ b/include/linux/nfs_fs_i.h
@@ -12,8 +12,8 @@ struct nlm_lockowner;
12 */ 12 */
13struct nfs_lock_info { 13struct nfs_lock_info {
14 u32 state; 14 u32 state;
15 u32 flags;
16 struct nlm_lockowner *owner; 15 struct nlm_lockowner *owner;
16 struct list_head list;
17}; 17};
18 18
19struct nfs4_lock_state; 19struct nfs4_lock_state;
@@ -21,10 +21,4 @@ struct nfs4_lock_info {
21 struct nfs4_lock_state *owner; 21 struct nfs4_lock_state *owner;
22}; 22};
23 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
30#endif 24#endif