aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/objlayout
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2011-05-26 14:45:34 -0400
committerBoaz Harrosh <bharrosh@panasas.com>2011-05-29 13:53:33 -0400
commitb6c05f1693115164c7b797152ac7ea3ef8e5d296 (patch)
tree24430851c2569f4db76b13f41e82514326fbb878 /fs/nfs/objlayout
parent09f5bf4e6d0607399c16ec7a2d8d166f31086686 (diff)
pnfs-obj: objio_osd device information retrieval and caching
When a new layout is received in objio_alloc_lseg all device_ids referenced are retrieved. The device information is queried for from MDS and then the osd_device is looked-up from the osd-initiator library. The devices are cached in a per-mount-point list, for later use. At unmount all devices are "put" back to the library. objlayout_get_deviceinfo(), objlayout_put_deviceinfo() middleware API for retrieving device information given a device_id. TODO: The device cache can get big. Cap its size. Keep an LRU and start to return devices which were not used, when list gets to big, or when new entries allocation fail. [pnfs-obj: Bugs in new global-device-cache code] Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> [gfp_flags] [use global device cache] [use layout driver in global device cache] Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Diffstat (limited to 'fs/nfs/objlayout')
-rw-r--r--fs/nfs/objlayout/objio_osd.c157
-rw-r--r--fs/nfs/objlayout/objlayout.c68
-rw-r--r--fs/nfs/objlayout/objlayout.h8
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
49struct objio_dev_ent {
50 struct nfs4_deviceid_node id_node;
51 struct osd_dev *od;
52};
53
54static void
55objio_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
64static 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
78static 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
49struct caps_buffers { 111struct 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 */
141static 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
192out:
193 dprintk("%s: return=%d\n", __func__, err);
194 objlayout_put_deviceinfo(deviceaddr);
195 return err ? ERR_PTR(err) : ode;
196}
197
198static 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
218out:
219 dprintk("%s: return=%d\n", __func__, err);
220 return err;
221}
222
77static int _verify_data_map(struct pnfs_osd_layout *layout) 223static 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
200void objio_free_lseg(struct pnfs_layout_segment *lseg) 349void 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
216MODULE_DESCRIPTION("pNFS Layout Driver for OSD2 objects"); 373MODULE_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 */
108struct 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 */
117int 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
159err_out:
160 __free_page(page);
161 return err;
162}
163
164void 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,
56extern void objio_free_lseg(struct pnfs_layout_segment *lseg); 56extern void objio_free_lseg(struct pnfs_layout_segment *lseg);
57 57
58/* 58/*
59 * callback API
60 */
61extern 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);
64extern 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 */
61extern struct pnfs_layout_segment *objlayout_alloc_lseg( 69extern struct pnfs_layout_segment *objlayout_alloc_lseg(