44 */
55#include <linux/exportfs.h>
66#include <linux/iomap.h>
7+ #include <linux/genhd.h>
78#include <linux/slab.h>
89#include <linux/pr.h>
910
1011#include <linux/nfsd/debug.h>
12+ #include <scsi/scsi_proto.h>
13+ #include <scsi/scsi_common.h>
14+ #include <scsi/scsi_request.h>
1115
1216#include "blocklayoutxdr.h"
1317#include "pnfs.h"
1418#include "filecache.h"
15- #include "vfs.h"
1619
1720#define NFSDDBG_FACILITY NFSDDBG_PNFS
1821
@@ -208,6 +211,109 @@ const struct nfsd4_layout_ops bl_layout_ops = {
208211#endif /* CONFIG_NFSD_BLOCKLAYOUT */
209212
210213#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+
211317#define NFSD_MDS_PR_KEY 0x0100000000000000ULL
212318
213319/*
@@ -219,31 +325,6 @@ static u64 nfsd4_scsi_pr_key(struct nfs4_client *clp)
219325 return ((u64 )clp -> cl_clientid .cl_boot << 32 ) | clp -> cl_clientid .cl_id ;
220326}
221327
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-
247328static int
248329nfsd4_block_get_device_info_scsi (struct super_block * sb ,
249330 struct nfs4_client * clp ,
@@ -252,7 +333,7 @@ nfsd4_block_get_device_info_scsi(struct super_block *sb,
252333 struct pnfs_block_deviceaddr * dev ;
253334 struct pnfs_block_volume * b ;
254335 const struct pr_ops * ops ;
255- int ret ;
336+ int error ;
256337
257338 dev = kzalloc (sizeof (struct pnfs_block_deviceaddr ) +
258339 sizeof (struct pnfs_block_volume ), GFP_KERNEL );
@@ -266,39 +347,33 @@ nfsd4_block_get_device_info_scsi(struct super_block *sb,
266347 b -> type = PNFS_BLOCK_VOLUME_SCSI ;
267348 b -> scsi .pr_key = nfsd4_scsi_pr_key (clp );
268349
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 ;
272353
273- ret = - EINVAL ;
274354 ops = sb -> s_bdev -> bd_disk -> fops -> pr_ops ;
275355 if (!ops ) {
276356 pr_err ("pNFS: device %s does not support PRs.\n" ,
277357 sb -> s_id );
278- goto out_free_dev ;
358+ return - EINVAL ;
279359 }
280360
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 ) {
283363 pr_err ("pNFS: failed to register key for device %s.\n" ,
284364 sb -> s_id );
285- goto out_free_dev ;
365+ return - EINVAL ;
286366 }
287367
288- ret = ops -> pr_reserve (sb -> s_bdev , NFSD_MDS_PR_KEY ,
368+ error = ops -> pr_reserve (sb -> s_bdev , NFSD_MDS_PR_KEY ,
289369 PR_EXCLUSIVE_ACCESS_REG_ONLY , 0 );
290- if (ret ) {
370+ if (error ) {
291371 pr_err ("pNFS: failed to reserve device %s.\n" ,
292372 sb -> s_id );
293- goto out_free_dev ;
373+ return - EINVAL ;
294374 }
295375
296376 return 0 ;
297-
298- out_free_dev :
299- kfree (dev );
300- gdp -> gd_device = NULL ;
301- return ret ;
302377}
303378
304379static __be32
0 commit comments