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 + -
显示快捷键?