2 * Module for the pnfs nfs4 file layout driver.
3 * Defines all I/O and Policy interface operations, plus code
4 * to register itself with the pNFS client.
7 * The Regents of the University of Michigan
10 * Dean Hildebrand <dhildebz@umich.edu>
12 * Permission is granted to use, copy, create derivative works, and
13 * redistribute this software and such derivative works for any purpose,
14 * so long as the name of the University of Michigan is not used in
15 * any advertising or publicity pertaining to the use or distribution
16 * of this software without specific, written prior authorization. If
17 * the above copyright notice or any other identification of the
18 * University of Michigan is included in any copy of any portion of
19 * this software, then the disclaimer below must also be included.
21 * This software is provided as is, without representation or warranty
22 * of any kind either express or implied, including without limitation
23 * the implied warranties of merchantability, fitness for a particular
24 * purpose, or noninfringement. The Regents of the University of
25 * Michigan shall not be liable for any damages, including special,
26 * indirect, incidental, or consequential damages, with respect to any
27 * claim arising out of or in connection with the use of the software,
28 * even if it has been or is hereafter advised of the possibility of
32 #include <linux/nfs_fs.h>
35 #include "nfs4filelayout.h"
37 #define NFSDBG_FACILITY NFSDBG_PNFS_LD
39 MODULE_LICENSE("GPL");
40 MODULE_AUTHOR("Dean Hildebrand <dhildebz@umich.edu>");
41 MODULE_DESCRIPTION("The NFSv4 file layout driver");
44 filelayout_set_layoutdriver(struct nfs_server
*nfss
)
46 int status
= pnfs_alloc_init_deviceid_cache(nfss
->nfs_client
,
47 nfs4_fl_free_deviceid_callback
);
49 printk(KERN_WARNING
"%s: deviceid cache could not be "
50 "initialized\n", __func__
);
53 dprintk("%s: deviceid cache has been initialized successfully\n",
58 /* Clear out the layout by destroying its device list */
60 filelayout_clear_layoutdriver(struct nfs_server
*nfss
)
62 dprintk("--> %s\n", __func__
);
64 if (nfss
->nfs_client
->cl_devid_cache
)
65 pnfs_put_deviceid_cache(nfss
->nfs_client
);
70 * filelayout_check_layout()
72 * Make sure layout segment parameters are sane WRT the device.
73 * At this point no generic layer initialization of the lseg has occurred,
74 * and nothing has been added to the layout_hdr cache.
78 filelayout_check_layout(struct pnfs_layout_hdr
*lo
,
79 struct nfs4_filelayout_segment
*fl
,
80 struct nfs4_layoutget_res
*lgr
,
81 struct nfs4_deviceid
*id
)
83 struct nfs4_file_layout_dsaddr
*dsaddr
;
85 struct nfs_server
*nfss
= NFS_SERVER(lo
->inode
);
87 dprintk("--> %s\n", __func__
);
89 if (fl
->pattern_offset
> lgr
->range
.offset
) {
90 dprintk("%s pattern_offset %lld to large\n",
91 __func__
, fl
->pattern_offset
);
95 if (fl
->stripe_unit
% PAGE_SIZE
) {
96 dprintk("%s Stripe unit (%u) not page aligned\n",
97 __func__
, fl
->stripe_unit
);
101 /* find and reference the deviceid */
102 dsaddr
= nfs4_fl_find_get_deviceid(nfss
->nfs_client
, id
);
103 if (dsaddr
== NULL
) {
104 dsaddr
= get_device_info(lo
->inode
, id
);
110 if (fl
->first_stripe_index
< 0 ||
111 fl
->first_stripe_index
>= dsaddr
->stripe_count
) {
112 dprintk("%s Bad first_stripe_index %d\n",
113 __func__
, fl
->first_stripe_index
);
117 if ((fl
->stripe_type
== STRIPE_SPARSE
&&
118 fl
->num_fh
> 1 && fl
->num_fh
!= dsaddr
->ds_num
) ||
119 (fl
->stripe_type
== STRIPE_DENSE
&&
120 fl
->num_fh
!= dsaddr
->stripe_count
)) {
121 dprintk("%s num_fh %u not valid for given packing\n",
122 __func__
, fl
->num_fh
);
126 if (fl
->stripe_unit
% nfss
->rsize
|| fl
->stripe_unit
% nfss
->wsize
) {
127 dprintk("%s Stripe unit (%u) not aligned with rsize %u "
128 "wsize %u\n", __func__
, fl
->stripe_unit
, nfss
->rsize
,
134 dprintk("--> %s returns %d\n", __func__
, status
);
137 pnfs_put_deviceid(nfss
->nfs_client
->cl_devid_cache
, &dsaddr
->deviceid
);
141 static void filelayout_free_fh_array(struct nfs4_filelayout_segment
*fl
)
145 for (i
= 0; i
< fl
->num_fh
; i
++) {
146 if (!fl
->fh_array
[i
])
148 kfree(fl
->fh_array
[i
]);
155 _filelayout_free_lseg(struct nfs4_filelayout_segment
*fl
)
157 filelayout_free_fh_array(fl
);
162 filelayout_decode_layout(struct pnfs_layout_hdr
*flo
,
163 struct nfs4_filelayout_segment
*fl
,
164 struct nfs4_layoutget_res
*lgr
,
165 struct nfs4_deviceid
*id
)
167 uint32_t *p
= (uint32_t *)lgr
->layout
.buf
;
171 dprintk("%s: set_layout_map Begin\n", __func__
);
173 memcpy(id
, p
, sizeof(*id
));
174 p
+= XDR_QUADLEN(NFS4_DEVICEID4_SIZE
);
177 nfl_util
= be32_to_cpup(p
++);
178 if (nfl_util
& NFL4_UFLG_COMMIT_THRU_MDS
)
179 fl
->commit_through_mds
= 1;
180 if (nfl_util
& NFL4_UFLG_DENSE
)
181 fl
->stripe_type
= STRIPE_DENSE
;
183 fl
->stripe_type
= STRIPE_SPARSE
;
184 fl
->stripe_unit
= nfl_util
& ~NFL4_UFLG_MASK
;
186 fl
->first_stripe_index
= be32_to_cpup(p
++);
187 p
= xdr_decode_hyper(p
, &fl
->pattern_offset
);
188 fl
->num_fh
= be32_to_cpup(p
++);
190 dprintk("%s: nfl_util 0x%X num_fh %u fsi %u po %llu\n",
191 __func__
, nfl_util
, fl
->num_fh
, fl
->first_stripe_index
,
194 fl
->fh_array
= kzalloc(fl
->num_fh
* sizeof(struct nfs_fh
*),
199 for (i
= 0; i
< fl
->num_fh
; i
++) {
200 /* Do we want to use a mempool here? */
201 fl
->fh_array
[i
] = kmalloc(sizeof(struct nfs_fh
), GFP_KERNEL
);
202 if (!fl
->fh_array
[i
]) {
203 filelayout_free_fh_array(fl
);
206 fl
->fh_array
[i
]->size
= be32_to_cpup(p
++);
207 if (sizeof(struct nfs_fh
) < fl
->fh_array
[i
]->size
) {
208 printk(KERN_ERR
"Too big fh %d received %d\n",
209 i
, fl
->fh_array
[i
]->size
);
210 filelayout_free_fh_array(fl
);
213 memcpy(fl
->fh_array
[i
]->data
, p
, fl
->fh_array
[i
]->size
);
214 p
+= XDR_QUADLEN(fl
->fh_array
[i
]->size
);
215 dprintk("DEBUG: %s: fh len %d\n", __func__
,
216 fl
->fh_array
[i
]->size
);
222 static struct pnfs_layout_segment
*
223 filelayout_alloc_lseg(struct pnfs_layout_hdr
*layoutid
,
224 struct nfs4_layoutget_res
*lgr
)
226 struct nfs4_filelayout_segment
*fl
;
228 struct nfs4_deviceid id
;
230 dprintk("--> %s\n", __func__
);
231 fl
= kzalloc(sizeof(*fl
), GFP_KERNEL
);
235 rc
= filelayout_decode_layout(layoutid
, fl
, lgr
, &id
);
236 if (rc
!= 0 || filelayout_check_layout(layoutid
, fl
, lgr
, &id
)) {
237 _filelayout_free_lseg(fl
);
240 return &fl
->generic_hdr
;
244 filelayout_free_lseg(struct pnfs_layout_segment
*lseg
)
246 struct nfs_server
*nfss
= NFS_SERVER(lseg
->layout
->inode
);
247 struct nfs4_filelayout_segment
*fl
= FILELAYOUT_LSEG(lseg
);
249 dprintk("--> %s\n", __func__
);
250 pnfs_put_deviceid(nfss
->nfs_client
->cl_devid_cache
,
251 &fl
->dsaddr
->deviceid
);
252 _filelayout_free_lseg(fl
);
255 static struct pnfs_layoutdriver_type filelayout_type
= {
256 .id
= LAYOUT_NFSV4_1_FILES
,
257 .name
= "LAYOUT_NFSV4_1_FILES",
258 .owner
= THIS_MODULE
,
259 .set_layoutdriver
= filelayout_set_layoutdriver
,
260 .clear_layoutdriver
= filelayout_clear_layoutdriver
,
261 .alloc_lseg
= filelayout_alloc_lseg
,
262 .free_lseg
= filelayout_free_lseg
,
265 static int __init
nfs4filelayout_init(void)
267 printk(KERN_INFO
"%s: NFSv4 File Layout Driver Registering...\n",
269 return pnfs_register_layoutdriver(&filelayout_type
);
272 static void __exit
nfs4filelayout_exit(void)
274 printk(KERN_INFO
"%s: NFSv4 File Layout Driver Unregistering...\n",
276 pnfs_unregister_layoutdriver(&filelayout_type
);
279 module_init(nfs4filelayout_init
);
280 module_exit(nfs4filelayout_exit
);