1 |
1275 |
phoenix |
/*
|
2 |
|
|
* Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
|
3 |
|
|
*/
|
4 |
|
|
|
5 |
|
|
#include <linux/config.h>
|
6 |
|
|
#include <linux/module.h>
|
7 |
|
|
#include <linux/sched.h>
|
8 |
|
|
#include <linux/blkdev.h>
|
9 |
|
|
#include <linux/vmalloc.h>
|
10 |
|
|
#include <asm/uaccess.h>
|
11 |
|
|
#include <linux/reiserfs_fs.h>
|
12 |
|
|
#include <linux/smp_lock.h>
|
13 |
|
|
#include <linux/locks.h>
|
14 |
|
|
#include <linux/init.h>
|
15 |
|
|
|
16 |
|
|
#define REISERFS_OLD_BLOCKSIZE 4096
|
17 |
|
|
#define REISERFS_SUPER_MAGIC_STRING_OFFSET_NJ 20
|
18 |
|
|
|
19 |
|
|
const char reiserfs_3_5_magic_string[] = REISERFS_SUPER_MAGIC_STRING;
|
20 |
|
|
const char reiserfs_3_6_magic_string[] = REISER2FS_SUPER_MAGIC_STRING;
|
21 |
|
|
const char reiserfs_jr_magic_string[] = REISER2FS_JR_SUPER_MAGIC_STRING;
|
22 |
|
|
|
23 |
|
|
int is_reiserfs_3_5 (struct reiserfs_super_block * rs)
|
24 |
|
|
{
|
25 |
|
|
return !strncmp (rs->s_v1.s_magic, reiserfs_3_5_magic_string,
|
26 |
|
|
strlen (reiserfs_3_5_magic_string));
|
27 |
|
|
}
|
28 |
|
|
|
29 |
|
|
|
30 |
|
|
int is_reiserfs_3_6 (struct reiserfs_super_block * rs)
|
31 |
|
|
{
|
32 |
|
|
return !strncmp (rs->s_v1.s_magic, reiserfs_3_6_magic_string,
|
33 |
|
|
strlen (reiserfs_3_6_magic_string));
|
34 |
|
|
}
|
35 |
|
|
|
36 |
|
|
|
37 |
|
|
int is_reiserfs_jr (struct reiserfs_super_block * rs)
|
38 |
|
|
{
|
39 |
|
|
return !strncmp (rs->s_v1.s_magic, reiserfs_jr_magic_string,
|
40 |
|
|
strlen (reiserfs_jr_magic_string));
|
41 |
|
|
}
|
42 |
|
|
|
43 |
|
|
|
44 |
|
|
static int is_any_reiserfs_magic_string (struct reiserfs_super_block * rs)
|
45 |
|
|
{
|
46 |
|
|
return (is_reiserfs_3_5 (rs) || is_reiserfs_3_6 (rs) ||
|
47 |
|
|
is_reiserfs_jr (rs));
|
48 |
|
|
}
|
49 |
|
|
|
50 |
|
|
static int reiserfs_remount (struct super_block * s, int * flags, char * data);
|
51 |
|
|
static int reiserfs_statfs (struct super_block * s, struct statfs * buf);
|
52 |
|
|
|
53 |
|
|
static void reiserfs_write_super (struct super_block * s)
|
54 |
|
|
{
|
55 |
|
|
|
56 |
|
|
int dirty = 0 ;
|
57 |
|
|
lock_kernel() ;
|
58 |
|
|
if (!(s->s_flags & MS_RDONLY)) {
|
59 |
|
|
dirty = flush_old_commits(s, 1) ;
|
60 |
|
|
}
|
61 |
|
|
s->s_dirt = dirty;
|
62 |
|
|
unlock_kernel() ;
|
63 |
|
|
}
|
64 |
|
|
|
65 |
|
|
static void reiserfs_write_super_lockfs (struct super_block * s)
|
66 |
|
|
{
|
67 |
|
|
|
68 |
|
|
int dirty = 0 ;
|
69 |
|
|
struct reiserfs_transaction_handle th ;
|
70 |
|
|
lock_kernel() ;
|
71 |
|
|
if (!(s->s_flags & MS_RDONLY)) {
|
72 |
|
|
journal_begin(&th, s, 1) ;
|
73 |
|
|
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
|
74 |
|
|
journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s));
|
75 |
|
|
reiserfs_block_writes(&th) ;
|
76 |
|
|
journal_end(&th, s, 1) ;
|
77 |
|
|
}
|
78 |
|
|
s->s_dirt = dirty;
|
79 |
|
|
unlock_kernel() ;
|
80 |
|
|
}
|
81 |
|
|
|
82 |
|
|
void reiserfs_unlockfs(struct super_block *s) {
|
83 |
|
|
reiserfs_allow_writes(s) ;
|
84 |
|
|
}
|
85 |
|
|
|
86 |
|
|
extern const struct key MAX_KEY;
|
87 |
|
|
|
88 |
|
|
|
89 |
|
|
/* this is used to delete "save link" when there are no items of a
|
90 |
|
|
file it points to. It can either happen if unlink is completed but
|
91 |
|
|
"save unlink" removal, or if file has both unlink and truncate
|
92 |
|
|
pending and as unlink completes first (because key of "save link"
|
93 |
|
|
protecting unlink is bigger that a key lf "save link" which
|
94 |
|
|
protects truncate), so there left no items to make truncate
|
95 |
|
|
completion on */
|
96 |
|
|
static void remove_save_link_only (struct super_block * s, struct key * key, int oid_free)
|
97 |
|
|
{
|
98 |
|
|
struct reiserfs_transaction_handle th;
|
99 |
|
|
|
100 |
|
|
/* we are going to do one balancing */
|
101 |
|
|
journal_begin (&th, s, JOURNAL_PER_BALANCE_CNT);
|
102 |
|
|
|
103 |
|
|
reiserfs_delete_solid_item (&th, key);
|
104 |
|
|
if (oid_free)
|
105 |
|
|
/* removals are protected by direct items */
|
106 |
|
|
reiserfs_release_objectid (&th, le32_to_cpu (key->k_objectid));
|
107 |
|
|
|
108 |
|
|
journal_end (&th, s, JOURNAL_PER_BALANCE_CNT);
|
109 |
|
|
}
|
110 |
|
|
|
111 |
|
|
|
112 |
|
|
/* look for uncompleted unlinks and truncates and complete them */
|
113 |
|
|
static void finish_unfinished (struct super_block * s)
|
114 |
|
|
{
|
115 |
|
|
INITIALIZE_PATH (path);
|
116 |
|
|
struct cpu_key max_cpu_key, obj_key;
|
117 |
|
|
struct key save_link_key;
|
118 |
|
|
int retval;
|
119 |
|
|
struct item_head * ih;
|
120 |
|
|
struct buffer_head * bh;
|
121 |
|
|
int item_pos;
|
122 |
|
|
char * item;
|
123 |
|
|
int done;
|
124 |
|
|
struct inode * inode;
|
125 |
|
|
int truncate;
|
126 |
|
|
|
127 |
|
|
|
128 |
|
|
/* compose key to look for "save" links */
|
129 |
|
|
max_cpu_key.version = KEY_FORMAT_3_5;
|
130 |
|
|
max_cpu_key.on_disk_key = MAX_KEY;
|
131 |
|
|
max_cpu_key.key_length = 3;
|
132 |
|
|
|
133 |
|
|
done = 0;
|
134 |
|
|
s -> u.reiserfs_sb.s_is_unlinked_ok = 1;
|
135 |
|
|
while (1) {
|
136 |
|
|
retval = search_item (s, &max_cpu_key, &path);
|
137 |
|
|
if (retval != ITEM_NOT_FOUND) {
|
138 |
|
|
reiserfs_warning (s, "vs-2140: finish_unfinished: search_by_key returned %d\n",
|
139 |
|
|
retval);
|
140 |
|
|
break;
|
141 |
|
|
}
|
142 |
|
|
|
143 |
|
|
bh = get_last_bh (&path);
|
144 |
|
|
item_pos = get_item_pos (&path);
|
145 |
|
|
if (item_pos != B_NR_ITEMS (bh)) {
|
146 |
|
|
reiserfs_warning (s, "vs-2060: finish_unfinished: wrong position found\n");
|
147 |
|
|
break;
|
148 |
|
|
}
|
149 |
|
|
item_pos --;
|
150 |
|
|
ih = B_N_PITEM_HEAD (bh, item_pos);
|
151 |
|
|
|
152 |
|
|
if (le32_to_cpu (ih->ih_key.k_dir_id) != MAX_KEY_OBJECTID)
|
153 |
|
|
/* there are no "save" links anymore */
|
154 |
|
|
break;
|
155 |
|
|
|
156 |
|
|
save_link_key = ih->ih_key;
|
157 |
|
|
if (is_indirect_le_ih (ih))
|
158 |
|
|
truncate = 1;
|
159 |
|
|
else
|
160 |
|
|
truncate = 0;
|
161 |
|
|
|
162 |
|
|
/* reiserfs_iget needs k_dirid and k_objectid only */
|
163 |
|
|
item = B_I_PITEM (bh, ih);
|
164 |
|
|
obj_key.on_disk_key.k_dir_id = le32_to_cpu (*(__u32 *)item);
|
165 |
|
|
obj_key.on_disk_key.k_objectid = le32_to_cpu (ih->ih_key.k_objectid);
|
166 |
|
|
obj_key.on_disk_key.u.k_offset_v1.k_offset = 0;
|
167 |
|
|
obj_key.on_disk_key.u.k_offset_v1.k_uniqueness = 0;
|
168 |
|
|
|
169 |
|
|
pathrelse (&path);
|
170 |
|
|
|
171 |
|
|
inode = reiserfs_iget (s, &obj_key);
|
172 |
|
|
if (!inode) {
|
173 |
|
|
/* the unlink almost completed, it just did not manage to remove
|
174 |
|
|
"save" link and release objectid */
|
175 |
|
|
reiserfs_warning (s, "vs-2180: finish_unfinished: iget failed for %K\n",
|
176 |
|
|
&obj_key);
|
177 |
|
|
remove_save_link_only (s, &save_link_key, 1);
|
178 |
|
|
continue;
|
179 |
|
|
}
|
180 |
|
|
|
181 |
|
|
if (!truncate && inode->i_nlink) {
|
182 |
|
|
/* file is not unlinked */
|
183 |
|
|
reiserfs_warning (s, "vs-2185: finish_unfinished: file %K is not unlinked\n",
|
184 |
|
|
&obj_key);
|
185 |
|
|
remove_save_link_only (s, &save_link_key, 0);
|
186 |
|
|
continue;
|
187 |
|
|
}
|
188 |
|
|
|
189 |
|
|
if (truncate && S_ISDIR (inode->i_mode) ) {
|
190 |
|
|
/* We got a truncate request for a dir which is impossible.
|
191 |
|
|
The only imaginable way is to execute unfinished truncate request
|
192 |
|
|
then boot into old kernel, remove the file and create dir with
|
193 |
|
|
the same key. */
|
194 |
|
|
reiserfs_warning(s, "green-2101: impossible truncate on a directory %k. Please report\n", INODE_PKEY (inode));
|
195 |
|
|
remove_save_link_only (s, &save_link_key, 0);
|
196 |
|
|
truncate = 0;
|
197 |
|
|
iput (inode);
|
198 |
|
|
continue;
|
199 |
|
|
}
|
200 |
|
|
|
201 |
|
|
if (truncate) {
|
202 |
|
|
inode -> u.reiserfs_i.i_flags |= i_link_saved_truncate_mask;
|
203 |
|
|
/* not completed truncate found. New size was committed together
|
204 |
|
|
with "save" link */
|
205 |
|
|
reiserfs_warning (s, "Truncating %k to %Ld ..",
|
206 |
|
|
INODE_PKEY (inode), inode->i_size);
|
207 |
|
|
reiserfs_truncate_file (inode, 0/*don't update modification time*/);
|
208 |
|
|
remove_save_link (inode, truncate);
|
209 |
|
|
} else {
|
210 |
|
|
inode -> u.reiserfs_i.i_flags |= i_link_saved_unlink_mask;
|
211 |
|
|
/* not completed unlink (rmdir) found */
|
212 |
|
|
reiserfs_warning (s, "Removing %k..", INODE_PKEY (inode));
|
213 |
|
|
/* removal gets completed in iput */
|
214 |
|
|
}
|
215 |
|
|
|
216 |
|
|
iput (inode);
|
217 |
|
|
printk ("done\n");
|
218 |
|
|
done ++;
|
219 |
|
|
}
|
220 |
|
|
s -> u.reiserfs_sb.s_is_unlinked_ok = 0;
|
221 |
|
|
|
222 |
|
|
pathrelse (&path);
|
223 |
|
|
if (done)
|
224 |
|
|
reiserfs_warning (s, "There were %d uncompleted unlinks/truncates. "
|
225 |
|
|
"Completed\n", done);
|
226 |
|
|
}
|
227 |
|
|
|
228 |
|
|
/* to protect file being unlinked from getting lost we "safe" link files
|
229 |
|
|
being unlinked. This link will be deleted in the same transaction with last
|
230 |
|
|
item of file. mounting the filesytem we scan all these links and remove
|
231 |
|
|
files which almost got lost */
|
232 |
|
|
void add_save_link (struct reiserfs_transaction_handle * th,
|
233 |
|
|
struct inode * inode, int truncate)
|
234 |
|
|
{
|
235 |
|
|
INITIALIZE_PATH (path);
|
236 |
|
|
int retval;
|
237 |
|
|
struct cpu_key key;
|
238 |
|
|
struct item_head ih;
|
239 |
|
|
__u32 link;
|
240 |
|
|
|
241 |
|
|
/* file can only get one "save link" of each kind */
|
242 |
|
|
RFALSE( truncate &&
|
243 |
|
|
( inode -> u.reiserfs_i.i_flags & i_link_saved_truncate_mask ),
|
244 |
|
|
"saved link already exists for truncated inode %lx",
|
245 |
|
|
( long ) inode -> i_ino );
|
246 |
|
|
RFALSE( !truncate &&
|
247 |
|
|
( inode -> u.reiserfs_i.i_flags & i_link_saved_unlink_mask ),
|
248 |
|
|
"saved link already exists for unlinked inode %lx",
|
249 |
|
|
( long ) inode -> i_ino );
|
250 |
|
|
|
251 |
|
|
/* setup key of "save" link */
|
252 |
|
|
key.version = KEY_FORMAT_3_5;
|
253 |
|
|
key.on_disk_key.k_dir_id = MAX_KEY_OBJECTID;
|
254 |
|
|
key.on_disk_key.k_objectid = inode->i_ino;
|
255 |
|
|
if (!truncate) {
|
256 |
|
|
/* unlink, rmdir, rename */
|
257 |
|
|
set_cpu_key_k_offset (&key, 1 + inode->i_sb->s_blocksize);
|
258 |
|
|
set_cpu_key_k_type (&key, TYPE_DIRECT);
|
259 |
|
|
|
260 |
|
|
/* item head of "safe" link */
|
261 |
|
|
make_le_item_head (&ih, &key, key.version, 1 + inode->i_sb->s_blocksize, TYPE_DIRECT,
|
262 |
|
|
4/*length*/, 0xffff/*free space*/);
|
263 |
|
|
} else {
|
264 |
|
|
/* truncate */
|
265 |
|
|
if (S_ISDIR (inode->i_mode))
|
266 |
|
|
reiserfs_warning(inode->i_sb, "green-2102: Adding a truncate savelink for a directory %k! Please report\n", INODE_PKEY(inode));
|
267 |
|
|
set_cpu_key_k_offset (&key, 1);
|
268 |
|
|
set_cpu_key_k_type (&key, TYPE_INDIRECT);
|
269 |
|
|
|
270 |
|
|
/* item head of "safe" link */
|
271 |
|
|
make_le_item_head (&ih, &key, key.version, 1, TYPE_INDIRECT,
|
272 |
|
|
4/*length*/, 0/*free space*/);
|
273 |
|
|
}
|
274 |
|
|
key.key_length = 3;
|
275 |
|
|
|
276 |
|
|
/* look for its place in the tree */
|
277 |
|
|
retval = search_item (inode->i_sb, &key, &path);
|
278 |
|
|
if (retval != ITEM_NOT_FOUND) {
|
279 |
|
|
if ( retval != -ENOSPC )
|
280 |
|
|
reiserfs_warning (inode->i_sb, "vs-2100: add_save_link:"
|
281 |
|
|
"search_by_key (%K) returned %d\n", &key, retval);
|
282 |
|
|
pathrelse (&path);
|
283 |
|
|
return;
|
284 |
|
|
}
|
285 |
|
|
|
286 |
|
|
/* body of "save" link */
|
287 |
|
|
link = INODE_PKEY (inode)->k_dir_id;
|
288 |
|
|
|
289 |
|
|
/* put "save" link inot tree */
|
290 |
|
|
retval = reiserfs_insert_item (th, &path, &key, &ih, (char *)&link);
|
291 |
|
|
if (retval) {
|
292 |
|
|
if (retval != -ENOSPC)
|
293 |
|
|
reiserfs_warning (inode->i_sb, "vs-2120: add_save_link: insert_item returned %d\n",
|
294 |
|
|
retval);
|
295 |
|
|
} else {
|
296 |
|
|
if( truncate )
|
297 |
|
|
inode -> u.reiserfs_i.i_flags |= i_link_saved_truncate_mask;
|
298 |
|
|
else
|
299 |
|
|
inode -> u.reiserfs_i.i_flags |= i_link_saved_unlink_mask;
|
300 |
|
|
}
|
301 |
|
|
}
|
302 |
|
|
|
303 |
|
|
|
304 |
|
|
/* this opens transaction unlike add_save_link */
|
305 |
|
|
void remove_save_link (struct inode * inode, int truncate)
|
306 |
|
|
{
|
307 |
|
|
struct reiserfs_transaction_handle th;
|
308 |
|
|
struct key key;
|
309 |
|
|
|
310 |
|
|
|
311 |
|
|
/* we are going to do one balancing only */
|
312 |
|
|
journal_begin (&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT);
|
313 |
|
|
|
314 |
|
|
/* setup key of "save" link */
|
315 |
|
|
key.k_dir_id = cpu_to_le32 (MAX_KEY_OBJECTID);
|
316 |
|
|
key.k_objectid = INODE_PKEY (inode)->k_objectid;
|
317 |
|
|
if (!truncate) {
|
318 |
|
|
/* unlink, rmdir, rename */
|
319 |
|
|
set_le_key_k_offset (KEY_FORMAT_3_5, &key,
|
320 |
|
|
1 + inode->i_sb->s_blocksize);
|
321 |
|
|
set_le_key_k_type (KEY_FORMAT_3_5, &key, TYPE_DIRECT);
|
322 |
|
|
} else {
|
323 |
|
|
/* truncate */
|
324 |
|
|
set_le_key_k_offset (KEY_FORMAT_3_5, &key, 1);
|
325 |
|
|
set_le_key_k_type (KEY_FORMAT_3_5, &key, TYPE_INDIRECT);
|
326 |
|
|
}
|
327 |
|
|
|
328 |
|
|
if( ( truncate &&
|
329 |
|
|
( inode -> u.reiserfs_i.i_flags & i_link_saved_truncate_mask ) ) ||
|
330 |
|
|
( !truncate &&
|
331 |
|
|
( inode -> u.reiserfs_i.i_flags & i_link_saved_unlink_mask ) ) )
|
332 |
|
|
reiserfs_delete_solid_item (&th, &key);
|
333 |
|
|
if (!truncate) {
|
334 |
|
|
reiserfs_release_objectid (&th, inode->i_ino);
|
335 |
|
|
inode -> u.reiserfs_i.i_flags &= ~i_link_saved_unlink_mask;
|
336 |
|
|
} else
|
337 |
|
|
inode -> u.reiserfs_i.i_flags &= ~i_link_saved_truncate_mask;
|
338 |
|
|
|
339 |
|
|
journal_end (&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT);
|
340 |
|
|
}
|
341 |
|
|
|
342 |
|
|
|
343 |
|
|
static void reiserfs_put_super (struct super_block * s)
|
344 |
|
|
{
|
345 |
|
|
int i;
|
346 |
|
|
struct reiserfs_transaction_handle th ;
|
347 |
|
|
|
348 |
|
|
/* change file system state to current state if it was mounted with read-write permissions */
|
349 |
|
|
if (!(s->s_flags & MS_RDONLY)) {
|
350 |
|
|
journal_begin(&th, s, 10) ;
|
351 |
|
|
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;
|
352 |
|
|
set_sb_umount_state( SB_DISK_SUPER_BLOCK(s), s->u.reiserfs_sb.s_mount_state );
|
353 |
|
|
journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s));
|
354 |
|
|
}
|
355 |
|
|
|
356 |
|
|
/* note, journal_release checks for readonly mount, and can decide not
|
357 |
|
|
** to do a journal_end
|
358 |
|
|
*/
|
359 |
|
|
journal_release(&th, s) ;
|
360 |
|
|
|
361 |
|
|
for (i = 0; i < SB_BMAP_NR (s); i ++)
|
362 |
|
|
brelse (SB_AP_BITMAP (s)[i].bh);
|
363 |
|
|
|
364 |
|
|
vfree (SB_AP_BITMAP (s));
|
365 |
|
|
|
366 |
|
|
brelse (SB_BUFFER_WITH_SB (s));
|
367 |
|
|
|
368 |
|
|
print_statistics (s);
|
369 |
|
|
|
370 |
|
|
if (s->u.reiserfs_sb.s_kmallocs != 0) {
|
371 |
|
|
reiserfs_warning (s, "vs-2004: reiserfs_put_super: allocated memory left %d\n",
|
372 |
|
|
s->u.reiserfs_sb.s_kmallocs);
|
373 |
|
|
}
|
374 |
|
|
|
375 |
|
|
if (s->u.reiserfs_sb.reserved_blocks != 0) {
|
376 |
|
|
reiserfs_warning (s, "green-2005: reiserfs_put_super: reserved blocks left %d\n",
|
377 |
|
|
s->u.reiserfs_sb.reserved_blocks);
|
378 |
|
|
}
|
379 |
|
|
|
380 |
|
|
reiserfs_proc_unregister( s, "journal" );
|
381 |
|
|
reiserfs_proc_unregister( s, "oidmap" );
|
382 |
|
|
reiserfs_proc_unregister( s, "on-disk-super" );
|
383 |
|
|
reiserfs_proc_unregister( s, "bitmap" );
|
384 |
|
|
reiserfs_proc_unregister( s, "per-level" );
|
385 |
|
|
reiserfs_proc_unregister( s, "super" );
|
386 |
|
|
reiserfs_proc_unregister( s, "version" );
|
387 |
|
|
reiserfs_proc_info_done( s );
|
388 |
|
|
return;
|
389 |
|
|
}
|
390 |
|
|
|
391 |
|
|
/* we don't mark inodes dirty, we just log them */
|
392 |
|
|
static void reiserfs_dirty_inode (struct inode * inode) {
|
393 |
|
|
struct reiserfs_transaction_handle th ;
|
394 |
|
|
|
395 |
|
|
if (inode->i_sb->s_flags & MS_RDONLY) {
|
396 |
|
|
reiserfs_warning(inode->i_sb, "clm-6006: writing inode %lu on readonly FS\n",
|
397 |
|
|
inode->i_ino) ;
|
398 |
|
|
return ;
|
399 |
|
|
}
|
400 |
|
|
lock_kernel() ;
|
401 |
|
|
|
402 |
|
|
/* this is really only used for atime updates, so they don't have
|
403 |
|
|
** to be included in O_SYNC or fsync
|
404 |
|
|
*/
|
405 |
|
|
journal_begin(&th, inode->i_sb, 1) ;
|
406 |
|
|
reiserfs_update_sd (&th, inode);
|
407 |
|
|
journal_end(&th, inode->i_sb, 1) ;
|
408 |
|
|
unlock_kernel() ;
|
409 |
|
|
}
|
410 |
|
|
|
411 |
|
|
struct super_operations reiserfs_sops =
|
412 |
|
|
{
|
413 |
|
|
read_inode: reiserfs_read_inode,
|
414 |
|
|
read_inode2: reiserfs_read_inode2,
|
415 |
|
|
write_inode: reiserfs_write_inode,
|
416 |
|
|
dirty_inode: reiserfs_dirty_inode,
|
417 |
|
|
delete_inode: reiserfs_delete_inode,
|
418 |
|
|
put_super: reiserfs_put_super,
|
419 |
|
|
write_super: reiserfs_write_super,
|
420 |
|
|
write_super_lockfs: reiserfs_write_super_lockfs,
|
421 |
|
|
unlockfs: reiserfs_unlockfs,
|
422 |
|
|
statfs: reiserfs_statfs,
|
423 |
|
|
remount_fs: reiserfs_remount,
|
424 |
|
|
|
425 |
|
|
fh_to_dentry: reiserfs_fh_to_dentry,
|
426 |
|
|
dentry_to_fh: reiserfs_dentry_to_fh,
|
427 |
|
|
|
428 |
|
|
};
|
429 |
|
|
|
430 |
|
|
/* this struct is used in reiserfs_getopt () for containing the value for those
|
431 |
|
|
mount options that have values rather than being toggles. */
|
432 |
|
|
typedef struct {
|
433 |
|
|
char * value;
|
434 |
|
|
int setmask; /* bitmask which is to set on mount_options bitmask when this
|
435 |
|
|
value is found, 0 is no bits are to be changed. */
|
436 |
|
|
int clrmask; /* bitmask which is to clear on mount_options bitmask when this
|
437 |
|
|
value is found, 0 is no bits are to be changed. This is
|
438 |
|
|
applied BEFORE setmask */
|
439 |
|
|
} arg_desc_t;
|
440 |
|
|
|
441 |
|
|
|
442 |
|
|
/* this struct is used in reiserfs_getopt() for describing the set of reiserfs
|
443 |
|
|
mount options */
|
444 |
|
|
typedef struct {
|
445 |
|
|
char * option_name;
|
446 |
|
|
int arg_required; /* 0 is argument is not required, not 0 otherwise */
|
447 |
|
|
const arg_desc_t * values; /* list of values accepted by an option */
|
448 |
|
|
int setmask; /* bitmask which is to set on mount_options bitmask when this
|
449 |
|
|
value is found, 0 is no bits are to be changed. */
|
450 |
|
|
int clrmask; /* bitmask which is to clear on mount_options bitmask when this
|
451 |
|
|
value is found, 0 is no bits are to be changed. This is
|
452 |
|
|
applied BEFORE setmask */
|
453 |
|
|
} opt_desc_t;
|
454 |
|
|
|
455 |
|
|
|
456 |
|
|
/* possible values for "-o hash=" and bits which are to be set in s_mount_opt
|
457 |
|
|
of reiserfs specific part of in-core super block */
|
458 |
|
|
static const arg_desc_t hash[] = {
|
459 |
|
|
{"rupasov", 1<<FORCE_RUPASOV_HASH,(1<<FORCE_TEA_HASH)|(1<<FORCE_R5_HASH)},
|
460 |
|
|
{"tea", 1<<FORCE_TEA_HASH,(1<<FORCE_RUPASOV_HASH)|(1<<FORCE_R5_HASH)},
|
461 |
|
|
{"r5", 1<<FORCE_R5_HASH,(1<<FORCE_RUPASOV_HASH)|(1<<FORCE_TEA_HASH)},
|
462 |
|
|
{"detect", 1<<FORCE_HASH_DETECT, (1<<FORCE_RUPASOV_HASH)|(1<<FORCE_TEA_HASH)|(1<<FORCE_R5_HASH)},
|
463 |
|
|
{NULL, 0, 0}
|
464 |
|
|
};
|
465 |
|
|
|
466 |
|
|
|
467 |
|
|
/* possible values for "-o block-allocator=" and bits which are to be set in
|
468 |
|
|
s_mount_opt of reiserfs specific part of in-core super block */
|
469 |
|
|
static const arg_desc_t balloc[] = {
|
470 |
|
|
{"noborder", 1<<REISERFS_NO_BORDER, 0},
|
471 |
|
|
{"border", 0, 1<<REISERFS_NO_BORDER},
|
472 |
|
|
{"no_unhashed_relocation", 1<<REISERFS_NO_UNHASHED_RELOCATION, 0},
|
473 |
|
|
{"hashed_relocation", 1<<REISERFS_HASHED_RELOCATION, 0},
|
474 |
|
|
{"test4", 1<<REISERFS_TEST4, 0},
|
475 |
|
|
{"notest4", 0, 1<<REISERFS_TEST4},
|
476 |
|
|
{NULL, 0, 0}
|
477 |
|
|
};
|
478 |
|
|
|
479 |
|
|
static const arg_desc_t tails[] = {
|
480 |
|
|
{"on", 1<<REISERFS_LARGETAIL, 1<<REISERFS_SMALLTAIL},
|
481 |
|
|
{"off", 0, (1<<REISERFS_LARGETAIL)|(1<<REISERFS_SMALLTAIL)},
|
482 |
|
|
{"small", 1<<REISERFS_SMALLTAIL, 1<<REISERFS_LARGETAIL},
|
483 |
|
|
{NULL, 0, 0}
|
484 |
|
|
};
|
485 |
|
|
|
486 |
|
|
|
487 |
|
|
/* proceed only one option from a list *cur - string containing of mount options
|
488 |
|
|
opts - array of options which are accepted
|
489 |
|
|
opt_arg - if option is found and requires an argument and if it is specifed
|
490 |
|
|
in the input - pointer to the argument is stored here
|
491 |
|
|
bit_flags - if option requires to set a certain bit - it is set here
|
492 |
|
|
return -1 if unknown option is found, opt->arg_required otherwise */
|
493 |
|
|
static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * opts, char ** opt_arg,
|
494 |
|
|
unsigned long * bit_flags)
|
495 |
|
|
{
|
496 |
|
|
char * p;
|
497 |
|
|
/* foo=bar,
|
498 |
|
|
^ ^ ^
|
499 |
|
|
| | +-- option_end
|
500 |
|
|
| +-- arg_start
|
501 |
|
|
+-- option_start
|
502 |
|
|
*/
|
503 |
|
|
const opt_desc_t * opt;
|
504 |
|
|
const arg_desc_t * arg;
|
505 |
|
|
|
506 |
|
|
|
507 |
|
|
p = *cur;
|
508 |
|
|
|
509 |
|
|
/* assume argument cannot contain commas */
|
510 |
|
|
*cur = strchr (p, ',');
|
511 |
|
|
if (*cur) {
|
512 |
|
|
*(*cur) = '\0';
|
513 |
|
|
(*cur) ++;
|
514 |
|
|
}
|
515 |
|
|
|
516 |
|
|
if ( !strncmp (p, "alloc=", 6) ) {
|
517 |
|
|
/* Ugly special case, probably we should redo options parser so that
|
518 |
|
|
it can understand several arguments for some options, also so that
|
519 |
|
|
it can fill several bitfields with option values. */
|
520 |
|
|
if ( reiserfs_parse_alloc_options( s, p + 6) ) {
|
521 |
|
|
return -1;
|
522 |
|
|
} else {
|
523 |
|
|
return 0;
|
524 |
|
|
}
|
525 |
|
|
}
|
526 |
|
|
|
527 |
|
|
/* for every option in the list */
|
528 |
|
|
for (opt = opts; opt->option_name; opt ++) {
|
529 |
|
|
if (!strncmp (p, opt->option_name, strlen (opt->option_name))) {
|
530 |
|
|
if (bit_flags) {
|
531 |
|
|
*bit_flags &= ~opt->clrmask;
|
532 |
|
|
*bit_flags |= opt->setmask;
|
533 |
|
|
}
|
534 |
|
|
break;
|
535 |
|
|
}
|
536 |
|
|
}
|
537 |
|
|
if (!opt->option_name) {
|
538 |
|
|
printk ("reiserfs_getopt: unknown option \"%s\"\n", p);
|
539 |
|
|
return -1;
|
540 |
|
|
}
|
541 |
|
|
|
542 |
|
|
p += strlen (opt->option_name);
|
543 |
|
|
switch (*p) {
|
544 |
|
|
case '=':
|
545 |
|
|
if (!opt->arg_required) {
|
546 |
|
|
printk ("reiserfs_getopt: the option \"%s\" does not require an argument\n",
|
547 |
|
|
opt->option_name);
|
548 |
|
|
return -1;
|
549 |
|
|
}
|
550 |
|
|
break;
|
551 |
|
|
|
552 |
|
|
case 0:
|
553 |
|
|
if (opt->arg_required) {
|
554 |
|
|
printk ("reiserfs_getopt: the option \"%s\" requires an argument\n", opt->option_name);
|
555 |
|
|
return -1;
|
556 |
|
|
}
|
557 |
|
|
break;
|
558 |
|
|
default:
|
559 |
|
|
printk ("reiserfs_getopt: head of option \"%s\" is only correct\n", opt->option_name);
|
560 |
|
|
return -1;
|
561 |
|
|
}
|
562 |
|
|
|
563 |
|
|
/* move to the argument, or to next option if argument is not required */
|
564 |
|
|
p ++;
|
565 |
|
|
|
566 |
|
|
if ( opt->arg_required && !strlen (p) ) {
|
567 |
|
|
/* this catches "option=," */
|
568 |
|
|
printk ("reiserfs_getopt: empty argument for \"%s\"\n", opt->option_name);
|
569 |
|
|
return -1;
|
570 |
|
|
}
|
571 |
|
|
|
572 |
|
|
if (!opt->values) {
|
573 |
|
|
/* *=NULLopt_arg contains pointer to argument */
|
574 |
|
|
*opt_arg = p;
|
575 |
|
|
return opt->arg_required;
|
576 |
|
|
}
|
577 |
|
|
|
578 |
|
|
/* values possible for this option are listed in opt->values */
|
579 |
|
|
for (arg = opt->values; arg->value; arg ++) {
|
580 |
|
|
if (!strcmp (p, arg->value)) {
|
581 |
|
|
if (bit_flags) {
|
582 |
|
|
*bit_flags &= ~arg->clrmask;
|
583 |
|
|
*bit_flags |= arg->setmask;
|
584 |
|
|
}
|
585 |
|
|
return opt->arg_required;
|
586 |
|
|
}
|
587 |
|
|
}
|
588 |
|
|
|
589 |
|
|
printk ("reiserfs_getopt: bad value \"%s\" for option \"%s\"\n", p, opt->option_name);
|
590 |
|
|
return -1;
|
591 |
|
|
}
|
592 |
|
|
|
593 |
|
|
/* returns 0 if something is wrong in option string, 1 - otherwise */
|
594 |
|
|
static int reiserfs_parse_options (struct super_block * s, char * options, /* string given via mount's -o */
|
595 |
|
|
unsigned long * mount_options,
|
596 |
|
|
/* after the parsing phase, contains the
|
597 |
|
|
collection of bitflags defining what
|
598 |
|
|
mount options were selected. */
|
599 |
|
|
unsigned long * blocks) /* strtol-ed from NNN of resize=NNN */
|
600 |
|
|
{
|
601 |
|
|
int c;
|
602 |
|
|
char * arg = NULL;
|
603 |
|
|
char * pos;
|
604 |
|
|
opt_desc_t opts[] = {
|
605 |
|
|
{"tails", 't', tails, 0, 0},
|
606 |
|
|
/* Compatibility stuff, so that -o notail
|
607 |
|
|
for old setups still work */
|
608 |
|
|
{"notail", 0, 0, 0, (1<<REISERFS_LARGETAIL)|(1<<REISERFS_SMALLTAIL)},
|
609 |
|
|
{"conv", 0, 0, 1<<REISERFS_CONVERT, 0},
|
610 |
|
|
{"nolog", 0, 0, 0, 0}, /* This is unsupported */
|
611 |
|
|
{"replayonly", 0, 0, 1<<REPLAYONLY, 0},
|
612 |
|
|
|
613 |
|
|
{"block-allocator", 'a', balloc, 0, 0},
|
614 |
|
|
{"hash", 'h', hash, 1<<FORCE_HASH_DETECT, 0},
|
615 |
|
|
|
616 |
|
|
{"resize", 'r', 0, 0, 0},
|
617 |
|
|
{"attrs", 0, 0, 1<<REISERFS_ATTRS, 0},
|
618 |
|
|
{"noattrs", 0, 0, 0, 1<<REISERFS_ATTRS},
|
619 |
|
|
{NULL, 0, 0, 0, 0}
|
620 |
|
|
};
|
621 |
|
|
|
622 |
|
|
*blocks = 0;
|
623 |
|
|
if (!options || !*options)
|
624 |
|
|
/* use default configuration: create tails, journaling on, no
|
625 |
|
|
conversion to newest format */
|
626 |
|
|
return 1;
|
627 |
|
|
|
628 |
|
|
for (pos = options; pos; ) {
|
629 |
|
|
c = reiserfs_getopt (s, &pos, opts, &arg, mount_options);
|
630 |
|
|
if (c == -1)
|
631 |
|
|
/* wrong option is given */
|
632 |
|
|
return 0;
|
633 |
|
|
|
634 |
|
|
if (c == 'r') {
|
635 |
|
|
char * p;
|
636 |
|
|
|
637 |
|
|
p = 0;
|
638 |
|
|
/* "resize=NNN" */
|
639 |
|
|
*blocks = simple_strtoul (arg, &p, 0);
|
640 |
|
|
if (*p != '\0') {
|
641 |
|
|
/* NNN does not look like a number */
|
642 |
|
|
printk ("reiserfs_parse_options: bad value %s\n", arg);
|
643 |
|
|
return 0;
|
644 |
|
|
}
|
645 |
|
|
}
|
646 |
|
|
}
|
647 |
|
|
|
648 |
|
|
return 1;
|
649 |
|
|
}
|
650 |
|
|
|
651 |
|
|
|
652 |
|
|
int reiserfs_is_super(struct super_block *s) {
|
653 |
|
|
return (s->s_dev != 0 && s->s_op == &reiserfs_sops) ;
|
654 |
|
|
}
|
655 |
|
|
|
656 |
|
|
|
657 |
|
|
static void handle_attrs( struct super_block *s )
|
658 |
|
|
{
|
659 |
|
|
struct reiserfs_super_block * rs;
|
660 |
|
|
|
661 |
|
|
if( reiserfs_attrs( s ) ) {
|
662 |
|
|
rs = SB_DISK_SUPER_BLOCK (s);
|
663 |
|
|
if( old_format_only(s) ) {
|
664 |
|
|
reiserfs_warning(s, "reiserfs: cannot support attributes on 3.5.x disk format\n" );
|
665 |
|
|
s -> u.reiserfs_sb.s_mount_opt &= ~ ( 1 << REISERFS_ATTRS );
|
666 |
|
|
return;
|
667 |
|
|
}
|
668 |
|
|
if( !( le32_to_cpu( rs -> s_flags ) & reiserfs_attrs_cleared ) ) {
|
669 |
|
|
reiserfs_warning(s, "reiserfs: cannot support attributes until flag is set in super-block\n" );
|
670 |
|
|
s -> u.reiserfs_sb.s_mount_opt &= ~ ( 1 << REISERFS_ATTRS );
|
671 |
|
|
}
|
672 |
|
|
}
|
673 |
|
|
}
|
674 |
|
|
|
675 |
|
|
static int reiserfs_remount (struct super_block * s, int * mount_flags, char * data)
|
676 |
|
|
{
|
677 |
|
|
struct reiserfs_super_block * rs;
|
678 |
|
|
struct reiserfs_transaction_handle th ;
|
679 |
|
|
unsigned long blocks;
|
680 |
|
|
unsigned long mount_options = s->u.reiserfs_sb.s_mount_opt;
|
681 |
|
|
unsigned long safe_mask = 0;
|
682 |
|
|
|
683 |
|
|
rs = SB_DISK_SUPER_BLOCK (s);
|
684 |
|
|
if (!reiserfs_parse_options(s, data, &mount_options, &blocks))
|
685 |
|
|
return -EINVAL;
|
686 |
|
|
|
687 |
|
|
/* Add options that are safe here */
|
688 |
|
|
safe_mask |= 1 << REISERFS_SMALLTAIL;
|
689 |
|
|
safe_mask |= 1 << REISERFS_LARGETAIL;
|
690 |
|
|
safe_mask |= 1 << REISERFS_NO_BORDER;
|
691 |
|
|
safe_mask |= 1 << REISERFS_NO_UNHASHED_RELOCATION;
|
692 |
|
|
safe_mask |= 1 << REISERFS_HASHED_RELOCATION;
|
693 |
|
|
safe_mask |= 1 << REISERFS_TEST4;
|
694 |
|
|
safe_mask |= 1 << REISERFS_ATTRS;
|
695 |
|
|
|
696 |
|
|
/* Update the bitmask, taking care to keep
|
697 |
|
|
* the bits we're not allowed to change here */
|
698 |
|
|
s->u.reiserfs_sb.s_mount_opt = (s->u.reiserfs_sb.s_mount_opt & ~safe_mask) | (mount_options & safe_mask);
|
699 |
|
|
|
700 |
|
|
handle_attrs( s );
|
701 |
|
|
|
702 |
|
|
if(blocks) {
|
703 |
|
|
int rc = reiserfs_resize(s, blocks);
|
704 |
|
|
if (rc != 0)
|
705 |
|
|
return rc;
|
706 |
|
|
}
|
707 |
|
|
|
708 |
|
|
if (*mount_flags & MS_RDONLY) {
|
709 |
|
|
/* remount read-only */
|
710 |
|
|
if (s->s_flags & MS_RDONLY)
|
711 |
|
|
/* it is read-only already */
|
712 |
|
|
return 0;
|
713 |
|
|
/* try to remount file system with read-only permissions */
|
714 |
|
|
if (sb_umount_state(rs) == REISERFS_VALID_FS || s->u.reiserfs_sb.s_mount_state != REISERFS_VALID_FS) {
|
715 |
|
|
return 0;
|
716 |
|
|
}
|
717 |
|
|
|
718 |
|
|
journal_begin(&th, s, 10) ;
|
719 |
|
|
/* Mounting a rw partition read-only. */
|
720 |
|
|
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;
|
721 |
|
|
set_sb_umount_state( rs, s->u.reiserfs_sb.s_mount_state );
|
722 |
|
|
journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s));
|
723 |
|
|
s->s_dirt = 0;
|
724 |
|
|
} else {
|
725 |
|
|
/* remount read-write */
|
726 |
|
|
if (!(s->s_flags & MS_RDONLY))
|
727 |
|
|
return 0; /* We are read-write already */
|
728 |
|
|
|
729 |
|
|
s->s_flags &= ~MS_RDONLY ; /* now it is safe to call journal_begin */
|
730 |
|
|
journal_begin(&th, s, 10) ;
|
731 |
|
|
|
732 |
|
|
/* Mount a partition which is read-only, read-write */
|
733 |
|
|
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;
|
734 |
|
|
s->u.reiserfs_sb.s_mount_state = sb_umount_state(rs);
|
735 |
|
|
s->s_flags &= ~MS_RDONLY;
|
736 |
|
|
set_sb_umount_state( rs, REISERFS_ERROR_FS );
|
737 |
|
|
/* mark_buffer_dirty (SB_BUFFER_WITH_SB (s), 1); */
|
738 |
|
|
journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s));
|
739 |
|
|
s->s_dirt = 0;
|
740 |
|
|
s->u.reiserfs_sb.s_mount_state = REISERFS_VALID_FS ;
|
741 |
|
|
}
|
742 |
|
|
/* this will force a full flush of all journal lists */
|
743 |
|
|
SB_JOURNAL(s)->j_must_wait = 1 ;
|
744 |
|
|
journal_end(&th, s, 10) ;
|
745 |
|
|
|
746 |
|
|
if (!( *mount_flags & MS_RDONLY ) )
|
747 |
|
|
finish_unfinished( s );
|
748 |
|
|
|
749 |
|
|
return 0;
|
750 |
|
|
}
|
751 |
|
|
|
752 |
|
|
/* load_bitmap_info_data - Sets up the reiserfs_bitmap_info structure from disk.
|
753 |
|
|
* @sb - superblock for this filesystem
|
754 |
|
|
* @bi - the bitmap info to be loaded. Requires that bi->bh is valid.
|
755 |
|
|
*
|
756 |
|
|
* This routine counts how many free bits there are, finding the first zero
|
757 |
|
|
* as a side effect. Could also be implemented as a loop of test_bit() calls, or
|
758 |
|
|
* a loop of find_first_zero_bit() calls. This implementation is similar to
|
759 |
|
|
* find_first_zero_bit(), but doesn't return after it finds the first bit.
|
760 |
|
|
* Should only be called on fs mount, but should be fairly efficient anyways.
|
761 |
|
|
*
|
762 |
|
|
* bi->first_zero_hint is considered unset if it == 0, since the bitmap itself
|
763 |
|
|
* will * invariably occupt block 0 represented in the bitmap. The only
|
764 |
|
|
* exception to this is when free_count also == 0, since there will be no
|
765 |
|
|
* free blocks at all.
|
766 |
|
|
*/
|
767 |
|
|
static void load_bitmap_info_data (struct super_block *sb,
|
768 |
|
|
struct reiserfs_bitmap_info *bi)
|
769 |
|
|
{
|
770 |
|
|
unsigned long *cur = (unsigned long *)bi->bh->b_data;
|
771 |
|
|
|
772 |
|
|
while ((char *)cur < (bi->bh->b_data + sb->s_blocksize)) {
|
773 |
|
|
|
774 |
|
|
/* No need to scan if all 0's or all 1's.
|
775 |
|
|
* Since we're only counting 0's, we can simply ignore all 1's */
|
776 |
|
|
if (*cur == 0) {
|
777 |
|
|
if (bi->first_zero_hint == 0) {
|
778 |
|
|
bi->first_zero_hint = ((char *)cur - bi->bh->b_data) << 3;
|
779 |
|
|
}
|
780 |
|
|
bi->free_count += sizeof ( unsigned long ) * 8;
|
781 |
|
|
} else if (*cur != ~0L) {
|
782 |
|
|
int b;
|
783 |
|
|
for (b = 0; b < sizeof ( unsigned long ) * 8; b++) {
|
784 |
|
|
if (!reiserfs_test_le_bit (b, cur)) {
|
785 |
|
|
bi->free_count ++;
|
786 |
|
|
if (bi->first_zero_hint == 0)
|
787 |
|
|
bi->first_zero_hint =
|
788 |
|
|
(((char *)cur - bi->bh->b_data) << 3) + b;
|
789 |
|
|
}
|
790 |
|
|
}
|
791 |
|
|
}
|
792 |
|
|
cur ++;
|
793 |
|
|
}
|
794 |
|
|
|
795 |
|
|
#ifdef CONFIG_REISERFS_CHECK
|
796 |
|
|
// This outputs a lot of unneded info on big FSes
|
797 |
|
|
// reiserfs_warning ("bitmap loaded from block %d: %d free blocks\n",
|
798 |
|
|
// bi->bh->b_blocknr, bi->free_count);
|
799 |
|
|
#endif
|
800 |
|
|
}
|
801 |
|
|
|
802 |
|
|
static int read_bitmaps (struct super_block * s)
|
803 |
|
|
{
|
804 |
|
|
int i, bmp;
|
805 |
|
|
|
806 |
|
|
SB_AP_BITMAP (s) = vmalloc (sizeof (struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
|
807 |
|
|
if (SB_AP_BITMAP (s) == 0)
|
808 |
|
|
return 1;
|
809 |
|
|
memset (SB_AP_BITMAP (s), 0, sizeof (struct reiserfs_bitmap_info) * SB_BMAP_NR(s));
|
810 |
|
|
|
811 |
|
|
for (i = 0, bmp = REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize + 1;
|
812 |
|
|
i < SB_BMAP_NR(s); i++, bmp = s->s_blocksize * 8 * i) {
|
813 |
|
|
SB_AP_BITMAP (s)[i].bh = sb_getblk (s, bmp);
|
814 |
|
|
if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh))
|
815 |
|
|
ll_rw_block(READ, 1, &SB_AP_BITMAP(s)[i].bh);
|
816 |
|
|
}
|
817 |
|
|
for (i = 0; i < SB_BMAP_NR(s); i++) {
|
818 |
|
|
wait_on_buffer(SB_AP_BITMAP (s)[i].bh);
|
819 |
|
|
if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
|
820 |
|
|
reiserfs_warning(s, "sh-2029: reiserfs read_bitmaps: "
|
821 |
|
|
"bitmap block (#%lu) reading failed\n",
|
822 |
|
|
SB_AP_BITMAP(s)[i].bh->b_blocknr);
|
823 |
|
|
for (i = 0; i < SB_BMAP_NR(s); i++)
|
824 |
|
|
brelse(SB_AP_BITMAP(s)[i].bh);
|
825 |
|
|
vfree(SB_AP_BITMAP(s));
|
826 |
|
|
SB_AP_BITMAP(s) = NULL;
|
827 |
|
|
return 1;
|
828 |
|
|
}
|
829 |
|
|
load_bitmap_info_data (s, SB_AP_BITMAP (s) + i);
|
830 |
|
|
}
|
831 |
|
|
return 0;
|
832 |
|
|
}
|
833 |
|
|
|
834 |
|
|
static int read_old_bitmaps (struct super_block * s)
|
835 |
|
|
{
|
836 |
|
|
int i ;
|
837 |
|
|
struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK(s);
|
838 |
|
|
int bmp1 = (REISERFS_OLD_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1; /* first of bitmap blocks */
|
839 |
|
|
|
840 |
|
|
/* read true bitmap */
|
841 |
|
|
SB_AP_BITMAP (s) = vmalloc (sizeof (struct reiserfs_buffer_info *) * sb_bmap_nr(rs));
|
842 |
|
|
if (SB_AP_BITMAP (s) == 0)
|
843 |
|
|
return 1;
|
844 |
|
|
|
845 |
|
|
memset (SB_AP_BITMAP (s), 0, sizeof (struct reiserfs_buffer_info *) * sb_bmap_nr(rs));
|
846 |
|
|
|
847 |
|
|
for (i = 0; i < sb_bmap_nr(rs); i ++) {
|
848 |
|
|
SB_AP_BITMAP (s)[i].bh = reiserfs_bread (s, bmp1 + i, s->s_blocksize);
|
849 |
|
|
if (!SB_AP_BITMAP (s)[i].bh)
|
850 |
|
|
return 1;
|
851 |
|
|
load_bitmap_info_data (s, SB_AP_BITMAP (s) + i);
|
852 |
|
|
}
|
853 |
|
|
|
854 |
|
|
return 0;
|
855 |
|
|
}
|
856 |
|
|
|
857 |
|
|
void check_bitmap (struct super_block * s)
|
858 |
|
|
{
|
859 |
|
|
int i = 0;
|
860 |
|
|
int free = 0;
|
861 |
|
|
char * buf;
|
862 |
|
|
|
863 |
|
|
while (i < SB_BLOCK_COUNT (s)) {
|
864 |
|
|
buf = SB_AP_BITMAP (s)[i / (s->s_blocksize * 8)].bh->b_data;
|
865 |
|
|
if (!reiserfs_test_le_bit (i % (s->s_blocksize * 8), buf))
|
866 |
|
|
free ++;
|
867 |
|
|
i ++;
|
868 |
|
|
}
|
869 |
|
|
|
870 |
|
|
if (free != SB_FREE_BLOCKS (s))
|
871 |
|
|
reiserfs_warning (s, "vs-4000: check_bitmap: %d free blocks, must be %d\n",
|
872 |
|
|
free, SB_FREE_BLOCKS (s));
|
873 |
|
|
}
|
874 |
|
|
|
875 |
|
|
static int read_super_block (struct super_block * s, int size, int offset)
|
876 |
|
|
{
|
877 |
|
|
struct buffer_head * bh;
|
878 |
|
|
struct reiserfs_super_block * rs;
|
879 |
|
|
|
880 |
|
|
|
881 |
|
|
bh = bread (s->s_dev, offset / size, size);
|
882 |
|
|
if (!bh) {
|
883 |
|
|
printk ("sh-2006: reiserfs read_super_block: "
|
884 |
|
|
"bread failed (dev %s, block %u, size %u)\n",
|
885 |
|
|
kdevname (s->s_dev), offset / size, size);
|
886 |
|
|
return 1;
|
887 |
|
|
}
|
888 |
|
|
|
889 |
|
|
rs = (struct reiserfs_super_block *)bh->b_data;
|
890 |
|
|
if (!is_any_reiserfs_magic_string (rs)) {
|
891 |
|
|
brelse (bh);
|
892 |
|
|
return 1;
|
893 |
|
|
}
|
894 |
|
|
|
895 |
|
|
//
|
896 |
|
|
// ok, reiserfs signature (old or new) found in at the given offset
|
897 |
|
|
//
|
898 |
|
|
s->s_blocksize = sb_blocksize(rs);
|
899 |
|
|
s->s_blocksize_bits = 0;
|
900 |
|
|
while ((1 << s->s_blocksize_bits) != s->s_blocksize)
|
901 |
|
|
s->s_blocksize_bits ++;
|
902 |
|
|
|
903 |
|
|
brelse (bh);
|
904 |
|
|
|
905 |
|
|
if (s->s_blocksize != 4096) {
|
906 |
|
|
printk("Unsupported reiserfs blocksize: %ld on %s, only 4096 bytes "
|
907 |
|
|
"blocksize is supported.\n", s->s_blocksize, kdevname (s->s_dev));
|
908 |
|
|
return 1;
|
909 |
|
|
}
|
910 |
|
|
|
911 |
|
|
if (s->s_blocksize != size)
|
912 |
|
|
set_blocksize (s->s_dev, s->s_blocksize);
|
913 |
|
|
|
914 |
|
|
bh = reiserfs_bread (s, offset / s->s_blocksize, s->s_blocksize);
|
915 |
|
|
if (!bh) {
|
916 |
|
|
printk("sh-2007: reiserfs read_super_block: "
|
917 |
|
|
"bread failed (dev %s, block %u, size %u)\n",
|
918 |
|
|
kdevname (s->s_dev), offset / size, size);
|
919 |
|
|
return 1;
|
920 |
|
|
}
|
921 |
|
|
|
922 |
|
|
rs = (struct reiserfs_super_block *)bh->b_data;
|
923 |
|
|
if (!is_any_reiserfs_magic_string (rs) || sb_blocksize(rs) !=
|
924 |
|
|
s->s_blocksize) {
|
925 |
|
|
printk ("sh-2011: read_super_block: "
|
926 |
|
|
"can't find a reiserfs filesystem on (dev %s, block %lu, size %lu)\n",
|
927 |
|
|
kdevname(s->s_dev), bh->b_blocknr, s->s_blocksize);
|
928 |
|
|
brelse (bh);
|
929 |
|
|
return 1;
|
930 |
|
|
}
|
931 |
|
|
|
932 |
|
|
if (sb_root_block(rs) == -1) {
|
933 |
|
|
brelse(bh) ;
|
934 |
|
|
printk("dev %s: Unfinished reiserfsck --rebuild-tree run detected. Please run\n"
|
935 |
|
|
"reiserfsck --rebuild-tree and wait for a completion. If that fails\n"
|
936 |
|
|
"get newer reiserfsprogs package\n", kdevname (s->s_dev));
|
937 |
|
|
return 1;
|
938 |
|
|
}
|
939 |
|
|
|
940 |
|
|
SB_BUFFER_WITH_SB (s) = bh;
|
941 |
|
|
SB_DISK_SUPER_BLOCK (s) = rs;
|
942 |
|
|
if (is_reiserfs_jr (rs)) {
|
943 |
|
|
/* magic is of non-standard journal filesystem, look at s_version to
|
944 |
|
|
find which format is in use */
|
945 |
|
|
if (sb_version(rs) == REISERFS_VERSION_2)
|
946 |
|
|
printk ("reiserfs: found format \"3.6\" with non-standard journal\n");
|
947 |
|
|
else if (sb_version(rs) == REISERFS_VERSION_1)
|
948 |
|
|
printk ("reiserfs: found format \"3.5\" with non-standard journal\n");
|
949 |
|
|
else {
|
950 |
|
|
printk ("sh-2012: read_super_block: found unknown format \"%u\" "
|
951 |
|
|
"of reiserfs with non-standard magic\n", sb_version(rs));
|
952 |
|
|
return 1;
|
953 |
|
|
}
|
954 |
|
|
}
|
955 |
|
|
else
|
956 |
|
|
/* s_version may contain incorrect information. Look at the magic
|
957 |
|
|
string */
|
958 |
|
|
printk ("reiserfs: found format \"%s\" with standard journal\n",
|
959 |
|
|
is_reiserfs_3_5 (rs) ? "3.5" : "3.6");
|
960 |
|
|
s->s_op = &reiserfs_sops;
|
961 |
|
|
|
962 |
|
|
/* new format is limited by the 32 bit wide i_blocks field, want to
|
963 |
|
|
** be one full block below that.
|
964 |
|
|
*/
|
965 |
|
|
s->s_maxbytes = (512LL << 32) - s->s_blocksize ;
|
966 |
|
|
return 0;
|
967 |
|
|
}
|
968 |
|
|
|
969 |
|
|
|
970 |
|
|
|
971 |
|
|
/* after journal replay, reread all bitmap and super blocks */
|
972 |
|
|
static int reread_meta_blocks(struct super_block *s) {
|
973 |
|
|
int i ;
|
974 |
|
|
ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s))) ;
|
975 |
|
|
wait_on_buffer(SB_BUFFER_WITH_SB(s)) ;
|
976 |
|
|
if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) {
|
977 |
|
|
reiserfs_warning(s, "sh-2016: reiserfs reread_meta_blocks, "
|
978 |
|
|
"error reading the super\n") ;
|
979 |
|
|
return 1 ;
|
980 |
|
|
}
|
981 |
|
|
|
982 |
|
|
for (i = 0; i < SB_BMAP_NR(s) ; i++) {
|
983 |
|
|
ll_rw_block(READ, 1, &(SB_AP_BITMAP(s)[i].bh)) ;
|
984 |
|
|
wait_on_buffer(SB_AP_BITMAP(s)[i].bh) ;
|
985 |
|
|
if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
|
986 |
|
|
reiserfs_warning(s, "reread_meta_blocks, error reading bitmap block number %d at %ld\n", i, SB_AP_BITMAP(s)[i].bh->b_blocknr) ;
|
987 |
|
|
return 1 ;
|
988 |
|
|
}
|
989 |
|
|
}
|
990 |
|
|
return 0 ;
|
991 |
|
|
|
992 |
|
|
}
|
993 |
|
|
|
994 |
|
|
|
995 |
|
|
/////////////////////////////////////////////////////
|
996 |
|
|
// hash detection stuff
|
997 |
|
|
|
998 |
|
|
|
999 |
|
|
// if root directory is empty - we set default - Yura's - hash and
|
1000 |
|
|
// warn about it
|
1001 |
|
|
// FIXME: we look for only one name in a directory. If tea and yura
|
1002 |
|
|
// bith have the same value - we ask user to send report to the
|
1003 |
|
|
// mailing list
|
1004 |
|
|
__u32 find_hash_out (struct super_block * s)
|
1005 |
|
|
{
|
1006 |
|
|
int retval;
|
1007 |
|
|
struct inode * inode;
|
1008 |
|
|
struct cpu_key key;
|
1009 |
|
|
INITIALIZE_PATH (path);
|
1010 |
|
|
struct reiserfs_dir_entry de;
|
1011 |
|
|
__u32 hash = DEFAULT_HASH;
|
1012 |
|
|
|
1013 |
|
|
inode = s->s_root->d_inode;
|
1014 |
|
|
|
1015 |
|
|
do { // Some serious "goto"-hater was there ;)
|
1016 |
|
|
u32 teahash, r5hash, yurahash;
|
1017 |
|
|
|
1018 |
|
|
make_cpu_key (&key, inode, ~0, TYPE_DIRENTRY, 3);
|
1019 |
|
|
retval = search_by_entry_key (s, &key, &path, &de);
|
1020 |
|
|
if (retval == IO_ERROR) {
|
1021 |
|
|
pathrelse (&path);
|
1022 |
|
|
return UNSET_HASH ;
|
1023 |
|
|
}
|
1024 |
|
|
if (retval == NAME_NOT_FOUND)
|
1025 |
|
|
de.de_entry_num --;
|
1026 |
|
|
set_de_name_and_namelen (&de);
|
1027 |
|
|
if (deh_offset( &(de.de_deh[de.de_entry_num]) ) == DOT_DOT_OFFSET) {
|
1028 |
|
|
/* allow override in this case */
|
1029 |
|
|
if (reiserfs_rupasov_hash(s)) {
|
1030 |
|
|
hash = YURA_HASH ;
|
1031 |
|
|
}
|
1032 |
|
|
reiserfs_warning(s, "reiserfs: FS seems to be empty, autodetect "
|
1033 |
|
|
"is using the default hash\n");
|
1034 |
|
|
break;
|
1035 |
|
|
}
|
1036 |
|
|
r5hash=GET_HASH_VALUE (r5_hash (de.de_name, de.de_namelen));
|
1037 |
|
|
teahash=GET_HASH_VALUE (keyed_hash (de.de_name, de.de_namelen));
|
1038 |
|
|
yurahash=GET_HASH_VALUE (yura_hash (de.de_name, de.de_namelen));
|
1039 |
|
|
if ( ( (teahash == r5hash) && (GET_HASH_VALUE( deh_offset(&(de.de_deh[de.de_entry_num]))) == r5hash) ) ||
|
1040 |
|
|
( (teahash == yurahash) && (yurahash == GET_HASH_VALUE( deh_offset(&(de.de_deh[de.de_entry_num])))) ) ||
|
1041 |
|
|
( (r5hash == yurahash) && (yurahash == GET_HASH_VALUE( deh_offset(&(de.de_deh[de.de_entry_num])))) ) ) {
|
1042 |
|
|
reiserfs_warning(s, "reiserfs: Unable to automatically detect hash"
|
1043 |
|
|
"function please mount with -o hash={tea,rupasov,r5}\n");
|
1044 |
|
|
hash = UNSET_HASH;
|
1045 |
|
|
break;
|
1046 |
|
|
}
|
1047 |
|
|
if (GET_HASH_VALUE( deh_offset(&(de.de_deh[de.de_entry_num])) ) == yurahash)
|
1048 |
|
|
hash = YURA_HASH;
|
1049 |
|
|
else if (GET_HASH_VALUE( deh_offset(&(de.de_deh[de.de_entry_num])) ) == teahash)
|
1050 |
|
|
hash = TEA_HASH;
|
1051 |
|
|
else if (GET_HASH_VALUE( deh_offset(&(de.de_deh[de.de_entry_num])) ) == r5hash)
|
1052 |
|
|
hash = R5_HASH;
|
1053 |
|
|
else {
|
1054 |
|
|
reiserfs_warning(s, "reiserfs: Unrecognised hash function\n");
|
1055 |
|
|
hash = UNSET_HASH;
|
1056 |
|
|
}
|
1057 |
|
|
} while (0);
|
1058 |
|
|
|
1059 |
|
|
pathrelse (&path);
|
1060 |
|
|
return hash;
|
1061 |
|
|
}
|
1062 |
|
|
|
1063 |
|
|
// finds out which hash names are sorted with
|
1064 |
|
|
static int what_hash (struct super_block * s)
|
1065 |
|
|
{
|
1066 |
|
|
__u32 code;
|
1067 |
|
|
|
1068 |
|
|
code = sb_hash_function_code(SB_DISK_SUPER_BLOCK(s));
|
1069 |
|
|
|
1070 |
|
|
/* reiserfs_hash_detect() == true if any of the hash mount options
|
1071 |
|
|
** were used. We must check them to make sure the user isn't
|
1072 |
|
|
** using a bad hash value
|
1073 |
|
|
*/
|
1074 |
|
|
if (code == UNSET_HASH || reiserfs_hash_detect(s))
|
1075 |
|
|
code = find_hash_out (s);
|
1076 |
|
|
|
1077 |
|
|
if (code != UNSET_HASH && reiserfs_hash_detect(s)) {
|
1078 |
|
|
/* detection has found the hash, and we must check against the
|
1079 |
|
|
** mount options
|
1080 |
|
|
*/
|
1081 |
|
|
if (reiserfs_rupasov_hash(s) && code != YURA_HASH) {
|
1082 |
|
|
printk("REISERFS: Error, %s hash detected, "
|
1083 |
|
|
"unable to force rupasov hash\n", reiserfs_hashname(code)) ;
|
1084 |
|
|
code = UNSET_HASH ;
|
1085 |
|
|
} else if (reiserfs_tea_hash(s) && code != TEA_HASH) {
|
1086 |
|
|
printk("REISERFS: Error, %s hash detected, "
|
1087 |
|
|
"unable to force tea hash\n", reiserfs_hashname(code)) ;
|
1088 |
|
|
code = UNSET_HASH ;
|
1089 |
|
|
} else if (reiserfs_r5_hash(s) && code != R5_HASH) {
|
1090 |
|
|
printk("REISERFS: Error, %s hash detected, "
|
1091 |
|
|
"unable to force r5 hash\n", reiserfs_hashname(code)) ;
|
1092 |
|
|
code = UNSET_HASH ;
|
1093 |
|
|
}
|
1094 |
|
|
} else {
|
1095 |
|
|
/* find_hash_out was not called or could not determine the hash */
|
1096 |
|
|
if (reiserfs_rupasov_hash(s)) {
|
1097 |
|
|
code = YURA_HASH ;
|
1098 |
|
|
} else if (reiserfs_tea_hash(s)) {
|
1099 |
|
|
code = TEA_HASH ;
|
1100 |
|
|
} else if (reiserfs_r5_hash(s)) {
|
1101 |
|
|
code = R5_HASH ;
|
1102 |
|
|
}
|
1103 |
|
|
}
|
1104 |
|
|
|
1105 |
|
|
/* if we are mounted RW, and we have a new valid hash code, update
|
1106 |
|
|
** the super
|
1107 |
|
|
*/
|
1108 |
|
|
if (code != UNSET_HASH &&
|
1109 |
|
|
!(s->s_flags & MS_RDONLY) &&
|
1110 |
|
|
code != sb_hash_function_code(SB_DISK_SUPER_BLOCK(s))) {
|
1111 |
|
|
set_sb_hash_function_code(SB_DISK_SUPER_BLOCK(s), code);
|
1112 |
|
|
}
|
1113 |
|
|
return code;
|
1114 |
|
|
}
|
1115 |
|
|
|
1116 |
|
|
// return pointer to appropriate function
|
1117 |
|
|
static hashf_t hash_function (struct super_block * s)
|
1118 |
|
|
{
|
1119 |
|
|
switch (what_hash (s)) {
|
1120 |
|
|
case TEA_HASH:
|
1121 |
|
|
reiserfs_warning (s, "Using tea hash to sort names\n");
|
1122 |
|
|
return keyed_hash;
|
1123 |
|
|
case YURA_HASH:
|
1124 |
|
|
reiserfs_warning (s, "Using rupasov hash to sort names\n");
|
1125 |
|
|
return yura_hash;
|
1126 |
|
|
case R5_HASH:
|
1127 |
|
|
reiserfs_warning (s, "Using r5 hash to sort names\n");
|
1128 |
|
|
return r5_hash;
|
1129 |
|
|
}
|
1130 |
|
|
return NULL;
|
1131 |
|
|
}
|
1132 |
|
|
|
1133 |
|
|
// this is used to set up correct value for old partitions
|
1134 |
|
|
int function2code (hashf_t func)
|
1135 |
|
|
{
|
1136 |
|
|
if (func == keyed_hash)
|
1137 |
|
|
return TEA_HASH;
|
1138 |
|
|
if (func == yura_hash)
|
1139 |
|
|
return YURA_HASH;
|
1140 |
|
|
if (func == r5_hash)
|
1141 |
|
|
return R5_HASH;
|
1142 |
|
|
|
1143 |
|
|
BUG() ; // should never happen
|
1144 |
|
|
|
1145 |
|
|
return 0;
|
1146 |
|
|
}
|
1147 |
|
|
|
1148 |
|
|
static struct super_block * reiserfs_read_super (struct super_block * s, void * data, int silent)
|
1149 |
|
|
{
|
1150 |
|
|
int size;
|
1151 |
|
|
struct inode *root_inode;
|
1152 |
|
|
kdev_t dev = s->s_dev;
|
1153 |
|
|
int j;
|
1154 |
|
|
struct reiserfs_transaction_handle th ;
|
1155 |
|
|
int old_format = 0;
|
1156 |
|
|
unsigned long blocks;
|
1157 |
|
|
int jinit_done = 0 ;
|
1158 |
|
|
struct reiserfs_iget4_args args ;
|
1159 |
|
|
char *jdev_name;
|
1160 |
|
|
struct reiserfs_super_block * rs;
|
1161 |
|
|
|
1162 |
|
|
|
1163 |
|
|
memset (&s->u.reiserfs_sb, 0, sizeof (struct reiserfs_sb_info));
|
1164 |
|
|
/* Set default values for options: non-aggressive tails */
|
1165 |
|
|
s->u.reiserfs_sb.s_mount_opt = ( 1 << REISERFS_SMALLTAIL );
|
1166 |
|
|
/* default block allocator option: skip_busy */
|
1167 |
|
|
s->u.reiserfs_sb.s_alloc_options.bits = ( 1 << 5);
|
1168 |
|
|
/* If file grew past 4 blocks, start preallocation blocks for it. */
|
1169 |
|
|
s->u.reiserfs_sb.s_alloc_options.preallocmin = 4;
|
1170 |
|
|
/* Preallocate by 8 blocks (9-1) at once */
|
1171 |
|
|
s->u.reiserfs_sb.s_alloc_options.preallocsize = 9;
|
1172 |
|
|
|
1173 |
|
|
if (reiserfs_parse_options (s, (char *) data, &(s->u.reiserfs_sb.s_mount_opt), &blocks) == 0) {
|
1174 |
|
|
return NULL;
|
1175 |
|
|
|
1176 |
|
|
|
1177 |
|
|
|
1178 |
|
|
}
|
1179 |
|
|
|
1180 |
|
|
if (blocks) {
|
1181 |
|
|
reiserfs_warning(s,"zam-2013: reserfs resize option for remount only\n");
|
1182 |
|
|
return NULL;
|
1183 |
|
|
}
|
1184 |
|
|
|
1185 |
|
|
if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)] != 0) {
|
1186 |
|
|
/* as blocksize is set for partition we use it */
|
1187 |
|
|
size = blksize_size[MAJOR(dev)][MINOR(dev)];
|
1188 |
|
|
} else {
|
1189 |
|
|
size = BLOCK_SIZE;
|
1190 |
|
|
set_blocksize (s->s_dev, BLOCK_SIZE);
|
1191 |
|
|
}
|
1192 |
|
|
/* try old format (undistributed bitmap, super block in 8-th 1k block of a device) */
|
1193 |
|
|
if (!read_super_block (s, size, REISERFS_OLD_DISK_OFFSET_IN_BYTES))
|
1194 |
|
|
old_format = 1;
|
1195 |
|
|
/* try new format (64-th 1k block), which can contain reiserfs super block */
|
1196 |
|
|
else if (read_super_block (s, size, REISERFS_DISK_OFFSET_IN_BYTES)) {
|
1197 |
|
|
printk("sh-2021: reiserfs_read_super: can not find reiserfs on %s\n", bdevname(s->s_dev));
|
1198 |
|
|
goto error;
|
1199 |
|
|
}
|
1200 |
|
|
|
1201 |
|
|
rs = SB_DISK_SUPER_BLOCK (s);
|
1202 |
|
|
|
1203 |
|
|
/* Let's do basic sanity check to verify that underlying device is not
|
1204 |
|
|
smaller than the filesystem. If the check fails then abort and scream,
|
1205 |
|
|
because bad stuff will happen otherwise. */
|
1206 |
|
|
if ( blk_size[MAJOR(dev)][MINOR(dev)] < sb_block_count(rs)*(sb_blocksize(rs)>>10) ) {
|
1207 |
|
|
printk("Filesystem on %s cannot be mounted because it is bigger than the device\n", kdevname(dev));
|
1208 |
|
|
printk("You may need to run fsck or increase size of your LVM partition\n");
|
1209 |
|
|
printk("Or may be you forgot to reboot after fdisk when it told you to\n");
|
1210 |
|
|
return NULL;
|
1211 |
|
|
}
|
1212 |
|
|
|
1213 |
|
|
s->u.reiserfs_sb.s_mount_state = SB_REISERFS_STATE(s);
|
1214 |
|
|
s->u.reiserfs_sb.s_mount_state = REISERFS_VALID_FS ;
|
1215 |
|
|
|
1216 |
|
|
if (old_format ? read_old_bitmaps(s) : read_bitmaps(s)) {
|
1217 |
|
|
reiserfs_warning (s, "sh-2014: reiserfs_read_super: unable to read bitmap\n");
|
1218 |
|
|
goto error;
|
1219 |
|
|
}
|
1220 |
|
|
#ifdef CONFIG_REISERFS_CHECK
|
1221 |
|
|
printk("reiserfs:warning: CONFIG_REISERFS_CHECK is set ON\n");
|
1222 |
|
|
printk("reiserfs:warning: - it is slow mode for debugging.\n");
|
1223 |
|
|
#endif
|
1224 |
|
|
|
1225 |
|
|
/* fixme */
|
1226 |
|
|
jdev_name = NULL;
|
1227 |
|
|
|
1228 |
|
|
if( journal_init(s, jdev_name, old_format) ) {
|
1229 |
|
|
reiserfs_warning(s, "sh-2022: reiserfs_read_super: unable to initialize journal space\n") ;
|
1230 |
|
|
goto error ;
|
1231 |
|
|
} else {
|
1232 |
|
|
jinit_done = 1 ; /* once this is set, journal_release must be called
|
1233 |
|
|
** if we error out of the mount
|
1234 |
|
|
*/
|
1235 |
|
|
}
|
1236 |
|
|
if (reread_meta_blocks(s)) {
|
1237 |
|
|
reiserfs_warning(s, "sh-2015: reiserfs_read_super: unable to reread meta blocks after journal init\n") ;
|
1238 |
|
|
goto error ;
|
1239 |
|
|
}
|
1240 |
|
|
|
1241 |
|
|
if (replay_only (s))
|
1242 |
|
|
goto error;
|
1243 |
|
|
|
1244 |
|
|
if (is_read_only(s->s_dev) && !(s->s_flags & MS_RDONLY)) {
|
1245 |
|
|
reiserfs_warning(s, "clm-7000: Detected readonly device, marking FS readonly\n") ;
|
1246 |
|
|
s->s_flags |= MS_RDONLY ;
|
1247 |
|
|
}
|
1248 |
|
|
args.objectid = REISERFS_ROOT_PARENT_OBJECTID ;
|
1249 |
|
|
root_inode = iget4 (s, REISERFS_ROOT_OBJECTID, 0, (void *)(&args));
|
1250 |
|
|
if (!root_inode) {
|
1251 |
|
|
reiserfs_warning (s, "reiserfs_read_super: get root inode failed\n");
|
1252 |
|
|
goto error;
|
1253 |
|
|
}
|
1254 |
|
|
|
1255 |
|
|
s->s_root = d_alloc_root(root_inode);
|
1256 |
|
|
if (!s->s_root) {
|
1257 |
|
|
iput(root_inode);
|
1258 |
|
|
goto error;
|
1259 |
|
|
}
|
1260 |
|
|
|
1261 |
|
|
// define and initialize hash function
|
1262 |
|
|
s->u.reiserfs_sb.s_hash_function = hash_function (s);
|
1263 |
|
|
if (s->u.reiserfs_sb.s_hash_function == NULL) {
|
1264 |
|
|
dput(s->s_root) ;
|
1265 |
|
|
s->s_root = NULL ;
|
1266 |
|
|
goto error ;
|
1267 |
|
|
}
|
1268 |
|
|
|
1269 |
|
|
if (is_reiserfs_3_5 (rs) || (is_reiserfs_jr (rs) && SB_VERSION (s) == REISERFS_VERSION_1))
|
1270 |
|
|
set_bit(REISERFS_3_5, &(s->u.reiserfs_sb.s_properties));
|
1271 |
|
|
else
|
1272 |
|
|
set_bit(REISERFS_3_6, &(s->u.reiserfs_sb.s_properties));
|
1273 |
|
|
|
1274 |
|
|
if (!(s->s_flags & MS_RDONLY)) {
|
1275 |
|
|
|
1276 |
|
|
journal_begin(&th, s, 1) ;
|
1277 |
|
|
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;
|
1278 |
|
|
|
1279 |
|
|
set_sb_umount_state( rs, REISERFS_ERROR_FS );
|
1280 |
|
|
set_sb_fs_state (rs, 0);
|
1281 |
|
|
|
1282 |
|
|
if (old_format_only(s)) {
|
1283 |
|
|
/* filesystem of format 3.5 either with standard or non-standard
|
1284 |
|
|
journal */
|
1285 |
|
|
if (convert_reiserfs (s)) {
|
1286 |
|
|
/* and -o conv is given */
|
1287 |
|
|
reiserfs_warning (s, "reiserfs: converting 3.5 filesystem to the 3.6 format\n") ;
|
1288 |
|
|
|
1289 |
|
|
if (is_reiserfs_3_5 (rs))
|
1290 |
|
|
/* put magic string of 3.6 format. 2.2 will not be able to
|
1291 |
|
|
mount this filesystem anymore */
|
1292 |
|
|
memcpy (rs->s_v1.s_magic, reiserfs_3_6_magic_string,
|
1293 |
|
|
sizeof (reiserfs_3_6_magic_string));
|
1294 |
|
|
|
1295 |
|
|
set_sb_version(rs,REISERFS_VERSION_2);
|
1296 |
|
|
reiserfs_convert_objectid_map_v1(s) ;
|
1297 |
|
|
set_bit(REISERFS_3_6, &(s->u.reiserfs_sb.s_properties));
|
1298 |
|
|
clear_bit(REISERFS_3_5, &(s->u.reiserfs_sb.s_properties));
|
1299 |
|
|
}
|
1300 |
|
|
}
|
1301 |
|
|
|
1302 |
|
|
journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s));
|
1303 |
|
|
journal_end(&th, s, 1) ;
|
1304 |
|
|
|
1305 |
|
|
/* look for files which were to be removed in previous session */
|
1306 |
|
|
finish_unfinished (s);
|
1307 |
|
|
|
1308 |
|
|
s->s_dirt = 0;
|
1309 |
|
|
}
|
1310 |
|
|
|
1311 |
|
|
// mark hash in super block: it could be unset. overwrite should be ok
|
1312 |
|
|
set_sb_hash_function_code( rs, function2code(s->u.reiserfs_sb.s_hash_function ) );
|
1313 |
|
|
|
1314 |
|
|
handle_attrs( s );
|
1315 |
|
|
|
1316 |
|
|
reiserfs_proc_info_init( s );
|
1317 |
|
|
reiserfs_proc_register( s, "version", reiserfs_version_in_proc );
|
1318 |
|
|
reiserfs_proc_register( s, "super", reiserfs_super_in_proc );
|
1319 |
|
|
reiserfs_proc_register( s, "per-level", reiserfs_per_level_in_proc );
|
1320 |
|
|
reiserfs_proc_register( s, "bitmap", reiserfs_bitmap_in_proc );
|
1321 |
|
|
reiserfs_proc_register( s, "on-disk-super", reiserfs_on_disk_super_in_proc );
|
1322 |
|
|
reiserfs_proc_register( s, "oidmap", reiserfs_oidmap_in_proc );
|
1323 |
|
|
reiserfs_proc_register( s, "journal", reiserfs_journal_in_proc );
|
1324 |
|
|
init_waitqueue_head (&(s->u.reiserfs_sb.s_wait));
|
1325 |
|
|
|
1326 |
|
|
return s;
|
1327 |
|
|
|
1328 |
|
|
error:
|
1329 |
|
|
if (jinit_done) { /* kill the commit thread, free journal ram */
|
1330 |
|
|
journal_release_error(NULL, s) ;
|
1331 |
|
|
}
|
1332 |
|
|
if (SB_DISK_SUPER_BLOCK (s)) {
|
1333 |
|
|
for (j = 0; j < SB_BMAP_NR (s); j ++) {
|
1334 |
|
|
if (SB_AP_BITMAP (s))
|
1335 |
|
|
brelse (SB_AP_BITMAP (s)[j].bh);
|
1336 |
|
|
}
|
1337 |
|
|
if (SB_AP_BITMAP (s))
|
1338 |
|
|
vfree (SB_AP_BITMAP (s));
|
1339 |
|
|
}
|
1340 |
|
|
if (SB_BUFFER_WITH_SB (s))
|
1341 |
|
|
brelse(SB_BUFFER_WITH_SB (s));
|
1342 |
|
|
|
1343 |
|
|
return NULL;
|
1344 |
|
|
}
|
1345 |
|
|
|
1346 |
|
|
|
1347 |
|
|
static int reiserfs_statfs (struct super_block * s, struct statfs * buf)
|
1348 |
|
|
{
|
1349 |
|
|
struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK (s);
|
1350 |
|
|
|
1351 |
|
|
buf->f_namelen = (REISERFS_MAX_NAME (s->s_blocksize));
|
1352 |
|
|
buf->f_ffree = -1;
|
1353 |
|
|
buf->f_files = -1;
|
1354 |
|
|
buf->f_bfree = sb_free_blocks(rs);
|
1355 |
|
|
buf->f_bavail = buf->f_bfree;
|
1356 |
|
|
buf->f_blocks = sb_block_count(rs) - sb_bmap_nr(rs) - 1;
|
1357 |
|
|
buf->f_bsize = s->s_blocksize;
|
1358 |
|
|
/* changed to accomodate gcc folks.*/
|
1359 |
|
|
buf->f_type = REISERFS_SUPER_MAGIC;
|
1360 |
|
|
return 0;
|
1361 |
|
|
}
|
1362 |
|
|
|
1363 |
|
|
static DECLARE_FSTYPE_DEV(reiserfs_fs_type,"reiserfs",reiserfs_read_super);
|
1364 |
|
|
|
1365 |
|
|
static int __init init_reiserfs_fs (void)
|
1366 |
|
|
{
|
1367 |
|
|
reiserfs_proc_info_global_init();
|
1368 |
|
|
reiserfs_proc_register_global( "version",
|
1369 |
|
|
reiserfs_global_version_in_proc );
|
1370 |
|
|
return register_filesystem(&reiserfs_fs_type);
|
1371 |
|
|
}
|
1372 |
|
|
|
1373 |
|
|
MODULE_DESCRIPTION("ReiserFS journaled filesystem");
|
1374 |
|
|
MODULE_AUTHOR("Hans Reiser <reiser@namesys.com>");
|
1375 |
|
|
MODULE_LICENSE("GPL");
|
1376 |
|
|
EXPORT_NO_SYMBOLS;
|
1377 |
|
|
|
1378 |
|
|
static void __exit exit_reiserfs_fs(void)
|
1379 |
|
|
{
|
1380 |
|
|
reiserfs_proc_unregister_global( "version" );
|
1381 |
|
|
reiserfs_proc_info_global_done();
|
1382 |
|
|
unregister_filesystem(&reiserfs_fs_type);
|
1383 |
|
|
}
|
1384 |
|
|
|
1385 |
|
|
|
1386 |
|
|
module_init(init_reiserfs_fs) ;
|
1387 |
|
|
module_exit(exit_reiserfs_fs) ;
|
1388 |
|
|
|
1389 |
|
|
|
1390 |
|
|
|