linux/drivers/staging/lustre/lustre/lov/lov_page.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_page for LOV layer.
  37 *
  38 *   Author: Nikita Danilov <nikita.danilov@sun.com>
  39 */
  40
  41#define DEBUG_SUBSYSTEM S_LOV
  42
  43#include "lov_cl_internal.h"
  44
  45/** \addtogroup lov
  46 *  @{
  47 */
  48
  49/*****************************************************************************
  50 *
  51 * Lov page operations.
  52 *
  53 */
  54
  55static int lov_page_invariant(const struct cl_page_slice *slice)
  56{
  57        const struct cl_page  *page = slice->cpl_page;
  58        const struct cl_page  *sub  = lov_sub_page(slice);
  59
  60        return ergo(sub != NULL,
  61                    page->cp_child == sub &&
  62                    sub->cp_parent == page &&
  63                    page->cp_state == sub->cp_state);
  64}
  65
  66static void lov_page_fini(const struct lu_env *env,
  67                          struct cl_page_slice *slice)
  68{
  69        struct cl_page  *sub = lov_sub_page(slice);
  70
  71        LINVRNT(lov_page_invariant(slice));
  72        ENTRY;
  73
  74        if (sub != NULL) {
  75                LASSERT(sub->cp_state == CPS_FREEING);
  76                lu_ref_del(&sub->cp_reference, "lov", sub->cp_parent);
  77                sub->cp_parent = NULL;
  78                slice->cpl_page->cp_child = NULL;
  79                cl_page_put(env, sub);
  80        }
  81        EXIT;
  82}
  83
  84static int lov_page_own(const struct lu_env *env,
  85                        const struct cl_page_slice *slice, struct cl_io *io,
  86                        int nonblock)
  87{
  88        struct lov_io     *lio = lov_env_io(env);
  89        struct lov_io_sub *sub;
  90
  91        LINVRNT(lov_page_invariant(slice));
  92        LINVRNT(!cl2lov_page(slice)->lps_invalid);
  93        ENTRY;
  94
  95        sub = lov_page_subio(env, lio, slice);
  96        if (!IS_ERR(sub)) {
  97                lov_sub_page(slice)->cp_owner = sub->sub_io;
  98                lov_sub_put(sub);
  99        } else
 100                LBUG(); /* Arrgh */
 101        RETURN(0);
 102}
 103
 104static void lov_page_assume(const struct lu_env *env,
 105                            const struct cl_page_slice *slice, struct cl_io *io)
 106{
 107        lov_page_own(env, slice, io, 0);
 108}
 109
 110static int lov_page_cache_add(const struct lu_env *env,
 111                              const struct cl_page_slice *slice,
 112                              struct cl_io *io)
 113{
 114        struct lov_io     *lio = lov_env_io(env);
 115        struct lov_io_sub *sub;
 116        int rc = 0;
 117
 118        LINVRNT(lov_page_invariant(slice));
 119        LINVRNT(!cl2lov_page(slice)->lps_invalid);
 120        ENTRY;
 121
 122        sub = lov_page_subio(env, lio, slice);
 123        if (!IS_ERR(sub)) {
 124                rc = cl_page_cache_add(sub->sub_env, sub->sub_io,
 125                                       slice->cpl_page->cp_child, CRT_WRITE);
 126                lov_sub_put(sub);
 127        } else {
 128                rc = PTR_ERR(sub);
 129                CL_PAGE_DEBUG(D_ERROR, env, slice->cpl_page, "rc = %d\n", rc);
 130        }
 131        RETURN(rc);
 132}
 133
 134static int lov_page_print(const struct lu_env *env,
 135                          const struct cl_page_slice *slice,
 136                          void *cookie, lu_printer_t printer)
 137{
 138        struct lov_page *lp = cl2lov_page(slice);
 139
 140        return (*printer)(env, cookie, LUSTRE_LOV_NAME"-page@%p\n", lp);
 141}
 142
 143static const struct cl_page_operations lov_page_ops = {
 144        .cpo_fini   = lov_page_fini,
 145        .cpo_own    = lov_page_own,
 146        .cpo_assume = lov_page_assume,
 147        .io = {
 148                [CRT_WRITE] = {
 149                        .cpo_cache_add = lov_page_cache_add
 150                }
 151        },
 152        .cpo_print  = lov_page_print
 153};
 154
 155static void lov_empty_page_fini(const struct lu_env *env,
 156                                struct cl_page_slice *slice)
 157{
 158        LASSERT(slice->cpl_page->cp_child == NULL);
 159}
 160
 161int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj,
 162                        struct cl_page *page, struct page *vmpage)
 163{
 164        struct lov_object *loo = cl2lov(obj);
 165        struct lov_layout_raid0 *r0 = lov_r0(loo);
 166        struct lov_io     *lio = lov_env_io(env);
 167        struct cl_page    *subpage;
 168        struct cl_object  *subobj;
 169        struct lov_io_sub *sub;
 170        struct lov_page   *lpg = cl_object_page_slice(obj, page);
 171        loff_t       offset;
 172        obd_off     suboff;
 173        int             stripe;
 174        int             rc;
 175        ENTRY;
 176
 177        offset = cl_offset(obj, page->cp_index);
 178        stripe = lov_stripe_number(loo->lo_lsm, offset);
 179        LASSERT(stripe < r0->lo_nr);
 180        rc = lov_stripe_offset(loo->lo_lsm, offset, stripe,
 181                                   &suboff);
 182        LASSERT(rc == 0);
 183
 184        lpg->lps_invalid = 1;
 185        cl_page_slice_add(page, &lpg->lps_cl, obj, &lov_page_ops);
 186
 187        sub = lov_sub_get(env, lio, stripe);
 188        if (IS_ERR(sub))
 189                GOTO(out, rc = PTR_ERR(sub));
 190
 191        subobj = lovsub2cl(r0->lo_sub[stripe]);
 192        subpage = cl_page_find_sub(sub->sub_env, subobj,
 193                                   cl_index(subobj, suboff), vmpage, page);
 194        lov_sub_put(sub);
 195        if (IS_ERR(subpage))
 196                GOTO(out, rc = PTR_ERR(subpage));
 197
 198        if (likely(subpage->cp_parent == page)) {
 199                lu_ref_add(&subpage->cp_reference, "lov", page);
 200                lpg->lps_invalid = 0;
 201                rc = 0;
 202        } else {
 203                CL_PAGE_DEBUG(D_ERROR, env, page, "parent page\n");
 204                CL_PAGE_DEBUG(D_ERROR, env, subpage, "child page\n");
 205                LASSERT(0);
 206        }
 207
 208        EXIT;
 209out:
 210        return rc;
 211}
 212
 213
 214static const struct cl_page_operations lov_empty_page_ops = {
 215        .cpo_fini   = lov_empty_page_fini,
 216        .cpo_print  = lov_page_print
 217};
 218
 219int lov_page_init_empty(const struct lu_env *env, struct cl_object *obj,
 220                        struct cl_page *page, struct page *vmpage)
 221{
 222        struct lov_page *lpg = cl_object_page_slice(obj, page);
 223        void *addr;
 224        ENTRY;
 225
 226        cl_page_slice_add(page, &lpg->lps_cl, obj, &lov_empty_page_ops);
 227        addr = kmap(vmpage);
 228        memset(addr, 0, cl_page_size(obj));
 229        kunmap(vmpage);
 230        cl_page_export(env, page, 1);
 231        RETURN(0);
 232}
 233
 234
 235/** @} lov */
 236