4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
27 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2012, Whamcloud, Inc.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/ofd/ofd_recovery.c
38 * Author: Alex Zhuravlev <bzzz@whamcloud.com>
39 * Author: Mikhail Pershin <tappro@whamcloud.com>
42 #define DEBUG_SUBSYSTEM S_FILTER
44 #include "ofd_internal.h"
46 struct thandle *ofd_trans_create(const struct lu_env *env,
47 struct ofd_device *ofd)
49 struct ofd_thread_info *info = ofd_info(env);
54 th = dt_trans_create(env, ofd->ofd_osd);
58 /* export can require sync operations */
59 if (info->fti_exp != NULL)
60 th->th_sync |= info->fti_exp->exp_need_sync;
64 int ofd_trans_start(const struct lu_env *env, struct ofd_device *ofd,
65 struct ofd_object *obj, struct thandle *th)
67 struct ofd_thread_info *info = ofd_info(env);
70 if (info->fti_exp == NULL)
73 /* declare last_rcvd update */
74 rc = dt_declare_record_write(env, ofd->ofd_lut.lut_last_rcvd,
75 sizeof(struct lsd_client_data),
76 info->fti_exp->exp_target_data.ted_lr_off,
81 /* declare last_rcvd header update */
82 rc = dt_declare_record_write(env, ofd->ofd_lut.lut_last_rcvd,
83 sizeof(ofd->ofd_lut.lut_lsd), 0, th);
87 /* version change is required for this object */
89 ofd_info(env)->fti_obj = obj;
90 rc = dt_declare_version_set(env, ofd_object_child(obj), th);
95 return dt_trans_start(env, ofd->ofd_osd, th);
98 void ofd_trans_stop(const struct lu_env *env, struct ofd_device *ofd,
99 struct thandle *th, int rc)
102 dt_trans_stop(env, ofd->ofd_osd, th);
106 * last_rcvd & last_committed update callbacks
108 static int ofd_last_rcvd_update(struct ofd_thread_info *info,
111 struct ofd_device *ofd = ofd_exp(info->fti_exp);
112 struct filter_export_data *fed;
113 struct lsd_client_data *lcd;
114 __s32 rc = th->th_result;
118 bool lw_client = false;
123 LASSERT(info->fti_exp);
125 if ((info->fti_exp->exp_connect_flags & OBD_CONNECT_LIGHTWEIGHT) != 0)
128 fed = &info->fti_exp->exp_filter_data;
130 lcd = fed->fed_ted.ted_lcd;
131 /* if the export has already been disconnected, we have no last_rcvd
132 * slot, update server data with latest transno then */
134 CWARN("commit transaction for disconnected client %s: rc %d\n",
135 info->fti_exp->exp_client_uuid.uuid, rc);
136 err = tgt_server_data_write(info->fti_env, &ofd->ofd_lut, th);
139 /* ofd connect may cause transaction before export has last_rcvd
141 if (fed->fed_ted.ted_lr_idx < 0 && !lw_client)
143 off = fed->fed_ted.ted_lr_off;
145 transno_p = &lcd->lcd_last_transno;
146 lcd->lcd_last_xid = info->fti_xid;
149 * When we store zero transno in mcd we can lost last transno value
150 * because mcd contains 0, but msd is not yet written
151 * The server data should be updated also if the latest
152 * transno is rewritten by zero. See the bug 11125 for details.
154 if (info->fti_transno == 0 &&
155 *transno_p == ofd->ofd_lut.lut_last_transno) {
156 spin_lock(&ofd->ofd_lut.lut_translock);
157 ofd->ofd_lut.lut_lsd.lsd_last_transno =
158 ofd->ofd_lut.lut_last_transno;
159 spin_unlock(&ofd->ofd_lut.lut_translock);
160 tgt_server_data_write(info->fti_env, &ofd->ofd_lut, th);
163 *transno_p = info->fti_transno;
165 /* Although lightweight (LW) connections have no slot in
166 * last_rcvd, we still want to maintain the in-memory
167 * lsd_client_data structure in order to properly handle reply
169 struct lu_target *tg =&ofd->ofd_lut;
173 /* All operations performed by LW clients are synchronous and
174 * we store the committed transno in the last_rcvd header */
175 spin_lock(&tg->lut_translock);
176 if (info->fti_transno > tg->lut_lsd.lsd_last_transno) {
177 tg->lut_lsd.lsd_last_transno = info->fti_transno;
180 spin_unlock(&tg->lut_translock);
182 err = tgt_server_data_write(info->fti_env, tg, th);
184 LASSERT(fed->fed_ted.ted_lr_off > 0);
185 err = tgt_client_data_write(info->fti_env, &ofd->ofd_lut, lcd,
192 /* Update last_rcvd records with the latest transaction data */
193 int ofd_txn_stop_cb(const struct lu_env *env, struct thandle *txn,
196 struct ofd_device *ofd = cookie;
197 struct ofd_thread_info *info;
201 info = lu_context_key_get(&env->le_ctx, &ofd_thread_key);
203 if (info->fti_exp == NULL)
206 LASSERT(ofd_exp(info->fti_exp) == ofd);
207 if (info->fti_has_trans) {
208 if (info->fti_mult_trans == 0) {
209 CERROR("More than one transaction "LPU64"\n",
213 /* we need another transno to be assigned */
214 info->fti_transno = 0;
215 } else if (txn->th_result == 0) {
216 info->fti_has_trans = 1;
219 spin_lock(&ofd->ofd_lut.lut_translock);
220 if (txn->th_result != 0) {
221 if (info->fti_transno != 0) {
222 CERROR("Replay transno "LPU64" failed: rc %d\n",
223 info->fti_transno, txn->th_result);
224 info->fti_transno = 0;
226 } else if (info->fti_transno == 0) {
227 info->fti_transno = ++ofd->ofd_lut.lut_last_transno;
229 /* should be replay */
230 if (info->fti_transno > ofd->ofd_lut.lut_last_transno)
231 ofd->ofd_lut.lut_last_transno = info->fti_transno;
233 spin_unlock(&ofd->ofd_lut.lut_translock);
235 /** VBR: set new versions */
236 if (txn->th_result == 0 && info->fti_obj != NULL) {
237 dt_version_set(env, ofd_object_child(info->fti_obj),
238 info->fti_transno, txn);
239 info->fti_obj = NULL;
242 /* filling reply data */
243 CDEBUG(D_INODE, "transno = %llu, last_committed = %llu\n",
244 info->fti_transno, ofd_obd(ofd)->obd_last_committed);
246 /* if can't add callback, do sync write */
247 txn->th_sync = !!tgt_last_commit_cb_add(txn, &ofd->ofd_lut,
251 return ofd_last_rcvd_update(info, txn);