4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
23 * Copyright (c) 2017 Intel Corporation.
26 * This file is part of Lustre, http://www.lustre.org/
28 * Implementation of cl_device, cl_req for MDC layer.
30 * Author: Mikhail Pershin <mike.pershin@intel.com>
33 #define DEBUG_SUBSYSTEM S_MDC
35 #include <obd_class.h>
36 #include <lustre_osc.h>
38 #include "mdc_internal.h"
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)
50 * An implementation of cl_io_operations specific methods for MDC layer.
53 static int mdc_async_upcall(void *a, int rc)
55 struct osc_async_cbargs *args = a;
58 complete(&args->opc_sync);
62 static int mdc_io_setattr_start(const struct lu_env *env,
63 const struct cl_io_slice *slice)
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;
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,
85 if (oio->oi_lockless == 0) {
86 cl_object_attr_lock(obj);
87 rc = cl_object_attr_get(env, obj, attr);
89 struct ost_lvb *lvb = &io->u.ci_setattr.sa_attr;
90 unsigned int cl_valid = 0;
92 if (ia_valid & ATTR_SIZE) {
93 attr->cat_size = attr->cat_kms = size;
94 cl_valid = (CAT_SIZE | CAT_KMS);
96 if (ia_valid & ATTR_MTIME_SET) {
97 attr->cat_mtime = lvb->lvb_mtime;
98 cl_valid |= CAT_MTIME;
100 if (ia_valid & ATTR_ATIME_SET) {
101 attr->cat_atime = lvb->lvb_atime;
102 cl_valid |= CAT_ATIME;
104 if (ia_valid & ATTR_CTIME_SET) {
105 attr->cat_ctime = lvb->lvb_ctime;
106 cl_valid |= CAT_CTIME;
108 rc = cl_object_attr_update(env, obj, attr, cl_valid);
110 cl_object_attr_unlock(obj);
115 if (!(ia_valid & ATTR_SIZE))
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;
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 |
129 if (oio->oi_lockless) {
130 oa->o_flags = OBD_FL_SRVLOCK;
131 oa->o_valid |= OBD_MD_FLFLAGS;
134 init_completion(&cbargs->opc_sync);
136 rc = osc_punch_send(osc_export(cl2osc(obj)), oa,
137 mdc_async_upcall, cbargs);
138 cbargs->opc_rpc_sent = rc == 0;
142 static struct cl_io_operations mdc_io_ops = {
145 .cio_iter_init = osc_io_iter_init,
146 .cio_iter_fini = osc_io_iter_fini,
147 .cio_start = osc_io_read_start,
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,
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,
161 /* no support for data version so far */
162 [CIT_DATA_VERSION] = {
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,
173 .cio_start = osc_io_fsync_start,
174 .cio_end = osc_io_fsync_end,
177 .cio_submit = osc_io_submit,
178 .cio_commit_async = osc_io_commit_async,
181 int mdc_io_init(const struct lu_env *env, struct cl_object *obj,
184 struct osc_io *oio = osc_env_io(env);
186 CL_IO_SLICE_CLEAN(oio, oi_cl);
187 cl_io_slice_add(io, &oio->oi_cl, obj, &mdc_io_ops);
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
196 static void mdc_req_attr_set(const struct lu_env *env, struct cl_object *obj,
197 struct cl_req_attr *attr)
199 u64 flags = attr->cra_flags;
201 /* Copy object FID to cl_attr */
202 attr->cra_oa->o_oi.oi_fid = *lu_object_fid(&obj->co_lu);
204 if (flags & OBD_MD_FLGROUP)
205 attr->cra_oa->o_valid |= OBD_MD_FLGROUP;
207 if (flags & OBD_MD_FLID)
208 attr->cra_oa->o_valid |= OBD_MD_FLID;
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,
221 static int mdc_object_init(const struct lu_env *env, struct lu_object *obj,
222 const struct lu_object_conf *conf)
224 struct osc_object *osc = lu2osc(obj);
226 if (osc->oo_initialized)
229 osc->oo_initialized = true;
231 return osc_object_init(env, obj, conf);
234 static void mdc_object_free(const struct lu_env *env, struct lu_object *obj)
236 osc_object_free(env, obj);
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
248 struct lu_object *mdc_object_alloc(const struct lu_env *env,
249 const struct lu_object_header *unused,
250 struct lu_device *dev)
252 struct osc_object *osc;
253 struct lu_object *obj;
255 OBD_SLAB_ALLOC_PTR_GFP(osc, osc_object_kmem, GFP_NOFS);
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;
268 static int mdc_cl_process_config(const struct lu_env *env,
269 struct lu_device *d, struct lustre_cfg *cfg)
271 return mdc_process_config(d->ld_obd, 0, cfg);
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,
280 static struct lu_device *mdc_device_alloc(const struct lu_env *env,
281 struct lu_device_type *t,
282 struct lustre_cfg *cfg)
285 struct osc_device *od;
286 struct obd_device *obd;
291 RETURN(ERR_PTR(-ENOMEM));
293 cl_device_init(&od->od_cl, t);
295 d->ld_ops = &mdc_lu_ops;
298 obd = class_name2obd(lustre_cfg_string(cfg, 0));
300 RETURN(ERR_PTR(-ENODEV));
302 rc = mdc_setup(obd, cfg);
304 osc_device_free(env, d);
307 od->od_exp = obd->obd_self_export;
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
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