diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/objlayout/objio_osd.c | 157 | ||||
-rw-r--r-- | fs/nfs/objlayout/objlayout.c | 68 | ||||
-rw-r--r-- | fs/nfs/objlayout/objlayout.h | 8 |
3 files changed, 233 insertions, 0 deletions
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index 08f1d90b4ce7..2255e2d22d05 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c | |||
@@ -46,6 +46,68 @@ | |||
46 | 46 | ||
47 | #define _LLU(x) ((unsigned long long)x) | 47 | #define _LLU(x) ((unsigned long long)x) |
48 | 48 | ||
49 | struct objio_dev_ent { | ||
50 | struct nfs4_deviceid_node id_node; | ||
51 | struct osd_dev *od; | ||
52 | }; | ||
53 | |||
54 | static void | ||
55 | objio_free_deviceid_node(struct nfs4_deviceid_node *d) | ||
56 | { | ||
57 | struct objio_dev_ent *de = container_of(d, struct objio_dev_ent, id_node); | ||
58 | |||
59 | dprintk("%s: free od=%p\n", __func__, de->od); | ||
60 | osduld_put_device(de->od); | ||
61 | kfree(de); | ||
62 | } | ||
63 | |||
64 | static struct objio_dev_ent *_dev_list_find(const struct nfs_server *nfss, | ||
65 | const struct nfs4_deviceid *d_id) | ||
66 | { | ||
67 | struct nfs4_deviceid_node *d; | ||
68 | struct objio_dev_ent *de; | ||
69 | |||
70 | d = nfs4_find_get_deviceid(nfss->pnfs_curr_ld, nfss->nfs_client, d_id); | ||
71 | if (!d) | ||
72 | return NULL; | ||
73 | |||
74 | de = container_of(d, struct objio_dev_ent, id_node); | ||
75 | return de; | ||
76 | } | ||
77 | |||
78 | static struct objio_dev_ent * | ||
79 | _dev_list_add(const struct nfs_server *nfss, | ||
80 | const struct nfs4_deviceid *d_id, struct osd_dev *od, | ||
81 | gfp_t gfp_flags) | ||
82 | { | ||
83 | struct nfs4_deviceid_node *d; | ||
84 | struct objio_dev_ent *de = kzalloc(sizeof(*de), gfp_flags); | ||
85 | struct objio_dev_ent *n; | ||
86 | |||
87 | if (!de) { | ||
88 | dprintk("%s: -ENOMEM od=%p\n", __func__, od); | ||
89 | return NULL; | ||
90 | } | ||
91 | |||
92 | dprintk("%s: Adding od=%p\n", __func__, od); | ||
93 | nfs4_init_deviceid_node(&de->id_node, | ||
94 | nfss->pnfs_curr_ld, | ||
95 | nfss->nfs_client, | ||
96 | d_id); | ||
97 | de->od = od; | ||
98 | |||
99 | d = nfs4_insert_deviceid_node(&de->id_node); | ||
100 | n = container_of(d, struct objio_dev_ent, id_node); | ||
101 | if (n != de) { | ||
102 | dprintk("%s: Race with other n->od=%p\n", __func__, n->od); | ||
103 | objio_free_deviceid_node(&de->id_node); | ||
104 | de = n; | ||
105 | } | ||
106 | |||
107 | atomic_inc(&de->id_node.ref); | ||
108 | return de; | ||
109 | } | ||
110 | |||
49 | struct caps_buffers { | 111 | struct caps_buffers { |
50 | u8 caps_key[OSD_CRYPTO_KEYID_SIZE]; | 112 | u8 caps_key[OSD_CRYPTO_KEYID_SIZE]; |
51 | u8 creds[OSD_CAP_LEN]; | 113 | u8 creds[OSD_CAP_LEN]; |
@@ -74,6 +136,90 @@ OBJIO_LSEG(struct pnfs_layout_segment *lseg) | |||
74 | return container_of(lseg, struct objio_segment, lseg); | 136 | return container_of(lseg, struct objio_segment, lseg); |
75 | } | 137 | } |
76 | 138 | ||
139 | /* Send and wait for a get_device_info of devices in the layout, | ||
140 | then look them up with the osd_initiator library */ | ||
141 | static struct objio_dev_ent *_device_lookup(struct pnfs_layout_hdr *pnfslay, | ||
142 | struct objio_segment *objio_seg, unsigned comp, | ||
143 | gfp_t gfp_flags) | ||
144 | { | ||
145 | struct pnfs_osd_deviceaddr *deviceaddr; | ||
146 | struct nfs4_deviceid *d_id; | ||
147 | struct objio_dev_ent *ode; | ||
148 | struct osd_dev *od; | ||
149 | struct osd_dev_info odi; | ||
150 | int err; | ||
151 | |||
152 | d_id = &objio_seg->comps[comp].oc_object_id.oid_device_id; | ||
153 | |||
154 | ode = _dev_list_find(NFS_SERVER(pnfslay->plh_inode), d_id); | ||
155 | if (ode) | ||
156 | return ode; | ||
157 | |||
158 | err = objlayout_get_deviceinfo(pnfslay, d_id, &deviceaddr, gfp_flags); | ||
159 | if (unlikely(err)) { | ||
160 | dprintk("%s: objlayout_get_deviceinfo dev(%llx:%llx) =>%d\n", | ||
161 | __func__, _DEVID_LO(d_id), _DEVID_HI(d_id), err); | ||
162 | return ERR_PTR(err); | ||
163 | } | ||
164 | |||
165 | odi.systemid_len = deviceaddr->oda_systemid.len; | ||
166 | if (odi.systemid_len > sizeof(odi.systemid)) { | ||
167 | err = -EINVAL; | ||
168 | goto out; | ||
169 | } else if (odi.systemid_len) | ||
170 | memcpy(odi.systemid, deviceaddr->oda_systemid.data, | ||
171 | odi.systemid_len); | ||
172 | odi.osdname_len = deviceaddr->oda_osdname.len; | ||
173 | odi.osdname = (u8 *)deviceaddr->oda_osdname.data; | ||
174 | |||
175 | if (!odi.osdname_len && !odi.systemid_len) { | ||
176 | dprintk("%s: !odi.osdname_len && !odi.systemid_len\n", | ||
177 | __func__); | ||
178 | err = -ENODEV; | ||
179 | goto out; | ||
180 | } | ||
181 | |||
182 | od = osduld_info_lookup(&odi); | ||
183 | if (unlikely(IS_ERR(od))) { | ||
184 | err = PTR_ERR(od); | ||
185 | dprintk("%s: osduld_info_lookup => %d\n", __func__, err); | ||
186 | goto out; | ||
187 | } | ||
188 | |||
189 | ode = _dev_list_add(NFS_SERVER(pnfslay->plh_inode), d_id, od, | ||
190 | gfp_flags); | ||
191 | |||
192 | out: | ||
193 | dprintk("%s: return=%d\n", __func__, err); | ||
194 | objlayout_put_deviceinfo(deviceaddr); | ||
195 | return err ? ERR_PTR(err) : ode; | ||
196 | } | ||
197 | |||
198 | static int objio_devices_lookup(struct pnfs_layout_hdr *pnfslay, | ||
199 | struct objio_segment *objio_seg, | ||
200 | gfp_t gfp_flags) | ||
201 | { | ||
202 | unsigned i; | ||
203 | int err; | ||
204 | |||
205 | /* lookup all devices */ | ||
206 | for (i = 0; i < objio_seg->num_comps; i++) { | ||
207 | struct objio_dev_ent *ode; | ||
208 | |||
209 | ode = _device_lookup(pnfslay, objio_seg, i, gfp_flags); | ||
210 | if (unlikely(IS_ERR(ode))) { | ||
211 | err = PTR_ERR(ode); | ||
212 | goto out; | ||
213 | } | ||
214 | objio_seg->ods[i] = ode; | ||
215 | } | ||
216 | err = 0; | ||
217 | |||
218 | out: | ||
219 | dprintk("%s: return=%d\n", __func__, err); | ||
220 | return err; | ||
221 | } | ||
222 | |||
77 | static int _verify_data_map(struct pnfs_osd_layout *layout) | 223 | static int _verify_data_map(struct pnfs_osd_layout *layout) |
78 | { | 224 | { |
79 | struct pnfs_osd_data_map *data_map = &layout->olo_map; | 225 | struct pnfs_osd_data_map *data_map = &layout->olo_map; |
@@ -171,6 +317,9 @@ int objio_alloc_lseg(struct pnfs_layout_segment **outp, | |||
171 | 317 | ||
172 | objio_seg->num_comps = layout.olo_num_comps; | 318 | objio_seg->num_comps = layout.olo_num_comps; |
173 | objio_seg->comps_index = layout.olo_comps_index; | 319 | objio_seg->comps_index = layout.olo_comps_index; |
320 | err = objio_devices_lookup(pnfslay, objio_seg, gfp_flags); | ||
321 | if (err) | ||
322 | goto err; | ||
174 | 323 | ||
175 | objio_seg->mirrors_p1 = layout.olo_map.odm_mirror_cnt + 1; | 324 | objio_seg->mirrors_p1 = layout.olo_map.odm_mirror_cnt + 1; |
176 | objio_seg->stripe_unit = layout.olo_map.odm_stripe_unit; | 325 | objio_seg->stripe_unit = layout.olo_map.odm_stripe_unit; |
@@ -199,8 +348,14 @@ err: | |||
199 | 348 | ||
200 | void objio_free_lseg(struct pnfs_layout_segment *lseg) | 349 | void objio_free_lseg(struct pnfs_layout_segment *lseg) |
201 | { | 350 | { |
351 | int i; | ||
202 | struct objio_segment *objio_seg = OBJIO_LSEG(lseg); | 352 | struct objio_segment *objio_seg = OBJIO_LSEG(lseg); |
203 | 353 | ||
354 | for (i = 0; i < objio_seg->num_comps; i++) { | ||
355 | if (!objio_seg->ods[i]) | ||
356 | break; | ||
357 | nfs4_put_deviceid_node(&objio_seg->ods[i]->id_node); | ||
358 | } | ||
204 | kfree(objio_seg); | 359 | kfree(objio_seg); |
205 | } | 360 | } |
206 | 361 | ||
@@ -211,6 +366,8 @@ static struct pnfs_layoutdriver_type objlayout_type = { | |||
211 | 366 | ||
212 | .alloc_lseg = objlayout_alloc_lseg, | 367 | .alloc_lseg = objlayout_alloc_lseg, |
213 | .free_lseg = objlayout_free_lseg, | 368 | .free_lseg = objlayout_free_lseg, |
369 | |||
370 | .free_deviceid_node = objio_free_deviceid_node, | ||
214 | }; | 371 | }; |
215 | 372 | ||
216 | MODULE_DESCRIPTION("pNFS Layout Driver for OSD2 objects"); | 373 | MODULE_DESCRIPTION("pNFS Layout Driver for OSD2 objects"); |
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c index 946526763d38..10e5fca3b7fb 100644 --- a/fs/nfs/objlayout/objlayout.c +++ b/fs/nfs/objlayout/objlayout.c | |||
@@ -102,3 +102,71 @@ objlayout_free_lseg(struct pnfs_layout_segment *lseg) | |||
102 | objio_free_lseg(lseg); | 102 | objio_free_lseg(lseg); |
103 | } | 103 | } |
104 | 104 | ||
105 | /* | ||
106 | * Get Device Info API for io engines | ||
107 | */ | ||
108 | struct objlayout_deviceinfo { | ||
109 | struct page *page; | ||
110 | struct pnfs_osd_deviceaddr da; /* This must be last */ | ||
111 | }; | ||
112 | |||
113 | /* Initialize and call nfs_getdeviceinfo, then decode and return a | ||
114 | * "struct pnfs_osd_deviceaddr *" Eventually objlayout_put_deviceinfo() | ||
115 | * should be called. | ||
116 | */ | ||
117 | int objlayout_get_deviceinfo(struct pnfs_layout_hdr *pnfslay, | ||
118 | struct nfs4_deviceid *d_id, struct pnfs_osd_deviceaddr **deviceaddr, | ||
119 | gfp_t gfp_flags) | ||
120 | { | ||
121 | struct objlayout_deviceinfo *odi; | ||
122 | struct pnfs_device pd; | ||
123 | struct super_block *sb; | ||
124 | struct page *page, **pages; | ||
125 | u32 *p; | ||
126 | int err; | ||
127 | |||
128 | page = alloc_page(gfp_flags); | ||
129 | if (!page) | ||
130 | return -ENOMEM; | ||
131 | |||
132 | pages = &page; | ||
133 | pd.pages = pages; | ||
134 | |||
135 | memcpy(&pd.dev_id, d_id, sizeof(*d_id)); | ||
136 | pd.layout_type = LAYOUT_OSD2_OBJECTS; | ||
137 | pd.pages = &page; | ||
138 | pd.pgbase = 0; | ||
139 | pd.pglen = PAGE_SIZE; | ||
140 | pd.mincount = 0; | ||
141 | |||
142 | sb = pnfslay->plh_inode->i_sb; | ||
143 | err = nfs4_proc_getdeviceinfo(NFS_SERVER(pnfslay->plh_inode), &pd); | ||
144 | dprintk("%s nfs_getdeviceinfo returned %d\n", __func__, err); | ||
145 | if (err) | ||
146 | goto err_out; | ||
147 | |||
148 | p = page_address(page); | ||
149 | odi = kzalloc(sizeof(*odi), gfp_flags); | ||
150 | if (!odi) { | ||
151 | err = -ENOMEM; | ||
152 | goto err_out; | ||
153 | } | ||
154 | pnfs_osd_xdr_decode_deviceaddr(&odi->da, p); | ||
155 | odi->page = page; | ||
156 | *deviceaddr = &odi->da; | ||
157 | return 0; | ||
158 | |||
159 | err_out: | ||
160 | __free_page(page); | ||
161 | return err; | ||
162 | } | ||
163 | |||
164 | void objlayout_put_deviceinfo(struct pnfs_osd_deviceaddr *deviceaddr) | ||
165 | { | ||
166 | struct objlayout_deviceinfo *odi = container_of(deviceaddr, | ||
167 | struct objlayout_deviceinfo, | ||
168 | da); | ||
169 | |||
170 | __free_page(odi->page); | ||
171 | kfree(odi); | ||
172 | } | ||
diff --git a/fs/nfs/objlayout/objlayout.h b/fs/nfs/objlayout/objlayout.h index 066280a07fa8..0814271bb9ba 100644 --- a/fs/nfs/objlayout/objlayout.h +++ b/fs/nfs/objlayout/objlayout.h | |||
@@ -56,6 +56,14 @@ extern int objio_alloc_lseg(struct pnfs_layout_segment **outp, | |||
56 | extern void objio_free_lseg(struct pnfs_layout_segment *lseg); | 56 | extern void objio_free_lseg(struct pnfs_layout_segment *lseg); |
57 | 57 | ||
58 | /* | 58 | /* |
59 | * callback API | ||
60 | */ | ||
61 | extern int objlayout_get_deviceinfo(struct pnfs_layout_hdr *pnfslay, | ||
62 | struct nfs4_deviceid *d_id, struct pnfs_osd_deviceaddr **deviceaddr, | ||
63 | gfp_t gfp_flags); | ||
64 | extern void objlayout_put_deviceinfo(struct pnfs_osd_deviceaddr *deviceaddr); | ||
65 | |||
66 | /* | ||
59 | * exported generic objects function vectors | 67 | * exported generic objects function vectors |
60 | */ | 68 | */ |
61 | extern struct pnfs_layout_segment *objlayout_alloc_lseg( | 69 | extern struct pnfs_layout_segment *objlayout_alloc_lseg( |