diff options
author | Christoph Hellwig <hch@infradead.org> | 2011-02-28 20:34:21 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-03-11 15:38:43 -0500 |
commit | ea8eecdd11ee6becd09c095c8efa88aa7df95961 (patch) | |
tree | 4db9c584989d006790637e255657a010c8243cb9 /fs/nfs/pnfs.c | |
parent | cbdabc7f8bf14ca1d40ab1cb86f64b3bc09716e8 (diff) |
NFSv4.1 move deviceid cache to filelayout driver
No need for generic cache with only one user.
Keep a simple hash of deviceids in the filelayout driver.
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Acked-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r-- | fs/nfs/pnfs.c | 147 |
1 files changed, 2 insertions, 145 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 86c154bad5db..1f4c153441a1 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -75,10 +75,8 @@ find_pnfs_driver(u32 id) | |||
75 | void | 75 | void |
76 | unset_pnfs_layoutdriver(struct nfs_server *nfss) | 76 | unset_pnfs_layoutdriver(struct nfs_server *nfss) |
77 | { | 77 | { |
78 | if (nfss->pnfs_curr_ld) { | 78 | if (nfss->pnfs_curr_ld) |
79 | nfss->pnfs_curr_ld->clear_layoutdriver(nfss); | ||
80 | module_put(nfss->pnfs_curr_ld->owner); | 79 | module_put(nfss->pnfs_curr_ld->owner); |
81 | } | ||
82 | nfss->pnfs_curr_ld = NULL; | 80 | nfss->pnfs_curr_ld = NULL; |
83 | } | 81 | } |
84 | 82 | ||
@@ -116,13 +114,7 @@ set_pnfs_layoutdriver(struct nfs_server *server, u32 id) | |||
116 | goto out_no_driver; | 114 | goto out_no_driver; |
117 | } | 115 | } |
118 | server->pnfs_curr_ld = ld_type; | 116 | server->pnfs_curr_ld = ld_type; |
119 | if (ld_type->set_layoutdriver(server)) { | 117 | |
120 | printk(KERN_ERR | ||
121 | "%s: Error initializing mount point for layout driver %u.\n", | ||
122 | __func__, id); | ||
123 | module_put(ld_type->owner); | ||
124 | goto out_no_driver; | ||
125 | } | ||
126 | dprintk("%s: pNFS module for %u set\n", __func__, id); | 118 | dprintk("%s: pNFS module for %u set\n", __func__, id); |
127 | return; | 119 | return; |
128 | 120 | ||
@@ -906,138 +898,3 @@ pnfs_try_to_read_data(struct nfs_read_data *rdata, | |||
906 | dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs); | 898 | dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs); |
907 | return trypnfs; | 899 | return trypnfs; |
908 | } | 900 | } |
909 | |||
910 | /* | ||
911 | * Device ID cache. Currently supports one layout type per struct nfs_client. | ||
912 | * Add layout type to the lookup key to expand to support multiple types. | ||
913 | */ | ||
914 | int | ||
915 | pnfs_alloc_init_deviceid_cache(struct nfs_client *clp, | ||
916 | void (*free_callback)(struct pnfs_deviceid_node *)) | ||
917 | { | ||
918 | struct pnfs_deviceid_cache *c; | ||
919 | |||
920 | c = kzalloc(sizeof(struct pnfs_deviceid_cache), GFP_KERNEL); | ||
921 | if (!c) | ||
922 | return -ENOMEM; | ||
923 | spin_lock(&clp->cl_lock); | ||
924 | if (clp->cl_devid_cache != NULL) { | ||
925 | atomic_inc(&clp->cl_devid_cache->dc_ref); | ||
926 | dprintk("%s [kref [%d]]\n", __func__, | ||
927 | atomic_read(&clp->cl_devid_cache->dc_ref)); | ||
928 | kfree(c); | ||
929 | } else { | ||
930 | /* kzalloc initializes hlists */ | ||
931 | spin_lock_init(&c->dc_lock); | ||
932 | atomic_set(&c->dc_ref, 1); | ||
933 | c->dc_free_callback = free_callback; | ||
934 | clp->cl_devid_cache = c; | ||
935 | dprintk("%s [new]\n", __func__); | ||
936 | } | ||
937 | spin_unlock(&clp->cl_lock); | ||
938 | return 0; | ||
939 | } | ||
940 | EXPORT_SYMBOL_GPL(pnfs_alloc_init_deviceid_cache); | ||
941 | |||
942 | /* | ||
943 | * Called from pnfs_layoutdriver_type->free_lseg | ||
944 | * last layout segment reference frees deviceid | ||
945 | */ | ||
946 | void | ||
947 | pnfs_put_deviceid(struct pnfs_deviceid_cache *c, | ||
948 | struct pnfs_deviceid_node *devid) | ||
949 | { | ||
950 | struct nfs4_deviceid *id = &devid->de_id; | ||
951 | struct pnfs_deviceid_node *d; | ||
952 | struct hlist_node *n; | ||
953 | long h = nfs4_deviceid_hash(id); | ||
954 | |||
955 | dprintk("%s [%d]\n", __func__, atomic_read(&devid->de_ref)); | ||
956 | if (!atomic_dec_and_lock(&devid->de_ref, &c->dc_lock)) | ||
957 | return; | ||
958 | |||
959 | hlist_for_each_entry_rcu(d, n, &c->dc_deviceids[h], de_node) | ||
960 | if (!memcmp(&d->de_id, id, sizeof(*id))) { | ||
961 | hlist_del_rcu(&d->de_node); | ||
962 | spin_unlock(&c->dc_lock); | ||
963 | synchronize_rcu(); | ||
964 | c->dc_free_callback(devid); | ||
965 | return; | ||
966 | } | ||
967 | spin_unlock(&c->dc_lock); | ||
968 | /* Why wasn't it found in the list? */ | ||
969 | BUG(); | ||
970 | } | ||
971 | EXPORT_SYMBOL_GPL(pnfs_put_deviceid); | ||
972 | |||
973 | /* Find and reference a deviceid */ | ||
974 | struct pnfs_deviceid_node * | ||
975 | pnfs_find_get_deviceid(struct pnfs_deviceid_cache *c, struct nfs4_deviceid *id) | ||
976 | { | ||
977 | struct pnfs_deviceid_node *d; | ||
978 | struct hlist_node *n; | ||
979 | long hash = nfs4_deviceid_hash(id); | ||
980 | |||
981 | dprintk("--> %s hash %ld\n", __func__, hash); | ||
982 | rcu_read_lock(); | ||
983 | hlist_for_each_entry_rcu(d, n, &c->dc_deviceids[hash], de_node) { | ||
984 | if (!memcmp(&d->de_id, id, sizeof(*id))) { | ||
985 | if (!atomic_inc_not_zero(&d->de_ref)) { | ||
986 | goto fail; | ||
987 | } else { | ||
988 | rcu_read_unlock(); | ||
989 | return d; | ||
990 | } | ||
991 | } | ||
992 | } | ||
993 | fail: | ||
994 | rcu_read_unlock(); | ||
995 | return NULL; | ||
996 | } | ||
997 | EXPORT_SYMBOL_GPL(pnfs_find_get_deviceid); | ||
998 | |||
999 | /* | ||
1000 | * Add a deviceid to the cache. | ||
1001 | * GETDEVICEINFOs for same deviceid can race. If deviceid is found, discard new | ||
1002 | */ | ||
1003 | struct pnfs_deviceid_node * | ||
1004 | pnfs_add_deviceid(struct pnfs_deviceid_cache *c, struct pnfs_deviceid_node *new) | ||
1005 | { | ||
1006 | struct pnfs_deviceid_node *d; | ||
1007 | long hash = nfs4_deviceid_hash(&new->de_id); | ||
1008 | |||
1009 | dprintk("--> %s hash %ld\n", __func__, hash); | ||
1010 | spin_lock(&c->dc_lock); | ||
1011 | d = pnfs_find_get_deviceid(c, &new->de_id); | ||
1012 | if (d) { | ||
1013 | spin_unlock(&c->dc_lock); | ||
1014 | dprintk("%s [discard]\n", __func__); | ||
1015 | c->dc_free_callback(new); | ||
1016 | return d; | ||
1017 | } | ||
1018 | INIT_HLIST_NODE(&new->de_node); | ||
1019 | atomic_set(&new->de_ref, 1); | ||
1020 | hlist_add_head_rcu(&new->de_node, &c->dc_deviceids[hash]); | ||
1021 | spin_unlock(&c->dc_lock); | ||
1022 | dprintk("%s [new]\n", __func__); | ||
1023 | return new; | ||
1024 | } | ||
1025 | EXPORT_SYMBOL_GPL(pnfs_add_deviceid); | ||
1026 | |||
1027 | void | ||
1028 | pnfs_put_deviceid_cache(struct nfs_client *clp) | ||
1029 | { | ||
1030 | struct pnfs_deviceid_cache *local = clp->cl_devid_cache; | ||
1031 | |||
1032 | dprintk("--> %s ({%d})\n", __func__, atomic_read(&local->dc_ref)); | ||
1033 | if (atomic_dec_and_lock(&local->dc_ref, &clp->cl_lock)) { | ||
1034 | int i; | ||
1035 | /* Verify cache is empty */ | ||
1036 | for (i = 0; i < NFS4_DEVICE_ID_HASH_SIZE; i++) | ||
1037 | BUG_ON(!hlist_empty(&local->dc_deviceids[i])); | ||
1038 | clp->cl_devid_cache = NULL; | ||
1039 | spin_unlock(&clp->cl_lock); | ||
1040 | kfree(local); | ||
1041 | } | ||
1042 | } | ||
1043 | EXPORT_SYMBOL_GPL(pnfs_put_deviceid_cache); | ||