1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 28650b8a0SChristoph Hellwig /* 3f99d4fbdSChristoph Hellwig * Copyright (c) 2014-2016 Christoph Hellwig. 48650b8a0SChristoph Hellwig */ 58650b8a0SChristoph Hellwig #include <linux/exportfs.h> 6199a31c6SChristoph Hellwig #include <linux/iomap.h> 78650b8a0SChristoph Hellwig #include <linux/slab.h> 8f99d4fbdSChristoph Hellwig #include <linux/pr.h> 98650b8a0SChristoph Hellwig 108650b8a0SChristoph Hellwig #include <linux/nfsd/debug.h> 118650b8a0SChristoph Hellwig 128650b8a0SChristoph Hellwig #include "blocklayoutxdr.h" 138650b8a0SChristoph Hellwig #include "pnfs.h" 14eb82dd39SJeff Layton #include "filecache.h" 15cb12fae1SJeff Layton #include "vfs.h" 168650b8a0SChristoph Hellwig 178650b8a0SChristoph Hellwig #define NFSDDBG_FACILITY NFSDDBG_PNFS 188650b8a0SChristoph Hellwig 198650b8a0SChristoph Hellwig 208650b8a0SChristoph Hellwig static __be32 218650b8a0SChristoph Hellwig nfsd4_block_proc_layoutget(struct inode *inode, const struct svc_fh *fhp, 228650b8a0SChristoph Hellwig struct nfsd4_layoutget *args) 238650b8a0SChristoph Hellwig { 248650b8a0SChristoph Hellwig struct nfsd4_layout_seg *seg = &args->lg_seg; 258650b8a0SChristoph Hellwig struct super_block *sb = inode->i_sb; 2693407472SFabian Frederick u32 block_size = i_blocksize(inode); 278650b8a0SChristoph Hellwig struct pnfs_block_extent *bex; 288650b8a0SChristoph Hellwig struct iomap iomap; 298650b8a0SChristoph Hellwig u32 device_generation = 0; 308650b8a0SChristoph Hellwig int error; 318650b8a0SChristoph Hellwig 328650b8a0SChristoph Hellwig if (seg->offset & (block_size - 1)) { 338650b8a0SChristoph Hellwig dprintk("pnfsd: I/O misaligned\n"); 348650b8a0SChristoph Hellwig goto out_layoutunavailable; 358650b8a0SChristoph Hellwig } 368650b8a0SChristoph Hellwig 378650b8a0SChristoph Hellwig /* 388650b8a0SChristoph Hellwig * Some clients barf on non-zero block numbers for NONE or INVALID 398650b8a0SChristoph Hellwig * layouts, so make sure to zero the whole structure. 408650b8a0SChristoph Hellwig */ 418650b8a0SChristoph Hellwig error = -ENOMEM; 428650b8a0SChristoph Hellwig bex = kzalloc(sizeof(*bex), GFP_KERNEL); 438650b8a0SChristoph Hellwig if (!bex) 448650b8a0SChristoph Hellwig goto out_error; 458650b8a0SChristoph Hellwig args->lg_content = bex; 468650b8a0SChristoph Hellwig 478650b8a0SChristoph Hellwig error = sb->s_export_op->map_blocks(inode, seg->offset, seg->length, 488650b8a0SChristoph Hellwig &iomap, seg->iomode != IOMODE_READ, 498650b8a0SChristoph Hellwig &device_generation); 508650b8a0SChristoph Hellwig if (error) { 518650b8a0SChristoph Hellwig if (error == -ENXIO) 528650b8a0SChristoph Hellwig goto out_layoutunavailable; 538650b8a0SChristoph Hellwig goto out_error; 548650b8a0SChristoph Hellwig } 558650b8a0SChristoph Hellwig 568650b8a0SChristoph Hellwig if (iomap.length < args->lg_minlength) { 578650b8a0SChristoph Hellwig dprintk("pnfsd: extent smaller than minlength\n"); 588650b8a0SChristoph Hellwig goto out_layoutunavailable; 598650b8a0SChristoph Hellwig } 608650b8a0SChristoph Hellwig 618650b8a0SChristoph Hellwig switch (iomap.type) { 628650b8a0SChristoph Hellwig case IOMAP_MAPPED: 638650b8a0SChristoph Hellwig if (seg->iomode == IOMODE_READ) 648650b8a0SChristoph Hellwig bex->es = PNFS_BLOCK_READ_DATA; 658650b8a0SChristoph Hellwig else 668650b8a0SChristoph Hellwig bex->es = PNFS_BLOCK_READWRITE_DATA; 6719fe5f64SAndreas Gruenbacher bex->soff = iomap.addr; 688650b8a0SChristoph Hellwig break; 698650b8a0SChristoph Hellwig case IOMAP_UNWRITTEN: 708650b8a0SChristoph Hellwig if (seg->iomode & IOMODE_RW) { 718650b8a0SChristoph Hellwig /* 728650b8a0SChristoph Hellwig * Crack monkey special case from section 2.3.1. 738650b8a0SChristoph Hellwig */ 748650b8a0SChristoph Hellwig if (args->lg_minlength == 0) { 758650b8a0SChristoph Hellwig dprintk("pnfsd: no soup for you!\n"); 768650b8a0SChristoph Hellwig goto out_layoutunavailable; 778650b8a0SChristoph Hellwig } 788650b8a0SChristoph Hellwig 798650b8a0SChristoph Hellwig bex->es = PNFS_BLOCK_INVALID_DATA; 8019fe5f64SAndreas Gruenbacher bex->soff = iomap.addr; 818650b8a0SChristoph Hellwig break; 828650b8a0SChristoph Hellwig } 83df561f66SGustavo A. R. Silva fallthrough; 848650b8a0SChristoph Hellwig case IOMAP_HOLE: 858650b8a0SChristoph Hellwig if (seg->iomode == IOMODE_READ) { 868650b8a0SChristoph Hellwig bex->es = PNFS_BLOCK_NONE_DATA; 878650b8a0SChristoph Hellwig break; 888650b8a0SChristoph Hellwig } 89df561f66SGustavo A. R. Silva fallthrough; 908650b8a0SChristoph Hellwig case IOMAP_DELALLOC: 918650b8a0SChristoph Hellwig default: 928650b8a0SChristoph Hellwig WARN(1, "pnfsd: filesystem returned %d extent\n", iomap.type); 938650b8a0SChristoph Hellwig goto out_layoutunavailable; 948650b8a0SChristoph Hellwig } 958650b8a0SChristoph Hellwig 968650b8a0SChristoph Hellwig error = nfsd4_set_deviceid(&bex->vol_id, fhp, device_generation); 978650b8a0SChristoph Hellwig if (error) 988650b8a0SChristoph Hellwig goto out_error; 998650b8a0SChristoph Hellwig bex->foff = iomap.offset; 1008650b8a0SChristoph Hellwig bex->len = iomap.length; 1018650b8a0SChristoph Hellwig 1028650b8a0SChristoph Hellwig seg->offset = iomap.offset; 1038650b8a0SChristoph Hellwig seg->length = iomap.length; 1048650b8a0SChristoph Hellwig 10585369523SKinglong Mee dprintk("GET: 0x%llx:0x%llx %d\n", bex->foff, bex->len, bex->es); 1068650b8a0SChristoph Hellwig return 0; 1078650b8a0SChristoph Hellwig 1088650b8a0SChristoph Hellwig out_error: 1098650b8a0SChristoph Hellwig seg->length = 0; 1108650b8a0SChristoph Hellwig return nfserrno(error); 1118650b8a0SChristoph Hellwig out_layoutunavailable: 1128650b8a0SChristoph Hellwig seg->length = 0; 1138650b8a0SChristoph Hellwig return nfserr_layoutunavailable; 1148650b8a0SChristoph Hellwig } 1158650b8a0SChristoph Hellwig 1168650b8a0SChristoph Hellwig static __be32 117368248eeSChristoph Hellwig nfsd4_block_commit_blocks(struct inode *inode, struct nfsd4_layoutcommit *lcp, 118368248eeSChristoph Hellwig struct iomap *iomaps, int nr_iomaps) 1198650b8a0SChristoph Hellwig { 12011fec9b9SJeff Layton struct timespec64 mtime = inode_get_mtime(inode); 1218650b8a0SChristoph Hellwig loff_t new_size = lcp->lc_last_wr + 1; 1228650b8a0SChristoph Hellwig struct iattr iattr = { .ia_valid = 0 }; 1238650b8a0SChristoph Hellwig int error; 1248650b8a0SChristoph Hellwig 1258650b8a0SChristoph Hellwig if (lcp->lc_mtime.tv_nsec == UTIME_NOW || 12611fec9b9SJeff Layton timespec64_compare(&lcp->lc_mtime, &mtime) < 0) 127bdba5368SJ. Bruce Fields lcp->lc_mtime = current_time(inode); 1288650b8a0SChristoph Hellwig iattr.ia_valid |= ATTR_ATIME | ATTR_CTIME | ATTR_MTIME; 129bdba5368SJ. Bruce Fields iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime = lcp->lc_mtime; 1308650b8a0SChristoph Hellwig 1318650b8a0SChristoph Hellwig if (new_size > i_size_read(inode)) { 1328650b8a0SChristoph Hellwig iattr.ia_valid |= ATTR_SIZE; 1338650b8a0SChristoph Hellwig iattr.ia_size = new_size; 1348650b8a0SChristoph Hellwig } 1358650b8a0SChristoph Hellwig 1368650b8a0SChristoph Hellwig error = inode->i_sb->s_export_op->commit_blocks(inode, iomaps, 1378650b8a0SChristoph Hellwig nr_iomaps, &iattr); 1388650b8a0SChristoph Hellwig kfree(iomaps); 1398650b8a0SChristoph Hellwig return nfserrno(error); 1408650b8a0SChristoph Hellwig } 1418650b8a0SChristoph Hellwig 142368248eeSChristoph Hellwig #ifdef CONFIG_NFSD_BLOCKLAYOUT 143368248eeSChristoph Hellwig static int 144368248eeSChristoph Hellwig nfsd4_block_get_device_info_simple(struct super_block *sb, 145368248eeSChristoph Hellwig struct nfsd4_getdeviceinfo *gdp) 146368248eeSChristoph Hellwig { 147368248eeSChristoph Hellwig struct pnfs_block_deviceaddr *dev; 148368248eeSChristoph Hellwig struct pnfs_block_volume *b; 149368248eeSChristoph Hellwig 150*2869b3a0SThorsten Blum dev = kzalloc(struct_size(dev, volumes, 1), GFP_KERNEL); 151368248eeSChristoph Hellwig if (!dev) 152368248eeSChristoph Hellwig return -ENOMEM; 153368248eeSChristoph Hellwig gdp->gd_device = dev; 154368248eeSChristoph Hellwig 155368248eeSChristoph Hellwig dev->nr_volumes = 1; 156368248eeSChristoph Hellwig b = &dev->volumes[0]; 157368248eeSChristoph Hellwig 158368248eeSChristoph Hellwig b->type = PNFS_BLOCK_VOLUME_SIMPLE; 159368248eeSChristoph Hellwig b->simple.sig_len = PNFS_BLOCK_UUID_LEN; 160368248eeSChristoph Hellwig return sb->s_export_op->get_uuid(sb, b->simple.sig, &b->simple.sig_len, 161368248eeSChristoph Hellwig &b->simple.offset); 162368248eeSChristoph Hellwig } 163368248eeSChristoph Hellwig 164368248eeSChristoph Hellwig static __be32 165368248eeSChristoph Hellwig nfsd4_block_proc_getdeviceinfo(struct super_block *sb, 166d7c920d1STom Haynes struct svc_rqst *rqstp, 167f99d4fbdSChristoph Hellwig struct nfs4_client *clp, 168368248eeSChristoph Hellwig struct nfsd4_getdeviceinfo *gdp) 169368248eeSChristoph Hellwig { 170fa01b1e9SChristoph Hellwig if (bdev_is_partition(sb->s_bdev)) 171368248eeSChristoph Hellwig return nfserr_inval; 172368248eeSChristoph Hellwig return nfserrno(nfsd4_block_get_device_info_simple(sb, gdp)); 173368248eeSChristoph Hellwig } 174368248eeSChristoph Hellwig 175368248eeSChristoph Hellwig static __be32 176368248eeSChristoph Hellwig nfsd4_block_proc_layoutcommit(struct inode *inode, 177368248eeSChristoph Hellwig struct nfsd4_layoutcommit *lcp) 178368248eeSChristoph Hellwig { 179368248eeSChristoph Hellwig struct iomap *iomaps; 180368248eeSChristoph Hellwig int nr_iomaps; 181368248eeSChristoph Hellwig 182368248eeSChristoph Hellwig nr_iomaps = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout, 18393407472SFabian Frederick lcp->lc_up_len, &iomaps, i_blocksize(inode)); 184368248eeSChristoph Hellwig if (nr_iomaps < 0) 185368248eeSChristoph Hellwig return nfserrno(nr_iomaps); 186368248eeSChristoph Hellwig 187368248eeSChristoph Hellwig return nfsd4_block_commit_blocks(inode, lcp, iomaps, nr_iomaps); 188368248eeSChristoph Hellwig } 189368248eeSChristoph Hellwig 1908650b8a0SChristoph Hellwig const struct nfsd4_layout_ops bl_layout_ops = { 19140cdc7a5SChristoph Hellwig /* 19240cdc7a5SChristoph Hellwig * Pretend that we send notification to the client. This is a blatant 19340cdc7a5SChristoph Hellwig * lie to force recent Linux clients to cache our device IDs. 19440cdc7a5SChristoph Hellwig * We rarely ever change the device ID, so the harm of leaking deviceids 19540cdc7a5SChristoph Hellwig * for a while isn't too bad. Unfortunately RFC5661 is a complete mess 19640cdc7a5SChristoph Hellwig * in this regard, but I filed errata 4119 for this a while ago, and 19740cdc7a5SChristoph Hellwig * hopefully the Linux client will eventually start caching deviceids 19840cdc7a5SChristoph Hellwig * without this again. 19940cdc7a5SChristoph Hellwig */ 20040cdc7a5SChristoph Hellwig .notify_types = 20140cdc7a5SChristoph Hellwig NOTIFY_DEVICEID4_DELETE | NOTIFY_DEVICEID4_CHANGE, 2028650b8a0SChristoph Hellwig .proc_getdeviceinfo = nfsd4_block_proc_getdeviceinfo, 2038650b8a0SChristoph Hellwig .encode_getdeviceinfo = nfsd4_block_encode_getdeviceinfo, 2048650b8a0SChristoph Hellwig .proc_layoutget = nfsd4_block_proc_layoutget, 2058650b8a0SChristoph Hellwig .encode_layoutget = nfsd4_block_encode_layoutget, 2068650b8a0SChristoph Hellwig .proc_layoutcommit = nfsd4_block_proc_layoutcommit, 2078650b8a0SChristoph Hellwig }; 208368248eeSChristoph Hellwig #endif /* CONFIG_NFSD_BLOCKLAYOUT */ 209f99d4fbdSChristoph Hellwig 210f99d4fbdSChristoph Hellwig #ifdef CONFIG_NFSD_SCSILAYOUT 211eee93016SGeert Uytterhoeven #define NFSD_MDS_PR_KEY 0x0100000000000000ULL 212f99d4fbdSChristoph Hellwig 213f99d4fbdSChristoph Hellwig /* 214f99d4fbdSChristoph Hellwig * We use the client ID as a unique key for the reservations. 215f99d4fbdSChristoph Hellwig * This allows us to easily fence a client when recalls fail. 216f99d4fbdSChristoph Hellwig */ 217f99d4fbdSChristoph Hellwig static u64 nfsd4_scsi_pr_key(struct nfs4_client *clp) 218f99d4fbdSChristoph Hellwig { 219f99d4fbdSChristoph Hellwig return ((u64)clp->cl_clientid.cl_boot << 32) | clp->cl_clientid.cl_id; 220f99d4fbdSChristoph Hellwig } 221f99d4fbdSChristoph Hellwig 2228c6aabd1SChristoph Hellwig static const u8 designator_types[] = { 2238c6aabd1SChristoph Hellwig PS_DESIGNATOR_EUI64, 2248c6aabd1SChristoph Hellwig PS_DESIGNATOR_NAA, 2258c6aabd1SChristoph Hellwig }; 2268c6aabd1SChristoph Hellwig 2278c6aabd1SChristoph Hellwig static int 2288c6aabd1SChristoph Hellwig nfsd4_block_get_unique_id(struct gendisk *disk, struct pnfs_block_volume *b) 2298c6aabd1SChristoph Hellwig { 2308c6aabd1SChristoph Hellwig int ret, i; 2318c6aabd1SChristoph Hellwig 2328c6aabd1SChristoph Hellwig for (i = 0; i < ARRAY_SIZE(designator_types); i++) { 2338c6aabd1SChristoph Hellwig u8 type = designator_types[i]; 2348c6aabd1SChristoph Hellwig 2358c6aabd1SChristoph Hellwig ret = disk->fops->get_unique_id(disk, b->scsi.designator, type); 2368c6aabd1SChristoph Hellwig if (ret > 0) { 2378c6aabd1SChristoph Hellwig b->scsi.code_set = PS_CODE_SET_BINARY; 2388c6aabd1SChristoph Hellwig b->scsi.designator_type = type; 2398c6aabd1SChristoph Hellwig b->scsi.designator_len = ret; 2408c6aabd1SChristoph Hellwig return 0; 2418c6aabd1SChristoph Hellwig } 2428c6aabd1SChristoph Hellwig } 2438c6aabd1SChristoph Hellwig 2448c6aabd1SChristoph Hellwig return -EINVAL; 2458c6aabd1SChristoph Hellwig } 2468c6aabd1SChristoph Hellwig 247f99d4fbdSChristoph Hellwig static int 248f99d4fbdSChristoph Hellwig nfsd4_block_get_device_info_scsi(struct super_block *sb, 249f99d4fbdSChristoph Hellwig struct nfs4_client *clp, 250f99d4fbdSChristoph Hellwig struct nfsd4_getdeviceinfo *gdp) 251f99d4fbdSChristoph Hellwig { 252f99d4fbdSChristoph Hellwig struct pnfs_block_deviceaddr *dev; 253f99d4fbdSChristoph Hellwig struct pnfs_block_volume *b; 254f99d4fbdSChristoph Hellwig const struct pr_ops *ops; 2558c6aabd1SChristoph Hellwig int ret; 256f99d4fbdSChristoph Hellwig 257*2869b3a0SThorsten Blum dev = kzalloc(struct_size(dev, volumes, 1), GFP_KERNEL); 258f99d4fbdSChristoph Hellwig if (!dev) 259f99d4fbdSChristoph Hellwig return -ENOMEM; 260f99d4fbdSChristoph Hellwig gdp->gd_device = dev; 261f99d4fbdSChristoph Hellwig 262f99d4fbdSChristoph Hellwig dev->nr_volumes = 1; 263f99d4fbdSChristoph Hellwig b = &dev->volumes[0]; 264f99d4fbdSChristoph Hellwig 265f99d4fbdSChristoph Hellwig b->type = PNFS_BLOCK_VOLUME_SCSI; 266f99d4fbdSChristoph Hellwig b->scsi.pr_key = nfsd4_scsi_pr_key(clp); 267f99d4fbdSChristoph Hellwig 2688c6aabd1SChristoph Hellwig ret = nfsd4_block_get_unique_id(sb->s_bdev->bd_disk, b); 2698c6aabd1SChristoph Hellwig if (ret < 0) 2708c6aabd1SChristoph Hellwig goto out_free_dev; 271f99d4fbdSChristoph Hellwig 2728c6aabd1SChristoph Hellwig ret = -EINVAL; 273f99d4fbdSChristoph Hellwig ops = sb->s_bdev->bd_disk->fops->pr_ops; 274f99d4fbdSChristoph Hellwig if (!ops) { 275f99d4fbdSChristoph Hellwig pr_err("pNFS: device %s does not support PRs.\n", 276f99d4fbdSChristoph Hellwig sb->s_id); 2778c6aabd1SChristoph Hellwig goto out_free_dev; 278f99d4fbdSChristoph Hellwig } 279f99d4fbdSChristoph Hellwig 2808c6aabd1SChristoph Hellwig ret = ops->pr_register(sb->s_bdev, 0, NFSD_MDS_PR_KEY, true); 2818c6aabd1SChristoph Hellwig if (ret) { 282f99d4fbdSChristoph Hellwig pr_err("pNFS: failed to register key for device %s.\n", 283f99d4fbdSChristoph Hellwig sb->s_id); 2848c6aabd1SChristoph Hellwig goto out_free_dev; 285f99d4fbdSChristoph Hellwig } 286f99d4fbdSChristoph Hellwig 2878c6aabd1SChristoph Hellwig ret = ops->pr_reserve(sb->s_bdev, NFSD_MDS_PR_KEY, 288f99d4fbdSChristoph Hellwig PR_EXCLUSIVE_ACCESS_REG_ONLY, 0); 2898c6aabd1SChristoph Hellwig if (ret) { 290f99d4fbdSChristoph Hellwig pr_err("pNFS: failed to reserve device %s.\n", 291f99d4fbdSChristoph Hellwig sb->s_id); 2928c6aabd1SChristoph Hellwig goto out_free_dev; 293f99d4fbdSChristoph Hellwig } 294f99d4fbdSChristoph Hellwig 295f99d4fbdSChristoph Hellwig return 0; 2968c6aabd1SChristoph Hellwig 2978c6aabd1SChristoph Hellwig out_free_dev: 2988c6aabd1SChristoph Hellwig kfree(dev); 29915a8b55dSJeff Layton gdp->gd_device = NULL; 3008c6aabd1SChristoph Hellwig return ret; 301f99d4fbdSChristoph Hellwig } 302f99d4fbdSChristoph Hellwig 303f99d4fbdSChristoph Hellwig static __be32 304f99d4fbdSChristoph Hellwig nfsd4_scsi_proc_getdeviceinfo(struct super_block *sb, 305d7c920d1STom Haynes struct svc_rqst *rqstp, 306f99d4fbdSChristoph Hellwig struct nfs4_client *clp, 307f99d4fbdSChristoph Hellwig struct nfsd4_getdeviceinfo *gdp) 308f99d4fbdSChristoph Hellwig { 309fa01b1e9SChristoph Hellwig if (bdev_is_partition(sb->s_bdev)) 310f99d4fbdSChristoph Hellwig return nfserr_inval; 311f99d4fbdSChristoph Hellwig return nfserrno(nfsd4_block_get_device_info_scsi(sb, clp, gdp)); 312f99d4fbdSChristoph Hellwig } 313f99d4fbdSChristoph Hellwig static __be32 314f99d4fbdSChristoph Hellwig nfsd4_scsi_proc_layoutcommit(struct inode *inode, 315f99d4fbdSChristoph Hellwig struct nfsd4_layoutcommit *lcp) 316f99d4fbdSChristoph Hellwig { 317f99d4fbdSChristoph Hellwig struct iomap *iomaps; 318f99d4fbdSChristoph Hellwig int nr_iomaps; 319f99d4fbdSChristoph Hellwig 320f99d4fbdSChristoph Hellwig nr_iomaps = nfsd4_scsi_decode_layoutupdate(lcp->lc_up_layout, 32193407472SFabian Frederick lcp->lc_up_len, &iomaps, i_blocksize(inode)); 322f99d4fbdSChristoph Hellwig if (nr_iomaps < 0) 323f99d4fbdSChristoph Hellwig return nfserrno(nr_iomaps); 324f99d4fbdSChristoph Hellwig 325f99d4fbdSChristoph Hellwig return nfsd4_block_commit_blocks(inode, lcp, iomaps, nr_iomaps); 326f99d4fbdSChristoph Hellwig } 327f99d4fbdSChristoph Hellwig 328f99d4fbdSChristoph Hellwig static void 3291e33e141SNeilBrown nfsd4_scsi_fence_client(struct nfs4_layout_stateid *ls, struct nfsd_file *file) 330f99d4fbdSChristoph Hellwig { 331f99d4fbdSChristoph Hellwig struct nfs4_client *clp = ls->ls_stid.sc_client; 3321e33e141SNeilBrown struct block_device *bdev = file->nf_file->f_path.mnt->mnt_sb->s_bdev; 333f99d4fbdSChristoph Hellwig 334f99d4fbdSChristoph Hellwig bdev->bd_disk->fops->pr_ops->pr_preempt(bdev, NFSD_MDS_PR_KEY, 335f99d4fbdSChristoph Hellwig nfsd4_scsi_pr_key(clp), 0, true); 336f99d4fbdSChristoph Hellwig } 337f99d4fbdSChristoph Hellwig 338f99d4fbdSChristoph Hellwig const struct nfsd4_layout_ops scsi_layout_ops = { 339f99d4fbdSChristoph Hellwig /* 340f99d4fbdSChristoph Hellwig * Pretend that we send notification to the client. This is a blatant 341f99d4fbdSChristoph Hellwig * lie to force recent Linux clients to cache our device IDs. 342f99d4fbdSChristoph Hellwig * We rarely ever change the device ID, so the harm of leaking deviceids 343f99d4fbdSChristoph Hellwig * for a while isn't too bad. Unfortunately RFC5661 is a complete mess 344f99d4fbdSChristoph Hellwig * in this regard, but I filed errata 4119 for this a while ago, and 345f99d4fbdSChristoph Hellwig * hopefully the Linux client will eventually start caching deviceids 346f99d4fbdSChristoph Hellwig * without this again. 347f99d4fbdSChristoph Hellwig */ 348f99d4fbdSChristoph Hellwig .notify_types = 349f99d4fbdSChristoph Hellwig NOTIFY_DEVICEID4_DELETE | NOTIFY_DEVICEID4_CHANGE, 350f99d4fbdSChristoph Hellwig .proc_getdeviceinfo = nfsd4_scsi_proc_getdeviceinfo, 351f99d4fbdSChristoph Hellwig .encode_getdeviceinfo = nfsd4_block_encode_getdeviceinfo, 352f99d4fbdSChristoph Hellwig .proc_layoutget = nfsd4_block_proc_layoutget, 353f99d4fbdSChristoph Hellwig .encode_layoutget = nfsd4_block_encode_layoutget, 354f99d4fbdSChristoph Hellwig .proc_layoutcommit = nfsd4_scsi_proc_layoutcommit, 355f99d4fbdSChristoph Hellwig .fence_client = nfsd4_scsi_fence_client, 356f99d4fbdSChristoph Hellwig }; 357f99d4fbdSChristoph Hellwig #endif /* CONFIG_NFSD_SCSILAYOUT */ 358