4
4
*/
5
5
#include <linux/exportfs.h>
6
6
#include <linux/iomap.h>
7
+ #include <linux/genhd.h>
7
8
#include <linux/slab.h>
8
9
#include <linux/pr.h>
9
10
10
11
#include <linux/nfsd/debug.h>
12
+ #include <scsi/scsi_proto.h>
13
+ #include <scsi/scsi_common.h>
14
+ #include <scsi/scsi_request.h>
11
15
12
16
#include "blocklayoutxdr.h"
13
17
#include "pnfs.h"
14
18
#include "filecache.h"
15
- #include "vfs.h"
16
19
17
20
#define NFSDDBG_FACILITY NFSDDBG_PNFS
18
21
@@ -208,6 +211,109 @@ const struct nfsd4_layout_ops bl_layout_ops = {
208
211
#endif /* CONFIG_NFSD_BLOCKLAYOUT */
209
212
210
213
#ifdef CONFIG_NFSD_SCSILAYOUT
214
+ static int nfsd4_scsi_identify_device (struct block_device * bdev ,
215
+ struct pnfs_block_volume * b )
216
+ {
217
+ struct request_queue * q = bdev -> bd_disk -> queue ;
218
+ struct request * rq ;
219
+ struct scsi_request * req ;
220
+ /*
221
+ * The allocation length (passed in bytes 3 and 4 of the INQUIRY
222
+ * command descriptor block) specifies the number of bytes that have
223
+ * been allocated for the data-in buffer.
224
+ * 252 is the highest one-byte value that is a multiple of 4.
225
+ * 65532 is the highest two-byte value that is a multiple of 4.
226
+ */
227
+ size_t bufflen = 252 , maxlen = 65532 , len , id_len ;
228
+ u8 * buf , * d , type , assoc ;
229
+ int retries = 1 , error ;
230
+
231
+ if (WARN_ON_ONCE (!blk_queue_scsi_passthrough (q )))
232
+ return - EINVAL ;
233
+
234
+ again :
235
+ buf = kzalloc (bufflen , GFP_KERNEL );
236
+ if (!buf )
237
+ return - ENOMEM ;
238
+
239
+ rq = blk_get_request (q , REQ_OP_DRV_IN , 0 );
240
+ if (IS_ERR (rq )) {
241
+ error = - ENOMEM ;
242
+ goto out_free_buf ;
243
+ }
244
+ req = scsi_req (rq );
245
+
246
+ error = blk_rq_map_kern (q , rq , buf , bufflen , GFP_KERNEL );
247
+ if (error )
248
+ goto out_put_request ;
249
+
250
+ req -> cmd [0 ] = INQUIRY ;
251
+ req -> cmd [1 ] = 1 ;
252
+ req -> cmd [2 ] = 0x83 ;
253
+ req -> cmd [3 ] = bufflen >> 8 ;
254
+ req -> cmd [4 ] = bufflen & 0xff ;
255
+ req -> cmd_len = COMMAND_SIZE (INQUIRY );
256
+
257
+ blk_execute_rq (NULL , rq , 1 );
258
+ if (req -> result ) {
259
+ pr_err ("pNFS: INQUIRY 0x83 failed with: %x\n" ,
260
+ req -> result );
261
+ error = - EIO ;
262
+ goto out_put_request ;
263
+ }
264
+
265
+ len = (buf [2 ] << 8 ) + buf [3 ] + 4 ;
266
+ if (len > bufflen ) {
267
+ if (len <= maxlen && retries -- ) {
268
+ blk_put_request (rq );
269
+ kfree (buf );
270
+ bufflen = len ;
271
+ goto again ;
272
+ }
273
+ pr_err ("pNFS: INQUIRY 0x83 response invalid (len = %zd)\n" ,
274
+ len );
275
+ goto out_put_request ;
276
+ }
277
+
278
+ d = buf + 4 ;
279
+ for (d = buf + 4 ; d < buf + len ; d += id_len + 4 ) {
280
+ id_len = d [3 ];
281
+ type = d [1 ] & 0xf ;
282
+ assoc = (d [1 ] >> 4 ) & 0x3 ;
283
+
284
+ /*
285
+ * We only care about a EUI-64 and NAA designator types
286
+ * with LU association.
287
+ */
288
+ if (assoc != 0x00 )
289
+ continue ;
290
+ if (type != 0x02 && type != 0x03 )
291
+ continue ;
292
+ if (id_len != 8 && id_len != 12 && id_len != 16 )
293
+ continue ;
294
+
295
+ b -> scsi .code_set = PS_CODE_SET_BINARY ;
296
+ b -> scsi .designator_type = type == 0x02 ?
297
+ PS_DESIGNATOR_EUI64 : PS_DESIGNATOR_NAA ;
298
+ b -> scsi .designator_len = id_len ;
299
+ memcpy (b -> scsi .designator , d + 4 , id_len );
300
+
301
+ /*
302
+ * If we found a 8 or 12 byte descriptor continue on to
303
+ * see if a 16 byte one is available. If we find a
304
+ * 16 byte descriptor we're done.
305
+ */
306
+ if (id_len == 16 )
307
+ break ;
308
+ }
309
+
310
+ out_put_request :
311
+ blk_put_request (rq );
312
+ out_free_buf :
313
+ kfree (buf );
314
+ return error ;
315
+ }
316
+
211
317
#define NFSD_MDS_PR_KEY 0x0100000000000000ULL
212
318
213
319
/*
@@ -219,31 +325,6 @@ static u64 nfsd4_scsi_pr_key(struct nfs4_client *clp)
219
325
return ((u64 )clp -> cl_clientid .cl_boot << 32 ) | clp -> cl_clientid .cl_id ;
220
326
}
221
327
222
- static const u8 designator_types [] = {
223
- PS_DESIGNATOR_EUI64 ,
224
- PS_DESIGNATOR_NAA ,
225
- };
226
-
227
- static int
228
- nfsd4_block_get_unique_id (struct gendisk * disk , struct pnfs_block_volume * b )
229
- {
230
- int ret , i ;
231
-
232
- for (i = 0 ; i < ARRAY_SIZE (designator_types ); i ++ ) {
233
- u8 type = designator_types [i ];
234
-
235
- ret = disk -> fops -> get_unique_id (disk , b -> scsi .designator , type );
236
- if (ret > 0 ) {
237
- b -> scsi .code_set = PS_CODE_SET_BINARY ;
238
- b -> scsi .designator_type = type ;
239
- b -> scsi .designator_len = ret ;
240
- return 0 ;
241
- }
242
- }
243
-
244
- return - EINVAL ;
245
- }
246
-
247
328
static int
248
329
nfsd4_block_get_device_info_scsi (struct super_block * sb ,
249
330
struct nfs4_client * clp ,
@@ -252,7 +333,7 @@ nfsd4_block_get_device_info_scsi(struct super_block *sb,
252
333
struct pnfs_block_deviceaddr * dev ;
253
334
struct pnfs_block_volume * b ;
254
335
const struct pr_ops * ops ;
255
- int ret ;
336
+ int error ;
256
337
257
338
dev = kzalloc (sizeof (struct pnfs_block_deviceaddr ) +
258
339
sizeof (struct pnfs_block_volume ), GFP_KERNEL );
@@ -266,39 +347,33 @@ nfsd4_block_get_device_info_scsi(struct super_block *sb,
266
347
b -> type = PNFS_BLOCK_VOLUME_SCSI ;
267
348
b -> scsi .pr_key = nfsd4_scsi_pr_key (clp );
268
349
269
- ret = nfsd4_block_get_unique_id (sb -> s_bdev -> bd_disk , b );
270
- if (ret < 0 )
271
- goto out_free_dev ;
350
+ error = nfsd4_scsi_identify_device (sb -> s_bdev , b );
351
+ if (error )
352
+ return error ;
272
353
273
- ret = - EINVAL ;
274
354
ops = sb -> s_bdev -> bd_disk -> fops -> pr_ops ;
275
355
if (!ops ) {
276
356
pr_err ("pNFS: device %s does not support PRs.\n" ,
277
357
sb -> s_id );
278
- goto out_free_dev ;
358
+ return - EINVAL ;
279
359
}
280
360
281
- ret = ops -> pr_register (sb -> s_bdev , 0 , NFSD_MDS_PR_KEY , true);
282
- if (ret ) {
361
+ error = ops -> pr_register (sb -> s_bdev , 0 , NFSD_MDS_PR_KEY , true);
362
+ if (error ) {
283
363
pr_err ("pNFS: failed to register key for device %s.\n" ,
284
364
sb -> s_id );
285
- goto out_free_dev ;
365
+ return - EINVAL ;
286
366
}
287
367
288
- ret = ops -> pr_reserve (sb -> s_bdev , NFSD_MDS_PR_KEY ,
368
+ error = ops -> pr_reserve (sb -> s_bdev , NFSD_MDS_PR_KEY ,
289
369
PR_EXCLUSIVE_ACCESS_REG_ONLY , 0 );
290
- if (ret ) {
370
+ if (error ) {
291
371
pr_err ("pNFS: failed to reserve device %s.\n" ,
292
372
sb -> s_id );
293
- goto out_free_dev ;
373
+ return - EINVAL ;
294
374
}
295
375
296
376
return 0 ;
297
-
298
- out_free_dev :
299
- kfree (dev );
300
- gdp -> gd_device = NULL ;
301
- return ret ;
302
377
}
303
378
304
379
static __be32
0 commit comments