/*
  * Global file hash table
  */
-#define FILE_HASH_BITS         5
+#define FILE_HASH_BITS         7
 #define FILE_NRHASH            (1<<FILE_HASH_BITS)
-static struct nlm_file *       nlm_files[FILE_NRHASH];
+static struct hlist_head       nlm_files[FILE_NRHASH];
 static DEFINE_MUTEX(nlm_file_mutex);
 
 #ifdef NFSD_DEBUG
 nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
                                        struct nfs_fh *f)
 {
+       struct hlist_node *pos;
        struct nlm_file *file;
        unsigned int    hash;
        u32             nfserr;
        /* Lock file table */
        mutex_lock(&nlm_file_mutex);
 
-       for (file = nlm_files[hash]; file; file = file->f_next)
+       hlist_for_each_entry(file, pos, &nlm_files[hash], f_list)
                if (!nfs_compare_fh(&file->f_handle, f))
                        goto found;
 
                goto out_unlock;
 
        memcpy(&file->f_handle, f, sizeof(struct nfs_fh));
-       file->f_hash = hash;
        init_MUTEX(&file->f_sema);
+       INIT_HLIST_NODE(&file->f_list);
        INIT_LIST_HEAD(&file->f_blocks);
 
        /* Open the file. Note that this must not sleep for too long, else
                goto out_free;
        }
 
-       file->f_next = nlm_files[hash];
-       nlm_files[hash] = file;
+       hlist_add_head(&file->f_list, &nlm_files[hash]);
 
 found:
        dprintk("lockd: found file %p (count %d)\n", file, file->f_count);
 static inline void
 nlm_delete_file(struct nlm_file *file)
 {
-       struct nlm_file **fp, *f;
-
        nlm_debug_print_file("closing file", file);
-
-       fp = nlm_files + file->f_hash;
-       while ((f = *fp) != NULL) {
-               if (f == file) {
-                       *fp = file->f_next;
-                       nlmsvc_ops->fclose(file->f_file);
-                       kfree(file);
-                       return;
-               }
-               fp = &f->f_next;
+       if (!hlist_unhashed(&file->f_list)) {
+               hlist_del(&file->f_list);
+               nlmsvc_ops->fclose(file->f_file);
+               kfree(file);
+       } else {
+               printk(KERN_WARNING "lockd: attempt to release unknown file!\n");
        }
-
-       printk(KERN_WARNING "lockd: attempt to release unknown file!\n");
 }
 
 /*
 static int
 nlm_traverse_files(struct nlm_host *host, int action)
 {
-       struct nlm_file *file, **fp;
+       struct hlist_node *pos, *next;
+       struct nlm_file *file;
        int i, ret = 0;
 
        mutex_lock(&nlm_file_mutex);
        for (i = 0; i < FILE_NRHASH; i++) {
-               fp = nlm_files + i;
-               while ((file = *fp) != NULL) {
+               hlist_for_each_entry_safe(file, pos, next, &nlm_files[i], f_list) {
                        file->f_count++;
                        mutex_unlock(&nlm_file_mutex);
 
                        /* No more references to this file. Let go of it. */
                        if (list_empty(&file->f_blocks) && !file->f_locks
                         && !file->f_shares && !file->f_count) {
-                               *fp = file->f_next;
+                               hlist_del(&file->f_list);
                                nlmsvc_ops->fclose(file->f_file);
                                kfree(file);
-                       } else {
-                               fp = &file->f_next;
                        }
                }
        }