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.sun.com/software/products/lustre/docs/GPLv2.pdf 19 * 20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 21 * CA 95054 USA or visit www.sun.com if you need additional information or 22 * have any questions. 23 * 24 * GPL HEADER END 25 */ 26/* 27 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 28 * Use is subject to license terms. 29 * 30 * Copyright (c) 2011, 2012, Intel Corporation. 31 */ 32/* 33 * This file is part of Lustre, http://www.lustre.org/ 34 * Lustre is a trademark of Sun Microsystems, Inc. 35 * 36 * Implementation of cl_object for OSC layer. 37 * 38 * Author: Nikita Danilov <nikita.danilov@sun.com> 39 */ 40 41#define DEBUG_SUBSYSTEM S_OSC 42 43#include "osc_cl_internal.h" 44 45/** \addtogroup osc 46 * @{ 47 */ 48 49/***************************************************************************** 50 * 51 * Type conversions. 52 * 53 */ 54 55static struct lu_object *osc2lu(struct osc_object *osc) 56{ 57 return &osc->oo_cl.co_lu; 58} 59 60static struct osc_object *lu2osc(const struct lu_object *obj) 61{ 62 LINVRNT(osc_is_object(obj)); 63 return container_of0(obj, struct osc_object, oo_cl.co_lu); 64} 65 66/***************************************************************************** 67 * 68 * Object operations. 69 * 70 */ 71 72static int osc_object_init(const struct lu_env *env, struct lu_object *obj, 73 const struct lu_object_conf *conf) 74{ 75 struct osc_object *osc = lu2osc(obj); 76 const struct cl_object_conf *cconf = lu2cl_conf(conf); 77 int i; 78 79 osc->oo_oinfo = cconf->u.coc_oinfo; 80 spin_lock_init(&osc->oo_seatbelt); 81 for (i = 0; i < CRT_NR; ++i) 82 INIT_LIST_HEAD(&osc->oo_inflight[i]); 83 84 INIT_LIST_HEAD(&osc->oo_ready_item); 85 INIT_LIST_HEAD(&osc->oo_hp_ready_item); 86 INIT_LIST_HEAD(&osc->oo_write_item); 87 INIT_LIST_HEAD(&osc->oo_read_item); 88 89 osc->oo_root.rb_node = NULL; 90 INIT_LIST_HEAD(&osc->oo_hp_exts); 91 INIT_LIST_HEAD(&osc->oo_urgent_exts); 92 INIT_LIST_HEAD(&osc->oo_rpc_exts); 93 INIT_LIST_HEAD(&osc->oo_reading_exts); 94 atomic_set(&osc->oo_nr_reads, 0); 95 atomic_set(&osc->oo_nr_writes, 0); 96 spin_lock_init(&osc->oo_lock); 97 98 cl_object_page_init(lu2cl(obj), sizeof(struct osc_page)); 99 100 return 0; 101} 102 103static 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 116 LASSERT(osc->oo_root.rb_node == NULL); 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); 123 124 lu_object_fini(obj); 125 OBD_SLAB_FREE_PTR(osc, osc_object_kmem); 126} 127 128int osc_lvb_print(const struct lu_env *env, void *cookie, 129 lu_printer_t p, const struct ost_lvb *lvb) 130{ 131 return (*p)(env, cookie, "size: %llu mtime: %llu atime: %llu ctime: %llu blocks: %llu", 132 lvb->lvb_size, lvb->lvb_mtime, lvb->lvb_atime, 133 lvb->lvb_ctime, lvb->lvb_blocks); 134} 135 136static int osc_object_print(const struct lu_env *env, void *cookie, 137 lu_printer_t p, const struct lu_object *obj) 138{ 139 struct osc_object *osc = lu2osc(obj); 140 struct lov_oinfo *oinfo = osc->oo_oinfo; 141 struct osc_async_rc *ar = &oinfo->loi_ar; 142 143 (*p)(env, cookie, "id: "DOSTID" " 144 "idx: %d gen: %d kms_valid: %u kms %llu rc: %d force_sync: %d min_xid: %llu ", 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 152 153static int osc_attr_get(const struct lu_env *env, struct cl_object *obj, 154 struct cl_attr *attr) 155{ 156 struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo; 157 158 cl_lvb2attr(attr, &oinfo->loi_lvb); 159 attr->cat_kms = oinfo->loi_kms_valid ? oinfo->loi_kms : 0; 160 return 0; 161} 162 163int osc_attr_set(const struct lu_env *env, struct cl_object *obj, 164 const struct cl_attr *attr, unsigned valid) 165{ 166 struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo; 167 struct ost_lvb *lvb = &oinfo->loi_lvb; 168 169 if (valid & CAT_SIZE) 170 lvb->lvb_size = attr->cat_size; 171 if (valid & CAT_MTIME) 172 lvb->lvb_mtime = attr->cat_mtime; 173 if (valid & CAT_ATIME) 174 lvb->lvb_atime = attr->cat_atime; 175 if (valid & CAT_CTIME) 176 lvb->lvb_ctime = attr->cat_ctime; 177 if (valid & CAT_BLOCKS) 178 lvb->lvb_blocks = attr->cat_blocks; 179 if (valid & CAT_KMS) { 180 CDEBUG(D_CACHE, "set kms from %llu to %llu\n", 181 oinfo->loi_kms, (__u64)attr->cat_kms); 182 loi_kms_set(oinfo, attr->cat_kms); 183 } 184 return 0; 185} 186 187static int osc_object_glimpse(const struct lu_env *env, 188 const struct cl_object *obj, struct ost_lvb *lvb) 189{ 190 struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo; 191 192 lvb->lvb_size = oinfo->loi_kms; 193 lvb->lvb_blocks = oinfo->loi_lvb.lvb_blocks; 194 return 0; 195} 196 197 198void osc_object_set_contended(struct osc_object *obj) 199{ 200 obj->oo_contention_time = cfs_time_current(); 201 /* mb(); */ 202 obj->oo_contended = 1; 203} 204 205void osc_object_clear_contended(struct osc_object *obj) 206{ 207 obj->oo_contended = 0; 208} 209 210int osc_object_is_contended(struct osc_object *obj) 211{ 212 struct osc_device *dev = lu2osc_dev(obj->oo_cl.co_lu.lo_dev); 213 int osc_contention_time = dev->od_contention_time; 214 unsigned long cur_time = cfs_time_current(); 215 unsigned long retry_time; 216 217 if (OBD_FAIL_CHECK(OBD_FAIL_OSC_OBJECT_CONTENTION)) 218 return 1; 219 220 if (!obj->oo_contended) 221 return 0; 222 223 /* 224 * I like copy-paste. the code is copied from 225 * ll_file_is_contended. 226 */ 227 retry_time = cfs_time_add(obj->oo_contention_time, 228 cfs_time_seconds(osc_contention_time)); 229 if (cfs_time_after(cur_time, retry_time)) { 230 osc_object_clear_contended(obj); 231 return 0; 232 } 233 return 1; 234} 235 236static const struct cl_object_operations osc_ops = { 237 .coo_page_init = osc_page_init, 238 .coo_lock_init = osc_lock_init, 239 .coo_io_init = osc_io_init, 240 .coo_attr_get = osc_attr_get, 241 .coo_attr_set = osc_attr_set, 242 .coo_glimpse = osc_object_glimpse 243}; 244 245static const struct lu_object_operations osc_lu_obj_ops = { 246 .loo_object_init = osc_object_init, 247 .loo_object_delete = NULL, 248 .loo_object_release = NULL, 249 .loo_object_free = osc_object_free, 250 .loo_object_print = osc_object_print, 251 .loo_object_invariant = NULL 252}; 253 254struct lu_object *osc_object_alloc(const struct lu_env *env, 255 const struct lu_object_header *unused, 256 struct lu_device *dev) 257{ 258 struct osc_object *osc; 259 struct lu_object *obj; 260 261 OBD_SLAB_ALLOC_PTR_GFP(osc, osc_object_kmem, GFP_NOFS); 262 if (osc != NULL) { 263 obj = osc2lu(osc); 264 lu_object_init(obj, NULL, dev); 265 osc->oo_cl.co_ops = &osc_ops; 266 obj->lo_ops = &osc_lu_obj_ops; 267 } else 268 obj = NULL; 269 return obj; 270} 271 272/** @} osc */ 273