]>
Commit | Line | Data |
---|---|---|
85e174ba RL |
1 | /* |
2 | * pNFS client data structures. | |
3 | * | |
4 | * Copyright (c) 2002 | |
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 | #ifndef FS_NFS_PNFS_H | |
31 | #define FS_NFS_PNFS_H | |
32 | ||
4541d16c FI |
33 | enum { |
34 | NFS_LSEG_VALID = 0, /* cleared when lseg is recalled/returned */ | |
f7e8917a | 35 | NFS_LSEG_ROC, /* roc bit received from server */ |
4541d16c FI |
36 | }; |
37 | ||
974cec8c | 38 | struct pnfs_layout_segment { |
566052c5 FI |
39 | struct list_head pls_list; |
40 | struct pnfs_layout_range pls_range; | |
4541d16c FI |
41 | atomic_t pls_refcount; |
42 | unsigned long pls_flags; | |
566052c5 | 43 | struct pnfs_layout_hdr *pls_layout; |
974cec8c AA |
44 | }; |
45 | ||
85e174ba RL |
46 | #ifdef CONFIG_NFS_V4_1 |
47 | ||
48 | #define LAYOUT_NFSV4_1_MODULE_PREFIX "nfs-layouttype4" | |
49 | ||
e5e94017 BH |
50 | enum { |
51 | NFS_LAYOUT_RO_FAILED = 0, /* get ro layout failed stop trying */ | |
52 | NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */ | |
43f1b3da | 53 | NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */ |
f7e8917a | 54 | NFS_LAYOUT_ROC, /* some lseg had roc bit set */ |
4541d16c | 55 | NFS_LAYOUT_DESTROYED, /* no new use of layout allowed */ |
e5e94017 BH |
56 | }; |
57 | ||
85e174ba RL |
58 | /* Per-layout driver specific registration structure */ |
59 | struct pnfs_layoutdriver_type { | |
02c35fca FI |
60 | struct list_head pnfs_tblid; |
61 | const u32 id; | |
62 | const char *name; | |
63 | struct module *owner; | |
1c787096 TM |
64 | int (*set_layoutdriver) (struct nfs_server *); |
65 | int (*clear_layoutdriver) (struct nfs_server *); | |
b1f69b75 AA |
66 | struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr); |
67 | void (*free_lseg) (struct pnfs_layout_segment *lseg); | |
85e174ba RL |
68 | }; |
69 | ||
e5e94017 | 70 | struct pnfs_layout_hdr { |
cc6e5340 | 71 | atomic_t plh_refcount; |
b7edfaa1 | 72 | struct list_head plh_layouts; /* other client layouts */ |
43f1b3da | 73 | struct list_head plh_bulk_recall; /* clnt list of bulk recalls */ |
b7edfaa1 | 74 | struct list_head plh_segs; /* layout segments list */ |
b7edfaa1 | 75 | nfs4_stateid plh_stateid; |
cf7d63f1 | 76 | atomic_t plh_outstanding; /* number of RPCs out */ |
f7e8917a | 77 | unsigned long plh_block_lgets; /* block LAYOUTGET if >0 */ |
43f1b3da | 78 | u32 plh_barrier; /* ignore lower seqids */ |
566052c5 | 79 | unsigned long plh_flags; |
b7edfaa1 | 80 | struct inode *plh_inode; |
e5e94017 BH |
81 | }; |
82 | ||
b1f69b75 AA |
83 | struct pnfs_device { |
84 | struct nfs4_deviceid dev_id; | |
85 | unsigned int layout_type; | |
86 | unsigned int mincount; | |
87 | struct page **pages; | |
88 | void *area; | |
89 | unsigned int pgbase; | |
90 | unsigned int pglen; | |
91 | }; | |
92 | ||
93 | /* | |
94 | * Device ID RCU cache. A device ID is unique per client ID and layout type. | |
95 | */ | |
96 | #define NFS4_DEVICE_ID_HASH_BITS 5 | |
97 | #define NFS4_DEVICE_ID_HASH_SIZE (1 << NFS4_DEVICE_ID_HASH_BITS) | |
98 | #define NFS4_DEVICE_ID_HASH_MASK (NFS4_DEVICE_ID_HASH_SIZE - 1) | |
99 | ||
100 | static inline u32 | |
101 | nfs4_deviceid_hash(struct nfs4_deviceid *id) | |
102 | { | |
103 | unsigned char *cptr = (unsigned char *)id->data; | |
104 | unsigned int nbytes = NFS4_DEVICEID4_SIZE; | |
105 | u32 x = 0; | |
106 | ||
107 | while (nbytes--) { | |
108 | x *= 37; | |
109 | x += *cptr++; | |
110 | } | |
111 | return x & NFS4_DEVICE_ID_HASH_MASK; | |
112 | } | |
113 | ||
114 | struct pnfs_deviceid_node { | |
115 | struct hlist_node de_node; | |
116 | struct nfs4_deviceid de_id; | |
117 | atomic_t de_ref; | |
118 | }; | |
119 | ||
120 | struct pnfs_deviceid_cache { | |
121 | spinlock_t dc_lock; | |
122 | atomic_t dc_ref; | |
123 | void (*dc_free_callback)(struct pnfs_deviceid_node *); | |
124 | struct hlist_head dc_deviceids[NFS4_DEVICE_ID_HASH_SIZE]; | |
125 | }; | |
126 | ||
127 | extern int pnfs_alloc_init_deviceid_cache(struct nfs_client *, | |
128 | void (*free_callback)(struct pnfs_deviceid_node *)); | |
129 | extern void pnfs_put_deviceid_cache(struct nfs_client *); | |
130 | extern struct pnfs_deviceid_node *pnfs_find_get_deviceid( | |
131 | struct pnfs_deviceid_cache *, | |
132 | struct nfs4_deviceid *); | |
133 | extern struct pnfs_deviceid_node *pnfs_add_deviceid( | |
134 | struct pnfs_deviceid_cache *, | |
135 | struct pnfs_deviceid_node *); | |
136 | extern void pnfs_put_deviceid(struct pnfs_deviceid_cache *c, | |
137 | struct pnfs_deviceid_node *devid); | |
138 | ||
02c35fca FI |
139 | extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *); |
140 | extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *); | |
141 | ||
b1f69b75 AA |
142 | /* nfs4proc.c */ |
143 | extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, | |
144 | struct pnfs_device *dev); | |
145 | extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp); | |
146 | ||
147 | /* pnfs.c */ | |
43f1b3da | 148 | void get_layout_hdr(struct pnfs_layout_hdr *lo); |
e5e94017 BH |
149 | struct pnfs_layout_segment * |
150 | pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, | |
151 | enum pnfs_iomode access_type); | |
85e174ba RL |
152 | void set_pnfs_layoutdriver(struct nfs_server *, u32 id); |
153 | void unset_pnfs_layoutdriver(struct nfs_server *); | |
b1f69b75 | 154 | int pnfs_layout_process(struct nfs4_layoutget *lgp); |
43f1b3da | 155 | void pnfs_free_lseg_list(struct list_head *tmp_list); |
e5e94017 | 156 | void pnfs_destroy_layout(struct nfs_inode *); |
974cec8c | 157 | void pnfs_destroy_all_layouts(struct nfs_client *); |
cc6e5340 | 158 | void put_layout_hdr(struct pnfs_layout_hdr *lo); |
43f1b3da FI |
159 | void pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, |
160 | const nfs4_stateid *new, | |
161 | bool update_barrier); | |
fd6002e9 FI |
162 | int pnfs_choose_layoutget_stateid(nfs4_stateid *dst, |
163 | struct pnfs_layout_hdr *lo, | |
164 | struct nfs4_state *open_state); | |
43f1b3da FI |
165 | int mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo, |
166 | struct list_head *tmp_list, | |
167 | u32 iomode); | |
f7e8917a FI |
168 | bool pnfs_roc(struct inode *ino); |
169 | void pnfs_roc_release(struct inode *ino); | |
170 | void pnfs_roc_set_barrier(struct inode *ino, u32 barrier); | |
171 | bool pnfs_roc_drain(struct inode *ino, u32 *barrier); | |
e5e94017 BH |
172 | |
173 | ||
174 | static inline int lo_fail_bit(u32 iomode) | |
175 | { | |
176 | return iomode == IOMODE_RW ? | |
177 | NFS_LAYOUT_RW_FAILED : NFS_LAYOUT_RO_FAILED; | |
178 | } | |
179 | ||
d684d2ae FI |
180 | static inline struct pnfs_layout_segment * |
181 | get_lseg(struct pnfs_layout_segment *lseg) | |
182 | { | |
183 | if (lseg) { | |
184 | atomic_inc(&lseg->pls_refcount); | |
185 | smp_mb__after_atomic_inc(); | |
186 | } | |
187 | return lseg; | |
188 | } | |
189 | ||
e5e94017 BH |
190 | /* Return true if a layout driver is being used for this mountpoint */ |
191 | static inline int pnfs_enabled_sb(struct nfs_server *nfss) | |
192 | { | |
193 | return nfss->pnfs_curr_ld != NULL; | |
194 | } | |
85e174ba RL |
195 | |
196 | #else /* CONFIG_NFS_V4_1 */ | |
197 | ||
974cec8c AA |
198 | static inline void pnfs_destroy_all_layouts(struct nfs_client *clp) |
199 | { | |
200 | } | |
201 | ||
e5e94017 BH |
202 | static inline void pnfs_destroy_layout(struct nfs_inode *nfsi) |
203 | { | |
204 | } | |
205 | ||
d684d2ae FI |
206 | static inline struct pnfs_layout_segment * |
207 | get_lseg(struct pnfs_layout_segment *lseg) | |
208 | { | |
209 | return NULL; | |
210 | } | |
211 | ||
212 | static inline void put_lseg(struct pnfs_layout_segment *lseg) | |
213 | { | |
214 | } | |
215 | ||
e5e94017 BH |
216 | static inline struct pnfs_layout_segment * |
217 | pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx, | |
218 | enum pnfs_iomode access_type) | |
219 | { | |
220 | return NULL; | |
221 | } | |
222 | ||
f7e8917a FI |
223 | static inline bool |
224 | pnfs_roc(struct inode *ino) | |
225 | { | |
226 | return false; | |
227 | } | |
228 | ||
229 | static inline void | |
230 | pnfs_roc_release(struct inode *ino) | |
231 | { | |
232 | } | |
233 | ||
234 | static inline void | |
235 | pnfs_roc_set_barrier(struct inode *ino, u32 barrier) | |
236 | { | |
237 | } | |
238 | ||
239 | static inline bool | |
240 | pnfs_roc_drain(struct inode *ino, u32 *barrier) | |
241 | { | |
242 | return false; | |
243 | } | |
244 | ||
85e174ba RL |
245 | static inline void set_pnfs_layoutdriver(struct nfs_server *s, u32 id) |
246 | { | |
247 | } | |
248 | ||
249 | static inline void unset_pnfs_layoutdriver(struct nfs_server *s) | |
250 | { | |
251 | } | |
252 | ||
253 | #endif /* CONFIG_NFS_V4_1 */ | |
254 | ||
255 | #endif /* FS_NFS_PNFS_H */ |