1717#define NFSDDBG_FACILITY NFSDDBG_PNFS
1818
1919
20+ /*
21+ * Get an extent from the file system that starts at offset or below
22+ * and may be shorter than the requested length.
23+ */
2024static __be32
21- nfsd4_block_proc_layoutget (struct svc_rqst * rqstp , struct inode * inode ,
22- const struct svc_fh * fhp , struct nfsd4_layoutget * args )
25+ nfsd4_block_map_extent (struct inode * inode , const struct svc_fh * fhp ,
26+ u64 offset , u64 length , u32 iomode , u64 minlength ,
27+ struct pnfs_block_extent * bex )
2328{
24- struct nfsd4_layout_seg * seg = & args -> lg_seg ;
2529 struct super_block * sb = inode -> i_sb ;
26- u64 length ;
27- u32 block_size = i_blocksize (inode );
28- struct pnfs_block_extent * bex ;
2930 struct iomap iomap ;
3031 u32 device_generation = 0 ;
3132 int error ;
3233
33- if (locks_in_grace (SVC_NET (rqstp )))
34- return nfserr_grace ;
35-
36- if (seg -> offset & (block_size - 1 )) {
37- dprintk ("pnfsd: I/O misaligned\n" );
38- goto out_layoutunavailable ;
39- }
40-
41- /*
42- * Some clients barf on non-zero block numbers for NONE or INVALID
43- * layouts, so make sure to zero the whole structure.
44- */
45- error = - ENOMEM ;
46- bex = kzalloc (sizeof (* bex ), GFP_KERNEL );
47- if (!bex )
48- goto out_error ;
49- args -> lg_content = bex ;
50-
51- error = sb -> s_export_op -> map_blocks (inode , seg -> offset , seg -> length ,
52- & iomap , seg -> iomode != IOMODE_READ ,
53- & device_generation );
34+ error = sb -> s_export_op -> map_blocks (inode , offset , length , & iomap ,
35+ iomode != IOMODE_READ , & device_generation );
5436 if (error ) {
5537 if (error == - ENXIO )
56- goto out_layoutunavailable ;
57- goto out_error ;
58- }
59-
60- length = iomap .offset + iomap .length - seg -> offset ;
61- if (length < args -> lg_minlength ) {
62- dprintk ("pnfsd: extent smaller than minlength\n" );
63- goto out_layoutunavailable ;
38+ return nfserr_layoutunavailable ;
39+ return nfserrno (error );
6440 }
6541
6642 switch (iomap .type ) {
6743 case IOMAP_MAPPED :
68- if (seg -> iomode == IOMODE_READ )
44+ if (iomode == IOMODE_READ )
6945 bex -> es = PNFS_BLOCK_READ_DATA ;
7046 else
7147 bex -> es = PNFS_BLOCK_READWRITE_DATA ;
7248 bex -> soff = iomap .addr ;
7349 break ;
7450 case IOMAP_UNWRITTEN :
75- if (seg -> iomode & IOMODE_RW ) {
51+ if (iomode & IOMODE_RW ) {
7652 /*
7753 * Crack monkey special case from section 2.3.1.
7854 */
79- if (args -> lg_minlength == 0 ) {
55+ if (minlength == 0 ) {
8056 dprintk ("pnfsd: no soup for you!\n" );
81- goto out_layoutunavailable ;
57+ return nfserr_layoutunavailable ;
8258 }
8359
8460 bex -> es = PNFS_BLOCK_INVALID_DATA ;
@@ -87,35 +63,76 @@ nfsd4_block_proc_layoutget(struct svc_rqst *rqstp, struct inode *inode,
8763 }
8864 fallthrough ;
8965 case IOMAP_HOLE :
90- if (seg -> iomode == IOMODE_READ ) {
66+ if (iomode == IOMODE_READ ) {
9167 bex -> es = PNFS_BLOCK_NONE_DATA ;
9268 break ;
9369 }
9470 fallthrough ;
9571 case IOMAP_DELALLOC :
9672 default :
9773 WARN (1 , "pnfsd: filesystem returned %d extent\n" , iomap .type );
98- goto out_layoutunavailable ;
74+ return nfserr_layoutunavailable ;
9975 }
10076
10177 error = nfsd4_set_deviceid (& bex -> vol_id , fhp , device_generation );
10278 if (error )
103- goto out_error ;
79+ return nfserrno (error );
80+
10481 bex -> foff = iomap .offset ;
10582 bex -> len = iomap .length ;
83+ return nfs_ok ;
84+ }
85+
86+ static __be32
87+ nfsd4_block_proc_layoutget (struct svc_rqst * rqstp , struct inode * inode ,
88+ const struct svc_fh * fhp , struct nfsd4_layoutget * args )
89+ {
90+ struct nfsd4_layout_seg * seg = & args -> lg_seg ;
91+ struct pnfs_block_extent * bex ;
92+ u64 length ;
93+ u32 block_size = i_blocksize (inode );
94+ __be32 nfserr ;
95+
96+ if (locks_in_grace (SVC_NET (rqstp )))
97+ return nfserr_grace ;
10698
107- seg -> offset = iomap .offset ;
108- seg -> length = iomap .length ;
99+ nfserr = nfserr_layoutunavailable ;
100+ if (seg -> offset & (block_size - 1 )) {
101+ dprintk ("pnfsd: I/O misaligned\n" );
102+ goto out_error ;
103+ }
104+
105+ /*
106+ * Some clients barf on non-zero block numbers for NONE or INVALID
107+ * layouts, so make sure to zero the whole structure.
108+ */
109+ nfserr = nfserrno (- ENOMEM );
110+ bex = kzalloc (sizeof (* bex ), GFP_KERNEL );
111+ if (!bex )
112+ goto out_error ;
113+ args -> lg_content = bex ;
114+
115+ nfserr = nfsd4_block_map_extent (inode , fhp , seg -> offset , seg -> length ,
116+ seg -> iomode , args -> lg_minlength , bex );
117+ if (nfserr != nfs_ok )
118+ goto out_error ;
119+
120+ nfserr = nfserr_layoutunavailable ;
121+ length = bex -> foff + bex -> len - seg -> offset ;
122+ if (length < args -> lg_minlength ) {
123+ dprintk ("pnfsd: extent smaller than minlength\n" );
124+ goto out_error ;
125+ }
126+
127+ seg -> offset = bex -> foff ;
128+ seg -> length = bex -> len ;
109129
110130 dprintk ("GET: 0x%llx:0x%llx %d\n" , bex -> foff , bex -> len , bex -> es );
111- return 0 ;
131+ return nfs_ok ;
112132
113133out_error :
114134 seg -> length = 0 ;
115- return nfserrno (error );
116- out_layoutunavailable :
117- seg -> length = 0 ;
118- return nfserr_layoutunavailable ;
135+ return nfserr ;
119136}
120137
121138static __be32
0 commit comments