Commit | Line | Data |
---|---|---|
85e174ba RL |
1 | /* |
2 | * pNFS functions to call and manage layout drivers. | |
3 | * | |
4 | * Copyright (c) 2002 [year of first publication] | |
5 | * The Regents of the University of Michigan | |
6 | * All Rights Reserved | |
7 | * | |
8 | * Dean Hildebrand <dhildebz@umich.edu> | |
9 | * | |
10 | * Permission is granted to use, copy, create derivative works, and | |
11 | * redistribute this software and such derivative works for any purpose, | |
12 | * so long as the name of the University of Michigan is not used in | |
13 | * any advertising or publicity pertaining to the use or distribution | |
14 | * of this software without specific, written prior authorization. If | |
15 | * the above copyright notice or any other identification of the | |
16 | * University of Michigan is included in any copy of any portion of | |
17 | * this software, then the disclaimer below must also be included. | |
18 | * | |
19 | * This software is provided as is, without representation or warranty | |
20 | * of any kind either express or implied, including without limitation | |
21 | * the implied warranties of merchantability, fitness for a particular | |
22 | * purpose, or noninfringement. The Regents of the University of | |
23 | * Michigan shall not be liable for any damages, including special, | |
24 | * indirect, incidental, or consequential damages, with respect to any | |
25 | * claim arising out of or in connection with the use of the software, | |
26 | * even if it has been or is hereafter advised of the possibility of | |
27 | * such damages. | |
28 | */ | |
29 | ||
30 | #include <linux/nfs_fs.h> | |
31 | #include "pnfs.h" | |
32 | ||
33 | #define NFSDBG_FACILITY NFSDBG_PNFS | |
34 | ||
02c35fca FI |
35 | /* Locking: |
36 | * | |
37 | * pnfs_spinlock: | |
38 | * protects pnfs_modules_tbl. | |
39 | */ | |
40 | static DEFINE_SPINLOCK(pnfs_spinlock); | |
41 | ||
42 | /* | |
43 | * pnfs_modules_tbl holds all pnfs modules | |
44 | */ | |
45 | static LIST_HEAD(pnfs_modules_tbl); | |
46 | ||
47 | /* Return the registered pnfs layout driver module matching given id */ | |
48 | static struct pnfs_layoutdriver_type * | |
49 | find_pnfs_driver_locked(u32 id) | |
50 | { | |
51 | struct pnfs_layoutdriver_type *local; | |
52 | ||
53 | list_for_each_entry(local, &pnfs_modules_tbl, pnfs_tblid) | |
54 | if (local->id == id) | |
55 | goto out; | |
56 | local = NULL; | |
57 | out: | |
58 | dprintk("%s: Searching for id %u, found %p\n", __func__, id, local); | |
59 | return local; | |
60 | } | |
61 | ||
85e174ba RL |
62 | static struct pnfs_layoutdriver_type * |
63 | find_pnfs_driver(u32 id) | |
64 | { | |
02c35fca FI |
65 | struct pnfs_layoutdriver_type *local; |
66 | ||
67 | spin_lock(&pnfs_spinlock); | |
68 | local = find_pnfs_driver_locked(id); | |
69 | spin_unlock(&pnfs_spinlock); | |
70 | return local; | |
85e174ba RL |
71 | } |
72 | ||
73 | void | |
74 | unset_pnfs_layoutdriver(struct nfs_server *nfss) | |
75 | { | |
02c35fca FI |
76 | if (nfss->pnfs_curr_ld) { |
77 | nfss->pnfs_curr_ld->uninitialize_mountpoint(nfss); | |
78 | module_put(nfss->pnfs_curr_ld->owner); | |
79 | } | |
85e174ba RL |
80 | nfss->pnfs_curr_ld = NULL; |
81 | } | |
82 | ||
83 | /* | |
84 | * Try to set the server's pnfs module to the pnfs layout type specified by id. | |
85 | * Currently only one pNFS layout driver per filesystem is supported. | |
86 | * | |
87 | * @id layout type. Zero (illegal layout type) indicates pNFS not in use. | |
88 | */ | |
89 | void | |
90 | set_pnfs_layoutdriver(struct nfs_server *server, u32 id) | |
91 | { | |
92 | struct pnfs_layoutdriver_type *ld_type = NULL; | |
93 | ||
94 | if (id == 0) | |
95 | goto out_no_driver; | |
96 | if (!(server->nfs_client->cl_exchange_flags & | |
97 | (EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS))) { | |
98 | printk(KERN_ERR "%s: id %u cl_exchange_flags 0x%x\n", __func__, | |
99 | id, server->nfs_client->cl_exchange_flags); | |
100 | goto out_no_driver; | |
101 | } | |
102 | ld_type = find_pnfs_driver(id); | |
103 | if (!ld_type) { | |
104 | request_module("%s-%u", LAYOUT_NFSV4_1_MODULE_PREFIX, id); | |
105 | ld_type = find_pnfs_driver(id); | |
106 | if (!ld_type) { | |
107 | dprintk("%s: No pNFS module found for %u.\n", | |
108 | __func__, id); | |
109 | goto out_no_driver; | |
110 | } | |
111 | } | |
02c35fca FI |
112 | if (!try_module_get(ld_type->owner)) { |
113 | dprintk("%s: Could not grab reference on module\n", __func__); | |
114 | goto out_no_driver; | |
115 | } | |
85e174ba | 116 | server->pnfs_curr_ld = ld_type; |
02c35fca FI |
117 | if (ld_type->initialize_mountpoint(server)) { |
118 | printk(KERN_ERR | |
119 | "%s: Error initializing mount point for layout driver %u.\n", | |
120 | __func__, id); | |
121 | module_put(ld_type->owner); | |
122 | goto out_no_driver; | |
123 | } | |
85e174ba RL |
124 | dprintk("%s: pNFS module for %u set\n", __func__, id); |
125 | return; | |
126 | ||
127 | out_no_driver: | |
128 | dprintk("%s: Using NFSv4 I/O\n", __func__); | |
129 | server->pnfs_curr_ld = NULL; | |
130 | } | |
02c35fca FI |
131 | |
132 | int | |
133 | pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *ld_type) | |
134 | { | |
135 | int status = -EINVAL; | |
136 | struct pnfs_layoutdriver_type *tmp; | |
137 | ||
138 | if (ld_type->id == 0) { | |
139 | printk(KERN_ERR "%s id 0 is reserved\n", __func__); | |
140 | return status; | |
141 | } | |
142 | ||
143 | spin_lock(&pnfs_spinlock); | |
144 | tmp = find_pnfs_driver_locked(ld_type->id); | |
145 | if (!tmp) { | |
146 | list_add(&ld_type->pnfs_tblid, &pnfs_modules_tbl); | |
147 | status = 0; | |
148 | dprintk("%s Registering id:%u name:%s\n", __func__, ld_type->id, | |
149 | ld_type->name); | |
150 | } else { | |
151 | printk(KERN_ERR "%s Module with id %d already loaded!\n", | |
152 | __func__, ld_type->id); | |
153 | } | |
154 | spin_unlock(&pnfs_spinlock); | |
155 | ||
156 | return status; | |
157 | } | |
158 | EXPORT_SYMBOL_GPL(pnfs_register_layoutdriver); | |
159 | ||
160 | void | |
161 | pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *ld_type) | |
162 | { | |
163 | dprintk("%s Deregistering id:%u\n", __func__, ld_type->id); | |
164 | spin_lock(&pnfs_spinlock); | |
165 | list_del(&ld_type->pnfs_tblid); | |
166 | spin_unlock(&pnfs_spinlock); | |
167 | } | |
168 | EXPORT_SYMBOL_GPL(pnfs_unregister_layoutdriver); |