1433d6423SLionel Sambuc /* Created (MFS based):
2433d6423SLionel Sambuc * February 2010 (Evgeniy Ivanov)
3433d6423SLionel Sambuc */
4433d6423SLionel Sambuc
5433d6423SLionel Sambuc #include "fs.h"
6433d6423SLionel Sambuc #include "buf.h"
7433d6423SLionel Sambuc #include "inode.h"
8433d6423SLionel Sambuc #include "super.h"
9433d6423SLionel Sambuc
10433d6423SLionel Sambuc
11433d6423SLionel Sambuc /*===========================================================================*
12*6c46a77dSDavid van Moolenbroek * get_block *
13*6c46a77dSDavid van Moolenbroek *===========================================================================*/
get_block(dev_t dev,block_t block,int how)14*6c46a77dSDavid van Moolenbroek struct buf *get_block(dev_t dev, block_t block, int how)
15*6c46a77dSDavid van Moolenbroek {
16*6c46a77dSDavid van Moolenbroek /* Wrapper routine for lmfs_get_block(). This ext2 implementation does not deal
17*6c46a77dSDavid van Moolenbroek * well with block read errors pretty much anywhere. To prevent corruption due
18*6c46a77dSDavid van Moolenbroek * to unchecked error conditions, we panic upon an I/O failure here.
19*6c46a77dSDavid van Moolenbroek */
20*6c46a77dSDavid van Moolenbroek struct buf *bp;
21*6c46a77dSDavid van Moolenbroek int r;
22*6c46a77dSDavid van Moolenbroek
23*6c46a77dSDavid van Moolenbroek if ((r = lmfs_get_block(&bp, dev, block, how)) != OK && r != ENOENT)
24*6c46a77dSDavid van Moolenbroek panic("ext2: error getting block (%llu,%u): %d", dev, block, r);
25*6c46a77dSDavid van Moolenbroek
26*6c46a77dSDavid van Moolenbroek assert(r == OK || how == PEEK);
27*6c46a77dSDavid van Moolenbroek
28*6c46a77dSDavid van Moolenbroek return (r == OK) ? bp : NULL;
29*6c46a77dSDavid van Moolenbroek }
30*6c46a77dSDavid van Moolenbroek
31*6c46a77dSDavid van Moolenbroek
32*6c46a77dSDavid van Moolenbroek
33*6c46a77dSDavid van Moolenbroek /*===========================================================================*
34433d6423SLionel Sambuc * conv2 *
35433d6423SLionel Sambuc *===========================================================================*/
conv2(norm,w)36433d6423SLionel Sambuc unsigned conv2(norm, w)
37433d6423SLionel Sambuc int norm; /* TRUE if no swap, FALSE for byte swap */
38433d6423SLionel Sambuc int w; /* promotion of 16-bit word to be swapped */
39433d6423SLionel Sambuc {
40433d6423SLionel Sambuc /* Possibly swap a 16-bit word between 8086 and 68000 byte order. */
41433d6423SLionel Sambuc if (norm) return( (unsigned) w & 0xFFFF);
42433d6423SLionel Sambuc return( ((w&BYTE) << 8) | ( (w>>8) & BYTE));
43433d6423SLionel Sambuc }
44433d6423SLionel Sambuc
45433d6423SLionel Sambuc
46433d6423SLionel Sambuc /*===========================================================================*
47433d6423SLionel Sambuc * conv4 *
48433d6423SLionel Sambuc *===========================================================================*/
conv4(norm,x)49433d6423SLionel Sambuc long conv4(norm, x)
50433d6423SLionel Sambuc int norm; /* TRUE if no swap, FALSE for byte swap */
51433d6423SLionel Sambuc long x; /* 32-bit long to be byte swapped */
52433d6423SLionel Sambuc {
53433d6423SLionel Sambuc /* Possibly swap a 32-bit long between 8086 and 68000 byte order. */
54433d6423SLionel Sambuc unsigned lo, hi;
55433d6423SLionel Sambuc long l;
56433d6423SLionel Sambuc
57433d6423SLionel Sambuc if (norm) return(x); /* byte order was already ok */
58433d6423SLionel Sambuc lo = conv2(FALSE, (int) x & 0xFFFF); /* low-order half, byte swapped */
59433d6423SLionel Sambuc hi = conv2(FALSE, (int) (x>>16) & 0xFFFF); /* high-order half, swapped */
60433d6423SLionel Sambuc l = ( (long) lo <<16) | hi;
61433d6423SLionel Sambuc return(l);
62433d6423SLionel Sambuc }
63433d6423SLionel Sambuc
64433d6423SLionel Sambuc
65433d6423SLionel Sambuc /*===========================================================================*
66433d6423SLionel Sambuc * ansi_strcmp *
67433d6423SLionel Sambuc *===========================================================================*/
ansi_strcmp(register const char * ansi_s,register const char * s2,register size_t ansi_s_length)68433d6423SLionel Sambuc int ansi_strcmp(register const char* ansi_s, register const char *s2,
69433d6423SLionel Sambuc register size_t ansi_s_length)
70433d6423SLionel Sambuc {
71433d6423SLionel Sambuc /* Compare non null-terminated string ansi_s (length=ansi_s_length)
72433d6423SLionel Sambuc * with C-string s2.
73433d6423SLionel Sambuc * It returns 0 if strings are equal, otherwise -1 is returned.
74433d6423SLionel Sambuc */
75433d6423SLionel Sambuc if (ansi_s_length) {
76433d6423SLionel Sambuc do {
77433d6423SLionel Sambuc if (*s2 == '\0')
78433d6423SLionel Sambuc return -1;
79433d6423SLionel Sambuc if (*ansi_s++ != *s2++)
80433d6423SLionel Sambuc return -1;
81433d6423SLionel Sambuc } while (--ansi_s_length > 0);
82433d6423SLionel Sambuc
83433d6423SLionel Sambuc if (*s2 == '\0')
84433d6423SLionel Sambuc return 0;
85433d6423SLionel Sambuc else
86433d6423SLionel Sambuc return -1;
87433d6423SLionel Sambuc }
88433d6423SLionel Sambuc return 0;
89433d6423SLionel Sambuc }
90433d6423SLionel Sambuc
91433d6423SLionel Sambuc
92433d6423SLionel Sambuc /*===========================================================================*
93433d6423SLionel Sambuc * setbit *
94433d6423SLionel Sambuc *===========================================================================*/
setbit(bitchunk_t * bitmap,bit_t max_bits,unsigned int word)95433d6423SLionel Sambuc bit_t setbit(bitchunk_t *bitmap, bit_t max_bits, unsigned int word)
96433d6423SLionel Sambuc {
97433d6423SLionel Sambuc /* Find free bit in bitmap and set. Return number of the bit,
98433d6423SLionel Sambuc * if failed return -1.
99433d6423SLionel Sambuc */
100433d6423SLionel Sambuc bitchunk_t *wptr, *wlim;
101433d6423SLionel Sambuc bit_t b = -1;
102433d6423SLionel Sambuc
103433d6423SLionel Sambuc /* TODO: do we need to add 1? I saw a situation, when it was
104433d6423SLionel Sambuc * required, and since we check bit number with max_bits it
105433d6423SLionel Sambuc * should be safe.
106433d6423SLionel Sambuc */
107433d6423SLionel Sambuc wlim = &bitmap[FS_BITMAP_CHUNKS(max_bits >> 3)];
108433d6423SLionel Sambuc
109433d6423SLionel Sambuc /* Iterate over the words in block. */
110433d6423SLionel Sambuc for (wptr = &bitmap[word]; wptr < wlim; wptr++) {
111433d6423SLionel Sambuc bit_t i;
112433d6423SLionel Sambuc bitchunk_t k;
113433d6423SLionel Sambuc
114433d6423SLionel Sambuc /* Does this word contain a free bit? */
115433d6423SLionel Sambuc if (*wptr == (bitchunk_t) ~0)
116433d6423SLionel Sambuc continue;
117433d6423SLionel Sambuc
118433d6423SLionel Sambuc /* Find and allocate the free bit. */
119433d6423SLionel Sambuc k = (int) *wptr;
120433d6423SLionel Sambuc for (i = 0; (k & (1 << i)) != 0; ++i) {}
121433d6423SLionel Sambuc
122433d6423SLionel Sambuc /* Bit number from the start of the bit map. */
123433d6423SLionel Sambuc b = (wptr - &bitmap[0]) * FS_BITCHUNK_BITS + i;
124433d6423SLionel Sambuc
125433d6423SLionel Sambuc /* Don't allocate bits beyond the end of the map. */
126433d6423SLionel Sambuc if (b >= max_bits) {
127433d6423SLionel Sambuc b = -1;
128433d6423SLionel Sambuc continue;
129433d6423SLionel Sambuc }
130433d6423SLionel Sambuc
131433d6423SLionel Sambuc /* Allocate bit number. */
132433d6423SLionel Sambuc k |= 1 << i;
133433d6423SLionel Sambuc *wptr = (int) k;
134433d6423SLionel Sambuc break;
135433d6423SLionel Sambuc }
136433d6423SLionel Sambuc
137433d6423SLionel Sambuc return b;
138433d6423SLionel Sambuc }
139433d6423SLionel Sambuc
140433d6423SLionel Sambuc
141433d6423SLionel Sambuc /*===========================================================================*
142433d6423SLionel Sambuc * setbyte *
143433d6423SLionel Sambuc *===========================================================================*/
setbyte(bitchunk_t * bitmap,bit_t max_bits)144433d6423SLionel Sambuc bit_t setbyte(bitchunk_t *bitmap, bit_t max_bits)
145433d6423SLionel Sambuc {
146433d6423SLionel Sambuc /* Find free byte in bitmap and set it. Return number of the starting bit,
147433d6423SLionel Sambuc * if failed return -1.
148433d6423SLionel Sambuc */
149433d6423SLionel Sambuc unsigned char *wptr, *wlim;
150433d6423SLionel Sambuc bit_t b = -1;
151433d6423SLionel Sambuc
152433d6423SLionel Sambuc wptr = (unsigned char*) &bitmap[0];
153433d6423SLionel Sambuc /* TODO: do we need to add 1? I saw a situation, when it was
154433d6423SLionel Sambuc * required, and since we check bit number with max_bits it
155433d6423SLionel Sambuc * should be safe.
156433d6423SLionel Sambuc */
157433d6423SLionel Sambuc wlim = &wptr[(max_bits >> 3)];
158433d6423SLionel Sambuc
159433d6423SLionel Sambuc /* Iterate over the words in block. */
160433d6423SLionel Sambuc for ( ; wptr < wlim; wptr++) {
161433d6423SLionel Sambuc /* Is it a free byte? */
162433d6423SLionel Sambuc if (*wptr | 0)
163433d6423SLionel Sambuc continue;
164433d6423SLionel Sambuc
165433d6423SLionel Sambuc /* Bit number from the start of the bit map. */
166433d6423SLionel Sambuc b = (wptr - (unsigned char*) &bitmap[0]) * CHAR_BIT;
167433d6423SLionel Sambuc
168433d6423SLionel Sambuc /* Don't allocate bits beyond the end of the map. */
169433d6423SLionel Sambuc if (b + CHAR_BIT >= max_bits) {
170433d6423SLionel Sambuc b = -1;
171433d6423SLionel Sambuc continue;
172433d6423SLionel Sambuc }
173433d6423SLionel Sambuc
174433d6423SLionel Sambuc /* Allocate byte number. */
175433d6423SLionel Sambuc *wptr = (unsigned char) ~0;
176433d6423SLionel Sambuc break;
177433d6423SLionel Sambuc }
178433d6423SLionel Sambuc return b;
179433d6423SLionel Sambuc }
180433d6423SLionel Sambuc
181433d6423SLionel Sambuc
182433d6423SLionel Sambuc /*===========================================================================*
183433d6423SLionel Sambuc * unsetbit *
184433d6423SLionel Sambuc *===========================================================================*/
unsetbit(bitchunk_t * bitmap,bit_t bit)185433d6423SLionel Sambuc int unsetbit(bitchunk_t *bitmap, bit_t bit)
186433d6423SLionel Sambuc {
187433d6423SLionel Sambuc /* Unset specified bit. If requested bit is already free return -1,
188433d6423SLionel Sambuc * otherwise return 0.
189433d6423SLionel Sambuc */
190433d6423SLionel Sambuc unsigned int word; /* bit_returned word in bitmap */
191433d6423SLionel Sambuc bitchunk_t k, mask;
192433d6423SLionel Sambuc
193433d6423SLionel Sambuc word = bit / FS_BITCHUNK_BITS;
194433d6423SLionel Sambuc bit = bit % FS_BITCHUNK_BITS; /* index in word */
195433d6423SLionel Sambuc mask = 1 << bit;
196433d6423SLionel Sambuc
197433d6423SLionel Sambuc k = (int) bitmap[word];
198433d6423SLionel Sambuc if (!(k & mask))
199433d6423SLionel Sambuc return -1;
200433d6423SLionel Sambuc
201433d6423SLionel Sambuc k &= ~mask;
202433d6423SLionel Sambuc bitmap[word] = (int) k;
203433d6423SLionel Sambuc return 0;
204433d6423SLionel Sambuc }
205