import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / fs / ufs / util.c
1 /*
2  *  linux/fs/ufs/util.c
3  *
4  * Copyright (C) 1998
5  * Daniel Pirkl <daniel.pirkl@email.cz>
6  * Charles University, Faculty of Mathematics and Physics
7  */
8  
9 #include <linux/string.h>
10 #include <linux/slab.h>
11 #include <linux/locks.h>
12
13 #include "swab.h"
14 #include "util.h"
15
16 #undef UFS_UTILS_DEBUG
17
18 #ifdef UFS_UTILS_DEBUG
19 #define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
20 #else
21 #define UFSD(x)
22 #endif
23
24
25 struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi,
26         struct super_block *sb, unsigned fragment, unsigned size)
27 {
28         struct ufs_buffer_head * ubh;
29         unsigned i, j, count;
30         if (size & ~uspi->s_fmask)
31                 return NULL;
32         count = size >> uspi->s_fshift;
33         if (count > UFS_MAXFRAG)
34                 return NULL;
35         ubh = (struct ufs_buffer_head *)
36                 kmalloc (sizeof (struct ufs_buffer_head), GFP_KERNEL);
37         if (!ubh)
38                 return NULL;
39         ubh->fragment = fragment;
40         ubh->count = count;
41         for (i = 0; i < count; i++)
42                 if (!(ubh->bh[i] = sb_bread(sb, fragment + i)))
43                         goto failed;
44         for (; i < UFS_MAXFRAG; i++)
45                 ubh->bh[i] = NULL;
46         return ubh;
47 failed:
48         for (j = 0; j < i; j++)
49                 brelse (ubh->bh[j]);
50         kfree(ubh);
51         return NULL;
52 }
53
54 struct ufs_buffer_head * ubh_bread_uspi (struct ufs_sb_private_info * uspi,
55         struct super_block *sb, unsigned fragment, unsigned size)
56 {
57         unsigned i, j, count;
58         if (size & ~uspi->s_fmask)
59                 return NULL;
60         count = size >> uspi->s_fshift;
61         if (count <= 0 || count > UFS_MAXFRAG)
62                 return NULL;
63         USPI_UBH->fragment = fragment;
64         USPI_UBH->count = count;
65         for (i = 0; i < count; i++)
66                 if (!(USPI_UBH->bh[i] = sb_bread(sb, fragment + i)))
67                         goto failed;
68         for (; i < UFS_MAXFRAG; i++)
69                 USPI_UBH->bh[i] = NULL;
70         return USPI_UBH;
71 failed:
72         for (j = 0; j < i; j++)
73                 brelse (USPI_UBH->bh[j]);
74         return NULL;
75 }
76
77 void ubh_brelse (struct ufs_buffer_head * ubh)
78 {
79         unsigned i;
80         if (!ubh)
81                 return;
82         for (i = 0; i < ubh->count; i++)
83                 brelse (ubh->bh[i]);
84         kfree (ubh);
85 }
86
87 void ubh_brelse_uspi (struct ufs_sb_private_info * uspi)
88 {
89         unsigned i;
90         if (!USPI_UBH)
91                 return;
92         for ( i = 0; i < USPI_UBH->count; i++ ) {
93                 brelse (USPI_UBH->bh[i]);
94                 USPI_UBH->bh[i] = NULL;
95         }
96 }
97
98 void ubh_mark_buffer_dirty (struct ufs_buffer_head * ubh)
99 {
100         unsigned i;
101         if (!ubh)
102                 return;
103         for ( i = 0; i < ubh->count; i++ )
104                 mark_buffer_dirty (ubh->bh[i]);
105 }
106
107 void ubh_mark_buffer_uptodate (struct ufs_buffer_head * ubh, int flag)
108 {
109         unsigned i;
110         if (!ubh)
111                 return;
112         for ( i = 0; i < ubh->count; i++ )
113                 mark_buffer_uptodate (ubh->bh[i], flag);
114 }
115
116 void ubh_ll_rw_block (int rw, unsigned nr, struct ufs_buffer_head * ubh[])
117 {
118         unsigned i;
119         if (!ubh)
120                 return;
121         for ( i = 0; i < nr; i++ )
122                 ll_rw_block (rw, ubh[i]->count, ubh[i]->bh);
123 }
124
125 void ubh_wait_on_buffer (struct ufs_buffer_head * ubh)
126 {
127         unsigned i;
128         if (!ubh)
129                 return;
130         for ( i = 0; i < ubh->count; i++ )
131                 wait_on_buffer (ubh->bh[i]);
132 }
133
134 unsigned ubh_max_bcount (struct ufs_buffer_head * ubh)
135 {
136         unsigned i;
137         unsigned max = 0;
138         if (!ubh)
139                 return 0;
140         for ( i = 0; i < ubh->count; i++ ) 
141                 if ( atomic_read(&ubh->bh[i]->b_count) > max )
142                         max = atomic_read(&ubh->bh[i]->b_count);
143         return max;
144 }
145
146 void ubh_bforget (struct ufs_buffer_head * ubh)
147 {
148         unsigned i;
149         if (!ubh) 
150                 return;
151         for ( i = 0; i < ubh->count; i++ ) if ( ubh->bh[i] ) 
152                 bforget (ubh->bh[i]);
153 }
154  
155 int ubh_buffer_dirty (struct ufs_buffer_head * ubh)
156 {
157         unsigned i;
158         unsigned result = 0;
159         if (!ubh)
160                 return 0;
161         for ( i = 0; i < ubh->count; i++ )
162                 result |= buffer_dirty(ubh->bh[i]);
163         return result;
164 }
165
166 void _ubh_ubhcpymem_(struct ufs_sb_private_info * uspi, 
167         unsigned char * mem, struct ufs_buffer_head * ubh, unsigned size)
168 {
169         unsigned len, bhno;
170         if (size > (ubh->count << uspi->s_fshift))
171                 size = ubh->count << uspi->s_fshift;
172         bhno = 0;
173         while (size) {
174                 len = min_t(unsigned int, size, uspi->s_fsize);
175                 memcpy (mem, ubh->bh[bhno]->b_data, len);
176                 mem += uspi->s_fsize;
177                 size -= len;
178                 bhno++;
179         }
180 }
181
182 void _ubh_memcpyubh_(struct ufs_sb_private_info * uspi, 
183         struct ufs_buffer_head * ubh, unsigned char * mem, unsigned size)
184 {
185         unsigned len, bhno;
186         if (size > (ubh->count << uspi->s_fshift))
187                 size = ubh->count << uspi->s_fshift;
188         bhno = 0;
189         while (size) {
190                 len = min_t(unsigned int, size, uspi->s_fsize);
191                 memcpy (ubh->bh[bhno]->b_data, mem, len);
192                 mem += uspi->s_fsize;
193                 size -= len;
194                 bhno++;
195         }
196 }