linux/drivers/staging/lustre/lustre/osc/osc_object.c
<<
>>
Prefs
   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 " idx: %d gen: %d kms_valid: %u kms %llu rc: %d force_sync: %d min_xid: %llu ",
 144             POSTID(&oinfo->loi_oi), oinfo->loi_ost_idx,
 145             oinfo->loi_ost_gen, oinfo->loi_kms_valid, oinfo->loi_kms,
 146             ar->ar_rc, ar->ar_force_sync, ar->ar_min_xid);
 147        osc_lvb_print(env, cookie, p, &oinfo->loi_lvb);
 148        return 0;
 149}
 150
 151
 152static 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
 162int osc_attr_set(const struct lu_env *env, struct cl_object *obj,
 163                 const struct cl_attr *attr, unsigned valid)
 164{
 165        struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo;
 166        struct ost_lvb *lvb = &oinfo->loi_lvb;
 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) {
 179                CDEBUG(D_CACHE, "set kms from %llu to %llu\n",
 180                       oinfo->loi_kms, (__u64)attr->cat_kms);
 181                loi_kms_set(oinfo, attr->cat_kms);
 182        }
 183        return 0;
 184}
 185
 186static 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
 191        lvb->lvb_size = oinfo->loi_kms;
 192        lvb->lvb_blocks = oinfo->loi_lvb.lvb_blocks;
 193        return 0;
 194}
 195
 196
 197void osc_object_set_contended(struct osc_object *obj)
 198{
 199        obj->oo_contention_time = cfs_time_current();
 200        /* mb(); */
 201        obj->oo_contended = 1;
 202}
 203
 204void osc_object_clear_contended(struct osc_object *obj)
 205{
 206        obj->oo_contended = 0;
 207}
 208
 209int osc_object_is_contended(struct osc_object *obj)
 210{
 211        struct osc_device *dev = lu2osc_dev(obj->oo_cl.co_lu.lo_dev);
 212        int osc_contention_time = dev->od_contention_time;
 213        unsigned long cur_time = cfs_time_current();
 214        unsigned long retry_time;
 215
 216        if (OBD_FAIL_CHECK(OBD_FAIL_OSC_OBJECT_CONTENTION))
 217                return 1;
 218
 219        if (!obj->oo_contended)
 220                return 0;
 221
 222        /*
 223         * I like copy-paste. the code is copied from
 224         * ll_file_is_contended.
 225         */
 226        retry_time = cfs_time_add(obj->oo_contention_time,
 227                                  cfs_time_seconds(osc_contention_time));
 228        if (cfs_time_after(cur_time, retry_time)) {
 229                osc_object_clear_contended(obj);
 230                return 0;
 231        }
 232        return 1;
 233}
 234
 235static const struct cl_object_operations osc_ops = {
 236        .coo_page_init = osc_page_init,
 237        .coo_lock_init = osc_lock_init,
 238        .coo_io_init   = osc_io_init,
 239        .coo_attr_get  = osc_attr_get,
 240        .coo_attr_set  = osc_attr_set,
 241        .coo_glimpse   = osc_object_glimpse
 242};
 243
 244static const struct lu_object_operations osc_lu_obj_ops = {
 245        .loo_object_init      = osc_object_init,
 246        .loo_object_delete    = NULL,
 247        .loo_object_release   = NULL,
 248        .loo_object_free      = osc_object_free,
 249        .loo_object_print     = osc_object_print,
 250        .loo_object_invariant = NULL
 251};
 252
 253struct lu_object *osc_object_alloc(const struct lu_env *env,
 254                                   const struct lu_object_header *unused,
 255                                   struct lu_device *dev)
 256{
 257        struct osc_object *osc;
 258        struct lu_object *obj;
 259
 260        OBD_SLAB_ALLOC_PTR_GFP(osc, osc_object_kmem, GFP_NOFS);
 261        if (osc != NULL) {
 262                obj = osc2lu(osc);
 263                lu_object_init(obj, NULL, dev);
 264                osc->oo_cl.co_ops = &osc_ops;
 265                obj->lo_ops = &osc_lu_obj_ops;
 266        } else
 267                obj = NULL;
 268        return obj;
 269}
 270
 271/** @} osc */
 272