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) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 28 * Use is subject to license terms. 29 */ 30/* 31 * Copyright (c) 2011, 2012, Intel Corporation. 32 */ 33/* 34 * This file is part of Lustre, http://www.lustre.org/ 35 * Lustre is a trademark of Sun Microsystems, Inc. 36 * 37 * lustre/include/lustre_mdc.h 38 * 39 * MDS data structures. 40 * See also lustre_idl.h for wire formats of requests. 41 */ 42 43#ifndef _LUSTRE_MDC_H 44#define _LUSTRE_MDC_H 45 46/** \defgroup mdc mdc 47 * 48 * @{ 49 */ 50 51#include <linux/fs.h> 52#include <linux/dcache.h> 53#include "lustre_intent.h" 54#include "lustre_handles.h" 55#include "../../include/linux/libcfs/libcfs.h" 56#include "obd_class.h" 57#include "lustre/lustre_idl.h" 58#include "lustre_lib.h" 59#include "lustre_dlm.h" 60#include "lustre_export.h" 61 62struct ptlrpc_client; 63struct obd_export; 64struct ptlrpc_request; 65struct obd_device; 66 67struct mdc_rpc_lock { 68 struct mutex rpcl_mutex; 69 struct lookup_intent *rpcl_it; 70 int rpcl_fakes; 71}; 72 73#define MDC_FAKE_RPCL_IT ((void *)0x2c0012bfUL) 74 75static inline void mdc_init_rpc_lock(struct mdc_rpc_lock *lck) 76{ 77 mutex_init(&lck->rpcl_mutex); 78 lck->rpcl_it = NULL; 79} 80 81static inline void mdc_get_rpc_lock(struct mdc_rpc_lock *lck, 82 struct lookup_intent *it) 83{ 84 if (it != NULL && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP || 85 it->it_op == IT_LAYOUT)) 86 return; 87 88 /* This would normally block until the existing request finishes. 89 * If fail_loc is set it will block until the regular request is 90 * done, then set rpcl_it to MDC_FAKE_RPCL_IT. Once that is set 91 * it will only be cleared when all fake requests are finished. 92 * Only when all fake requests are finished can normal requests 93 * be sent, to ensure they are recoverable again. */ 94 again: 95 mutex_lock(&lck->rpcl_mutex); 96 97 if (CFS_FAIL_CHECK_QUIET(OBD_FAIL_MDC_RPCS_SEM)) { 98 lck->rpcl_it = MDC_FAKE_RPCL_IT; 99 lck->rpcl_fakes++; 100 mutex_unlock(&lck->rpcl_mutex); 101 return; 102 } 103 104 /* This will only happen when the CFS_FAIL_CHECK() was 105 * just turned off but there are still requests in progress. 106 * Wait until they finish. It doesn't need to be efficient 107 * in this extremely rare case, just have low overhead in 108 * the common case when it isn't true. */ 109 while (unlikely(lck->rpcl_it == MDC_FAKE_RPCL_IT)) { 110 mutex_unlock(&lck->rpcl_mutex); 111 schedule_timeout(cfs_time_seconds(1) / 4); 112 goto again; 113 } 114 115 LASSERT(lck->rpcl_it == NULL); 116 lck->rpcl_it = it; 117} 118 119static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck, 120 struct lookup_intent *it) 121{ 122 if (it != NULL && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP || 123 it->it_op == IT_LAYOUT)) 124 return; 125 126 if (lck->rpcl_it == MDC_FAKE_RPCL_IT) { /* OBD_FAIL_MDC_RPCS_SEM */ 127 mutex_lock(&lck->rpcl_mutex); 128 129 LASSERTF(lck->rpcl_fakes > 0, "%d\n", lck->rpcl_fakes); 130 lck->rpcl_fakes--; 131 132 if (lck->rpcl_fakes == 0) 133 lck->rpcl_it = NULL; 134 135 } else { 136 LASSERTF(it == lck->rpcl_it, "%p != %p\n", it, lck->rpcl_it); 137 lck->rpcl_it = NULL; 138 } 139 140 mutex_unlock(&lck->rpcl_mutex); 141} 142 143/* Update the maximum observed easize and cookiesize. The default easize 144 * and cookiesize is initialized to the minimum value but allowed to grow 145 * up to a single page in size if required to handle the common case. 146 */ 147static inline void mdc_update_max_ea_from_body(struct obd_export *exp, 148 struct mdt_body *body) 149{ 150 if (body->valid & OBD_MD_FLMODEASIZE) { 151 struct client_obd *cli = &exp->exp_obd->u.cli; 152 153 if (cli->cl_max_mds_easize < body->max_mdsize) { 154 cli->cl_max_mds_easize = body->max_mdsize; 155 cli->cl_default_mds_easize = 156 min_t(__u32, body->max_mdsize, PAGE_CACHE_SIZE); 157 } 158 if (cli->cl_max_mds_cookiesize < body->max_cookiesize) { 159 cli->cl_max_mds_cookiesize = body->max_cookiesize; 160 cli->cl_default_mds_cookiesize = 161 min_t(__u32, body->max_cookiesize, PAGE_CACHE_SIZE); 162 } 163 } 164} 165 166 167struct mdc_cache_waiter { 168 struct list_head mcw_entry; 169 wait_queue_head_t mcw_waitq; 170}; 171 172/* mdc/mdc_locks.c */ 173int it_disposition(struct lookup_intent *it, int flag); 174void it_clear_disposition(struct lookup_intent *it, int flag); 175void it_set_disposition(struct lookup_intent *it, int flag); 176int it_open_error(int phase, struct lookup_intent *it); 177 178static inline bool cl_is_lov_delay_create(unsigned int flags) 179{ 180 return (flags & O_LOV_DELAY_CREATE) == O_LOV_DELAY_CREATE; 181} 182 183static inline void cl_lov_delay_create_clear(unsigned int *flags) 184{ 185 if ((*flags & O_LOV_DELAY_CREATE) == O_LOV_DELAY_CREATE) 186 *flags &= ~O_LOV_DELAY_CREATE; 187} 188 189/** @} mdc */ 190 191#endif 192