/* -*- mode: c; c-basic-offset: 8; -*- * vim: noexpandtab sw=8 ts=8 sts=0: * * mark_journal_dirty.c * * Marks the journal for a given slot # as dirty. * * Copyright (C) 2005 Oracle. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License, version 2, as published by the Free Software Foundation. * * This program 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 GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 021110-1307, USA. * * Authors: Mark Fasheh */ #define _XOPEN_SOURCE 600 /* Triggers magic in features.h */ #define _LARGEFILE64_SOURCE #include #include #include #include #include "ocfs2/byteorder.h" #include "ocfs2/ocfs2.h" static int debug = 0; static void print_usage(void) { fprintf(stderr, "Usage: mark_journal_dirty \n"); fprintf(stderr, "Will insert node into slot and " "mark the journal in as needing recovery.\n"); } static errcode_t mark_journal(ocfs2_filesys *fs, uint64_t blkno) { errcode_t ret; char *buf = NULL; struct ocfs2_dinode *di; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) return ret; ret = ocfs2_read_inode(fs, blkno, buf); if (ret) goto out_free; di = (struct ocfs2_dinode *) buf; if (!(di->i_flags & OCFS2_JOURNAL_FL)) { ret = OCFS2_ET_INVALID_ARGUMENT; fprintf(stderr, "Block %"PRIu64" is not a journal inode!\n", blkno); goto out_free; } di->id1.journal1.ij_flags |= OCFS2_JOURNAL_DIRTY_FL; ret = ocfs2_write_inode(fs, blkno, buf); out_free: ocfs2_free(&buf); return ret; } static errcode_t write_back_slot_map(ocfs2_filesys *fs, uint64_t slot_map_blkno, char *slots_buf) { errcode_t ret; char *di_buf = NULL; struct ocfs2_dinode *di; uint64_t block; struct ocfs2_extent_list *el; ret = ocfs2_malloc_block(fs->fs_io, &di_buf); if (ret) return ret; ret = ocfs2_read_inode(fs, slot_map_blkno, di_buf); if (ret) goto out_free; di = (struct ocfs2_dinode *) di_buf; el = &di->id2.i_list; block = el->l_recs[0].e_blkno; if (el->l_tree_depth || !block) { ret = OCFS2_ET_INVALID_EXTENT_LOOKUP; goto out_free; } if (debug) fprintf(stdout, "Write back slot data at block %"PRIu64"\n", block); ret = io_write_block(fs->fs_io, block, 1, slots_buf); out_free: ocfs2_free(&di_buf); return ret; } static errcode_t insert_node_into_slot(ocfs2_filesys *fs, int node, int slot) { errcode_t ret; int i, num_slots; char *buf = NULL; uint64_t slot_map_blkno; int len = fs->fs_blocksize; int16_t *slots; ret = ocfs2_lookup_system_inode(fs, SLOT_MAP_SYSTEM_INODE, -1, &slot_map_blkno); if (ret) goto out; ret = ocfs2_read_whole_file(fs, slot_map_blkno, &buf, &len); if (ret) goto out; num_slots = fs->fs_super->id2.i_super.s_max_slots; if (debug) fprintf(stdout, "%d slots on this device\n", num_slots); if (len < fs->fs_blocksize) { ret = OCFS2_ET_SHORT_READ; goto out; } slots = (int16_t *) buf; /* We'll allow the caller to put a different node in a * currently filled slot, but we must watch out for duplicate * nodes in slots. */ for(i = 0; i < num_slots; i++) { if (le16_to_cpu(slots[i]) == node) { ret = OCFS2_ET_INTERNAL_FAILURE; fprintf(stdout, "node %d already found in slot_map " "slot %d\n", node, i); goto out; } } slots[slot] = cpu_to_le16(node); ret = write_back_slot_map(fs, slot_map_blkno, buf); out: return ret; } static unsigned int read_number(const char *num) { unsigned long val; char *ptr; val = strtoul(num, &ptr, 0); if (!ptr || *ptr) return -1; return (unsigned int) val; } extern int opterr, optind; extern char *optarg; int main(int argc, char *argv[]) { errcode_t ret; int slot, node; uint64_t journal_blkno; char *filename; ocfs2_filesys *fs; initialize_ocfs_error_table(); if (argc < 4) { fprintf(stderr, "Missing parameters\n"); print_usage(); return 1; } filename = argv[1]; node = read_number(argv[2]); if (node == -1) { fprintf(stderr, "invalid node number\n"); print_usage(); return 1; } slot = read_number(argv[3]); if (slot == -1) { fprintf(stderr, "invalid slot number\n"); print_usage(); return 1; } ret = ocfs2_open(filename, OCFS2_FLAG_RW, 0, 0, &fs); if (ret) { com_err(argv[0], ret, "while opening file \"%s\"", filename); goto out_close; } if (debug) fprintf(stdout, "Inserting node %d into slot %d\n", node, slot); ret = insert_node_into_slot(fs, node, slot); if (ret) { com_err(argv[0], ret, "while inserting node\n"); goto out_close; } ret = ocfs2_lookup_system_inode(fs, JOURNAL_SYSTEM_INODE, slot, &journal_blkno); if (ret) { com_err(argv[0], ret, "while looking up journal in slot %d\n", slot); goto out_close; } if (debug) fprintf(stdout, "Marking journal (block %"PRIu64") in slot " "%d\n", journal_blkno, slot); ret = mark_journal(fs, journal_blkno); if (ret) { com_err(argv[0], ret, "while marking journal dirty"); goto out_close; } out_close: ret = ocfs2_close(fs); if (ret) { com_err(argv[0], ret, "while closing file \"%s\"", filename); } return 0; }