llog_lvfs.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 927 行 · 第 1/3 页
C
927 行
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * Copyright (C) 2001-2003 Cluster File Systems, Inc. * Author: Andreas Dilger <adilger@clusterfs.com> * * This file is part of the Lustre file system, http://www.lustre.org * Lustre is a trademark of Cluster File Systems, Inc. * * You may have signed or agreed to another license before downloading * this software. If so, you are bound by the terms and conditions * of that agreement, and the following does not apply to you. See the * LICENSE file included with this distribution for more information. * * If you did not agree to a different license, then this copy of Lustre * is open source software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * In either case, Lustre is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * license text for more details. * * OST<->MDS recovery logging infrastructure. * * Invariants in implementation: * - we do not share logs among different OST<->MDS connections, so that * if an OST or MDS fails it need only look at log(s) relevant to itself */#define DEBUG_SUBSYSTEM S_LOG#ifndef EXPORT_SYMTAB#define EXPORT_SYMTAB#endif#ifndef __KERNEL__#include <liblustre.h>#endif#include <obd.h>#include <obd_class.h>#include <lustre_log.h>#include <obd_ost.h>#include <libcfs/list.h>#include <lvfs.h>#include <lustre_fsfilt.h>#include <lustre_disk.h>#include "llog_internal.h"#if defined(__KERNEL__) && defined(LLOG_LVFS)static int llog_lvfs_pad(struct obd_device *obd, struct l_file *file, int len, int index){ struct llog_rec_hdr rec = { 0 }; struct llog_rec_tail tail; int rc; ENTRY; LASSERT(len >= LLOG_MIN_REC_SIZE && (len & 0x7) == 0); tail.lrt_len = rec.lrh_len = len; tail.lrt_index = rec.lrh_index = index; rec.lrh_type = LLOG_PAD_MAGIC; rc = fsfilt_write_record(obd, file, &rec, sizeof(rec), &file->f_pos, 0); if (rc) { CERROR("error writing padding record: rc %d\n", rc); goto out; } file->f_pos += len - sizeof(rec) - sizeof(tail); rc = fsfilt_write_record(obd, file, &tail, sizeof(tail),&file->f_pos,0); if (rc) { CERROR("error writing padding record: rc %d\n", rc); goto out; } out: RETURN(rc);}static int llog_lvfs_write_blob(struct obd_device *obd, struct l_file *file, struct llog_rec_hdr *rec, void *buf, loff_t off){ int rc; struct llog_rec_tail end; loff_t saved_off = file->f_pos; int buflen = rec->lrh_len; ENTRY; file->f_pos = off; if (buflen == 0) CWARN("0-length record\n"); if (!buf) { rc = fsfilt_write_record(obd, file, rec, buflen,&file->f_pos,0); if (rc) { CERROR("error writing log record: rc %d\n", rc); goto out; } GOTO(out, rc = 0); } /* the buf case */ rec->lrh_len = sizeof(*rec) + buflen + sizeof(end); rc = fsfilt_write_record(obd, file, rec, sizeof(*rec), &file->f_pos, 0); if (rc) { CERROR("error writing log hdr: rc %d\n", rc); goto out; } rc = fsfilt_write_record(obd, file, buf, buflen, &file->f_pos, 0); if (rc) { CERROR("error writing log buffer: rc %d\n", rc); goto out; } end.lrt_len = rec->lrh_len; end.lrt_index = rec->lrh_index; rc = fsfilt_write_record(obd, file, &end, sizeof(end), &file->f_pos, 0); if (rc) { CERROR("error writing log tail: rc %d\n", rc); goto out; } rc = 0; out: if (saved_off > file->f_pos) file->f_pos = saved_off; LASSERT(rc <= 0); RETURN(rc);}static int llog_lvfs_read_blob(struct obd_device *obd, struct l_file *file, void *buf, int size, loff_t off){ loff_t offset = off; int rc; ENTRY; rc = fsfilt_read_record(obd, file, buf, size, &offset); if (rc) { CERROR("error reading log record: rc %d\n", rc); RETURN(rc); } RETURN(0);}static int llog_lvfs_read_header(struct llog_handle *handle){ struct obd_device *obd; int rc; ENTRY; LASSERT(sizeof(*handle->lgh_hdr) == LLOG_CHUNK_SIZE); obd = handle->lgh_ctxt->loc_exp->exp_obd; if (i_size_read(handle->lgh_file->f_dentry->d_inode) == 0) { CDEBUG(D_RPCTRACE, "not reading header from 0-byte log\n"); RETURN(LLOG_EEMPTY); } rc = llog_lvfs_read_blob(obd, handle->lgh_file, handle->lgh_hdr, LLOG_CHUNK_SIZE, 0); if (rc) { CERROR("error reading log header from %.*s\n", handle->lgh_file->f_dentry->d_name.len, handle->lgh_file->f_dentry->d_name.name); } else { struct llog_rec_hdr *llh_hdr = &handle->lgh_hdr->llh_hdr; if (LLOG_REC_HDR_NEEDS_SWABBING(llh_hdr)) lustre_swab_llog_hdr(handle->lgh_hdr); if (llh_hdr->lrh_type != LLOG_HDR_MAGIC) { CERROR("bad log %.*s header magic: %#x (expected %#x)\n", handle->lgh_file->f_dentry->d_name.len, handle->lgh_file->f_dentry->d_name.name, llh_hdr->lrh_type, LLOG_HDR_MAGIC); rc = -EIO; } else if (llh_hdr->lrh_len != LLOG_CHUNK_SIZE) { CERROR("incorrectly sized log %.*s header: %#x " "(expected %#x)\n", handle->lgh_file->f_dentry->d_name.len, handle->lgh_file->f_dentry->d_name.name, llh_hdr->lrh_len, LLOG_CHUNK_SIZE); CERROR("you may need to re-run lconf --write_conf.\n"); rc = -EIO; } } handle->lgh_last_idx = handle->lgh_hdr->llh_tail.lrt_index; handle->lgh_file->f_pos = i_size_read(handle->lgh_file->f_dentry->d_inode); RETURN(rc);}/* returns negative in on error; 0 if success && reccookie == 0; 1 otherwise *//* appends if idx == -1, otherwise overwrites record idx. */static int llog_lvfs_write_rec(struct llog_handle *loghandle, struct llog_rec_hdr *rec, struct llog_cookie *reccookie, int cookiecount, void *buf, int idx){ struct llog_log_hdr *llh; int reclen = rec->lrh_len, index, rc; struct llog_rec_tail *lrt; struct obd_device *obd; struct file *file; size_t left; ENTRY; llh = loghandle->lgh_hdr; file = loghandle->lgh_file; obd = loghandle->lgh_ctxt->loc_exp->exp_obd; /* record length should not bigger than LLOG_CHUNK_SIZE */ if (buf) rc = (reclen > LLOG_CHUNK_SIZE - sizeof(struct llog_rec_hdr) - sizeof(struct llog_rec_tail)) ? -E2BIG : 0; else rc = (reclen > LLOG_CHUNK_SIZE) ? -E2BIG : 0; if (rc) RETURN(rc); if (buf) /* write_blob adds header and tail to lrh_len. */ reclen = sizeof(*rec) + rec->lrh_len + sizeof(struct llog_rec_tail); if (idx != -1) { loff_t saved_offset; /* no header: only allowed to insert record 1 */ if (idx != 1 && !i_size_read(file->f_dentry->d_inode)) { CERROR("idx != -1 in empty log\n"); LBUG(); } if (idx && llh->llh_size && llh->llh_size != rec->lrh_len) RETURN(-EINVAL); if (!ext2_test_bit(idx, llh->llh_bitmap)) CERROR("Modify unset record %u\n", idx); if (idx != rec->lrh_index) CERROR("Index mismatch %d %u\n", idx, rec->lrh_index); rc = llog_lvfs_write_blob(obd, file, &llh->llh_hdr, NULL, 0); /* we are done if we only write the header or on error */ if (rc || idx == 0) RETURN(rc); /* Assumes constant lrh_len */ saved_offset = sizeof(*llh) + (idx - 1) * reclen; if (buf) { struct llog_rec_hdr check; /* We assume that caller has set lgh_cur_* */ saved_offset = loghandle->lgh_cur_offset; CDEBUG(D_OTHER, "modify record "LPX64": idx:%d/%u/%d, len:%u " "offset %llu\n", loghandle->lgh_id.lgl_oid, idx, rec->lrh_index, loghandle->lgh_cur_idx, rec->lrh_len, (long long)(saved_offset - sizeof(*llh))); if (rec->lrh_index != loghandle->lgh_cur_idx) { CERROR("modify idx mismatch %u/%d\n", idx, loghandle->lgh_cur_idx); RETURN(-EFAULT); }#if 1 /* FIXME remove this safety check at some point */ /* Verify that the record we're modifying is the right one. */ rc = llog_lvfs_read_blob(obd, file, &check, sizeof(check), saved_offset); if (check.lrh_index != idx || check.lrh_len != reclen) { CERROR("Bad modify idx %u/%u size %u/%u (%d)\n", idx, check.lrh_index, reclen, check.lrh_len, rc); RETURN(-EFAULT); }#endif } rc = llog_lvfs_write_blob(obd, file, rec, buf, saved_offset); if (rc == 0 && reccookie) { reccookie->lgc_lgl = loghandle->lgh_id; reccookie->lgc_index = idx; rc = 1; } RETURN(rc); } /* Make sure that records don't cross a chunk boundary, so we can * process them page-at-a-time if needed. If it will cross a chunk * boundary, write in a fake (but referenced) entry to pad the chunk. * * We know that llog_current_log() will return a loghandle that is * big enough to hold reclen, so all we care about is padding here. */ left = LLOG_CHUNK_SIZE - (file->f_pos & (LLOG_CHUNK_SIZE - 1)); /* NOTE: padding is a record, but no bit is set */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?