|
|
1.1 ! root 1: /* ! 2: dblspace_buffer.c ! 3: ! 4: DMSDOS CVF-FAT module: low-level buffered read-write access functions ! 5: ! 6: ****************************************************************************** ! 7: DMSDOS (compressed MSDOS filesystem support) for Linux ! 8: written 1995-1998 by Frank Gockel and Pavel Pisa ! 9: ! 10: (C) Copyright 1995-1998 by Frank Gockel ! 11: (C) Copyright 1996-1998 by Pavel Pisa ! 12: ! 13: Some code of dmsdos has been copied from the msdos filesystem ! 14: so there are the following additional copyrights: ! 15: ! 16: (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem) ! 17: (C) Copyright 1994,1995 by Jacques Gelinas (mmap code) ! 18: (C) Copyright 1992-1995 by Linus Torvalds ! 19: ! 20: DMSDOS was inspired by the THS filesystem (a simple doublespace ! 21: DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann. ! 22: ! 23: The DMSDOS code is distributed under the Gnu General Public Licence. ! 24: See file COPYING for details. ! 25: ****************************************************************************** ! 26: ! 27: */ ! 28: ! 29: #ifndef __KERNEL__ ! 30: #error This file needs __KERNEL__ ! 31: #endif ! 32: ! 33: #include <linux/fs.h> ! 34: #include <linux/msdos_fs.h> ! 35: #include <linux/sched.h> ! 36: #include <linux/kernel.h> ! 37: #include <linux/errno.h> ! 38: #include <linux/string.h> ! 39: #include <linux/stat.h> ! 40: #include <linux/mm.h> ! 41: #include <linux/malloc.h> ! 42: #include "dmsdos.h" ! 43: ! 44: /* This is just cut'n'paste from the fat fs original :) ! 45: We don't do a virtual sector translation here */ ! 46: ! 47: struct buffer_head *raw_bread ( ! 48: struct super_block *sb, ! 49: int block) ! 50: { ! 51: struct buffer_head *ret = NULL; ! 52: ! 53: /* Note that the blocksize is 512 or 1024, but the first read ! 54: is always of size 1024. Doing readahead may be counterproductive ! 55: or just plain wrong. */ ! 56: if (sb->s_blocksize == 512) { ! 57: ret = bread (sb->s_dev,block,512); ! 58: } else { ! 59: struct buffer_head *real = bread (sb->s_dev,block>>1,1024); ! 60: ! 61: if (real != NULL){ ! 62: ret = (struct buffer_head *) ! 63: kmalloc (sizeof(struct buffer_head), GFP_KERNEL); ! 64: if (ret != NULL) { ! 65: /* #Specification: msdos / strategy / special device / dummy blocks ! 66: Many special device (Scsi optical disk for one) use ! 67: larger hardware sector size. This allows for higher ! 68: capacity. ! 69: ! 70: Most of the time, the MsDOS file system that sit ! 71: on this device is totally unaligned. It use logically ! 72: 512 bytes sector size, with logical sector starting ! 73: in the middle of a hardware block. The bad news is ! 74: that a hardware sector may hold data own by two ! 75: different files. This means that the hardware sector ! 76: must be read, patch and written almost all the time. ! 77: ! 78: Needless to say that it kills write performance ! 79: on all OS. ! 80: ! 81: Internally the linux msdos fs is using 512 bytes ! 82: logical sector. When accessing such a device, we ! 83: allocate dummy buffer cache blocks, that we stuff ! 84: with the information of a real one (1k large). ! 85: ! 86: This strategy is used to hide this difference to ! 87: the core of the msdos fs. The slowdown is not ! 88: hidden though! ! 89: */ ! 90: /* ! 91: The memset is there only to catch errors. The msdos ! 92: fs is only using b_data ! 93: */ ! 94: memset (ret,0,sizeof(*ret)); ! 95: ret->b_data = real->b_data; ! 96: if (block & 1) ret->b_data += 512; ! 97: ret->b_next = real; ! 98: }else{ ! 99: brelse (real); ! 100: } ! 101: } ! 102: } ! 103: return ret; ! 104: } ! 105: struct buffer_head *raw_getblk ( ! 106: struct super_block *sb, ! 107: int block) ! 108: { ! 109: struct buffer_head *ret = NULL; ! 110: if (sb->s_blocksize == 512){ ! 111: ret = getblk (sb->s_dev,block,512); ! 112: }else{ ! 113: /* #Specification: msdos / special device / writing ! 114: A write is always preceded by a read of the complete block ! 115: (large hardware sector size). This defeat write performance. ! 116: There is a possibility to optimize this when writing large ! 117: chunk by making sure we are filling large block. Volunteer ? ! 118: */ ! 119: ret = raw_bread (sb,block); ! 120: } ! 121: return ret; ! 122: } ! 123: ! 124: void raw_brelse ( ! 125: struct super_block *sb, ! 126: struct buffer_head *bh) ! 127: { ! 128: if (bh != NULL){ ! 129: if (sb->s_blocksize == 512){ ! 130: brelse (bh); ! 131: }else{ ! 132: brelse (bh->b_next); ! 133: /* We can free the dummy because a new one is allocated at ! 134: each fat_getblk() and fat_bread(). ! 135: */ ! 136: kfree (bh); ! 137: } ! 138: } ! 139: } ! 140: ! 141: void raw_mark_buffer_dirty ( ! 142: struct super_block *sb, ! 143: struct buffer_head *bh, ! 144: int dirty_val) ! 145: { ! 146: ! 147: #ifdef DBL_WRITEACCESS ! 148: if (sb->s_blocksize != 512){ ! 149: bh = bh->b_next; ! 150: } ! 151: mark_buffer_dirty (bh,dirty_val); ! 152: #else ! 153: printk(KERN_NOTICE "DMSDOS: write access not compiled in, ignored\n"); ! 154: #endif ! 155: ! 156: } ! 157: ! 158: void raw_set_uptodate ( ! 159: struct super_block *sb, ! 160: struct buffer_head *bh, ! 161: int val) ! 162: { ! 163: if (sb->s_blocksize != 512){ ! 164: bh = bh->b_next; ! 165: } ! 166: mark_buffer_uptodate(bh, val); ! 167: } ! 168: int raw_is_uptodate ( ! 169: struct super_block *sb, ! 170: struct buffer_head *bh) ! 171: { ! 172: if (sb->s_blocksize != 512){ ! 173: bh = bh->b_next; ! 174: } ! 175: return buffer_uptodate(bh); ! 176: } ! 177: ! 178: /* we really need this for read-ahead */ ! 179: void raw_ll_rw_block ( ! 180: struct super_block *sb, ! 181: int opr, ! 182: int nbreq, ! 183: struct buffer_head *bh[32]) ! 184: { ! 185: if (sb->s_blocksize == 512){ ! 186: ll_rw_block(opr,nbreq,bh); ! 187: }else{ ! 188: struct buffer_head *tmp[32]; ! 189: int i; ! 190: for (i=0; i<nbreq; i++){ ! 191: tmp[i] = bh[i]->b_next; ! 192: } ! 193: ll_rw_block(opr,nbreq,tmp); ! 194: } ! 195: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.