13984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/* 23984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * undo_io.c --- This is the undo io manager that copies the old data that 33984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * copies the old data being overwritten into a tdb database 43984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 53984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Copyright IBM Corporation, 2007 63984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 73984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 83984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * %Begin-Header% 98558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * This file may be redistributed under the terms of the GNU Library 108558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * General Public License, version 2. 113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * %End-Header% 123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define _LARGEFILE_SOURCE 153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define _LARGEFILE64_SOURCE 163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <stdio.h> 183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <string.h> 193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#if HAVE_UNISTD_H 203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <unistd.h> 213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif 223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#if HAVE_ERRNO_H 233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <errno.h> 243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif 253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <fcntl.h> 263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <time.h> 273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef __linux__ 283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <sys/utsname.h> 293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif 303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#if HAVE_SYS_STAT_H 313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <sys/stat.h> 323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif 333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#if HAVE_SYS_TYPES_H 343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <sys/types.h> 353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif 363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#if HAVE_SYS_RESOURCE_H 373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <sys/resource.h> 383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif 393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include "tdb.h" 413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include "ext2_fs.h" 433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include "ext2fs.h" 443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef __GNUC__ 463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define ATTR(x) __attribute__(x) 473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#else 483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define ATTR(x) 493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif 503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/* 523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * For checking structure magic numbers... 533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define EXT2_CHECK_MAGIC(struct, code) \ 563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if ((struct)->magic != (code)) return (code) 573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstruct undo_private_data { 593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int magic; 603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt TDB_CONTEXT *tdb; 613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt char *tdb_file; 623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* The backing io channel */ 643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt io_channel real; 653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int tdb_data_size; 673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int tdb_written; 683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* to support offset in unix I/O manager */ 703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2_loff_t offset; 713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}; 723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_open(const char *name, int flags, io_channel *channel); 743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_close(io_channel channel); 753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_set_blksize(io_channel channel, int blksize); 763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_read_blk(io_channel channel, unsigned long block, 773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int count, void *data); 783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_write_blk(io_channel channel, unsigned long block, 793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int count, const void *data); 803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_flush(io_channel channel); 813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_write_byte(io_channel channel, unsigned long offset, 823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int size, const void *data); 833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_set_option(io_channel channel, const char *option, 843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt const char *arg); 853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic struct struct_io_manager struct_undo_manager = { 873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_ET_MAGIC_IO_MANAGER, 883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt "Undo I/O Manager", 893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt undo_open, 903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt undo_close, 913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt undo_set_blksize, 923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt undo_read_blk, 933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt undo_write_blk, 943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt undo_flush, 953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt undo_write_byte, 963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt undo_set_option 973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}; 983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtio_manager undo_io_manager = &struct_undo_manager; 1003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic io_manager undo_io_backing_manager ; 1013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic char *tdb_file; 1023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic int actual_size; 1033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic unsigned char mtime_key[] = "filesystem MTIME"; 1053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic unsigned char blksize_key[] = "filesystem BLKSIZE"; 1063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic unsigned char uuid_key[] = "filesystem UUID"; 1073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t set_undo_io_backing_manager(io_manager manager) 1093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 1103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* 1113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * We may want to do some validation later 1123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 1133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt undo_io_backing_manager = manager; 1143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return 0; 1153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 1163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t set_undo_io_backup_file(char *file_name) 1183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 1193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_file = strdup(file_name); 1203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (tdb_file == NULL) { 1223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return EXT2_ET_NO_MEMORY; 1233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 1243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return 0; 1263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 1273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t write_file_system_identity(io_channel undo_channel, 1293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt TDB_CONTEXT *tdb) 1303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 1313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode_t retval; 1323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt struct ext2_super_block super; 1333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt TDB_DATA tdb_key, tdb_data; 1343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt struct undo_private_data *data; 1353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt io_channel channel; 1363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int block_size ; 1373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data = (struct undo_private_data *) undo_channel->private_data; 1393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt channel = data->real; 1403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt block_size = channel->block_size; 1413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt io_channel_set_blksize(channel, SUPERBLOCK_OFFSET); 1433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = io_channel_read_blk(channel, 1, -SUPERBLOCK_SIZE, &super); 1443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) 1453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt goto err_out; 1463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* Write to tdb file in the file system byte order */ 1483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_key.dptr = mtime_key; 1493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_key.dsize = sizeof(mtime_key); 1503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_data.dptr = (unsigned char *) &(super.s_mtime); 1513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_data.dsize = sizeof(super.s_mtime); 1523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = tdb_store(tdb, tdb_key, tdb_data, TDB_INSERT); 1543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval == -1) { 1553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb); 1563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt goto err_out; 1573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 1583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_key.dptr = uuid_key; 1603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_key.dsize = sizeof(uuid_key); 1613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_data.dptr = (unsigned char *)&(super.s_uuid); 1623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_data.dsize = sizeof(super.s_uuid); 1633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = tdb_store(tdb, tdb_key, tdb_data, TDB_INSERT); 1653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval == -1) { 1663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb); 1673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 1683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterr_out: 1703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt io_channel_set_blksize(channel, block_size); 1713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 1723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 1733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t write_block_size(TDB_CONTEXT *tdb, int block_size) 1753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 1763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode_t retval; 1773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt TDB_DATA tdb_key, tdb_data; 1783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_key.dptr = blksize_key; 1803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_key.dsize = sizeof(blksize_key); 1813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_data.dptr = (unsigned char *)&(block_size); 1823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_data.dsize = sizeof(block_size); 1833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = tdb_store(tdb, tdb_key, tdb_data, TDB_INSERT); 1853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval == -1) { 1863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb); 1873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 1883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 1903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 1913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_write_tdb(io_channel channel, 1933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned long block, int count) 1943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 1963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int size, sz; 1973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned long block_num, backing_blk_num; 1983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode_t retval = 0; 1993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2_loff_t offset; 2003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt struct undo_private_data *data; 2013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt TDB_DATA tdb_key, tdb_data; 2023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned char *read_ptr; 2033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned long end_block; 2043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data = (struct undo_private_data *) channel->private_data; 2063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (data->tdb == NULL) { 2083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* 2093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Transaction database not initialized 2103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 2113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return 0; 2123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (count == 1) 2153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt size = channel->block_size; 2163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt else { 2173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (count < 0) 2183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt size = -count; 2193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt else 2203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt size = count * channel->block_size; 2213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* 2233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Data is stored in tdb database as blocks of tdb_data_size size 2243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * This helps in efficient lookup further. 2253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 2263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * We divide the disk to blocks of tdb_data_size. 2273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 2283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt offset = (block * channel->block_size) + data->offset ; 2293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt block_num = offset / data->tdb_data_size; 2303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt end_block = (offset + size) / data->tdb_data_size; 2313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_transaction_start(data->tdb); 2333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt while (block_num <= end_block ) { 2343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_key.dptr = (unsigned char *)&block_num; 2363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_key.dsize = sizeof(block_num); 2373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* 2383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Check if we have the record already 2393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 2403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (tdb_exists(data->tdb, tdb_key)) { 2413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* Try the next block */ 2423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt block_num++; 2433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt continue; 2443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* 2463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Read one block using the backing I/O manager 2473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * The backing I/O manager block size may be 2483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * different from the tdb_data_size. 2493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Also we need to recalcuate the block number with respect 2503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * to the backing I/O manager. 2513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 2523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt offset = block_num * data->tdb_data_size; 2533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt backing_blk_num = (offset - data->offset) / channel->block_size; 2543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt count = data->tdb_data_size + 2563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ((offset - data->offset) % channel->block_size); 2573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = ext2fs_get_mem(count, &read_ptr); 2583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) { 2593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_transaction_cancel(data->tdb); 2603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 2613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt memset(read_ptr, 0, count); 2643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt actual_size = 0; 2653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if ((count % channel->block_size) == 0) 2663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt sz = count / channel->block_size; 2673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt else 2683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt sz = -count; 2693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = io_channel_read_blk(data->real, backing_blk_num, 2703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt sz, read_ptr); 2713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) { 2723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval != EXT2_ET_SHORT_READ) { 2733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt free(read_ptr); 2743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_transaction_cancel(data->tdb); 2753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 2763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* 2783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * short read so update the record size 2793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * accordingly 2803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 2813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_data.dsize = actual_size; 2823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } else { 2833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_data.dsize = data->tdb_data_size; 2843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_data.dptr = read_ptr + 2863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ((offset - data->offset) % channel->block_size); 2873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef DEBUG 2883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt printf("Printing with key %ld data %x and size %d\n", 2893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt block_num, 2903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_data.dptr, 2913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_data.dsize); 2923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif 2933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!data->tdb_written) { 2943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data->tdb_written = 1; 2953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* Write the blocksize to tdb file */ 2963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = write_block_size(data->tdb, 2973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data->tdb_data_size); 2983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) { 2993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_transaction_cancel(data->tdb); 3003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = EXT2_ET_TDB_ERR_IO; 3013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt free(read_ptr); 3023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 3033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 3043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 3053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = tdb_store(data->tdb, tdb_key, tdb_data, TDB_INSERT); 3063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval == -1) { 3073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* 3083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * TDB_ERR_EXISTS cannot happen because we 3093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * have already verified it doesn't exist 3103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 3113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_transaction_cancel(data->tdb); 3123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = EXT2_ET_TDB_ERR_IO; 3133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt free(read_ptr); 3143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 3153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 3163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt free(read_ptr); 3173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* Next block */ 3183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt block_num++; 3193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 3203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_transaction_commit(data->tdb); 3213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 3233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 3243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_io_read_error(io_channel channel ATTR((unused)), 3263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned long block ATTR((unused)), 3273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int count ATTR((unused)), 3283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt void *data ATTR((unused)), 3293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt size_t size ATTR((unused)), 3303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int actual, 3313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode_t error ATTR((unused))) 3323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 3333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt actual_size = actual; 3343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return error; 3353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 3363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic void undo_err_handler_init(io_channel channel) 3383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 3393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt channel->read_error = undo_io_read_error; 3403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 3413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_open(const char *name, int flags, io_channel *channel) 3433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 3443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt io_channel io = NULL; 3453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt struct undo_private_data *data = NULL; 3463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode_t retval; 3473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (name == 0) 3493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return EXT2_ET_BAD_DEVICE_NAME; 3503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); 3513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) 3523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 3533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt memset(io, 0, sizeof(struct struct_io_channel)); 3543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt io->magic = EXT2_ET_MAGIC_IO_CHANNEL; 3553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = ext2fs_get_mem(sizeof(struct undo_private_data), &data); 3563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) 3573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt goto cleanup; 3583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt io->manager = undo_io_manager; 3603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = ext2fs_get_mem(strlen(name)+1, &io->name); 3613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) 3623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt goto cleanup; 3633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt strcpy(io->name, name); 3653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt io->private_data = data; 3663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt io->block_size = 1024; 3673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt io->read_error = 0; 3683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt io->write_error = 0; 3693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt io->refcount = 1; 3703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt memset(data, 0, sizeof(struct undo_private_data)); 3723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; 3733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (undo_io_backing_manager) { 3753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = undo_io_backing_manager->open(name, flags, 3763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt &data->real); 3773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) 3783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt goto cleanup; 3793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } else { 3803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data->real = 0; 3813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 3823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* setup the tdb file */ 3843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data->tdb = tdb_open(tdb_file, 0, TDB_CLEAR_IF_FIRST, 3853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600); 3863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!data->tdb) { 3873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = errno; 3883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt goto cleanup; 3893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 3903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* 3923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * setup err handler for read so that we know 3933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * when the backing manager fails do short read 3943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 3953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt undo_err_handler_init(data->real); 3963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *channel = io; 3983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return 0; 3993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtcleanup: 4013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (data->real) 4023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt io_channel_close(data->real); 4033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (data) 4043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_free_mem(&data); 4053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (io) 4063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_free_mem(&io); 4073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 4083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 4093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_close(io_channel channel) 4113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 4123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt struct undo_private_data *data; 4133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode_t retval = 0; 4143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 4163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data = (struct undo_private_data *) channel->private_data; 4173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 4183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (--channel->refcount > 0) 4203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return 0; 4213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* Before closing write the file system identity */ 4223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = write_file_system_identity(channel, data->tdb); 4233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) 4243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 4253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (data->real) 4263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = io_channel_close(data->real); 4273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (data->tdb) 4283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tdb_close(data->tdb); 4293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_free_mem(&channel->private_data); 4303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (channel->name) 4313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_free_mem(&channel->name); 4323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_free_mem(&channel); 4333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 4353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 4363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_set_blksize(io_channel channel, int blksize) 4383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 4393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt struct undo_private_data *data; 4403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode_t retval = 0; 4413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 4433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data = (struct undo_private_data *) channel->private_data; 4443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 4453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (data->real) 4473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = io_channel_set_blksize(data->real, blksize); 4483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* 4493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Set the block size used for tdb 4503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 4513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!data->tdb_data_size) { 4523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data->tdb_data_size = blksize; 4533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 4543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt channel->block_size = blksize; 4553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 4563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 4573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_read_blk(io_channel channel, unsigned long block, 4593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int count, void *buf) 4603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 4613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode_t retval = 0; 4623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt struct undo_private_data *data; 4633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 4653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data = (struct undo_private_data *) channel->private_data; 4663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 4673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (data->real) 4693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = io_channel_read_blk(data->real, block, count, buf); 4703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 4723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 4733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_write_blk(io_channel channel, unsigned long block, 4753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int count, const void *buf) 4763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 4773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt struct undo_private_data *data; 4783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode_t retval = 0; 4793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 4813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data = (struct undo_private_data *) channel->private_data; 4823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 4833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* 4843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * First write the existing content into database 4853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 4863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = undo_write_tdb(channel, block, count); 4873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) 4883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 4893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (data->real) 4903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = io_channel_write_blk(data->real, block, count, buf); 4913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 4933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 4943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 4953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_write_byte(io_channel channel, unsigned long offset, 4963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int size, const void *buf) 4973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 4983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt struct undo_private_data *data; 4993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode_t retval = 0; 5003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2_loff_t location; 5013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned long blk_num, count;; 5023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 5043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data = (struct undo_private_data *) channel->private_data; 5053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 5063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt location = offset + data->offset; 5083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt blk_num = location/channel->block_size; 5093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* 5103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * the size specified may spread across multiple blocks 5113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * also make sure we account for the fact that block start 5123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * offset for tdb is different from the backing I/O manager 5133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * due to possible different block size 5143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 5153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt count = (size + (location % channel->block_size) + 5163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt channel->block_size -1)/channel->block_size; 5173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = undo_write_tdb(channel, blk_num, count); 5183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) 5193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 5203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (data->real && data->real->manager->write_byte) 5213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = io_channel_write_byte(data->real, offset, size, buf); 5223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 5243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 5253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/* 5273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Flush data buffers to disk. 5283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 5293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_flush(io_channel channel) 5303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 5313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode_t retval = 0; 5323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt struct undo_private_data *data; 5333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 5353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data = (struct undo_private_data *) channel->private_data; 5363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 5373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (data->real) 5393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = io_channel_flush(data->real); 5403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 5423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 5433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic errcode_t undo_set_option(io_channel channel, const char *option, 5453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt const char *arg) 5463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 5473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode_t retval = 0; 5483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt struct undo_private_data *data; 5493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt unsigned long tmp; 5503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt char *end; 5513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 5533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data = (struct undo_private_data *) channel->private_data; 5543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); 5553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!strcmp(option, "tdb_data_size")) { 5573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!arg) 5583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return EXT2_ET_INVALID_ARGUMENT; 5593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tmp = strtoul(arg, &end, 0); 5613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (*end) 5623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return EXT2_ET_INVALID_ARGUMENT; 5633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!data->tdb_data_size || !data->tdb_written) { 5643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data->tdb_data_size = tmp; 5653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 5663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return 0; 5673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 5683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* 5693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Need to support offset option to work with 5703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Unix I/O manager 5713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 5723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (data->real && data->real->manager->set_option) { 5733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = data->real->manager->set_option(data->real, 5743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt option, arg); 5753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 5763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!retval && !strcmp(option, "offset")) { 5773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!arg) 5783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return EXT2_ET_INVALID_ARGUMENT; 5793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt tmp = strtoul(arg, &end, 0); 5813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (*end) 5823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return EXT2_ET_INVALID_ARGUMENT; 5833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt data->offset = tmp; 5843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 5853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 5863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 587