lockd: Change list of blocked list to list_node
Subsystems (2)
PATCH 10/22 lockd: Change list of blocked list to list_node
From: Olaf Kirch <[email protected]>
Subject: 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 <[email protected]>
fs/lockd/svclock.c | 112 ++++++++++++++++++++------------------------ fs/lockd/svcsubs.c | 8 +-- include/linux/lockd/lockd.h | 7 +- 3 files changed, 58 insertions(+), 69 deletions(-)
fs/lockd/svclock.c +51 -61
@@ -40,7 +40,7 @@static void nlmsvc_release_block (struct nlm_block *block);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 void nlmsvc_freegrantargs (struct nlm_rqst *call);
@@ -49,7 +49,7 @@ static const struct rpc_call_ops nlmsvc_/* * 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
@@ -57,48 +57,41 @@ static struct nlm_block * nlm_blocked;static void 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); -kref_get (&block->b_count); -if (block->b_queued) -nlmsvc_remove_block (block); - bp = &nlm_blocked; +if (list_empty (&block->b_list)) { +kref_get (&block->b_count); + }else { +list_del_init (&block->b_list); + } + + pos = &nlm_blocked;if (when !=NLM_NEVER ) {if ((when += jiffies) ==NLM_NEVER ) when ++; -while ((b = *bp) &&time_before_eq (b->b_when,when) && b->b_when !=NLM_NEVER ) - bp = &b->b_next; - }else -while ((b = *bp) !=0 ) - bp = &b->b_next; +list_for_each (pos, &nlm_blocked) { + b = list_entry(pos, struct nlm_block, b_list); +if (time_after (b->b_when,when) || b->b_when ==NLM_NEVER ) +break ; + } + } - block->b_queued =1 ; +list_add_tail (&block->b_list, pos); block->b_when = when; - block->b_next = b; - *bp = block; }/* * Remove a block from the global list */ -static int +static inline void nlmsvc_remove_block (struct nlm_block *block) { -struct nlm_block **bp, *b; - -if (!block->b_queued) -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 ; - } +if (!list_empty (&block->b_list)) { +list_del_init (&block->b_list); +nlmsvc_release_block (block); } - -return 0 ; }/*
@@ -107,14 +100,14 @@ nlmsvc_remove_block(struct nlm_block *blstatic struct nlm_block *nlmsvc_lookup_block (struct nlm_file *file,struct nlm_lock *lock) { -struct nlm_block **head, *block; +struct nlm_block *block;struct file_lock *fl;dprintk ("lockd: nlmsvc_lookup_block f=%p pd=%d %Ld-%Ld ty=%d\n" , file, lock->fl.fl_pid, (long long )lock->fl.fl_start, (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; dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n", block->b_file, fl->fl_pid,
@@ -147,16 +140,16 @@ nlmsvc_find_block(struct nlm_cookie *coo {struct nlm_block *block; -for (block = nlm_blocked; block; block = block->b_next) { -dprintk ("cookie: head of blocked queue %p, block %p\n" , - nlm_blocked, block); +list_for_each_entry (block, &nlm_blocked, b_list) {if (nlm_cookie_match (&block->b_call->a_args.cookie,cookie) &&nlm_cmp_addr (sin, &block->b_host->h_addr)) -break ; + goto found; } -if (block !=NULL ) -kref_get (&block->b_count); +return NULL ; + +found: +kref_get (&block->b_count);return block; }
@@ -192,6 +185,8 @@ nlmsvc_create_block(struct svc_rqst *rqsif (block ==NULL ) goto failed;kref_init (&block->b_count); +INIT_LIST_HEAD (&block->b_list); +INIT_LIST_HEAD (&block->b_flist);if (!nlmsvc_setgrantargs (call, lock)) goto failed_free;
@@ -210,8 +205,7 @@ nlmsvc_create_block(struct svc_rqst *rqs file->f_count++;/* Add to file's list of blocks */ - block->b_fnext = file->f_blocks; - file->f_blocks = block; +list_add (&block->b_flist, &file->f_blocks);/* Set up RPC arguments for callback */ block->b_call = call;
@@ -248,18 +242,12 @@ static void nlmsvc_free_block(struct kre { struct nlm_block *block = container_of(kref, struct nlm_block, b_count);struct nlm_file *file = block->b_file; -struct nlm_block **bp;dprintk ("lockd: freeing block %p...\n" , block); -down (&file->f_sema);/* Remove block from file's list of blocks */ -for (bp = &file->f_blocks; *bp; bp = &(*bp)->b_fnext) { -if (*bp == block) { - *bp = block->b_fnext; -break ; - } - } +down (&file->f_sema); +list_del_init (&block->b_flist);up (&file->f_sema);nlmsvc_freegrantargs (block->b_call);
@@ -290,10 +278,12 @@ static void nlmsvc_act_unlock(struct nlm restart: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)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 ;kref_get (&block->b_count);up (&file->f_sema);
@@ -528,10 +518,10 @@ nlmsvc_cancel_blocked(struct nlm_file *fstatic void 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); -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)) {nlmsvc_insert_block (block,0 );svc_wake_up (block->b_daemon);
@@ -700,16 +690,19 @@ nlmsvc_grant_reply(struct svc_rqst *rqstunsigned long 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 )break ; -if (time_after (block->b_when,jiffies)) +if (time_after (block->b_when,jiffies)) { + timeout = block->b_when - jiffies;break ; + } +dprintk ("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n" , block, block->b_when, block->b_done);kref_get (&block->b_count);
@@ -720,8 +713,5 @@ nlmsvc_retry_blocked(void)nlmsvc_release_block (block); } -if ((block = nlm_blocked) && block->b_when !=NLM_NEVER ) -return (block->b_when - jiffies); - -return MAX_SCHEDULE_TIMEOUT ; +return timeout; }
fs/lockd/svcsubs.c +4 -4
@@ -100,14 +100,14 @@ nlm_lookup_file(struct svc_rqst *rqstp,nlm_debug_print_fh ("creating file for" , f); nfserr = nlm_lck_denied_nolocks; - file = (struct nlm_file *)kmalloc (sizeof (*file),GFP_KERNEL ); + file = (struct nlm_file *)kzalloc (sizeof (*file),GFP_KERNEL );if (!file) goto out_unlock; -memset (file,0 ,sizeof (*file));memcpy (&file->f_handle, f,sizeof (struct nfs_fh )); file->f_hash = hash;init_MUTEX (&file->f_sema); +INIT_LIST_HEAD (&file->f_blocks);/* Open the file. Note that this must not sleep for too long, else * we would lock up lockd:-) So no NFS re-exports, folks.
@@ -221,7 +221,7 @@ nlm_inspect_file(struct nlm_host *host, {if (action ==NLM_ACT_CHECK ) {/* 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 ; }else {nlmsvc_traverse_blocks (host, file, action);
@@ -251,7 +251,7 @@ nlm_traverse_files(struct nlm_host *host }/* 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) { *fp = file->f_next; nlmsvc_ops->fclose (file->f_file);
include/linux/lockd/lockd.h +3 -4
@@ -109,7 +109,7 @@ struct nlm_file {struct nfs_fh f_handle;/* NFS file handle */ struct file * f_file;/* VFS file pointer */ 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_count;/* reference count */ struct semaphore f_sema;/* avoid concurrent access */
@@ -123,14 +123,13 @@ struct nlm_file {#define NLM_NEVER (~(unsigned long) 0)struct nlm_block {struct kref b_count;/* Reference count */ -struct nlm_block * b_next;/* linked list (all blocks) */ -struct nlm_block * b_fnext;/* linked list (per file) */ +struct list_head b_list;/* linked list of all blocks */ +struct list_head b_flist;/* linked list (per file) */ struct nlm_rqst * b_call;/* RPC args & callback info */ struct svc_serv * b_daemon;/* NLM service */ struct nlm_host * b_host;/* host handle for RPC clnt */ unsigned long b_when;/* next re-xmit */ unsigned int b_id;/* block id */ -unsigned char b_queued;/* re-queued */ unsigned char b_granted;/* VFS granted lock */ unsigned char b_done;/* callback complete */ struct nlm_file * b_file;/* file in question */
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs