Skip to content

Commit

Permalink
lockd: stop abusing file_lock_list
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Christoph Hellwig authored and Trond Myklebust committed Mar 20, 2006
1 parent 0426647 commit 26bcbf9
Show file tree
Hide file tree
Showing 7 changed files with 21 additions and 63 deletions.
54 changes: 9 additions & 45 deletions fs/lockd/clntlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,34 +154,6 @@ u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock)
* server crash.
*/

/*
* 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.owner == NULL)
continue;
if (fl->fl_u.nfs_fl.owner->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.
Expand All @@ -194,7 +166,12 @@ void nlmclnt_prepare_reclaim(struct nlm_host *host, u32 newstate)
host->h_state++;
host->h_nextrebind = 0;
nlm_rebind_host(host);
nlmclnt_mark_reclaim(host);

/*
* Mark the locks for reclaiming.
*/
list_splice_init(&host->h_granted, &host->h_reclaim);

dprintk("NLM: reclaiming locks for host %s", host->h_name);
}

Expand Down Expand Up @@ -223,9 +200,7 @@ reclaimer(void *ptr)
{
struct nlm_host *host = (struct nlm_host *) ptr;
struct nlm_wait *block;
struct list_head *tmp;
struct file_lock *fl;
struct inode *inode;
struct file_lock *fl, *next;

daemonize("%s-reclaim", host->h_name);
allow_signal(SIGKILL);
Expand All @@ -237,20 +212,9 @@ reclaimer(void *ptr)

/* First, reclaim all locks that have been marked. */
restart:
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.owner == NULL)
continue;
if (fl->fl_u.nfs_fl.owner->host != host)
continue;
if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_RECLAIM))
continue;
list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) {
list_del(&fl->fl_u.nfs_fl.list);

fl->fl_u.nfs_fl.flags &= ~NFS_LCK_RECLAIM;
nlmclnt_reclaim(host, fl);
if (signalled())
break;
Expand Down
11 changes: 6 additions & 5 deletions fs/lockd/clntproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,6 @@ static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *ho
{
BUG_ON(fl->fl_ops != NULL);
fl->fl_u.nfs_fl.state = 0;
fl->fl_u.nfs_fl.flags = 0;
fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner);
fl->fl_ops = &nlmclnt_lock_ops;
}
Expand Down Expand Up @@ -552,8 +551,8 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)

if (resp->status == NLM_LCK_GRANTED) {
fl->fl_u.nfs_fl.state = host->h_state;
fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
fl->fl_flags |= FL_SLEEP;
list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted);
do_vfs_lock(fl);
}
status = nlm_stat_to_errno(resp->status);
Expand Down Expand Up @@ -619,9 +618,11 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
struct nlm_res *resp = &req->a_res;
int status;

/* Clean the GRANTED flag now so the lock doesn't get
* reclaimed while we're stuck in the unlock call. */
fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED;
/*
* Remove from the granted list now so the lock doesn't get
* reclaimed while we're stuck in the unlock call.
*/
list_del(&fl->fl_u.nfs_fl.list);

/*
* Note: the server is supposed to either grant us the unlock
Expand Down
2 changes: 2 additions & 0 deletions fs/lockd/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ nlm_lookup_host(int server, struct sockaddr_in *sin,
nlm_hosts[hash] = host;
INIT_LIST_HEAD(&host->h_lockowners);
spin_lock_init(&host->h_lock);
INIT_LIST_HEAD(&host->h_granted);
INIT_LIST_HEAD(&host->h_reclaim);

if (++nrhosts > NLM_HOST_MAX)
next_gc = 0;
Expand Down
5 changes: 1 addition & 4 deletions fs/locks.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,7 @@ int lease_break_time = 45;
#define for_each_lock(inode, lockp) \
for (lockp = &inode->i_flock; *lockp != NULL; lockp = &(*lockp)->fl_next)

LIST_HEAD(file_lock_list);

EXPORT_SYMBOL(file_lock_list);

static LIST_HEAD(file_lock_list);
static LIST_HEAD(blocked_list);

static kmem_cache_t *filelock_cache;
Expand Down
2 changes: 0 additions & 2 deletions include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -730,8 +730,6 @@ struct file_lock {
#define OFFT_OFFSET_MAX INT_LIMIT(off_t)
#endif

extern struct list_head file_lock_list;

#include <linux/fcntl.h>

extern int fcntl_getlk(struct file *, struct flock __user *);
Expand Down
2 changes: 2 additions & 0 deletions include/linux/lockd/lockd.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ struct nlm_host {
unsigned long h_expires; /* eligible for GC */
struct list_head h_lockowners; /* Lockowners for the client */
spinlock_t h_lock;
struct list_head h_granted; /* Locks in GRANTED state */
struct list_head h_reclaim; /* Locks in RECLAIM state */
};

/*
Expand Down
8 changes: 1 addition & 7 deletions include/linux/nfs_fs_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,13 @@ struct nlm_lockowner;
*/
struct nfs_lock_info {
u32 state;
u32 flags;
struct nlm_lockowner *owner;
struct list_head list;
};

struct nfs4_lock_state;
struct nfs4_lock_info {
struct nfs4_lock_state *owner;
};

/*
* Lock flag values
*/
#define NFS_LCK_GRANTED 0x0001 /* lock has been granted */
#define NFS_LCK_RECLAIM 0x0002 /* lock marked for reclaiming */

#endif

0 comments on commit 26bcbf9

Please sign in to comment.