Whamcloud - gitweb
LU-3285 mdc: add IO methods to the MDC
[fs/lustre-release.git] / lustre / mdc / mdc_dev.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2017 Intel Corporation.
24  */
25 /*
26  * This file is part of Lustre, http://www.lustre.org/
27  *
28  * Implementation of cl_device, cl_req for MDC layer.
29  *
30  * Author: Mikhail Pershin <mike.pershin@intel.com>
31  */
32
33 #define DEBUG_SUBSYSTEM S_MDC
34
35 #include <obd_class.h>
36 #include <lustre_osc.h>
37
38 #include "mdc_internal.h"
39
40 int mdc_lock_init(const struct lu_env *env,
41                   struct cl_object *obj, struct cl_lock *lock,
42                   const struct cl_io *unused)
43 {
44         return 0;
45 }
46
47 /**
48  * IO operations.
49  *
50  * An implementation of cl_io_operations specific methods for MDC layer.
51  *
52  */
53 static int mdc_async_upcall(void *a, int rc)
54 {
55         struct osc_async_cbargs *args = a;
56
57         args->opc_rc = rc;
58         complete(&args->opc_sync);
59         return 0;
60 }
61
62 static int mdc_io_setattr_start(const struct lu_env *env,
63                                 const struct cl_io_slice *slice)
64 {
65         struct cl_io *io = slice->cis_io;
66         struct osc_io *oio = cl2osc_io(env, slice);
67         struct cl_object *obj = slice->cis_obj;
68         struct lov_oinfo *loi = cl2osc(obj)->oo_oinfo;
69         struct cl_attr *attr = &osc_env_info(env)->oti_attr;
70         struct obdo *oa = &oio->oi_oa;
71         struct osc_async_cbargs *cbargs = &oio->oi_cbarg;
72         __u64 size = io->u.ci_setattr.sa_attr.lvb_size;
73         unsigned int ia_valid = io->u.ci_setattr.sa_valid;
74         int rc;
75
76         /* silently ignore non-truncate setattr for Data-on-MDT object */
77         if (cl_io_is_trunc(io)) {
78                 /* truncate cache dirty pages first */
79                 rc = osc_cache_truncate_start(env, cl2osc(obj), size,
80                                               &oio->oi_trunc);
81                 if (rc < 0)
82                         return rc;
83         }
84
85         if (oio->oi_lockless == 0) {
86                 cl_object_attr_lock(obj);
87                 rc = cl_object_attr_get(env, obj, attr);
88                 if (rc == 0) {
89                         struct ost_lvb *lvb = &io->u.ci_setattr.sa_attr;
90                         unsigned int cl_valid = 0;
91
92                         if (ia_valid & ATTR_SIZE) {
93                                 attr->cat_size = attr->cat_kms = size;
94                                 cl_valid = (CAT_SIZE | CAT_KMS);
95                         }
96                         if (ia_valid & ATTR_MTIME_SET) {
97                                 attr->cat_mtime = lvb->lvb_mtime;
98                                 cl_valid |= CAT_MTIME;
99                         }
100                         if (ia_valid & ATTR_ATIME_SET) {
101                                 attr->cat_atime = lvb->lvb_atime;
102                                 cl_valid |= CAT_ATIME;
103                         }
104                         if (ia_valid & ATTR_CTIME_SET) {
105                                 attr->cat_ctime = lvb->lvb_ctime;
106                                 cl_valid |= CAT_CTIME;
107                         }
108                         rc = cl_object_attr_update(env, obj, attr, cl_valid);
109                 }
110                 cl_object_attr_unlock(obj);
111                 if (rc < 0)
112                         return rc;
113         }
114
115         if (!(ia_valid & ATTR_SIZE))
116                 return 0;
117
118         memset(oa, 0, sizeof(*oa));
119         oa->o_oi = loi->loi_oi;
120         oa->o_mtime = attr->cat_mtime;
121         oa->o_atime = attr->cat_atime;
122         oa->o_ctime = attr->cat_ctime;
123
124         oa->o_size = size;
125         oa->o_blocks = OBD_OBJECT_EOF;
126         oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP | OBD_MD_FLATIME |
127                       OBD_MD_FLCTIME | OBD_MD_FLMTIME | OBD_MD_FLSIZE |
128                       OBD_MD_FLBLOCKS;
129         if (oio->oi_lockless) {
130                 oa->o_flags = OBD_FL_SRVLOCK;
131                 oa->o_valid |= OBD_MD_FLFLAGS;
132         }
133
134         init_completion(&cbargs->opc_sync);
135
136         rc = osc_punch_send(osc_export(cl2osc(obj)), oa,
137                             mdc_async_upcall, cbargs);
138         cbargs->opc_rpc_sent = rc == 0;
139         return rc;
140 }
141
142 static struct cl_io_operations mdc_io_ops = {
143         .op = {
144                 [CIT_READ] = {
145                         .cio_iter_init = osc_io_iter_init,
146                         .cio_iter_fini = osc_io_iter_fini,
147                         .cio_start     = osc_io_read_start,
148                 },
149                 [CIT_WRITE] = {
150                         .cio_iter_init = osc_io_write_iter_init,
151                         .cio_iter_fini = osc_io_write_iter_fini,
152                         .cio_start     = osc_io_write_start,
153                         .cio_end       = osc_io_end,
154                 },
155                 [CIT_SETATTR] = {
156                         .cio_iter_init = osc_io_iter_init,
157                         .cio_iter_fini = osc_io_iter_fini,
158                         .cio_start     = mdc_io_setattr_start,
159                         .cio_end       = osc_io_setattr_end,
160                 },
161                 /* no support for data version so far */
162                 [CIT_DATA_VERSION] = {
163                         .cio_start = NULL,
164                         .cio_end   = NULL,
165                 },
166                 [CIT_FAULT] = {
167                         .cio_iter_init = osc_io_iter_init,
168                         .cio_iter_fini = osc_io_iter_fini,
169                         .cio_start     = osc_io_fault_start,
170                         .cio_end       = osc_io_end,
171                 },
172                 [CIT_FSYNC] = {
173                         .cio_start = osc_io_fsync_start,
174                         .cio_end   = osc_io_fsync_end,
175                 },
176         },
177         .cio_submit       = osc_io_submit,
178         .cio_commit_async = osc_io_commit_async,
179 };
180
181 int mdc_io_init(const struct lu_env *env, struct cl_object *obj,
182                 struct cl_io *io)
183 {
184         struct osc_io *oio = osc_env_io(env);
185
186         CL_IO_SLICE_CLEAN(oio, oi_cl);
187         cl_io_slice_add(io, &oio->oi_cl, obj, &mdc_io_ops);
188         return 0;
189 }
190
191 /**
192  * Implementation of struct cl_req_operations::cro_attr_set() for MDC
193  * layer. MDC is responsible for struct obdo::o_id and struct obdo::o_seq
194  * fields.
195  */
196 static void mdc_req_attr_set(const struct lu_env *env, struct cl_object *obj,
197                              struct cl_req_attr *attr)
198 {
199         u64 flags = attr->cra_flags;
200
201         /* Copy object FID to cl_attr */
202         attr->cra_oa->o_oi.oi_fid = *lu_object_fid(&obj->co_lu);
203
204         if (flags & OBD_MD_FLGROUP)
205                 attr->cra_oa->o_valid |= OBD_MD_FLGROUP;
206
207         if (flags & OBD_MD_FLID)
208                 attr->cra_oa->o_valid |= OBD_MD_FLID;
209 }
210
211 static const struct cl_object_operations mdc_ops = {
212         .coo_page_init = osc_page_init,
213         .coo_lock_init = mdc_lock_init,
214         .coo_io_init = mdc_io_init,
215         .coo_attr_get = osc_attr_get,
216         .coo_attr_update = osc_attr_update,
217         .coo_glimpse = osc_object_glimpse,
218         .coo_req_attr_set = mdc_req_attr_set,
219 };
220
221 static int mdc_object_init(const struct lu_env *env, struct lu_object *obj,
222                            const struct lu_object_conf *conf)
223 {
224         struct osc_object *osc = lu2osc(obj);
225
226         if (osc->oo_initialized)
227                 return 0;
228
229         osc->oo_initialized = true;
230
231         return osc_object_init(env, obj, conf);
232 }
233
234 static void mdc_object_free(const struct lu_env *env, struct lu_object *obj)
235 {
236         osc_object_free(env, obj);
237 }
238
239 static const struct lu_object_operations mdc_lu_obj_ops = {
240         .loo_object_init = mdc_object_init,
241         .loo_object_delete = NULL,
242         .loo_object_release = NULL,
243         .loo_object_free = mdc_object_free,
244         .loo_object_print = osc_object_print,
245         .loo_object_invariant = NULL
246 };
247
248 struct lu_object *mdc_object_alloc(const struct lu_env *env,
249                                    const struct lu_object_header *unused,
250                                    struct lu_device *dev)
251 {
252         struct osc_object *osc;
253         struct lu_object  *obj;
254
255         OBD_SLAB_ALLOC_PTR_GFP(osc, osc_object_kmem, GFP_NOFS);
256         if (osc != NULL) {
257                 obj = osc2lu(osc);
258                 lu_object_init(obj, NULL, dev);
259                 osc->oo_cl.co_ops = &mdc_ops;
260                 obj->lo_ops = &mdc_lu_obj_ops;
261                 osc->oo_initialized = false;
262         } else {
263                 obj = NULL;
264         }
265         return obj;
266 }
267
268 static int mdc_cl_process_config(const struct lu_env *env,
269                                  struct lu_device *d, struct lustre_cfg *cfg)
270 {
271         return mdc_process_config(d->ld_obd, 0, cfg);
272 }
273
274 const struct lu_device_operations mdc_lu_ops = {
275         .ldo_object_alloc = mdc_object_alloc,
276         .ldo_process_config = mdc_cl_process_config,
277         .ldo_recovery_complete = NULL,
278 };
279
280 static struct lu_device *mdc_device_alloc(const struct lu_env *env,
281                                           struct lu_device_type *t,
282                                           struct lustre_cfg *cfg)
283 {
284         struct lu_device *d;
285         struct osc_device *od;
286         struct obd_device *obd;
287         int rc;
288
289         OBD_ALLOC_PTR(od);
290         if (od == NULL)
291                 RETURN(ERR_PTR(-ENOMEM));
292
293         cl_device_init(&od->od_cl, t);
294         d = osc2lu_dev(od);
295         d->ld_ops = &mdc_lu_ops;
296
297         /* Setup MDC OBD */
298         obd = class_name2obd(lustre_cfg_string(cfg, 0));
299         if (obd == NULL)
300                 RETURN(ERR_PTR(-ENODEV));
301
302         rc = mdc_setup(obd, cfg);
303         if (rc < 0) {
304                 osc_device_free(env, d);
305                 RETURN(ERR_PTR(rc));
306         }
307         od->od_exp = obd->obd_self_export;
308         RETURN(d);
309 }
310
311 static const struct lu_device_type_operations mdc_device_type_ops = {
312         .ldto_device_alloc = mdc_device_alloc,
313         .ldto_device_free = osc_device_free,
314         .ldto_device_init = osc_device_init,
315         .ldto_device_fini = osc_device_fini
316 };
317
318 struct lu_device_type mdc_device_type = {
319         .ldt_tags = LU_DEVICE_CL,
320         .ldt_name = LUSTRE_MDC_NAME,
321         .ldt_ops = &mdc_device_type_ops,
322         .ldt_ctx_tags = LCT_CL_THREAD
323 };
324
325 /** @} osc */