Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 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 |
Oleg Drokin | 6a5b99a | 2016-06-14 23:33:40 -0400 | [diff] [blame] | 18 | * http://www.gnu.org/licenses/gpl-2.0.html |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 19 | * |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 20 | * GPL HEADER END |
| 21 | */ |
| 22 | /* |
| 23 | * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. |
| 24 | * Use is subject to license terms. |
| 25 | * |
Andreas Dilger | 1dc563a | 2015-11-08 18:09:37 -0500 | [diff] [blame] | 26 | * Copyright (c) 2011, 2015, Intel Corporation. |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 27 | */ |
| 28 | /* |
| 29 | * This file is part of Lustre, http://www.lustre.org/ |
| 30 | * Lustre is a trademark of Sun Microsystems, Inc. |
| 31 | * |
| 32 | * Implementation of cl_object for OSC layer. |
| 33 | * |
| 34 | * Author: Nikita Danilov <nikita.danilov@sun.com> |
Jinshan Xiong | d9d4790 | 2016-03-30 19:48:28 -0400 | [diff] [blame] | 35 | * Author: Jinshan Xiong <jinshan.xiong@intel.com> |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 36 | */ |
| 37 | |
| 38 | #define DEBUG_SUBSYSTEM S_OSC |
| 39 | |
| 40 | #include "osc_cl_internal.h" |
| 41 | |
| 42 | /** \addtogroup osc |
| 43 | * @{ |
| 44 | */ |
| 45 | |
| 46 | /***************************************************************************** |
| 47 | * |
| 48 | * Type conversions. |
| 49 | * |
| 50 | */ |
| 51 | |
| 52 | static struct lu_object *osc2lu(struct osc_object *osc) |
| 53 | { |
| 54 | return &osc->oo_cl.co_lu; |
| 55 | } |
| 56 | |
| 57 | static struct osc_object *lu2osc(const struct lu_object *obj) |
| 58 | { |
| 59 | LINVRNT(osc_is_object(obj)); |
| 60 | return container_of0(obj, struct osc_object, oo_cl.co_lu); |
| 61 | } |
| 62 | |
| 63 | /***************************************************************************** |
| 64 | * |
| 65 | * Object operations. |
| 66 | * |
| 67 | */ |
| 68 | |
| 69 | static int osc_object_init(const struct lu_env *env, struct lu_object *obj, |
| 70 | const struct lu_object_conf *conf) |
| 71 | { |
Chris Hanna | 29ac684 | 2015-06-03 10:23:42 -0400 | [diff] [blame] | 72 | struct osc_object *osc = lu2osc(obj); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 73 | const struct cl_object_conf *cconf = lu2cl_conf(conf); |
| 74 | int i; |
| 75 | |
| 76 | osc->oo_oinfo = cconf->u.coc_oinfo; |
| 77 | spin_lock_init(&osc->oo_seatbelt); |
| 78 | for (i = 0; i < CRT_NR; ++i) |
| 79 | INIT_LIST_HEAD(&osc->oo_inflight[i]); |
| 80 | |
| 81 | INIT_LIST_HEAD(&osc->oo_ready_item); |
| 82 | INIT_LIST_HEAD(&osc->oo_hp_ready_item); |
| 83 | INIT_LIST_HEAD(&osc->oo_write_item); |
| 84 | INIT_LIST_HEAD(&osc->oo_read_item); |
| 85 | |
| 86 | osc->oo_root.rb_node = NULL; |
| 87 | INIT_LIST_HEAD(&osc->oo_hp_exts); |
| 88 | INIT_LIST_HEAD(&osc->oo_urgent_exts); |
| 89 | INIT_LIST_HEAD(&osc->oo_rpc_exts); |
| 90 | INIT_LIST_HEAD(&osc->oo_reading_exts); |
| 91 | atomic_set(&osc->oo_nr_reads, 0); |
| 92 | atomic_set(&osc->oo_nr_writes, 0); |
| 93 | spin_lock_init(&osc->oo_lock); |
Jinshan Xiong | d9d4790 | 2016-03-30 19:48:28 -0400 | [diff] [blame] | 94 | spin_lock_init(&osc->oo_tree_lock); |
Jinshan Xiong | 06563b5 | 2016-03-30 19:48:40 -0400 | [diff] [blame] | 95 | spin_lock_init(&osc->oo_ol_spin); |
| 96 | INIT_LIST_HEAD(&osc->oo_ol_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 97 | |
| 98 | cl_object_page_init(lu2cl(obj), sizeof(struct osc_page)); |
| 99 | |
| 100 | return 0; |
| 101 | } |
| 102 | |
| 103 | static void osc_object_free(const struct lu_env *env, struct lu_object *obj) |
| 104 | { |
| 105 | struct osc_object *osc = lu2osc(obj); |
| 106 | int i; |
| 107 | |
| 108 | for (i = 0; i < CRT_NR; ++i) |
| 109 | LASSERT(list_empty(&osc->oo_inflight[i])); |
| 110 | |
| 111 | LASSERT(list_empty(&osc->oo_ready_item)); |
| 112 | LASSERT(list_empty(&osc->oo_hp_ready_item)); |
| 113 | LASSERT(list_empty(&osc->oo_write_item)); |
| 114 | LASSERT(list_empty(&osc->oo_read_item)); |
| 115 | |
Oleg Drokin | 7f1ae4c | 2016-02-16 00:46:57 -0500 | [diff] [blame] | 116 | LASSERT(!osc->oo_root.rb_node); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 117 | LASSERT(list_empty(&osc->oo_hp_exts)); |
| 118 | LASSERT(list_empty(&osc->oo_urgent_exts)); |
| 119 | LASSERT(list_empty(&osc->oo_rpc_exts)); |
| 120 | LASSERT(list_empty(&osc->oo_reading_exts)); |
| 121 | LASSERT(atomic_read(&osc->oo_nr_reads) == 0); |
| 122 | LASSERT(atomic_read(&osc->oo_nr_writes) == 0); |
Jinshan Xiong | 06563b5 | 2016-03-30 19:48:40 -0400 | [diff] [blame] | 123 | LASSERT(list_empty(&osc->oo_ol_list)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 124 | |
| 125 | lu_object_fini(obj); |
Mike Rapoport | 50d3036 | 2015-10-20 12:39:51 +0300 | [diff] [blame] | 126 | kmem_cache_free(osc_object_kmem, osc); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 127 | } |
| 128 | |
| 129 | int osc_lvb_print(const struct lu_env *env, void *cookie, |
| 130 | lu_printer_t p, const struct ost_lvb *lvb) |
| 131 | { |
Greg Kroah-Hartman | b0f5aad | 2014-07-12 20:06:04 -0700 | [diff] [blame] | 132 | return (*p)(env, cookie, "size: %llu mtime: %llu atime: %llu ctime: %llu blocks: %llu", |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 133 | lvb->lvb_size, lvb->lvb_mtime, lvb->lvb_atime, |
| 134 | lvb->lvb_ctime, lvb->lvb_blocks); |
| 135 | } |
| 136 | |
| 137 | static int osc_object_print(const struct lu_env *env, void *cookie, |
| 138 | lu_printer_t p, const struct lu_object *obj) |
| 139 | { |
Chris Hanna | 29ac684 | 2015-06-03 10:23:42 -0400 | [diff] [blame] | 140 | struct osc_object *osc = lu2osc(obj); |
| 141 | struct lov_oinfo *oinfo = osc->oo_oinfo; |
| 142 | struct osc_async_rc *ar = &oinfo->loi_ar; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 143 | |
Joe Perches | 2d00bd1 | 2014-11-23 11:28:50 -0800 | [diff] [blame] | 144 | (*p)(env, cookie, "id: " DOSTID " idx: %d gen: %d kms_valid: %u kms %llu rc: %d force_sync: %d min_xid: %llu ", |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 145 | POSTID(&oinfo->loi_oi), oinfo->loi_ost_idx, |
| 146 | oinfo->loi_ost_gen, oinfo->loi_kms_valid, oinfo->loi_kms, |
| 147 | ar->ar_rc, ar->ar_force_sync, ar->ar_min_xid); |
| 148 | osc_lvb_print(env, cookie, p, &oinfo->loi_lvb); |
| 149 | return 0; |
| 150 | } |
| 151 | |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 152 | static int osc_attr_get(const struct lu_env *env, struct cl_object *obj, |
| 153 | struct cl_attr *attr) |
| 154 | { |
| 155 | struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo; |
| 156 | |
| 157 | cl_lvb2attr(attr, &oinfo->loi_lvb); |
| 158 | attr->cat_kms = oinfo->loi_kms_valid ? oinfo->loi_kms : 0; |
| 159 | return 0; |
| 160 | } |
| 161 | |
Bobi Jam | 96234ec | 2016-09-18 16:38:43 -0400 | [diff] [blame] | 162 | static int osc_attr_update(const struct lu_env *env, struct cl_object *obj, |
| 163 | const struct cl_attr *attr, unsigned int valid) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 164 | { |
| 165 | struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo; |
Chris Hanna | 29ac684 | 2015-06-03 10:23:42 -0400 | [diff] [blame] | 166 | struct ost_lvb *lvb = &oinfo->loi_lvb; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 167 | |
| 168 | if (valid & CAT_SIZE) |
| 169 | lvb->lvb_size = attr->cat_size; |
| 170 | if (valid & CAT_MTIME) |
| 171 | lvb->lvb_mtime = attr->cat_mtime; |
| 172 | if (valid & CAT_ATIME) |
| 173 | lvb->lvb_atime = attr->cat_atime; |
| 174 | if (valid & CAT_CTIME) |
| 175 | lvb->lvb_ctime = attr->cat_ctime; |
| 176 | if (valid & CAT_BLOCKS) |
| 177 | lvb->lvb_blocks = attr->cat_blocks; |
| 178 | if (valid & CAT_KMS) { |
Greg Kroah-Hartman | b0f5aad | 2014-07-12 20:06:04 -0700 | [diff] [blame] | 179 | CDEBUG(D_CACHE, "set kms from %llu to %llu\n", |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 180 | oinfo->loi_kms, (__u64)attr->cat_kms); |
| 181 | loi_kms_set(oinfo, attr->cat_kms); |
| 182 | } |
| 183 | return 0; |
| 184 | } |
| 185 | |
| 186 | static int osc_object_glimpse(const struct lu_env *env, |
| 187 | const struct cl_object *obj, struct ost_lvb *lvb) |
| 188 | { |
| 189 | struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo; |
| 190 | |
Chris Hanna | 29ac684 | 2015-06-03 10:23:42 -0400 | [diff] [blame] | 191 | lvb->lvb_size = oinfo->loi_kms; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 192 | lvb->lvb_blocks = oinfo->loi_lvb.lvb_blocks; |
Greg Kroah-Hartman | 0a3bdb0 | 2013-08-03 10:35:28 +0800 | [diff] [blame] | 193 | return 0; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 194 | } |
| 195 | |
Jinshan Xiong | 06563b5 | 2016-03-30 19:48:40 -0400 | [diff] [blame] | 196 | static int osc_object_ast_clear(struct ldlm_lock *lock, void *data) |
| 197 | { |
Jinshan Xiong | 06563b5 | 2016-03-30 19:48:40 -0400 | [diff] [blame] | 198 | if (lock->l_ast_data == data) |
| 199 | lock->l_ast_data = NULL; |
| 200 | return LDLM_ITER_CONTINUE; |
| 201 | } |
| 202 | |
| 203 | static int osc_object_prune(const struct lu_env *env, struct cl_object *obj) |
| 204 | { |
| 205 | struct osc_object *osc = cl2osc(obj); |
| 206 | struct ldlm_res_id *resname = &osc_env_info(env)->oti_resname; |
| 207 | |
| 208 | LASSERTF(osc->oo_npages == 0, |
| 209 | DFID "still have %lu pages, obj: %p, osc: %p\n", |
| 210 | PFID(lu_object_fid(&obj->co_lu)), osc->oo_npages, obj, osc); |
| 211 | |
| 212 | /* DLM locks don't hold a reference of osc_object so we have to |
| 213 | * clear it before the object is being destroyed. |
| 214 | */ |
| 215 | ostid_build_res_name(&osc->oo_oinfo->loi_oi, resname); |
| 216 | ldlm_resource_iterate(osc_export(osc)->exp_obd->obd_namespace, resname, |
| 217 | osc_object_ast_clear, osc); |
| 218 | return 0; |
| 219 | } |
| 220 | |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 221 | void osc_object_set_contended(struct osc_object *obj) |
| 222 | { |
| 223 | obj->oo_contention_time = cfs_time_current(); |
| 224 | /* mb(); */ |
| 225 | obj->oo_contended = 1; |
| 226 | } |
| 227 | |
| 228 | void osc_object_clear_contended(struct osc_object *obj) |
| 229 | { |
| 230 | obj->oo_contended = 0; |
| 231 | } |
| 232 | |
| 233 | int osc_object_is_contended(struct osc_object *obj) |
| 234 | { |
Chris Hanna | 29ac684 | 2015-06-03 10:23:42 -0400 | [diff] [blame] | 235 | struct osc_device *dev = lu2osc_dev(obj->oo_cl.co_lu.lo_dev); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 236 | int osc_contention_time = dev->od_contention_time; |
Chris Hanna | 29ac684 | 2015-06-03 10:23:42 -0400 | [diff] [blame] | 237 | unsigned long cur_time = cfs_time_current(); |
Greg Kroah-Hartman | a649ad1 | 2014-07-12 00:27:46 -0700 | [diff] [blame] | 238 | unsigned long retry_time; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 239 | |
| 240 | if (OBD_FAIL_CHECK(OBD_FAIL_OSC_OBJECT_CONTENTION)) |
| 241 | return 1; |
| 242 | |
| 243 | if (!obj->oo_contended) |
| 244 | return 0; |
| 245 | |
| 246 | /* |
| 247 | * I like copy-paste. the code is copied from |
| 248 | * ll_file_is_contended. |
| 249 | */ |
| 250 | retry_time = cfs_time_add(obj->oo_contention_time, |
| 251 | cfs_time_seconds(osc_contention_time)); |
| 252 | if (cfs_time_after(cur_time, retry_time)) { |
| 253 | osc_object_clear_contended(obj); |
| 254 | return 0; |
| 255 | } |
| 256 | return 1; |
| 257 | } |
| 258 | |
| 259 | static const struct cl_object_operations osc_ops = { |
| 260 | .coo_page_init = osc_page_init, |
| 261 | .coo_lock_init = osc_lock_init, |
| 262 | .coo_io_init = osc_io_init, |
| 263 | .coo_attr_get = osc_attr_get, |
Bobi Jam | 96234ec | 2016-09-18 16:38:43 -0400 | [diff] [blame] | 264 | .coo_attr_update = osc_attr_update, |
Jinshan Xiong | 06563b5 | 2016-03-30 19:48:40 -0400 | [diff] [blame] | 265 | .coo_glimpse = osc_object_glimpse, |
| 266 | .coo_prune = osc_object_prune |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 267 | }; |
| 268 | |
| 269 | static const struct lu_object_operations osc_lu_obj_ops = { |
| 270 | .loo_object_init = osc_object_init, |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 271 | .loo_object_release = NULL, |
| 272 | .loo_object_free = osc_object_free, |
| 273 | .loo_object_print = osc_object_print, |
| 274 | .loo_object_invariant = NULL |
| 275 | }; |
| 276 | |
| 277 | struct lu_object *osc_object_alloc(const struct lu_env *env, |
| 278 | const struct lu_object_header *unused, |
| 279 | struct lu_device *dev) |
| 280 | { |
| 281 | struct osc_object *osc; |
Chris Hanna | 29ac684 | 2015-06-03 10:23:42 -0400 | [diff] [blame] | 282 | struct lu_object *obj; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 283 | |
Amitoj Kaur Chawla | c4418da | 2016-02-26 14:24:55 +0530 | [diff] [blame] | 284 | osc = kmem_cache_zalloc(osc_object_kmem, GFP_NOFS); |
Oleg Drokin | 7f1ae4c | 2016-02-16 00:46:57 -0500 | [diff] [blame] | 285 | if (osc) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 286 | obj = osc2lu(osc); |
| 287 | lu_object_init(obj, NULL, dev); |
| 288 | osc->oo_cl.co_ops = &osc_ops; |
| 289 | obj->lo_ops = &osc_lu_obj_ops; |
Oleg Drokin | da5ecb4 | 2016-04-01 15:18:01 -0400 | [diff] [blame] | 290 | } else { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 291 | obj = NULL; |
Oleg Drokin | da5ecb4 | 2016-04-01 15:18:01 -0400 | [diff] [blame] | 292 | } |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 293 | return obj; |
| 294 | } |
| 295 | |
| 296 | /** @} osc */ |