mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 06:12:08 +00:00
[PATCH] knfsd: lockd: Change list of blocked list to list_node
This patch changes the nlm_blocked list to use a list_node instead of homegrown linked list handling. Signed-off-by: Olaf Kirch <okir@suse.de> Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
0cea32761a
commit
68a2d76cea
@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
static void nlmsvc_release_block(struct nlm_block *block);
|
static void nlmsvc_release_block(struct nlm_block *block);
|
||||||
static void nlmsvc_insert_block(struct nlm_block *block, unsigned long);
|
static void nlmsvc_insert_block(struct nlm_block *block, unsigned long);
|
||||||
static int nlmsvc_remove_block(struct nlm_block *block);
|
static void nlmsvc_remove_block(struct nlm_block *block);
|
||||||
|
|
||||||
static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock);
|
static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock);
|
||||||
static void nlmsvc_freegrantargs(struct nlm_rqst *call);
|
static void nlmsvc_freegrantargs(struct nlm_rqst *call);
|
||||||
@ -49,7 +49,7 @@ static const struct rpc_call_ops nlmsvc_grant_ops;
|
|||||||
/*
|
/*
|
||||||
* The list of blocked locks to retry
|
* The list of blocked locks to retry
|
||||||
*/
|
*/
|
||||||
static struct nlm_block * nlm_blocked;
|
static LIST_HEAD(nlm_blocked);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert a blocked lock into the global list
|
* Insert a blocked lock into the global list
|
||||||
@ -57,48 +57,44 @@ static struct nlm_block * nlm_blocked;
|
|||||||
static void
|
static void
|
||||||
nlmsvc_insert_block(struct nlm_block *block, unsigned long when)
|
nlmsvc_insert_block(struct nlm_block *block, unsigned long when)
|
||||||
{
|
{
|
||||||
struct nlm_block **bp, *b;
|
struct nlm_block *b;
|
||||||
|
struct list_head *pos;
|
||||||
|
|
||||||
dprintk("lockd: nlmsvc_insert_block(%p, %ld)\n", block, when);
|
dprintk("lockd: nlmsvc_insert_block(%p, %ld)\n", block, when);
|
||||||
kref_get(&block->b_count);
|
if (list_empty(&block->b_list)) {
|
||||||
if (block->b_queued)
|
kref_get(&block->b_count);
|
||||||
nlmsvc_remove_block(block);
|
} else {
|
||||||
bp = &nlm_blocked;
|
list_del_init(&block->b_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = &nlm_blocked;
|
||||||
if (when != NLM_NEVER) {
|
if (when != NLM_NEVER) {
|
||||||
if ((when += jiffies) == NLM_NEVER)
|
if ((when += jiffies) == NLM_NEVER)
|
||||||
when ++;
|
when ++;
|
||||||
while ((b = *bp) && time_before_eq(b->b_when,when) && b->b_when != NLM_NEVER)
|
list_for_each(pos, &nlm_blocked) {
|
||||||
bp = &b->b_next;
|
b = list_entry(pos, struct nlm_block, b_list);
|
||||||
} else
|
if (time_after(b->b_when,when) || b->b_when == NLM_NEVER)
|
||||||
while ((b = *bp) != 0)
|
break;
|
||||||
bp = &b->b_next;
|
}
|
||||||
|
/* On normal exit from the loop, pos == &nlm_blocked,
|
||||||
|
* so we will be adding to the end of the list - good
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
block->b_queued = 1;
|
list_add_tail(&block->b_list, pos);
|
||||||
block->b_when = when;
|
block->b_when = when;
|
||||||
block->b_next = b;
|
|
||||||
*bp = block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove a block from the global list
|
* Remove a block from the global list
|
||||||
*/
|
*/
|
||||||
static int
|
static inline void
|
||||||
nlmsvc_remove_block(struct nlm_block *block)
|
nlmsvc_remove_block(struct nlm_block *block)
|
||||||
{
|
{
|
||||||
struct nlm_block **bp, *b;
|
if (!list_empty(&block->b_list)) {
|
||||||
|
list_del_init(&block->b_list);
|
||||||
if (!block->b_queued)
|
nlmsvc_release_block(block);
|
||||||
return 1;
|
|
||||||
for (bp = &nlm_blocked; (b = *bp) != 0; bp = &b->b_next) {
|
|
||||||
if (b == block) {
|
|
||||||
*bp = block->b_next;
|
|
||||||
block->b_queued = 0;
|
|
||||||
nlmsvc_release_block(block);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -107,14 +103,14 @@ nlmsvc_remove_block(struct nlm_block *block)
|
|||||||
static struct nlm_block *
|
static struct nlm_block *
|
||||||
nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock)
|
nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock)
|
||||||
{
|
{
|
||||||
struct nlm_block **head, *block;
|
struct nlm_block *block;
|
||||||
struct file_lock *fl;
|
struct file_lock *fl;
|
||||||
|
|
||||||
dprintk("lockd: nlmsvc_lookup_block f=%p pd=%d %Ld-%Ld ty=%d\n",
|
dprintk("lockd: nlmsvc_lookup_block f=%p pd=%d %Ld-%Ld ty=%d\n",
|
||||||
file, lock->fl.fl_pid,
|
file, lock->fl.fl_pid,
|
||||||
(long long)lock->fl.fl_start,
|
(long long)lock->fl.fl_start,
|
||||||
(long long)lock->fl.fl_end, lock->fl.fl_type);
|
(long long)lock->fl.fl_end, lock->fl.fl_type);
|
||||||
for (head = &nlm_blocked; (block = *head) != 0; head = &block->b_next) {
|
list_for_each_entry(block, &nlm_blocked, b_list) {
|
||||||
fl = &block->b_call->a_args.lock.fl;
|
fl = &block->b_call->a_args.lock.fl;
|
||||||
dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n",
|
dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n",
|
||||||
block->b_file, fl->fl_pid,
|
block->b_file, fl->fl_pid,
|
||||||
@ -147,16 +143,16 @@ nlmsvc_find_block(struct nlm_cookie *cookie, struct sockaddr_in *sin)
|
|||||||
{
|
{
|
||||||
struct nlm_block *block;
|
struct nlm_block *block;
|
||||||
|
|
||||||
for (block = nlm_blocked; block; block = block->b_next) {
|
list_for_each_entry(block, &nlm_blocked, b_list) {
|
||||||
dprintk("cookie: head of blocked queue %p, block %p\n",
|
|
||||||
nlm_blocked, block);
|
|
||||||
if (nlm_cookie_match(&block->b_call->a_args.cookie,cookie)
|
if (nlm_cookie_match(&block->b_call->a_args.cookie,cookie)
|
||||||
&& nlm_cmp_addr(sin, &block->b_host->h_addr))
|
&& nlm_cmp_addr(sin, &block->b_host->h_addr))
|
||||||
break;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block != NULL)
|
return NULL;
|
||||||
kref_get(&block->b_count);
|
|
||||||
|
found:
|
||||||
|
kref_get(&block->b_count);
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,6 +188,8 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
|
|||||||
if (block == NULL)
|
if (block == NULL)
|
||||||
goto failed;
|
goto failed;
|
||||||
kref_init(&block->b_count);
|
kref_init(&block->b_count);
|
||||||
|
INIT_LIST_HEAD(&block->b_list);
|
||||||
|
INIT_LIST_HEAD(&block->b_flist);
|
||||||
|
|
||||||
if (!nlmsvc_setgrantargs(call, lock))
|
if (!nlmsvc_setgrantargs(call, lock))
|
||||||
goto failed_free;
|
goto failed_free;
|
||||||
@ -210,8 +208,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
|
|||||||
file->f_count++;
|
file->f_count++;
|
||||||
|
|
||||||
/* Add to file's list of blocks */
|
/* Add to file's list of blocks */
|
||||||
block->b_fnext = file->f_blocks;
|
list_add(&block->b_flist, &file->f_blocks);
|
||||||
file->f_blocks = block;
|
|
||||||
|
|
||||||
/* Set up RPC arguments for callback */
|
/* Set up RPC arguments for callback */
|
||||||
block->b_call = call;
|
block->b_call = call;
|
||||||
@ -248,18 +245,12 @@ static void nlmsvc_free_block(struct kref *kref)
|
|||||||
{
|
{
|
||||||
struct nlm_block *block = container_of(kref, struct nlm_block, b_count);
|
struct nlm_block *block = container_of(kref, struct nlm_block, b_count);
|
||||||
struct nlm_file *file = block->b_file;
|
struct nlm_file *file = block->b_file;
|
||||||
struct nlm_block **bp;
|
|
||||||
|
|
||||||
dprintk("lockd: freeing block %p...\n", block);
|
dprintk("lockd: freeing block %p...\n", block);
|
||||||
|
|
||||||
down(&file->f_sema);
|
|
||||||
/* Remove block from file's list of blocks */
|
/* Remove block from file's list of blocks */
|
||||||
for (bp = &file->f_blocks; *bp; bp = &(*bp)->b_fnext) {
|
down(&file->f_sema);
|
||||||
if (*bp == block) {
|
list_del_init(&block->b_flist);
|
||||||
*bp = block->b_fnext;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
up(&file->f_sema);
|
up(&file->f_sema);
|
||||||
|
|
||||||
nlmsvc_freegrantargs(block->b_call);
|
nlmsvc_freegrantargs(block->b_call);
|
||||||
@ -279,21 +270,23 @@ static void nlmsvc_act_mark(struct nlm_host *host, struct nlm_file *file)
|
|||||||
struct nlm_block *block;
|
struct nlm_block *block;
|
||||||
|
|
||||||
down(&file->f_sema);
|
down(&file->f_sema);
|
||||||
for (block = file->f_blocks; block != NULL; block = block->b_fnext)
|
list_for_each_entry(block, &file->f_blocks, b_flist)
|
||||||
block->b_host->h_inuse = 1;
|
block->b_host->h_inuse = 1;
|
||||||
up(&file->f_sema);
|
up(&file->f_sema);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nlmsvc_act_unlock(struct nlm_host *host, struct nlm_file *file)
|
static void nlmsvc_act_unlock(struct nlm_host *host, struct nlm_file *file)
|
||||||
{
|
{
|
||||||
struct nlm_block *block;
|
struct nlm_block *block, *next;
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
down(&file->f_sema);
|
down(&file->f_sema);
|
||||||
for (block = file->f_blocks; block != NULL; block = block->b_fnext) {
|
list_for_each_entry_safe(block, next, &file->f_blocks, b_flist) {
|
||||||
if (host != NULL && host != block->b_host)
|
if (host != NULL && host != block->b_host)
|
||||||
continue;
|
continue;
|
||||||
if (!block->b_queued)
|
/* Do not destroy blocks that are not on
|
||||||
|
* the global retry list - why? */
|
||||||
|
if (list_empty(&block->b_list))
|
||||||
continue;
|
continue;
|
||||||
kref_get(&block->b_count);
|
kref_get(&block->b_count);
|
||||||
up(&file->f_sema);
|
up(&file->f_sema);
|
||||||
@ -528,10 +521,10 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
|
|||||||
static void
|
static void
|
||||||
nlmsvc_notify_blocked(struct file_lock *fl)
|
nlmsvc_notify_blocked(struct file_lock *fl)
|
||||||
{
|
{
|
||||||
struct nlm_block **bp, *block;
|
struct nlm_block *block;
|
||||||
|
|
||||||
dprintk("lockd: VFS unblock notification for block %p\n", fl);
|
dprintk("lockd: VFS unblock notification for block %p\n", fl);
|
||||||
for (bp = &nlm_blocked; (block = *bp) != 0; bp = &block->b_next) {
|
list_for_each_entry(block, &nlm_blocked, b_list) {
|
||||||
if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) {
|
if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) {
|
||||||
nlmsvc_insert_block(block, 0);
|
nlmsvc_insert_block(block, 0);
|
||||||
svc_wake_up(block->b_daemon);
|
svc_wake_up(block->b_daemon);
|
||||||
@ -697,16 +690,19 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status
|
|||||||
unsigned long
|
unsigned long
|
||||||
nlmsvc_retry_blocked(void)
|
nlmsvc_retry_blocked(void)
|
||||||
{
|
{
|
||||||
struct nlm_block *block;
|
unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
|
||||||
|
struct nlm_block *block;
|
||||||
|
|
||||||
|
while (!list_empty(&nlm_blocked)) {
|
||||||
|
block = list_entry(nlm_blocked.next, struct nlm_block, b_list);
|
||||||
|
|
||||||
dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
|
|
||||||
nlm_blocked,
|
|
||||||
nlm_blocked? nlm_blocked->b_when : 0);
|
|
||||||
while ((block = nlm_blocked) != 0) {
|
|
||||||
if (block->b_when == NLM_NEVER)
|
if (block->b_when == NLM_NEVER)
|
||||||
break;
|
break;
|
||||||
if (time_after(block->b_when,jiffies))
|
if (time_after(block->b_when,jiffies)) {
|
||||||
|
timeout = block->b_when - jiffies;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
|
dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
|
||||||
block, block->b_when);
|
block, block->b_when);
|
||||||
kref_get(&block->b_count);
|
kref_get(&block->b_count);
|
||||||
@ -714,8 +710,5 @@ nlmsvc_retry_blocked(void)
|
|||||||
nlmsvc_release_block(block);
|
nlmsvc_release_block(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((block = nlm_blocked) && block->b_when != NLM_NEVER)
|
return timeout;
|
||||||
return (block->b_when - jiffies);
|
|
||||||
|
|
||||||
return MAX_SCHEDULE_TIMEOUT;
|
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
|
|||||||
memcpy(&file->f_handle, f, sizeof(struct nfs_fh));
|
memcpy(&file->f_handle, f, sizeof(struct nfs_fh));
|
||||||
file->f_hash = hash;
|
file->f_hash = hash;
|
||||||
init_MUTEX(&file->f_sema);
|
init_MUTEX(&file->f_sema);
|
||||||
|
INIT_LIST_HEAD(&file->f_blocks);
|
||||||
|
|
||||||
/* Open the file. Note that this must not sleep for too long, else
|
/* Open the file. Note that this must not sleep for too long, else
|
||||||
* we would lock up lockd:-) So no NFS re-exports, folks.
|
* we would lock up lockd:-) So no NFS re-exports, folks.
|
||||||
@ -220,7 +221,7 @@ nlm_inspect_file(struct nlm_host *host, struct nlm_file *file, int action)
|
|||||||
{
|
{
|
||||||
if (action == NLM_ACT_CHECK) {
|
if (action == NLM_ACT_CHECK) {
|
||||||
/* Fast path for mark and sweep garbage collection */
|
/* Fast path for mark and sweep garbage collection */
|
||||||
if (file->f_count || file->f_blocks || file->f_shares)
|
if (file->f_count || list_empty(&file->f_blocks) || file->f_shares)
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
nlmsvc_traverse_blocks(host, file, action);
|
nlmsvc_traverse_blocks(host, file, action);
|
||||||
@ -253,7 +254,7 @@ nlm_traverse_files(struct nlm_host *host, int action)
|
|||||||
mutex_lock(&nlm_file_mutex);
|
mutex_lock(&nlm_file_mutex);
|
||||||
file->f_count--;
|
file->f_count--;
|
||||||
/* No more references to this file. Let go of it. */
|
/* No more references to this file. Let go of it. */
|
||||||
if (!file->f_blocks && !file->f_locks
|
if (list_empty(&file->f_blocks) && !file->f_locks
|
||||||
&& !file->f_shares && !file->f_count) {
|
&& !file->f_shares && !file->f_count) {
|
||||||
*fp = file->f_next;
|
*fp = file->f_next;
|
||||||
nlmsvc_ops->fclose(file->f_file);
|
nlmsvc_ops->fclose(file->f_file);
|
||||||
|
@ -109,7 +109,7 @@ struct nlm_file {
|
|||||||
struct nfs_fh f_handle; /* NFS file handle */
|
struct nfs_fh f_handle; /* NFS file handle */
|
||||||
struct file * f_file; /* VFS file pointer */
|
struct file * f_file; /* VFS file pointer */
|
||||||
struct nlm_share * f_shares; /* DOS shares */
|
struct nlm_share * f_shares; /* DOS shares */
|
||||||
struct nlm_block * f_blocks; /* blocked locks */
|
struct list_head f_blocks; /* blocked locks */
|
||||||
unsigned int f_locks; /* guesstimate # of locks */
|
unsigned int f_locks; /* guesstimate # of locks */
|
||||||
unsigned int f_count; /* reference count */
|
unsigned int f_count; /* reference count */
|
||||||
struct semaphore f_sema; /* avoid concurrent access */
|
struct semaphore f_sema; /* avoid concurrent access */
|
||||||
@ -123,14 +123,13 @@ struct nlm_file {
|
|||||||
#define NLM_NEVER (~(unsigned long) 0)
|
#define NLM_NEVER (~(unsigned long) 0)
|
||||||
struct nlm_block {
|
struct nlm_block {
|
||||||
struct kref b_count; /* Reference count */
|
struct kref b_count; /* Reference count */
|
||||||
struct nlm_block * b_next; /* linked list (all blocks) */
|
struct list_head b_list; /* linked list of all blocks */
|
||||||
struct nlm_block * b_fnext; /* linked list (per file) */
|
struct list_head b_flist; /* linked list (per file) */
|
||||||
struct nlm_rqst * b_call; /* RPC args & callback info */
|
struct nlm_rqst * b_call; /* RPC args & callback info */
|
||||||
struct svc_serv * b_daemon; /* NLM service */
|
struct svc_serv * b_daemon; /* NLM service */
|
||||||
struct nlm_host * b_host; /* host handle for RPC clnt */
|
struct nlm_host * b_host; /* host handle for RPC clnt */
|
||||||
unsigned long b_when; /* next re-xmit */
|
unsigned long b_when; /* next re-xmit */
|
||||||
unsigned int b_id; /* block id */
|
unsigned int b_id; /* block id */
|
||||||
unsigned char b_queued; /* re-queued */
|
|
||||||
unsigned char b_granted; /* VFS granted lock */
|
unsigned char b_granted; /* VFS granted lock */
|
||||||
struct nlm_file * b_file; /* file in question */
|
struct nlm_file * b_file; /* file in question */
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user