Blame view

fs/reiserfs/super.c 65.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
  /*
   * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
   *
   * Trivial changes by Alan Cox to add the LFS fixes
   *
   * Trivial Changes:
   * Rights granted to Hans Reiser to redistribute under other terms providing
   * he accepts all liability including but not limited to patent, fitness
   * for purpose, and direct or indirect claims arising from failure to perform.
   *
   * NO WARRANTY
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
14
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
19
20
  #include <linux/vmalloc.h>
  #include <linux/time.h>
  #include <asm/uaccess.h>
  #include <linux/reiserfs_fs.h>
  #include <linux/reiserfs_acl.h>
  #include <linux/reiserfs_xattr.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
  #include <linux/init.h>
  #include <linux/blkdev.h>
  #include <linux/buffer_head.h>
a56942551   Christoph Hellwig   knfsd: exportfs: ...
24
  #include <linux/exportfs.h>
74abb9890   Jan Kara   quota: move funct...
25
  #include <linux/quotaops.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
  #include <linux/vfs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
  #include <linux/mount.h>
  #include <linux/namei.h>
651d06230   Coly Li   fs/reiserfs: retu...
29
  #include <linux/crc32.h>
c3aa07764   Jan Kara   reiserfs: Properl...
30
  #include <linux/seq_file.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
33
34
35
36
  
  struct file_system_type reiserfs_fs_type;
  
  static const char reiserfs_3_5_magic_string[] = REISERFS_SUPER_MAGIC_STRING;
  static const char reiserfs_3_6_magic_string[] = REISER2FS_SUPER_MAGIC_STRING;
  static const char reiserfs_jr_magic_string[] = REISER2FS_JR_SUPER_MAGIC_STRING;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
37
  int is_reiserfs_3_5(struct reiserfs_super_block *rs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
39
40
  	return !strncmp(rs->s_v1.s_magic, reiserfs_3_5_magic_string,
  			strlen(reiserfs_3_5_magic_string));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
42
  int is_reiserfs_3_6(struct reiserfs_super_block *rs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
44
45
  	return !strncmp(rs->s_v1.s_magic, reiserfs_3_6_magic_string,
  			strlen(reiserfs_3_6_magic_string));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
47
  int is_reiserfs_jr(struct reiserfs_super_block *rs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
49
50
  	return !strncmp(rs->s_v1.s_magic, reiserfs_jr_magic_string,
  			strlen(reiserfs_jr_magic_string));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
52
  static int is_any_reiserfs_magic_string(struct reiserfs_super_block *rs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
54
55
  	return (is_reiserfs_3_5(rs) || is_reiserfs_3_6(rs) ||
  		is_reiserfs_jr(rs));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
57
  static int reiserfs_remount(struct super_block *s, int *flags, char *data);
726c33422   David Howells   [PATCH] VFS: Perm...
58
  static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf);
c3aa07764   Jan Kara   reiserfs: Properl...
59
  void show_alloc_options(struct seq_file *seq, struct super_block *s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60

bd4c625c0   Linus Torvalds   reiserfs: run scr...
61
  static int reiserfs_sync_fs(struct super_block *s, int wait)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
  {
5af7926ff   Christoph Hellwig   enforce ->sync_fs...
63
64
65
66
67
68
69
70
71
  	struct reiserfs_transaction_handle th;
  
  	reiserfs_write_lock(s);
  	if (!journal_begin(&th, s, 1))
  		if (!journal_end_sync(&th, s, 1))
  			reiserfs_flush_old_commits(s);
  	s->s_dirt = 0;	/* Even if it's not true.
  			 * We'll loop forever in sync_supers otherwise */
  	reiserfs_write_unlock(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
72
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
75
76
  }
  
  static void reiserfs_write_super(struct super_block *s)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
77
  	reiserfs_sync_fs(s, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  }
c4be0c1dc   Takashi Sato   filesystem freeze...
79
  static int reiserfs_freeze(struct super_block *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  	struct reiserfs_transaction_handle th;
  	reiserfs_write_lock(s);
  	if (!(s->s_flags & MS_RDONLY)) {
  		int err = journal_begin(&th, s, 1);
  		if (err) {
  			reiserfs_block_writes(&th);
  		} else {
  			reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s),
  						     1);
  			journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
  			reiserfs_block_writes(&th);
  			journal_end_sync(&th, s, 1);
  		}
  	}
  	s->s_dirt = 0;
  	reiserfs_write_unlock(s);
c4be0c1dc   Takashi Sato   filesystem freeze...
97
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  }
c4be0c1dc   Takashi Sato   filesystem freeze...
99
  static int reiserfs_unfreeze(struct super_block *s)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
100
101
  {
  	reiserfs_allow_writes(s);
c4be0c1dc   Takashi Sato   filesystem freeze...
102
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
104
  extern const struct in_core_key MAX_IN_CORE_KEY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
107
108
109
110
111
112
  
  /* this is used to delete "save link" when there are no items of a
     file it points to. It can either happen if unlink is completed but
     "save unlink" removal, or if file has both unlink and truncate
     pending and as unlink completes first (because key of "save link"
     protecting unlink is bigger that a key lf "save link" which
     protects truncate), so there left no items to make truncate
     completion on */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
113
114
  static int remove_save_link_only(struct super_block *s,
  				 struct reiserfs_key *key, int oid_free)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  	struct reiserfs_transaction_handle th;
  	int err;
  
  	/* we are going to do one balancing */
  	err = journal_begin(&th, s, JOURNAL_PER_BALANCE_CNT);
  	if (err)
  		return err;
  
  	reiserfs_delete_solid_item(&th, NULL, key);
  	if (oid_free)
  		/* removals are protected by direct items */
  		reiserfs_release_objectid(&th, le32_to_cpu(key->k_objectid));
  
  	return journal_end(&th, s, JOURNAL_PER_BALANCE_CNT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
131

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
134
  #ifdef CONFIG_QUOTA
  static int reiserfs_quota_on_mount(struct super_block *, int);
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
135

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  /* look for uncompleted unlinks and truncates and complete them */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
137
  static int finish_unfinished(struct super_block *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
139
140
  	INITIALIZE_PATH(path);
  	struct cpu_key max_cpu_key, obj_key;
fb46f341d   Lepton Wu   reiserfs: workaro...
141
  	struct reiserfs_key save_link_key, last_inode_key;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
142
143
144
145
146
147
148
149
  	int retval = 0;
  	struct item_head *ih;
  	struct buffer_head *bh;
  	int item_pos;
  	char *item;
  	int done;
  	struct inode *inode;
  	int truncate;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  #ifdef CONFIG_QUOTA
bd4c625c0   Linus Torvalds   reiserfs: run scr...
151
152
  	int i;
  	int ms_active_set;
f4b113ae6   Jan Kara   reiserfs: Fix res...
153
  	int quota_enabled[MAXQUOTAS];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
155
156
157
158
159
160
161
  
  	/* compose key to look for "save" links */
  	max_cpu_key.version = KEY_FORMAT_3_5;
  	max_cpu_key.on_disk_key.k_dir_id = ~0U;
  	max_cpu_key.on_disk_key.k_objectid = ~0U;
  	set_cpu_key_k_offset(&max_cpu_key, ~0U);
  	max_cpu_key.key_length = 3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162

fb46f341d   Lepton Wu   reiserfs: workaro...
163
  	memset(&last_inode_key, 0, sizeof(last_inode_key));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  #ifdef CONFIG_QUOTA
bd4c625c0   Linus Torvalds   reiserfs: run scr...
165
166
167
168
169
170
171
172
173
  	/* Needed for iput() to work correctly and not trash data */
  	if (s->s_flags & MS_ACTIVE) {
  		ms_active_set = 0;
  	} else {
  		ms_active_set = 1;
  		s->s_flags |= MS_ACTIVE;
  	}
  	/* Turn on quotas so that they are updated correctly */
  	for (i = 0; i < MAXQUOTAS; i++) {
f4b113ae6   Jan Kara   reiserfs: Fix res...
174
  		quota_enabled[i] = 1;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
175
  		if (REISERFS_SB(s)->s_qf_names[i]) {
f4b113ae6   Jan Kara   reiserfs: Fix res...
176
177
178
179
180
181
182
  			int ret;
  
  			if (sb_has_quota_active(s, i)) {
  				quota_enabled[i] = 0;
  				continue;
  			}
  			ret = reiserfs_quota_on_mount(s, i);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
183
  			if (ret < 0)
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
184
185
186
  				reiserfs_warning(s, "reiserfs-2500",
  						 "cannot turn on journaled "
  						 "quota: error %d", ret);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
187
188
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
190
191
192
193
194
195
  
  	done = 0;
  	REISERFS_SB(s)->s_is_unlinked_ok = 1;
  	while (!retval) {
  		retval = search_item(s, &max_cpu_key, &path);
  		if (retval != ITEM_NOT_FOUND) {
0030b6457   Jeff Mahoney   reiserfs: use rei...
196
197
  			reiserfs_error(s, "vs-2140",
  				       "search_by_key returned %d", retval);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
198
199
200
201
202
203
  			break;
  		}
  
  		bh = get_last_bh(&path);
  		item_pos = get_item_pos(&path);
  		if (item_pos != B_NR_ITEMS(bh)) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
204
205
  			reiserfs_warning(s, "vs-2060",
  					 "wrong position found");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  			break;
  		}
  		item_pos--;
  		ih = B_N_PITEM_HEAD(bh, item_pos);
  
  		if (le32_to_cpu(ih->ih_key.k_dir_id) != MAX_KEY_OBJECTID)
  			/* there are no "save" links anymore */
  			break;
  
  		save_link_key = ih->ih_key;
  		if (is_indirect_le_ih(ih))
  			truncate = 1;
  		else
  			truncate = 0;
  
  		/* reiserfs_iget needs k_dirid and k_objectid only */
  		item = B_I_PITEM(bh, ih);
  		obj_key.on_disk_key.k_dir_id = le32_to_cpu(*(__le32 *) item);
  		obj_key.on_disk_key.k_objectid =
  		    le32_to_cpu(ih->ih_key.k_objectid);
  		obj_key.on_disk_key.k_offset = 0;
  		obj_key.on_disk_key.k_type = 0;
  
  		pathrelse(&path);
  
  		inode = reiserfs_iget(s, &obj_key);
  		if (!inode) {
  			/* the unlink almost completed, it just did not manage to remove
  			   "save" link and release objectid */
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
235
  			reiserfs_warning(s, "vs-2180", "iget failed for %K",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
236
237
238
239
240
241
242
  					 &obj_key);
  			retval = remove_save_link_only(s, &save_link_key, 1);
  			continue;
  		}
  
  		if (!truncate && inode->i_nlink) {
  			/* file is not unlinked */
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
243
244
  			reiserfs_warning(s, "vs-2185",
  					 "file %K is not unlinked",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
245
246
247
248
  					 &obj_key);
  			retval = remove_save_link_only(s, &save_link_key, 0);
  			continue;
  		}
871a29315   Christoph Hellwig   dquot: cleanup dq...
249
  		dquot_initialize(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
250
251
252
253
254
255
  
  		if (truncate && S_ISDIR(inode->i_mode)) {
  			/* We got a truncate request for a dir which is impossible.
  			   The only imaginable way is to execute unfinished truncate request
  			   then boot into old kernel, remove the file and create dir with
  			   the same key. */
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
256
257
258
  			reiserfs_warning(s, "green-2101",
  					 "impossible truncate on a "
  					 "directory %k. Please report",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  					 INODE_PKEY(inode));
  			retval = remove_save_link_only(s, &save_link_key, 0);
  			truncate = 0;
  			iput(inode);
  			continue;
  		}
  
  		if (truncate) {
  			REISERFS_I(inode)->i_flags |=
  			    i_link_saved_truncate_mask;
  			/* not completed truncate found. New size was committed together
  			   with "save" link */
  			reiserfs_info(s, "Truncating %k to %Ld ..",
  				      INODE_PKEY(inode), inode->i_size);
  			reiserfs_truncate_file(inode,
  					       0
  					       /*don't update modification time */
  					       );
  			retval = remove_save_link(inode, truncate);
  		} else {
  			REISERFS_I(inode)->i_flags |= i_link_saved_unlink_mask;
  			/* not completed unlink (rmdir) found */
  			reiserfs_info(s, "Removing %k..", INODE_PKEY(inode));
fb46f341d   Lepton Wu   reiserfs: workaro...
282
283
284
285
286
287
  			if (memcmp(&last_inode_key, INODE_PKEY(inode),
  					sizeof(last_inode_key))){
  				last_inode_key = *INODE_PKEY(inode);
  				/* removal gets completed in iput */
  				retval = 0;
  			} else {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
288
289
290
291
292
  				reiserfs_warning(s, "super-2189", "Dead loop "
  						 "in finish_unfinished "
  						 "detected, just remove "
  						 "save link
  ");
fb46f341d   Lepton Wu   reiserfs: workaro...
293
294
295
  				retval = remove_save_link_only(s,
  							&save_link_key, 0);
  			}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
296
297
298
299
300
301
302
303
  		}
  
  		iput(inode);
  		printk("done
  ");
  		done++;
  	}
  	REISERFS_SB(s)->s_is_unlinked_ok = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
  #ifdef CONFIG_QUOTA
bd4c625c0   Linus Torvalds   reiserfs: run scr...
305
306
  	/* Turn quotas off */
  	for (i = 0; i < MAXQUOTAS; i++) {
f4b113ae6   Jan Kara   reiserfs: Fix res...
307
  		if (sb_dqopt(s)->files[i] && quota_enabled[i])
287a80958   Christoph Hellwig   quota: rename def...
308
  			dquot_quota_off(s, i);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
309
310
311
312
  	}
  	if (ms_active_set)
  		/* Restore the flag back */
  		s->s_flags &= ~MS_ACTIVE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
314
315
316
317
318
319
  	pathrelse(&path);
  	if (done)
  		reiserfs_info(s, "There were %d uncompleted unlinks/truncates. "
  			      "Completed
  ", done);
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
321

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
  /* to protect file being unlinked from getting lost we "safe" link files
     being unlinked. This link will be deleted in the same transaction with last
3a4fa0a25   Robert P. J. Day   Fix misspellings ...
324
     item of file. mounting the filesystem we scan all these links and remove
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
     files which almost got lost */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
326
327
  void add_save_link(struct reiserfs_transaction_handle *th,
  		   struct inode *inode, int truncate)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
  	INITIALIZE_PATH(path);
  	int retval;
  	struct cpu_key key;
  	struct item_head ih;
  	__le32 link;
  
  	BUG_ON(!th->t_trans_id);
  
  	/* file can only get one "save link" of each kind */
  	RFALSE(truncate &&
  	       (REISERFS_I(inode)->i_flags & i_link_saved_truncate_mask),
  	       "saved link already exists for truncated inode %lx",
  	       (long)inode->i_ino);
  	RFALSE(!truncate &&
  	       (REISERFS_I(inode)->i_flags & i_link_saved_unlink_mask),
  	       "saved link already exists for unlinked inode %lx",
  	       (long)inode->i_ino);
  
  	/* setup key of "save" link */
  	key.version = KEY_FORMAT_3_5;
  	key.on_disk_key.k_dir_id = MAX_KEY_OBJECTID;
  	key.on_disk_key.k_objectid = inode->i_ino;
  	if (!truncate) {
  		/* unlink, rmdir, rename */
  		set_cpu_key_k_offset(&key, 1 + inode->i_sb->s_blocksize);
  		set_cpu_key_k_type(&key, TYPE_DIRECT);
  
  		/* item head of "safe" link */
  		make_le_item_head(&ih, &key, key.version,
  				  1 + inode->i_sb->s_blocksize, TYPE_DIRECT,
  				  4 /*length */ , 0xffff /*free space */ );
  	} else {
  		/* truncate */
  		if (S_ISDIR(inode->i_mode))
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
363
364
365
  			reiserfs_warning(inode->i_sb, "green-2102",
  					 "Adding a truncate savelink for "
  					 "a directory %k! Please report",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
366
367
368
369
370
371
372
373
374
375
376
377
378
379
  					 INODE_PKEY(inode));
  		set_cpu_key_k_offset(&key, 1);
  		set_cpu_key_k_type(&key, TYPE_INDIRECT);
  
  		/* item head of "safe" link */
  		make_le_item_head(&ih, &key, key.version, 1, TYPE_INDIRECT,
  				  4 /*length */ , 0 /*free space */ );
  	}
  	key.key_length = 3;
  
  	/* look for its place in the tree */
  	retval = search_item(inode->i_sb, &key, &path);
  	if (retval != ITEM_NOT_FOUND) {
  		if (retval != -ENOSPC)
0030b6457   Jeff Mahoney   reiserfs: use rei...
380
381
382
  			reiserfs_error(inode->i_sb, "vs-2100",
  				       "search_by_key (%K) returned %d", &key,
  				       retval);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
383
384
385
  		pathrelse(&path);
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386

bd4c625c0   Linus Torvalds   reiserfs: run scr...
387
388
  	/* body of "save" link */
  	link = INODE_PKEY(inode)->k_dir_id;
25985edce   Lucas De Marchi   Fix common misspe...
389
  	/* put "save" link into tree, don't charge quota to anyone */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
390
391
392
393
  	retval =
  	    reiserfs_insert_item(th, &path, &key, &ih, NULL, (char *)&link);
  	if (retval) {
  		if (retval != -ENOSPC)
0030b6457   Jeff Mahoney   reiserfs: use rei...
394
395
  			reiserfs_error(inode->i_sb, "vs-2120",
  				       "insert_item returned %d", retval);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
396
397
398
399
400
401
402
403
  	} else {
  		if (truncate)
  			REISERFS_I(inode)->i_flags |=
  			    i_link_saved_truncate_mask;
  		else
  			REISERFS_I(inode)->i_flags |= i_link_saved_unlink_mask;
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
405
  
  /* this opens transaction unlike add_save_link */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
406
  int remove_save_link(struct inode *inode, int truncate)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
  	struct reiserfs_transaction_handle th;
  	struct reiserfs_key key;
  	int err;
  
  	/* we are going to do one balancing only */
  	err = journal_begin(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT);
  	if (err)
  		return err;
  
  	/* setup key of "save" link */
  	key.k_dir_id = cpu_to_le32(MAX_KEY_OBJECTID);
  	key.k_objectid = INODE_PKEY(inode)->k_objectid;
  	if (!truncate) {
  		/* unlink, rmdir, rename */
  		set_le_key_k_offset(KEY_FORMAT_3_5, &key,
  				    1 + inode->i_sb->s_blocksize);
  		set_le_key_k_type(KEY_FORMAT_3_5, &key, TYPE_DIRECT);
  	} else {
  		/* truncate */
  		set_le_key_k_offset(KEY_FORMAT_3_5, &key, 1);
  		set_le_key_k_type(KEY_FORMAT_3_5, &key, TYPE_INDIRECT);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430

bd4c625c0   Linus Torvalds   reiserfs: run scr...
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  	if ((truncate &&
  	     (REISERFS_I(inode)->i_flags & i_link_saved_truncate_mask)) ||
  	    (!truncate &&
  	     (REISERFS_I(inode)->i_flags & i_link_saved_unlink_mask)))
  		/* don't take quota bytes from anywhere */
  		reiserfs_delete_solid_item(&th, NULL, &key);
  	if (!truncate) {
  		reiserfs_release_objectid(&th, inode->i_ino);
  		REISERFS_I(inode)->i_flags &= ~i_link_saved_unlink_mask;
  	} else
  		REISERFS_I(inode)->i_flags &= ~i_link_saved_truncate_mask;
  
  	return journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445

edc666e2f   David Howells   [PATCH] ReiserFS:...
446
  static void reiserfs_kill_sb(struct super_block *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
  {
edc666e2f   David Howells   [PATCH] ReiserFS:...
448
  	if (REISERFS_SB(s)) {
a9e36da65   Jeff Mahoney   reiserfs: Force i...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
  		/*
  		 * Force any pending inode evictions to occur now. Any
  		 * inodes to be removed that have extended attributes
  		 * associated with them need to clean them up before
  		 * we can release the extended attribute root dentries.
  		 * shrink_dcache_for_umount will BUG if we don't release
  		 * those before it's called so ->put_super is too late.
  		 */
  		shrink_dcache_sb(s);
  
  		dput(REISERFS_SB(s)->xattr_root);
  		REISERFS_SB(s)->xattr_root = NULL;
  		dput(REISERFS_SB(s)->priv_root);
  		REISERFS_SB(s)->priv_root = NULL;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
463
  	}
edc666e2f   David Howells   [PATCH] ReiserFS:...
464
465
466
467
468
469
470
  	kill_block_super(s);
  }
  
  static void reiserfs_put_super(struct super_block *s)
  {
  	struct reiserfs_transaction_handle th;
  	th.t_trans_id = 0;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
471

e0ccfd959   Christoph Hellwig   quota: move unmou...
472
  	dquot_disable(s, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
473
  	reiserfs_write_lock(s);
6cfd01484   Christoph Hellwig   push BKL down int...
474

8c85e1251   Christoph Hellwig   remove ->write_su...
475
476
  	if (s->s_dirt)
  		reiserfs_write_super(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
  	/* change file system state to current state if it was mounted with read-write permissions */
  	if (!(s->s_flags & MS_RDONLY)) {
  		if (!journal_begin(&th, s, 10)) {
  			reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s),
  						     1);
  			set_sb_umount_state(SB_DISK_SUPER_BLOCK(s),
  					    REISERFS_SB(s)->s_mount_state);
  			journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
  		}
  	}
  
  	/* note, journal_release checks for readonly mount, and can decide not
  	 ** to do a journal_end
  	 */
  	journal_release(&th, s);
5065227b4   Jeff Mahoney   [PATCH] reiserfs:...
492
  	reiserfs_free_bitmap_cache(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
493
494
495
496
  
  	brelse(SB_BUFFER_WITH_SB(s));
  
  	print_statistics(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
497
  	if (REISERFS_SB(s)->reserved_blocks != 0) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
498
  		reiserfs_warning(s, "green-2005", "reserved blocks left %d",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
499
500
501
502
  				 REISERFS_SB(s)->reserved_blocks);
  	}
  
  	reiserfs_proc_info_done(s);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
503
504
  	reiserfs_write_unlock(s);
  	mutex_destroy(&REISERFS_SB(s)->lock);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
505
506
  	kfree(s->s_fs_info);
  	s->s_fs_info = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
507
  }
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
508
  static struct kmem_cache *reiserfs_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
510
511
512
  
  static struct inode *reiserfs_alloc_inode(struct super_block *sb)
  {
  	struct reiserfs_inode_info *ei;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
513
  	ei = (struct reiserfs_inode_info *)
e94b17660   Christoph Lameter   [PATCH] slab: rem...
514
  	    kmem_cache_alloc(reiserfs_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
  	if (!ei)
  		return NULL;
0e4f6a791   Al Viro   Fix reiserfs_file...
517
518
  	atomic_set(&ei->openers, 0);
  	mutex_init(&ei->tailpack);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
520
  	return &ei->vfs_inode;
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
521
  static void reiserfs_i_callback(struct rcu_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
  {
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
523
  	struct inode *inode = container_of(head, struct inode, i_rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524
525
  	kmem_cache_free(reiserfs_inode_cachep, REISERFS_I(inode));
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
526
527
528
529
  static void reiserfs_destroy_inode(struct inode *inode)
  {
  	call_rcu(&inode->i_rcu, reiserfs_i_callback);
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
530
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
532
  	struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *)foo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533

a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
534
535
  	INIT_LIST_HEAD(&ei->i_prealloc_list);
  	inode_init_once(&ei->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
537

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
539
540
  static int init_inodecache(void)
  {
  	reiserfs_inode_cachep = kmem_cache_create("reiser_inode_cache",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
541
542
  						  sizeof(struct
  							 reiserfs_inode_info),
fffb60f93   Paul Jackson   [PATCH] cpuset me...
543
544
  						  0, (SLAB_RECLAIM_ACCOUNT|
  							SLAB_MEM_SPREAD),
20c2df83d   Paul Mundt   mm: Remove slab d...
545
  						  init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
547
548
549
550
551
552
  	if (reiserfs_inode_cachep == NULL)
  		return -ENOMEM;
  	return 0;
  }
  
  static void destroy_inodecache(void)
  {
1a1d92c10   Alexey Dobriyan   [PATCH] Really ig...
553
  	kmem_cache_destroy(reiserfs_inode_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
555
556
  }
  
  /* we don't mark inodes dirty, we just log them */
aa3857295   Christoph Hellwig   fs: pass exact ty...
557
  static void reiserfs_dirty_inode(struct inode *inode, int flags)
bd4c625c0   Linus Torvalds   reiserfs: run scr...
558
559
560
561
  {
  	struct reiserfs_transaction_handle th;
  
  	int err = 0;
dc8f6d893   Frederic Weisbecker   kill-the-BKL/reis...
562
  	int lock_depth;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
563
  	if (inode->i_sb->s_flags & MS_RDONLY) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
564
565
  		reiserfs_warning(inode->i_sb, "clm-6006",
  				 "writing inode %lu on readonly FS",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
566
567
568
  				 inode->i_ino);
  		return;
  	}
dc8f6d893   Frederic Weisbecker   kill-the-BKL/reis...
569
  	lock_depth = reiserfs_write_lock_once(inode->i_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
570
571
572
573
574
  
  	/* this is really only used for atime updates, so they don't have
  	 ** to be included in O_SYNC or fsync
  	 */
  	err = journal_begin(&th, inode->i_sb, 1);
dc8f6d893   Frederic Weisbecker   kill-the-BKL/reis...
575
576
  	if (err)
  		goto out;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
577
578
  	reiserfs_update_sd(&th, inode);
  	journal_end(&th, inode->i_sb, 1);
dc8f6d893   Frederic Weisbecker   kill-the-BKL/reis...
579
580
581
  
  out:
  	reiserfs_write_unlock_once(inode->i_sb, lock_depth);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
  }
c3aa07764   Jan Kara   reiserfs: Properl...
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
  static int reiserfs_show_options(struct seq_file *seq, struct dentry *root)
  {
  	struct super_block *s = root->d_sb;
  	struct reiserfs_journal *journal = SB_JOURNAL(s);
  	long opts = REISERFS_SB(s)->s_mount_opt;
  
  	if (opts & (1 << REISERFS_LARGETAIL))
  		seq_puts(seq, ",tails=on");
  	else if (!(opts & (1 << REISERFS_SMALLTAIL)))
  		seq_puts(seq, ",notail");
  	/* tails=small is default so we don't show it */
  
  	if (!(opts & (1 << REISERFS_BARRIER_FLUSH)))
  		seq_puts(seq, ",barrier=none");
  	/* barrier=flush is default so we don't show it */
  
  	if (opts & (1 << REISERFS_ERROR_CONTINUE))
  		seq_puts(seq, ",errors=continue");
  	else if (opts & (1 << REISERFS_ERROR_PANIC))
  		seq_puts(seq, ",errors=panic");
  	/* errors=ro is default so we don't show it */
  
  	if (opts & (1 << REISERFS_DATA_LOG))
  		seq_puts(seq, ",data=journal");
  	else if (opts & (1 << REISERFS_DATA_WRITEBACK))
  		seq_puts(seq, ",data=writeback");
  	/* data=ordered is default so we don't show it */
  
  	if (opts & (1 << REISERFS_ATTRS))
  		seq_puts(seq, ",attrs");
  
  	if (opts & (1 << REISERFS_XATTRS_USER))
  		seq_puts(seq, ",user_xattr");
  
  	if (opts & (1 << REISERFS_EXPOSE_PRIVROOT))
  		seq_puts(seq, ",expose_privroot");
  
  	if (opts & (1 << REISERFS_POSIXACL))
  		seq_puts(seq, ",acl");
  
  	if (REISERFS_SB(s)->s_jdev)
  		seq_printf(seq, ",jdev=%s", REISERFS_SB(s)->s_jdev);
  
  	if (journal->j_max_commit_age != journal->j_default_max_commit_age)
  		seq_printf(seq, ",commit=%d", journal->j_max_commit_age);
  
  #ifdef CONFIG_QUOTA
  	if (REISERFS_SB(s)->s_qf_names[USRQUOTA])
  		seq_printf(seq, ",usrjquota=%s", REISERFS_SB(s)->s_qf_names[USRQUOTA]);
  	else if (opts & (1 << REISERFS_USRQUOTA))
  		seq_puts(seq, ",usrquota");
  	if (REISERFS_SB(s)->s_qf_names[GRPQUOTA])
  		seq_printf(seq, ",grpjquota=%s", REISERFS_SB(s)->s_qf_names[GRPQUOTA]);
  	else if (opts & (1 << REISERFS_GRPQUOTA))
  		seq_puts(seq, ",grpquota");
  	if (REISERFS_SB(s)->s_jquota_fmt) {
  		if (REISERFS_SB(s)->s_jquota_fmt == QFMT_VFS_OLD)
  			seq_puts(seq, ",jqfmt=vfsold");
  		else if (REISERFS_SB(s)->s_jquota_fmt == QFMT_VFS_V0)
  			seq_puts(seq, ",jqfmt=vfsv0");
  	}
  #endif
  
  	/* Block allocator options */
  	if (opts & (1 << REISERFS_NO_BORDER))
  		seq_puts(seq, ",block-allocator=noborder");
  	if (opts & (1 << REISERFS_NO_UNHASHED_RELOCATION))
  		seq_puts(seq, ",block-allocator=no_unhashed_relocation");
  	if (opts & (1 << REISERFS_HASHED_RELOCATION))
  		seq_puts(seq, ",block-allocator=hashed_relocation");
  	if (opts & (1 << REISERFS_TEST4))
  		seq_puts(seq, ",block-allocator=test4");
  	show_alloc_options(seq, s);
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
  #ifdef CONFIG_QUOTA
bd4c625c0   Linus Torvalds   reiserfs: run scr...
659
660
661
662
  static ssize_t reiserfs_quota_write(struct super_block *, int, const char *,
  				    size_t, loff_t);
  static ssize_t reiserfs_quota_read(struct super_block *, int, char *, size_t,
  				   loff_t);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663
  #endif
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
664
  static const struct super_operations reiserfs_sops = {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
665
666
667
668
  	.alloc_inode = reiserfs_alloc_inode,
  	.destroy_inode = reiserfs_destroy_inode,
  	.write_inode = reiserfs_write_inode,
  	.dirty_inode = reiserfs_dirty_inode,
845a2cc05   Al Viro   convert reiserfs ...
669
  	.evict_inode = reiserfs_evict_inode,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
670
671
672
  	.put_super = reiserfs_put_super,
  	.write_super = reiserfs_write_super,
  	.sync_fs = reiserfs_sync_fs,
c4be0c1dc   Takashi Sato   filesystem freeze...
673
674
  	.freeze_fs = reiserfs_freeze,
  	.unfreeze_fs = reiserfs_unfreeze,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
675
676
  	.statfs = reiserfs_statfs,
  	.remount_fs = reiserfs_remount,
c3aa07764   Jan Kara   reiserfs: Properl...
677
  	.show_options = reiserfs_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
  #ifdef CONFIG_QUOTA
bd4c625c0   Linus Torvalds   reiserfs: run scr...
679
680
  	.quota_read = reiserfs_quota_read,
  	.quota_write = reiserfs_quota_write,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
682
683
684
685
  #endif
  };
  
  #ifdef CONFIG_QUOTA
  #define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
688
689
690
  static int reiserfs_write_dquot(struct dquot *);
  static int reiserfs_acquire_dquot(struct dquot *);
  static int reiserfs_release_dquot(struct dquot *);
  static int reiserfs_mark_dquot_dirty(struct dquot *);
  static int reiserfs_write_info(struct super_block *, int);
f00c9e44a   Jan Kara   quota: Fix deadlo...
691
  static int reiserfs_quota_on(struct super_block *, int, int, struct path *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692

61e225dc3   Alexey Dobriyan   const: make struc...
693
  static const struct dquot_operations reiserfs_quota_operations = {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
694
695
696
697
698
  	.write_dquot = reiserfs_write_dquot,
  	.acquire_dquot = reiserfs_acquire_dquot,
  	.release_dquot = reiserfs_release_dquot,
  	.mark_dirty = reiserfs_mark_dquot_dirty,
  	.write_info = reiserfs_write_info,
4103003b3   Jan Kara   reiserfs: Add def...
699
700
  	.alloc_dquot	= dquot_alloc,
  	.destroy_dquot	= dquot_destroy,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
  };
0d54b217a   Alexey Dobriyan   const: make struc...
702
  static const struct quotactl_ops reiserfs_qctl_operations = {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
703
  	.quota_on = reiserfs_quota_on,
287a80958   Christoph Hellwig   quota: rename def...
704
705
706
707
708
709
  	.quota_off = dquot_quota_off,
  	.quota_sync = dquot_quota_sync,
  	.get_info = dquot_get_dqinfo,
  	.set_info = dquot_set_dqinfo,
  	.get_dqblk = dquot_get_dqblk,
  	.set_dqblk = dquot_set_dqblk,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
711
  };
  #endif
396551644   Christoph Hellwig   exportfs: make st...
712
  static const struct export_operations reiserfs_export_ops = {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
713
  	.encode_fh = reiserfs_encode_fh,
be55caf17   Christoph Hellwig   reiserfs: new exp...
714
715
  	.fh_to_dentry = reiserfs_fh_to_dentry,
  	.fh_to_parent = reiserfs_fh_to_parent,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
716
  	.get_parent = reiserfs_get_parent,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
717
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718
719
720
721
  
  /* this struct is used in reiserfs_getopt () for containing the value for those
     mount options that have values rather than being toggles. */
  typedef struct {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
722
723
724
725
726
727
  	char *value;
  	int setmask;		/* bitmask which is to set on mount_options bitmask when this
  				   value is found, 0 is no bits are to be changed. */
  	int clrmask;		/* bitmask which is to clear on mount_options bitmask when  this
  				   value is found, 0 is no bits are to be changed. This is
  				   applied BEFORE setmask */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
729
730
731
732
733
734
735
  } arg_desc_t;
  
  /* Set this bit in arg_required to allow empty arguments */
  #define REISERFS_OPT_ALLOWEMPTY 31
  
  /* this struct is used in reiserfs_getopt() for describing the set of reiserfs
     mount options */
  typedef struct {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
736
737
738
739
740
741
742
743
  	char *option_name;
  	int arg_required;	/* 0 if argument is not required, not 0 otherwise */
  	const arg_desc_t *values;	/* list of values accepted by an option */
  	int setmask;		/* bitmask which is to set on mount_options bitmask when this
  				   value is found, 0 is no bits are to be changed. */
  	int clrmask;		/* bitmask which is to clear on mount_options bitmask when  this
  				   value is found, 0 is no bits are to be changed. This is
  				   applied BEFORE setmask */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
746
747
  } opt_desc_t;
  
  /* possible values for -o data= */
  static const arg_desc_t logging_mode[] = {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
748
749
750
751
752
753
  	{"ordered", 1 << REISERFS_DATA_ORDERED,
  	 (1 << REISERFS_DATA_LOG | 1 << REISERFS_DATA_WRITEBACK)},
  	{"journal", 1 << REISERFS_DATA_LOG,
  	 (1 << REISERFS_DATA_ORDERED | 1 << REISERFS_DATA_WRITEBACK)},
  	{"writeback", 1 << REISERFS_DATA_WRITEBACK,
  	 (1 << REISERFS_DATA_ORDERED | 1 << REISERFS_DATA_LOG)},
cd02b966b   Vladimir V. Saveliev   [PATCH] reiserfs:...
754
  	{.value = NULL}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755
756
757
758
  };
  
  /* possible values for -o barrier= */
  static const arg_desc_t barrier_mode[] = {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
759
760
  	{"none", 1 << REISERFS_BARRIER_NONE, 1 << REISERFS_BARRIER_FLUSH},
  	{"flush", 1 << REISERFS_BARRIER_FLUSH, 1 << REISERFS_BARRIER_NONE},
cd02b966b   Vladimir V. Saveliev   [PATCH] reiserfs:...
761
  	{.value = NULL}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
763
764
765
766
  };
  
  /* possible values for "-o block-allocator=" and bits which are to be set in
     s_mount_opt of reiserfs specific part of in-core super block */
  static const arg_desc_t balloc[] = {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
767
768
769
770
771
772
773
  	{"noborder", 1 << REISERFS_NO_BORDER, 0},
  	{"border", 0, 1 << REISERFS_NO_BORDER},
  	{"no_unhashed_relocation", 1 << REISERFS_NO_UNHASHED_RELOCATION, 0},
  	{"hashed_relocation", 1 << REISERFS_HASHED_RELOCATION, 0},
  	{"test4", 1 << REISERFS_TEST4, 0},
  	{"notest4", 0, 1 << REISERFS_TEST4},
  	{NULL, 0, 0}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
775
776
  };
  
  static const arg_desc_t tails[] = {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
777
778
779
780
  	{"on", 1 << REISERFS_LARGETAIL, 1 << REISERFS_SMALLTAIL},
  	{"off", 0, (1 << REISERFS_LARGETAIL) | (1 << REISERFS_SMALLTAIL)},
  	{"small", 1 << REISERFS_SMALLTAIL, 1 << REISERFS_LARGETAIL},
  	{NULL, 0, 0}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
781
782
783
  };
  
  static const arg_desc_t error_actions[] = {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
784
785
786
787
  	{"panic", 1 << REISERFS_ERROR_PANIC,
  	 (1 << REISERFS_ERROR_RO | 1 << REISERFS_ERROR_CONTINUE)},
  	{"ro-remount", 1 << REISERFS_ERROR_RO,
  	 (1 << REISERFS_ERROR_PANIC | 1 << REISERFS_ERROR_CONTINUE)},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
  #ifdef REISERFS_JOURNAL_ERROR_ALLOWS_NO_LOG
bd4c625c0   Linus Torvalds   reiserfs: run scr...
789
790
  	{"continue", 1 << REISERFS_ERROR_CONTINUE,
  	 (1 << REISERFS_ERROR_PANIC | 1 << REISERFS_ERROR_RO)},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
792
  	{NULL, 0, 0},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
793
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794
795
796
797
798
799
  /* proceed only one option from a list *cur - string containing of mount options
     opts - array of options which are accepted
     opt_arg - if option is found and requires an argument and if it is specifed
     in the input - pointer to the argument is stored here
     bit_flags - if option requires to set a certain bit - it is set here
     return -1 if unknown option is found, opt->arg_required otherwise */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
800
801
  static int reiserfs_getopt(struct super_block *s, char **cur, opt_desc_t * opts,
  			   char **opt_arg, unsigned long *bit_flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
803
  	char *p;
0222e6571   Jeff Mahoney   reiserfs: strip t...
804
  	/* foo=bar,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
  	   ^   ^  ^
  	   |   |  +-- option_end
  	   |   +-- arg_start
  	   +-- option_start
  	 */
  	const opt_desc_t *opt;
  	const arg_desc_t *arg;
  
  	p = *cur;
  
  	/* assume argument cannot contain commas */
  	*cur = strchr(p, ',');
  	if (*cur) {
  		*(*cur) = '\0';
  		(*cur)++;
  	}
  
  	if (!strncmp(p, "alloc=", 6)) {
  		/* Ugly special case, probably we should redo options parser so that
  		   it can understand several arguments for some options, also so that
  		   it can fill several bitfields with option values. */
  		if (reiserfs_parse_alloc_options(s, p + 6)) {
  			return -1;
  		} else {
  			return 0;
  		}
  	}
  
  	/* for every option in the list */
  	for (opt = opts; opt->option_name; opt++) {
  		if (!strncmp(p, opt->option_name, strlen(opt->option_name))) {
  			if (bit_flags) {
  				if (opt->clrmask ==
  				    (1 << REISERFS_UNSUPPORTED_OPT))
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
839
840
841
  					reiserfs_warning(s, "super-6500",
  							 "%s not supported.
  ",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
842
843
844
845
846
  							 p);
  				else
  					*bit_flags &= ~opt->clrmask;
  				if (opt->setmask ==
  				    (1 << REISERFS_UNSUPPORTED_OPT))
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
847
848
849
  					reiserfs_warning(s, "super-6501",
  							 "%s not supported.
  ",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
850
851
852
853
854
855
856
857
  							 p);
  				else
  					*bit_flags |= opt->setmask;
  			}
  			break;
  		}
  	}
  	if (!opt->option_name) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
858
859
  		reiserfs_warning(s, "super-6502",
  				 "unknown mount option \"%s\"", p);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
860
861
862
863
864
865
866
  		return -1;
  	}
  
  	p += strlen(opt->option_name);
  	switch (*p) {
  	case '=':
  		if (!opt->arg_required) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
867
868
869
870
  			reiserfs_warning(s, "super-6503",
  					 "the option \"%s\" does not "
  					 "require an argument
  ",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
871
872
873
874
875
876
877
  					 opt->option_name);
  			return -1;
  		}
  		break;
  
  	case 0:
  		if (opt->arg_required) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
878
879
880
881
  			reiserfs_warning(s, "super-6504",
  					 "the option \"%s\" requires an "
  					 "argument
  ", opt->option_name);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
882
883
884
885
  			return -1;
  		}
  		break;
  	default:
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
886
887
888
  		reiserfs_warning(s, "super-6505",
  				 "head of option \"%s\" is only correct
  ",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
889
890
891
892
893
894
895
896
897
898
899
  				 opt->option_name);
  		return -1;
  	}
  
  	/* move to the argument, or to next option if argument is not required */
  	p++;
  
  	if (opt->arg_required
  	    && !(opt->arg_required & (1 << REISERFS_OPT_ALLOWEMPTY))
  	    && !strlen(p)) {
  		/* this catches "option=," if not allowed */
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
900
901
902
  		reiserfs_warning(s, "super-6506",
  				 "empty argument for \"%s\"
  ",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
  				 opt->option_name);
  		return -1;
  	}
  
  	if (!opt->values) {
  		/* *=NULLopt_arg contains pointer to argument */
  		*opt_arg = p;
  		return opt->arg_required & ~(1 << REISERFS_OPT_ALLOWEMPTY);
  	}
  
  	/* values possible for this option are listed in opt->values */
  	for (arg = opt->values; arg->value; arg++) {
  		if (!strcmp(p, arg->value)) {
  			if (bit_flags) {
  				*bit_flags &= ~arg->clrmask;
  				*bit_flags |= arg->setmask;
  			}
  			return opt->arg_required;
  		}
  	}
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
923
924
925
  	reiserfs_warning(s, "super-6506",
  			 "bad value \"%s\" for option \"%s\"
  ", p,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
926
  			 opt->option_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
927
  	return -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
929
930
  }
  
  /* returns 0 if something is wrong in option string, 1 - otherwise */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
931
932
933
934
935
936
937
  static int reiserfs_parse_options(struct super_block *s, char *options,	/* string given via mount's -o */
  				  unsigned long *mount_options,
  				  /* after the parsing phase, contains the
  				     collection of bitflags defining what
  				     mount options were selected. */
  				  unsigned long *blocks,	/* strtol-ed from NNN of resize=NNN */
  				  char **jdev_name,
00b441970   Jan Kara   reiserfs: correct...
938
939
940
  				  unsigned int *commit_max_age,
  				  char **qf_names,
  				  unsigned int *qfmt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
941
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
942
943
944
945
946
947
948
949
950
951
952
  	int c;
  	char *arg = NULL;
  	char *pos;
  	opt_desc_t opts[] = {
  		/* Compatibility stuff, so that -o notail for old setups still work */
  		{"tails",.arg_required = 't',.values = tails},
  		{"notail",.clrmask =
  		 (1 << REISERFS_LARGETAIL) | (1 << REISERFS_SMALLTAIL)},
  		{"conv",.setmask = 1 << REISERFS_CONVERT},
  		{"attrs",.setmask = 1 << REISERFS_ATTRS},
  		{"noattrs",.clrmask = 1 << REISERFS_ATTRS},
73422811d   Jeff Mahoney   reiserfs: allow e...
953
  		{"expose_privroot", .setmask = 1 << REISERFS_EXPOSE_PRIVROOT},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
954
  #ifdef CONFIG_REISERFS_FS_XATTR
bd4c625c0   Linus Torvalds   reiserfs: run scr...
955
956
  		{"user_xattr",.setmask = 1 << REISERFS_XATTRS_USER},
  		{"nouser_xattr",.clrmask = 1 << REISERFS_XATTRS_USER},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957
  #else
bd4c625c0   Linus Torvalds   reiserfs: run scr...
958
959
  		{"user_xattr",.setmask = 1 << REISERFS_UNSUPPORTED_OPT},
  		{"nouser_xattr",.clrmask = 1 << REISERFS_UNSUPPORTED_OPT},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960
961
  #endif
  #ifdef CONFIG_REISERFS_FS_POSIX_ACL
bd4c625c0   Linus Torvalds   reiserfs: run scr...
962
963
  		{"acl",.setmask = 1 << REISERFS_POSIXACL},
  		{"noacl",.clrmask = 1 << REISERFS_POSIXACL},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964
  #else
bd4c625c0   Linus Torvalds   reiserfs: run scr...
965
966
  		{"acl",.setmask = 1 << REISERFS_UNSUPPORTED_OPT},
  		{"noacl",.clrmask = 1 << REISERFS_UNSUPPORTED_OPT},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
  #endif
cd02b966b   Vladimir V. Saveliev   [PATCH] reiserfs:...
968
  		{.option_name = "nolog"},
bd4c625c0   Linus Torvalds   reiserfs: run scr...
969
970
971
972
973
974
975
976
  		{"replayonly",.setmask = 1 << REPLAYONLY},
  		{"block-allocator",.arg_required = 'a',.values = balloc},
  		{"data",.arg_required = 'd',.values = logging_mode},
  		{"barrier",.arg_required = 'b',.values = barrier_mode},
  		{"resize",.arg_required = 'r',.values = NULL},
  		{"jdev",.arg_required = 'j',.values = NULL},
  		{"nolargeio",.arg_required = 'w',.values = NULL},
  		{"commit",.arg_required = 'c',.values = NULL},
c3aa07764   Jan Kara   reiserfs: Properl...
977
978
979
  		{"usrquota",.setmask = 1 << REISERFS_USRQUOTA},
  		{"grpquota",.setmask = 1 << REISERFS_GRPQUOTA},
  		{"noquota",.clrmask = 1 << REISERFS_USRQUOTA | 1 << REISERFS_GRPQUOTA},
bd4c625c0   Linus Torvalds   reiserfs: run scr...
980
981
982
983
984
985
  		{"errors",.arg_required = 'e',.values = error_actions},
  		{"usrjquota",.arg_required =
  		 'u' | (1 << REISERFS_OPT_ALLOWEMPTY),.values = NULL},
  		{"grpjquota",.arg_required =
  		 'g' | (1 << REISERFS_OPT_ALLOWEMPTY),.values = NULL},
  		{"jqfmt",.arg_required = 'f',.values = NULL},
cd02b966b   Vladimir V. Saveliev   [PATCH] reiserfs:...
986
  		{.option_name = NULL}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
987
988
989
990
991
992
993
994
995
996
997
998
  	};
  
  	*blocks = 0;
  	if (!options || !*options)
  		/* use default configuration: create tails, journaling on, no
  		   conversion to newest format */
  		return 1;
  
  	for (pos = options; pos;) {
  		c = reiserfs_getopt(s, &pos, opts, &arg, mount_options);
  		if (c == -1)
  			/* wrong option is given */
9a3bb3017   Paolo 'Blaisorblade' Giarrusso   [PATCH] reiserfs:...
999
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1000

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
  		if (c == 'r') {
  			char *p;
  
  			p = NULL;
  			/* "resize=NNN" or "resize=auto" */
  
  			if (!strcmp(arg, "auto")) {
  				/* From JFS code, to auto-get the size. */
  				*blocks =
  				    s->s_bdev->bd_inode->i_size >> s->
  				    s_blocksize_bits;
  			} else {
  				*blocks = simple_strtoul(arg, &p, 0);
  				if (*p != '\0') {
  					/* NNN does not look like a number */
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1016
1017
1018
1019
  					reiserfs_warning(s, "super-6507",
  							 "bad value %s for "
  							 "-oresize
  ", arg);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1020
1021
1022
  					return 0;
  				}
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1024

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1025
1026
1027
1028
1029
  		if (c == 'c') {
  			char *p = NULL;
  			unsigned long val = simple_strtoul(arg, &p, 0);
  			/* commit=NNN (time in seconds) */
  			if (*p != '\0' || val >= (unsigned int)-1) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1030
1031
1032
  				reiserfs_warning(s, "super-6508",
  						 "bad value %s for -ocommit
  ",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1033
1034
1035
1036
  						 arg);
  				return 0;
  			}
  			*commit_max_age = (unsigned int)val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1038

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1039
  		if (c == 'w') {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1040
1041
  			reiserfs_warning(s, "super-6509", "nolargeio option "
  					 "is no longer supported");
36b756f2b   Adrian Bunk   [PATCH] reiserfs:...
1042
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1043
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1044

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1045
1046
1047
  		if (c == 'j') {
  			if (arg && *arg && jdev_name) {
  				if (*jdev_name) {	//Hm, already assigned?
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1048
1049
1050
1051
  					reiserfs_warning(s, "super-6510",
  							 "journal device was "
  							 "already specified to "
  							 "be %s", *jdev_name);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1052
1053
1054
1055
  					return 0;
  				}
  				*jdev_name = arg;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1056
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1057
1058
1059
  #ifdef CONFIG_QUOTA
  		if (c == 'u' || c == 'g') {
  			int qtype = c == 'u' ? USRQUOTA : GRPQUOTA;
6929f8912   Jan Kara   reiserfs: Use sb_...
1060
  			if (sb_any_quota_loaded(s) &&
00b441970   Jan Kara   reiserfs: correct...
1061
  			    (!*arg != !REISERFS_SB(s)->s_qf_names[qtype])) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1062
1063
1064
1065
  				reiserfs_warning(s, "super-6511",
  						 "cannot change journaled "
  						 "quota options when quota "
  						 "turned on.");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1066
1067
1068
1069
1070
1071
  				return 0;
  			}
  			if (*arg) {	/* Some filename specified? */
  				if (REISERFS_SB(s)->s_qf_names[qtype]
  				    && strcmp(REISERFS_SB(s)->s_qf_names[qtype],
  					      arg)) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1072
1073
1074
  					reiserfs_warning(s, "super-6512",
  							 "%s quota file "
  							 "already specified.",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1075
1076
1077
1078
  							 QTYPE2NAME(qtype));
  					return 0;
  				}
  				if (strchr(arg, '/')) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1079
1080
1081
  					reiserfs_warning(s, "super-6513",
  							 "quotafile must be "
  							 "on filesystem root.");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1082
1083
  					return 0;
  				}
00b441970   Jan Kara   reiserfs: correct...
1084
  				qf_names[qtype] =
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1085
  				    kmalloc(strlen(arg) + 1, GFP_KERNEL);
00b441970   Jan Kara   reiserfs: correct...
1086
  				if (!qf_names[qtype]) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1087
1088
1089
1090
  					reiserfs_warning(s, "reiserfs-2502",
  							 "not enough memory "
  							 "for storing "
  							 "quotafile name.");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1091
1092
  					return 0;
  				}
00b441970   Jan Kara   reiserfs: correct...
1093
  				strcpy(qf_names[qtype], arg);
c3aa07764   Jan Kara   reiserfs: Properl...
1094
1095
1096
1097
  				if (qtype == USRQUOTA)
  					*mount_options |= 1 << REISERFS_USRQUOTA;
  				else
  					*mount_options |= 1 << REISERFS_GRPQUOTA;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1098
  			} else {
00b441970   Jan Kara   reiserfs: correct...
1099
1100
1101
1102
  				if (qf_names[qtype] !=
  				    REISERFS_SB(s)->s_qf_names[qtype])
  					kfree(qf_names[qtype]);
  				qf_names[qtype] = NULL;
c3aa07764   Jan Kara   reiserfs: Properl...
1103
1104
1105
1106
  				if (qtype == USRQUOTA)
  					*mount_options &= ~(1 << REISERFS_USRQUOTA);
  				else
  					*mount_options &= ~(1 << REISERFS_GRPQUOTA);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1107
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1108
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1109
1110
  		if (c == 'f') {
  			if (!strcmp(arg, "vfsold"))
00b441970   Jan Kara   reiserfs: correct...
1111
  				*qfmt = QFMT_VFS_OLD;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1112
  			else if (!strcmp(arg, "vfsv0"))
00b441970   Jan Kara   reiserfs: correct...
1113
  				*qfmt = QFMT_VFS_V0;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1114
  			else {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1115
1116
1117
  				reiserfs_warning(s, "super-6514",
  						 "unknown quota format "
  						 "specified.");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1118
1119
  				return 0;
  			}
6929f8912   Jan Kara   reiserfs: Use sb_...
1120
  			if (sb_any_quota_loaded(s) &&
00b441970   Jan Kara   reiserfs: correct...
1121
  			    *qfmt != REISERFS_SB(s)->s_jquota_fmt) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1122
1123
1124
1125
  				reiserfs_warning(s, "super-6515",
  						 "cannot change journaled "
  						 "quota options when quota "
  						 "turned on.");
00b441970   Jan Kara   reiserfs: correct...
1126
1127
  				return 0;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1128
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1129
1130
  #else
  		if (c == 'u' || c == 'g' || c == 'f') {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1131
1132
  			reiserfs_warning(s, "reiserfs-2503", "journaled "
  					 "quota options not supported.");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1133
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1135
1136
1137
1138
  #endif
  	}
  
  #ifdef CONFIG_QUOTA
00b441970   Jan Kara   reiserfs: correct...
1139
1140
  	if (!REISERFS_SB(s)->s_jquota_fmt && !*qfmt
  	    && (qf_names[USRQUOTA] || qf_names[GRPQUOTA])) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1141
1142
  		reiserfs_warning(s, "super-6515",
  				 "journaled quota format not specified.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1144
  	}
c3aa07764   Jan Kara   reiserfs: Properl...
1145
1146
1147
1148
  	if ((!(*mount_options & (1 << REISERFS_USRQUOTA)) &&
  	       sb_has_quota_loaded(s, USRQUOTA)) ||
  	    (!(*mount_options & (1 << REISERFS_GRPQUOTA)) &&
  	       sb_has_quota_loaded(s, GRPQUOTA))) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1149
1150
  		reiserfs_warning(s, "super-6516", "quota options must "
  				 "be present when quota is turned on.");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1151
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1152
1153
  	}
  #endif
556a2a45b   Jan Kara   [PATCH] quota: re...
1154

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1155
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1156
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1157
1158
1159
1160
1161
1162
  static void switch_data_mode(struct super_block *s, unsigned long mode)
  {
  	REISERFS_SB(s)->s_mount_opt &= ~((1 << REISERFS_DATA_LOG) |
  					 (1 << REISERFS_DATA_ORDERED) |
  					 (1 << REISERFS_DATA_WRITEBACK));
  	REISERFS_SB(s)->s_mount_opt |= (1 << mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1163
1164
1165
1166
  }
  
  static void handle_data_mode(struct super_block *s, unsigned long mount_options)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
  	if (mount_options & (1 << REISERFS_DATA_LOG)) {
  		if (!reiserfs_data_log(s)) {
  			switch_data_mode(s, REISERFS_DATA_LOG);
  			reiserfs_info(s, "switching to journaled data mode
  ");
  		}
  	} else if (mount_options & (1 << REISERFS_DATA_ORDERED)) {
  		if (!reiserfs_data_ordered(s)) {
  			switch_data_mode(s, REISERFS_DATA_ORDERED);
  			reiserfs_info(s, "switching to ordered data mode
  ");
  		}
  	} else if (mount_options & (1 << REISERFS_DATA_WRITEBACK)) {
  		if (!reiserfs_data_writeback(s)) {
  			switch_data_mode(s, REISERFS_DATA_WRITEBACK);
  			reiserfs_info(s, "switching to writeback data mode
  ");
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
  static void handle_barrier_mode(struct super_block *s, unsigned long bits)
  {
  	int flush = (1 << REISERFS_BARRIER_FLUSH);
  	int none = (1 << REISERFS_BARRIER_NONE);
  	int all_barrier = flush | none;
  
  	if (bits & all_barrier) {
  		REISERFS_SB(s)->s_mount_opt &= ~all_barrier;
  		if (bits & flush) {
  			REISERFS_SB(s)->s_mount_opt |= flush;
  			printk("reiserfs: enabling write barrier flush mode
  ");
  		} else if (bits & none) {
  			REISERFS_SB(s)->s_mount_opt |= none;
  			printk("reiserfs: write barriers turned off
  ");
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1206
  static void handle_attrs(struct super_block *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1207
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1208
  	struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1209

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1210
1211
  	if (reiserfs_attrs(s)) {
  		if (old_format_only(s)) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1212
1213
  			reiserfs_warning(s, "super-6517", "cannot support "
  					 "attributes on 3.5.x disk format");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1214
  			REISERFS_SB(s)->s_mount_opt &= ~(1 << REISERFS_ATTRS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1215
1216
  			return;
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1217
  		if (!(le32_to_cpu(rs->s_flags) & reiserfs_attrs_cleared)) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1218
1219
1220
  			reiserfs_warning(s, "super-6518", "cannot support "
  					 "attributes until flag is set in "
  					 "super-block");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1221
  			REISERFS_SB(s)->s_mount_opt &= ~(1 << REISERFS_ATTRS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1222
1223
1224
  		}
  	}
  }
00b441970   Jan Kara   reiserfs: correct...
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
  #ifdef CONFIG_QUOTA
  static void handle_quota_files(struct super_block *s, char **qf_names,
  			       unsigned int *qfmt)
  {
  	int i;
  
  	for (i = 0; i < MAXQUOTAS; i++) {
  		if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i])
  			kfree(REISERFS_SB(s)->s_qf_names[i]);
  		REISERFS_SB(s)->s_qf_names[i] = qf_names[i];
  	}
a06d789b4   Jan Kara   reiserfs: Fix quo...
1236
1237
  	if (*qfmt)
  		REISERFS_SB(s)->s_jquota_fmt = *qfmt;
00b441970   Jan Kara   reiserfs: correct...
1238
1239
  }
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1240
  static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1242
1243
1244
1245
1246
1247
1248
  	struct reiserfs_super_block *rs;
  	struct reiserfs_transaction_handle th;
  	unsigned long blocks;
  	unsigned long mount_options = REISERFS_SB(s)->s_mount_opt;
  	unsigned long safe_mask = 0;
  	unsigned int commit_max_age = (unsigned int)-1;
  	struct reiserfs_journal *journal = SB_JOURNAL(s);
cdf6ccc8b   Miklos Szeredi   mount options: fi...
1249
  	char *new_opts = kstrdup(arg, GFP_KERNEL);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1250
  	int err;
00b441970   Jan Kara   reiserfs: correct...
1251
1252
  	char *qf_names[MAXQUOTAS];
  	unsigned int qfmt = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1253
  #ifdef CONFIG_QUOTA
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1254
  	int i;
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1255
  #endif
00b441970   Jan Kara   reiserfs: correct...
1256

8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1257
  	reiserfs_write_lock(s);
00b441970   Jan Kara   reiserfs: correct...
1258

8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1259
  #ifdef CONFIG_QUOTA
00b441970   Jan Kara   reiserfs: correct...
1260
  	memcpy(qf_names, REISERFS_SB(s)->s_qf_names, sizeof(qf_names));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1261
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1262
  	rs = SB_DISK_SUPER_BLOCK(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1263

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1264
  	if (!reiserfs_parse_options
00b441970   Jan Kara   reiserfs: correct...
1265
1266
  	    (s, arg, &mount_options, &blocks, NULL, &commit_max_age,
  	    qf_names, &qfmt)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
  #ifdef CONFIG_QUOTA
00b441970   Jan Kara   reiserfs: correct...
1268
1269
1270
  		for (i = 0; i < MAXQUOTAS; i++)
  			if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i])
  				kfree(qf_names[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1271
  #endif
cdf6ccc8b   Miklos Szeredi   mount options: fi...
1272
1273
  		err = -EINVAL;
  		goto out_err;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1274
  	}
00b441970   Jan Kara   reiserfs: correct...
1275
1276
1277
  #ifdef CONFIG_QUOTA
  	handle_quota_files(s, qf_names, &qfmt);
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
  
  	handle_attrs(s);
  
  	/* Add options that are safe here */
  	safe_mask |= 1 << REISERFS_SMALLTAIL;
  	safe_mask |= 1 << REISERFS_LARGETAIL;
  	safe_mask |= 1 << REISERFS_NO_BORDER;
  	safe_mask |= 1 << REISERFS_NO_UNHASHED_RELOCATION;
  	safe_mask |= 1 << REISERFS_HASHED_RELOCATION;
  	safe_mask |= 1 << REISERFS_TEST4;
  	safe_mask |= 1 << REISERFS_ATTRS;
  	safe_mask |= 1 << REISERFS_XATTRS_USER;
  	safe_mask |= 1 << REISERFS_POSIXACL;
  	safe_mask |= 1 << REISERFS_BARRIER_FLUSH;
  	safe_mask |= 1 << REISERFS_BARRIER_NONE;
  	safe_mask |= 1 << REISERFS_ERROR_RO;
  	safe_mask |= 1 << REISERFS_ERROR_CONTINUE;
  	safe_mask |= 1 << REISERFS_ERROR_PANIC;
c3aa07764   Jan Kara   reiserfs: Properl...
1296
1297
  	safe_mask |= 1 << REISERFS_USRQUOTA;
  	safe_mask |= 1 << REISERFS_GRPQUOTA;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
  
  	/* Update the bitmask, taking care to keep
  	 * the bits we're not allowed to change here */
  	REISERFS_SB(s)->s_mount_opt =
  	    (REISERFS_SB(s)->
  	     s_mount_opt & ~safe_mask) | (mount_options & safe_mask);
  
  	if (commit_max_age != 0 && commit_max_age != (unsigned int)-1) {
  		journal->j_max_commit_age = commit_max_age;
  		journal->j_max_trans_age = commit_max_age;
  	} else if (commit_max_age == 0) {
  		/* 0 means restore defaults. */
  		journal->j_max_commit_age = journal->j_default_max_commit_age;
  		journal->j_max_trans_age = JOURNAL_MAX_TRANS_AGE;
  	}
  
  	if (blocks) {
cdf6ccc8b   Miklos Szeredi   mount options: fi...
1315
1316
1317
  		err = reiserfs_resize(s, blocks);
  		if (err != 0)
  			goto out_err;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1318
1319
1320
1321
1322
1323
1324
  	}
  
  	if (*mount_flags & MS_RDONLY) {
  		reiserfs_xattr_init(s, *mount_flags);
  		/* remount read-only */
  		if (s->s_flags & MS_RDONLY)
  			/* it is read-only already */
cdf6ccc8b   Miklos Szeredi   mount options: fi...
1325
  			goto out_ok;
c79d967de   Christoph Hellwig   quota: move remou...
1326

0f0dd62fd   Christoph Hellwig   quota: kill the v...
1327
1328
  		err = dquot_suspend(s, -1);
  		if (err < 0)
c79d967de   Christoph Hellwig   quota: move remou...
1329
  			goto out_err;
c79d967de   Christoph Hellwig   quota: move remou...
1330

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1331
1332
1333
  		/* try to remount file system with read-only permissions */
  		if (sb_umount_state(rs) == REISERFS_VALID_FS
  		    || REISERFS_SB(s)->s_mount_state != REISERFS_VALID_FS) {
cdf6ccc8b   Miklos Szeredi   mount options: fi...
1334
  			goto out_ok;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1335
1336
1337
1338
  		}
  
  		err = journal_begin(&th, s, 10);
  		if (err)
cdf6ccc8b   Miklos Szeredi   mount options: fi...
1339
  			goto out_err;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1340
1341
1342
1343
1344
1345
1346
1347
1348
  
  		/* Mounting a rw partition read-only. */
  		reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
  		set_sb_umount_state(rs, REISERFS_SB(s)->s_mount_state);
  		journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
  	} else {
  		/* remount read-write */
  		if (!(s->s_flags & MS_RDONLY)) {
  			reiserfs_xattr_init(s, *mount_flags);
cdf6ccc8b   Miklos Szeredi   mount options: fi...
1349
  			goto out_ok;	/* We are read-write already */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1350
  		}
cdf6ccc8b   Miklos Szeredi   mount options: fi...
1351
1352
1353
1354
  		if (reiserfs_is_journal_aborted(journal)) {
  			err = journal->j_errno;
  			goto out_err;
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1355
1356
1357
1358
1359
1360
1361
  
  		handle_data_mode(s, mount_options);
  		handle_barrier_mode(s, mount_options);
  		REISERFS_SB(s)->s_mount_state = sb_umount_state(rs);
  		s->s_flags &= ~MS_RDONLY;	/* now it is safe to call journal_begin */
  		err = journal_begin(&th, s, 10);
  		if (err)
cdf6ccc8b   Miklos Szeredi   mount options: fi...
1362
  			goto out_err;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1363
1364
1365
1366
1367
1368
  
  		/* Mount a partition which is read-only, read-write */
  		reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
  		REISERFS_SB(s)->s_mount_state = sb_umount_state(rs);
  		s->s_flags &= ~MS_RDONLY;
  		set_sb_umount_state(rs, REISERFS_ERROR_FS);
702d21c6f   Jeff Mahoney   reiserfs: add sup...
1369
1370
  		if (!old_format_only(s))
  			set_sb_mnt_count(rs, sb_mnt_count(rs) + 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1371
1372
1373
1374
1375
1376
1377
1378
  		/* mark_buffer_dirty (SB_BUFFER_WITH_SB (s), 1); */
  		journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
  		REISERFS_SB(s)->s_mount_state = REISERFS_VALID_FS;
  	}
  	/* this will force a full flush of all journal lists */
  	SB_JOURNAL(s)->j_must_wait = 1;
  	err = journal_end(&th, s, 10);
  	if (err)
cdf6ccc8b   Miklos Szeredi   mount options: fi...
1379
  		goto out_err;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1380
1381
1382
  	s->s_dirt = 0;
  
  	if (!(*mount_flags & MS_RDONLY)) {
0f0dd62fd   Christoph Hellwig   quota: kill the v...
1383
  		dquot_resume(s, -1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1384
1385
1386
  		finish_unfinished(s);
  		reiserfs_xattr_init(s, *mount_flags);
  	}
cdf6ccc8b   Miklos Szeredi   mount options: fi...
1387
  out_ok:
2a32cebd6   Al Viro   Fix races around ...
1388
  	replace_mount_options(s, new_opts);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1389
  	reiserfs_write_unlock(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1390
  	return 0;
cdf6ccc8b   Miklos Szeredi   mount options: fi...
1391
1392
1393
  
  out_err:
  	kfree(new_opts);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1394
  	reiserfs_write_unlock(s);
cdf6ccc8b   Miklos Szeredi   mount options: fi...
1395
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1396
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1397
  static int read_super_block(struct super_block *s, int offset)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1398
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1399
1400
1401
  	struct buffer_head *bh;
  	struct reiserfs_super_block *rs;
  	int fs_blocksize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1402

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1403
1404
  	bh = sb_bread(s, offset / s->s_blocksize);
  	if (!bh) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1405
  		reiserfs_warning(s, "sh-2006",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1406
1407
1408
1409
1410
  				 "bread failed (dev %s, block %lu, size %lu)",
  				 reiserfs_bdevname(s), offset / s->s_blocksize,
  				 s->s_blocksize);
  		return 1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1411

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1412
1413
1414
1415
1416
1417
1418
  	rs = (struct reiserfs_super_block *)bh->b_data;
  	if (!is_any_reiserfs_magic_string(rs)) {
  		brelse(bh);
  		return 1;
  	}
  	//
  	// ok, reiserfs signature (old or new) found in at the given offset
0222e6571   Jeff Mahoney   reiserfs: strip t...
1419
  	//
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1420
1421
1422
  	fs_blocksize = sb_blocksize(rs);
  	brelse(bh);
  	sb_set_blocksize(s, fs_blocksize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1423

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1424
1425
  	bh = sb_bread(s, offset / s->s_blocksize);
  	if (!bh) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1426
1427
  		reiserfs_warning(s, "sh-2007",
  				 "bread failed (dev %s, block %lu, size %lu)",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1428
1429
1430
1431
  				 reiserfs_bdevname(s), offset / s->s_blocksize,
  				 s->s_blocksize);
  		return 1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1432

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1433
1434
  	rs = (struct reiserfs_super_block *)bh->b_data;
  	if (sb_blocksize(rs) != s->s_blocksize) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1435
1436
  		reiserfs_warning(s, "sh-2011", "can't find a reiserfs "
  				 "filesystem on (dev %s, block %Lu, size %lu)",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1437
1438
1439
1440
1441
1442
  				 reiserfs_bdevname(s),
  				 (unsigned long long)bh->b_blocknr,
  				 s->s_blocksize);
  		brelse(bh);
  		return 1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1443

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1444
1445
  	if (rs->s_v1.s_root_block == cpu_to_le32(-1)) {
  		brelse(bh);
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1446
1447
1448
1449
1450
1451
  		reiserfs_warning(s, "super-6519", "Unfinished reiserfsck "
  				 "--rebuild-tree run detected. Please run
  "
  				 "reiserfsck --rebuild-tree and wait for a "
  				 "completion. If that fails
  "
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1452
1453
  				 "get newer reiserfsprogs package");
  		return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1454
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1455

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1456
1457
1458
1459
1460
1461
1462
  	SB_BUFFER_WITH_SB(s) = bh;
  	SB_DISK_SUPER_BLOCK(s) = rs;
  
  	if (is_reiserfs_jr(rs)) {
  		/* magic is of non-standard journal filesystem, look at s_version to
  		   find which format is in use */
  		if (sb_version(rs) == REISERFS_VERSION_2)
1d889d995   Jeff Mahoney   reiserfs: make so...
1463
1464
1465
  			reiserfs_info(s, "found reiserfs format \"3.6\""
  				      " with non-standard journal
  ");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1466
  		else if (sb_version(rs) == REISERFS_VERSION_1)
1d889d995   Jeff Mahoney   reiserfs: make so...
1467
1468
1469
  			reiserfs_info(s, "found reiserfs format \"3.5\""
  				      " with non-standard journal
  ");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1470
  		else {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1471
1472
1473
  			reiserfs_warning(s, "sh-2012", "found unknown "
  					 "format \"%u\" of reiserfs with "
  					 "non-standard magic", sb_version(rs));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
  			return 1;
  		}
  	} else
  		/* s_version of standard format may contain incorrect information,
  		   so we just look at the magic string */
  		reiserfs_info(s,
  			      "found reiserfs format \"%s\" with standard journal
  ",
  			      is_reiserfs_3_5(rs) ? "3.5" : "3.6");
  
  	s->s_op = &reiserfs_sops;
  	s->s_export_op = &reiserfs_export_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1486
  #ifdef CONFIG_QUOTA
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1487
1488
  	s->s_qcop = &reiserfs_qctl_operations;
  	s->dq_op = &reiserfs_quota_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1489
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1490
1491
1492
1493
1494
  	/* new format is limited by the 32 bit wide i_blocks field, want to
  	 ** be one full block below that.
  	 */
  	s->s_maxbytes = (512LL << 32) - s->s_blocksize;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1495
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1496
  /* after journal replay, reread all bitmap and super blocks */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1497
1498
  static int reread_meta_blocks(struct super_block *s)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1499
1500
1501
  	ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s)));
  	wait_on_buffer(SB_BUFFER_WITH_SB(s));
  	if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1502
  		reiserfs_warning(s, "reiserfs-2504", "error reading the super");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1503
1504
  		return 1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1505

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1506
  	return 0;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1507
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1508
1509
1510
  
  /////////////////////////////////////////////////////
  // hash detection stuff
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1511
1512
1513
1514
1515
  // if root directory is empty - we set default - Yura's - hash and
  // warn about it
  // FIXME: we look for only one name in a directory. If tea and yura
  // bith have the same value - we ask user to send report to the
  // mailing list
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1516
  static __u32 find_hash_out(struct super_block *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
  	int retval;
  	struct inode *inode;
  	struct cpu_key key;
  	INITIALIZE_PATH(path);
  	struct reiserfs_dir_entry de;
  	__u32 hash = DEFAULT_HASH;
  
  	inode = s->s_root->d_inode;
  
  	do {			// Some serious "goto"-hater was there ;)
  		u32 teahash, r5hash, yurahash;
  
  		make_cpu_key(&key, inode, ~0, TYPE_DIRENTRY, 3);
  		retval = search_by_entry_key(s, &key, &path, &de);
  		if (retval == IO_ERROR) {
  			pathrelse(&path);
  			return UNSET_HASH;
  		}
  		if (retval == NAME_NOT_FOUND)
  			de.de_entry_num--;
  		set_de_name_and_namelen(&de);
  		if (deh_offset(&(de.de_deh[de.de_entry_num])) == DOT_DOT_OFFSET) {
  			/* allow override in this case */
  			if (reiserfs_rupasov_hash(s)) {
  				hash = YURA_HASH;
  			}
1d889d995   Jeff Mahoney   reiserfs: make so...
1544
1545
1546
  			reiserfs_info(s, "FS seems to be empty, autodetect "
  					 "is using the default hash
  ");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
  			break;
  		}
  		r5hash = GET_HASH_VALUE(r5_hash(de.de_name, de.de_namelen));
  		teahash = GET_HASH_VALUE(keyed_hash(de.de_name, de.de_namelen));
  		yurahash = GET_HASH_VALUE(yura_hash(de.de_name, de.de_namelen));
  		if (((teahash == r5hash)
  		     &&
  		     (GET_HASH_VALUE(deh_offset(&(de.de_deh[de.de_entry_num])))
  		      == r5hash)) || ((teahash == yurahash)
  				      && (yurahash ==
  					  GET_HASH_VALUE(deh_offset
  							 (&
  							  (de.
  							   de_deh[de.
  								  de_entry_num])))))
  		    || ((r5hash == yurahash)
  			&& (yurahash ==
  			    GET_HASH_VALUE(deh_offset
  					   (&(de.de_deh[de.de_entry_num])))))) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1566
1567
1568
1569
  			reiserfs_warning(s, "reiserfs-2506", "Unable to "
  					 "automatically detect hash function. "
  					 "Please mount with -o "
  					 "hash={tea,rupasov,r5}");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
  			hash = UNSET_HASH;
  			break;
  		}
  		if (GET_HASH_VALUE(deh_offset(&(de.de_deh[de.de_entry_num]))) ==
  		    yurahash)
  			hash = YURA_HASH;
  		else if (GET_HASH_VALUE
  			 (deh_offset(&(de.de_deh[de.de_entry_num]))) == teahash)
  			hash = TEA_HASH;
  		else if (GET_HASH_VALUE
  			 (deh_offset(&(de.de_deh[de.de_entry_num]))) == r5hash)
  			hash = R5_HASH;
  		else {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1583
1584
  			reiserfs_warning(s, "reiserfs-2506",
  					 "Unrecognised hash function");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1585
1586
1587
1588
1589
1590
  			hash = UNSET_HASH;
  		}
  	} while (0);
  
  	pathrelse(&path);
  	return hash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1591
1592
1593
  }
  
  // finds out which hash names are sorted with
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1594
  static int what_hash(struct super_block *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1595
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
  	__u32 code;
  
  	code = sb_hash_function_code(SB_DISK_SUPER_BLOCK(s));
  
  	/* reiserfs_hash_detect() == true if any of the hash mount options
  	 ** were used.  We must check them to make sure the user isn't
  	 ** using a bad hash value
  	 */
  	if (code == UNSET_HASH || reiserfs_hash_detect(s))
  		code = find_hash_out(s);
  
  	if (code != UNSET_HASH && reiserfs_hash_detect(s)) {
0222e6571   Jeff Mahoney   reiserfs: strip t...
1608
1609
  		/* detection has found the hash, and we must check against the
  		 ** mount options
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1610
1611
  		 */
  		if (reiserfs_rupasov_hash(s) && code != YURA_HASH) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1612
1613
  			reiserfs_warning(s, "reiserfs-2507",
  					 "Error, %s hash detected, "
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1614
1615
1616
1617
  					 "unable to force rupasov hash",
  					 reiserfs_hashname(code));
  			code = UNSET_HASH;
  		} else if (reiserfs_tea_hash(s) && code != TEA_HASH) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1618
1619
  			reiserfs_warning(s, "reiserfs-2508",
  					 "Error, %s hash detected, "
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1620
1621
1622
1623
  					 "unable to force tea hash",
  					 reiserfs_hashname(code));
  			code = UNSET_HASH;
  		} else if (reiserfs_r5_hash(s) && code != R5_HASH) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1624
1625
  			reiserfs_warning(s, "reiserfs-2509",
  					 "Error, %s hash detected, "
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
  					 "unable to force r5 hash",
  					 reiserfs_hashname(code));
  			code = UNSET_HASH;
  		}
  	} else {
  		/* find_hash_out was not called or could not determine the hash */
  		if (reiserfs_rupasov_hash(s)) {
  			code = YURA_HASH;
  		} else if (reiserfs_tea_hash(s)) {
  			code = TEA_HASH;
  		} else if (reiserfs_r5_hash(s)) {
  			code = R5_HASH;
  		}
  	}
0222e6571   Jeff Mahoney   reiserfs: strip t...
1640
  	/* if we are mounted RW, and we have a new valid hash code, update
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1641
1642
1643
1644
1645
1646
1647
1648
  	 ** the super
  	 */
  	if (code != UNSET_HASH &&
  	    !(s->s_flags & MS_RDONLY) &&
  	    code != sb_hash_function_code(SB_DISK_SUPER_BLOCK(s))) {
  		set_sb_hash_function_code(SB_DISK_SUPER_BLOCK(s), code);
  	}
  	return code;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1649
1650
1651
  }
  
  // return pointer to appropriate function
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1652
  static hashf_t hash_function(struct super_block *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1653
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
  	switch (what_hash(s)) {
  	case TEA_HASH:
  		reiserfs_info(s, "Using tea hash to sort names
  ");
  		return keyed_hash;
  	case YURA_HASH:
  		reiserfs_info(s, "Using rupasov hash to sort names
  ");
  		return yura_hash;
  	case R5_HASH:
  		reiserfs_info(s, "Using r5 hash to sort names
  ");
  		return r5_hash;
  	}
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1669
1670
1671
  }
  
  // this is used to set up correct value for old partitions
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1672
  static int function2code(hashf_t func)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1673
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1674
1675
1676
1677
1678
1679
  	if (func == keyed_hash)
  		return TEA_HASH;
  	if (func == yura_hash)
  		return YURA_HASH;
  	if (func == r5_hash)
  		return R5_HASH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1680

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1681
  	BUG();			// should never happen
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1682

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1683
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1684
  }
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1685
  #define SWARN(silent, s, id, ...)			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1686
  	if (!(silent))				\
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1687
  		reiserfs_warning(s, id, __VA_ARGS__)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1688

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1689
  static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1690
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1691
  	struct inode *root_inode;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
  	struct reiserfs_transaction_handle th;
  	int old_format = 0;
  	unsigned long blocks;
  	unsigned int commit_max_age = 0;
  	int jinit_done = 0;
  	struct reiserfs_iget_args args;
  	struct reiserfs_super_block *rs;
  	char *jdev_name;
  	struct reiserfs_sb_info *sbi;
  	int errval = -EINVAL;
00b441970   Jan Kara   reiserfs: correct...
1702
1703
  	char *qf_names[MAXQUOTAS] = {};
  	unsigned int qfmt = 0;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1704

cdf6ccc8b   Miklos Szeredi   mount options: fi...
1705
  	save_mount_options(s, data);
01afb2134   Yan Burman   [PATCH] reiser: r...
1706
  	sbi = kzalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL);
b7b7fa431   Jeff Mahoney   reiserfs: Fix loc...
1707
1708
  	if (!sbi)
  		return -ENOMEM;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1709
  	s->s_fs_info = sbi;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1710
1711
1712
  	/* Set default values for options: non-aggressive tails, RO on errors */
  	REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_SMALLTAIL);
  	REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_ERROR_RO);
b4d5b10fb   Christoph Hellwig   reiserfs: make re...
1713
  	REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_BARRIER_FLUSH);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1714
1715
1716
1717
1718
  	/* no preallocation minimum, be smart in
  	   reiserfs_file_write instead */
  	REISERFS_SB(s)->s_alloc_options.preallocmin = 0;
  	/* Preallocate by 16 blocks (17-1) at once */
  	REISERFS_SB(s)->s_alloc_options.preallocsize = 17;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1719
1720
  	/* setup default block allocator options */
  	reiserfs_init_alloc_options(s);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1721
1722
  	mutex_init(&REISERFS_SB(s)->lock);
  	REISERFS_SB(s)->lock_depth = -1;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1723
1724
1725
  	jdev_name = NULL;
  	if (reiserfs_parse_options
  	    (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name,
00b441970   Jan Kara   reiserfs: correct...
1726
  	     &commit_max_age, qf_names, &qfmt) == 0) {
f32485be8   Frederic Weisbecker   reiserfs: delay r...
1727
  		goto error_unlocked;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1728
  	}
c3aa07764   Jan Kara   reiserfs: Properl...
1729
1730
1731
1732
1733
1734
1735
1736
  	if (jdev_name && jdev_name[0]) {
  		REISERFS_SB(s)->s_jdev = kstrdup(jdev_name, GFP_KERNEL);
  		if (!REISERFS_SB(s)->s_jdev) {
  			SWARN(silent, s, "", "Cannot allocate memory for "
  				"journal device name");
  			goto error;
  		}
  	}
00b441970   Jan Kara   reiserfs: correct...
1737
1738
1739
  #ifdef CONFIG_QUOTA
  	handle_quota_files(s, qf_names, &qfmt);
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1740
1741
  
  	if (blocks) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1742
  		SWARN(silent, s, "jmacd-7", "resize option for remount only");
f32485be8   Frederic Weisbecker   reiserfs: delay r...
1743
  		goto error_unlocked;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1744
1745
1746
1747
1748
1749
1750
  	}
  
  	/* try old format (undistributed bitmap, super block in 8-th 1k block of a device) */
  	if (!read_super_block(s, REISERFS_OLD_DISK_OFFSET_IN_BYTES))
  		old_format = 1;
  	/* try new format (64-th 1k block), which can contain reiserfs super block */
  	else if (read_super_block(s, REISERFS_DISK_OFFSET_IN_BYTES)) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1751
  		SWARN(silent, s, "sh-2021", "can not find reiserfs on %s",
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1752
  		      reiserfs_bdevname(s));
f32485be8   Frederic Weisbecker   reiserfs: delay r...
1753
  		goto error_unlocked;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1754
1755
1756
1757
1758
1759
1760
1761
1762
  	}
  
  	rs = SB_DISK_SUPER_BLOCK(s);
  	/* Let's do basic sanity check to verify that underlying device is not
  	   smaller than the filesystem. If the check fails then abort and scream,
  	   because bad stuff will happen otherwise. */
  	if (s->s_bdev && s->s_bdev->bd_inode
  	    && i_size_read(s->s_bdev->bd_inode) <
  	    sb_block_count(rs) * sb_blocksize(rs)) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1763
1764
1765
1766
1767
1768
  		SWARN(silent, s, "", "Filesystem cannot be "
  		      "mounted because it is bigger than the device");
  		SWARN(silent, s, "", "You may need to run fsck "
  		      "or increase size of your LVM partition");
  		SWARN(silent, s, "", "Or may be you forgot to "
  		      "reboot after fdisk when it told you to");
f32485be8   Frederic Weisbecker   reiserfs: delay r...
1769
  		goto error_unlocked;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1770
1771
1772
1773
  	}
  
  	sbi->s_mount_state = SB_REISERFS_STATE(s);
  	sbi->s_mount_state = REISERFS_VALID_FS;
6f01046b3   Jeff Mahoney   [PATCH] reiserfs:...
1774
  	if ((errval = reiserfs_init_bitmap_cache(s))) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1775
  		SWARN(silent, s, "jmacd-8", "unable to read bitmap");
f32485be8   Frederic Weisbecker   reiserfs: delay r...
1776
  		goto error_unlocked;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1777
  	}
f32485be8   Frederic Weisbecker   reiserfs: delay r...
1778

d2c89a428   Jeff Mahoney   [PATCH] reiserfs:...
1779
  	errval = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1780
  #ifdef CONFIG_REISERFS_CHECK
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1781
1782
  	SWARN(silent, s, "", "CONFIG_REISERFS_CHECK is set ON");
  	SWARN(silent, s, "", "- it is slow mode for debugging.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1783
  #endif
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
  	/* make data=ordered the default */
  	if (!reiserfs_data_log(s) && !reiserfs_data_ordered(s) &&
  	    !reiserfs_data_writeback(s)) {
  		REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_DATA_ORDERED);
  	}
  
  	if (reiserfs_data_log(s)) {
  		reiserfs_info(s, "using journaled data mode
  ");
  	} else if (reiserfs_data_ordered(s)) {
  		reiserfs_info(s, "using ordered data mode
  ");
  	} else {
  		reiserfs_info(s, "using writeback data mode
  ");
  	}
  	if (reiserfs_barrier_flush(s)) {
  		printk("reiserfs: using flush barriers
  ");
  	}
f32485be8   Frederic Weisbecker   reiserfs: delay r...
1804

37c69b98d   Frederic Weisbecker   reiserfs: don't l...
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
  	// set_device_ro(s->s_dev, 1) ;
  	if (journal_init(s, jdev_name, old_format, commit_max_age)) {
  		SWARN(silent, s, "sh-2022",
  		      "unable to initialize journal space");
  		goto error_unlocked;
  	} else {
  		jinit_done = 1;	/* once this is set, journal_release must be called
  				 ** if we error out of the mount
  				 */
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1815
  	if (reread_meta_blocks(s)) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1816
1817
  		SWARN(silent, s, "jmacd-9",
  		      "unable to reread meta blocks after journal init");
9b467e6eb   Frederic Weisbecker   reiserfs: don't l...
1818
  		goto error_unlocked;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1819
1820
1821
  	}
  
  	if (replay_only(s))
9b467e6eb   Frederic Weisbecker   reiserfs: don't l...
1822
  		goto error_unlocked;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1823
1824
  
  	if (bdev_read_only(s->s_bdev) && !(s->s_flags & MS_RDONLY)) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1825
1826
  		SWARN(silent, s, "clm-7000",
  		      "Detected readonly device, marking FS readonly");
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1827
1828
1829
1830
1831
1832
1833
1834
  		s->s_flags |= MS_RDONLY;
  	}
  	args.objectid = REISERFS_ROOT_OBJECTID;
  	args.dirid = REISERFS_ROOT_PARENT_OBJECTID;
  	root_inode =
  	    iget5_locked(s, REISERFS_ROOT_OBJECTID, reiserfs_find_actor,
  			 reiserfs_init_locked_inode, (void *)(&args));
  	if (!root_inode) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1835
  		SWARN(silent, s, "jmacd-10", "get root inode failed");
9b467e6eb   Frederic Weisbecker   reiserfs: don't l...
1836
  		goto error_unlocked;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1837
  	}
9b467e6eb   Frederic Weisbecker   reiserfs: don't l...
1838
1839
1840
1841
1842
1843
1844
1845
1846
  	/*
  	 * This path assumed to be called with the BKL in the old times.
  	 * Now we have inherited the big reiserfs lock from it and many
  	 * reiserfs helpers called in the mount path and elsewhere require
  	 * this lock to be held even if it's not always necessary. Let's be
  	 * conservative and hold it early. The window can be reduced after
  	 * careful review of the code.
  	 */
  	reiserfs_write_lock(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
  	if (root_inode->i_state & I_NEW) {
  		reiserfs_read_locked_inode(root_inode, &args);
  		unlock_new_inode(root_inode);
  	}
  
  	s->s_root = d_alloc_root(root_inode);
  	if (!s->s_root) {
  		iput(root_inode);
  		goto error;
  	}
  	// define and initialize hash function
  	sbi->s_hash_function = hash_function(s);
  	if (sbi->s_hash_function == NULL) {
  		dput(s->s_root);
  		s->s_root = NULL;
  		goto error;
  	}
  
  	if (is_reiserfs_3_5(rs)
  	    || (is_reiserfs_jr(rs) && SB_VERSION(s) == REISERFS_VERSION_1))
  		set_bit(REISERFS_3_5, &(sbi->s_properties));
e1fabd3cc   Jeff Mahoney   [PATCH] reiserfs:...
1868
1869
  	else if (old_format)
  		set_bit(REISERFS_OLD_FORMAT, &(sbi->s_properties));
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
  	else
  		set_bit(REISERFS_3_6, &(sbi->s_properties));
  
  	if (!(s->s_flags & MS_RDONLY)) {
  
  		errval = journal_begin(&th, s, 1);
  		if (errval) {
  			dput(s->s_root);
  			s->s_root = NULL;
  			goto error;
  		}
  		reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
  
  		set_sb_umount_state(rs, REISERFS_ERROR_FS);
  		set_sb_fs_state(rs, 0);
cb680c1be   Jeff Mahoney   reiserfs: ignore ...
1885
1886
1887
1888
1889
1890
  		/* Clear out s_bmap_nr if it would wrap. We can handle this
  		 * case, but older revisions can't. This will cause the
  		 * file system to fail mount on those older implementations,
  		 * avoiding corruption. -jeffm */
  		if (bmap_would_wrap(reiserfs_bmap_count(s)) &&
  		    sb_bmap_nr(rs) != 0) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
1891
  			reiserfs_warning(s, "super-2030", "This file system "
cb680c1be   Jeff Mahoney   reiserfs: ignore ...
1892
1893
1894
1895
1896
1897
1898
  					"claims to use %u bitmap blocks in "
  					"its super block, but requires %u. "
  					"Clearing to zero.", sb_bmap_nr(rs),
  					reiserfs_bmap_count(s));
  
  			set_sb_bmap_nr(rs, 0);
  		}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
  		if (old_format_only(s)) {
  			/* filesystem of format 3.5 either with standard or non-standard
  			   journal */
  			if (convert_reiserfs(s)) {
  				/* and -o conv is given */
  				if (!silent)
  					reiserfs_info(s,
  						      "converting 3.5 filesystem to the 3.6 format");
  
  				if (is_reiserfs_3_5(rs))
  					/* put magic string of 3.6 format. 2.2 will not be able to
  					   mount this filesystem anymore */
  					memcpy(rs->s_v1.s_magic,
  					       reiserfs_3_6_magic_string,
  					       sizeof
  					       (reiserfs_3_6_magic_string));
  
  				set_sb_version(rs, REISERFS_VERSION_2);
  				reiserfs_convert_objectid_map_v1(s);
  				set_bit(REISERFS_3_6, &(sbi->s_properties));
  				clear_bit(REISERFS_3_5, &(sbi->s_properties));
  			} else if (!silent) {
  				reiserfs_info(s, "using 3.5.x disk format
  ");
  			}
702d21c6f   Jeff Mahoney   reiserfs: add sup...
1924
1925
  		} else
  			set_sb_mnt_count(rs, sb_mnt_count(rs) + 1);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1926
1927
1928
1929
1930
1931
1932
1933
  
  		journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
  		errval = journal_end(&th, s, 1);
  		if (errval) {
  			dput(s->s_root);
  			s->s_root = NULL;
  			goto error;
  		}
edcc37a04   Al Viro   Always lookup pri...
1934
1935
  		if ((errval = reiserfs_lookup_privroot(s)) ||
  		    (errval = reiserfs_xattr_init(s, s->s_flags))) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
  			dput(s->s_root);
  			s->s_root = NULL;
  			goto error;
  		}
  
  		/* look for files which were to be removed in previous session */
  		finish_unfinished(s);
  	} else {
  		if (old_format_only(s) && !silent) {
  			reiserfs_info(s, "using 3.5.x disk format
  ");
  		}
edcc37a04   Al Viro   Always lookup pri...
1948
1949
  		if ((errval = reiserfs_lookup_privroot(s)) ||
  		    (errval = reiserfs_xattr_init(s, s->s_flags))) {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
  			dput(s->s_root);
  			s->s_root = NULL;
  			goto error;
  		}
  	}
  	// mark hash in super block: it could be unset. overwrite should be ok
  	set_sb_hash_function_code(rs, function2code(sbi->s_hash_function));
  
  	handle_attrs(s);
  
  	reiserfs_proc_info_init(s);
  
  	init_waitqueue_head(&(sbi->s_wait));
  	spin_lock_init(&sbi->bitmap_lock);
8ebc42323   Frederic Weisbecker   reiserfs: kill-th...
1964
  	reiserfs_write_unlock(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1965
  	return (0);
00b441970   Jan Kara   reiserfs: correct...
1966
  error:
f32485be8   Frederic Weisbecker   reiserfs: delay r...
1967
1968
1969
1970
1971
1972
  	reiserfs_write_unlock(s);
  
  error_unlocked:
  	/* kill the commit thread, free journal ram */
  	if (jinit_done) {
  		reiserfs_write_lock(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1973
  		journal_release_error(NULL, s);
f32485be8   Frederic Weisbecker   reiserfs: delay r...
1974
  		reiserfs_write_unlock(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1975
  	}
5065227b4   Jeff Mahoney   [PATCH] reiserfs:...
1976
1977
  
  	reiserfs_free_bitmap_cache(s);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1978
1979
  	if (SB_BUFFER_WITH_SB(s))
  		brelse(SB_BUFFER_WITH_SB(s));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1980
  #ifdef CONFIG_QUOTA
5065227b4   Jeff Mahoney   [PATCH] reiserfs:...
1981
1982
  	{
  		int j;
00b441970   Jan Kara   reiserfs: correct...
1983
1984
  		for (j = 0; j < MAXQUOTAS; j++)
  			kfree(qf_names[j]);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1985
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1986
  #endif
833d304b2   James Lamanna   [PATCH] reiserfs:...
1987
  	kfree(sbi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1988

bd4c625c0   Linus Torvalds   reiserfs: run scr...
1989
1990
  	s->s_fs_info = NULL;
  	return errval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1991
  }
726c33422   David Howells   [PATCH] VFS: Perm...
1992
  static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1993
  {
726c33422   David Howells   [PATCH] VFS: Perm...
1994
  	struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(dentry->d_sb);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
1995
1996
1997
1998
1999
  
  	buf->f_namelen = (REISERFS_MAX_NAME(s->s_blocksize));
  	buf->f_bfree = sb_free_blocks(rs);
  	buf->f_bavail = buf->f_bfree;
  	buf->f_blocks = sb_block_count(rs) - sb_bmap_nr(rs) - 1;
726c33422   David Howells   [PATCH] VFS: Perm...
2000
  	buf->f_bsize = dentry->d_sb->s_blocksize;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2001
2002
  	/* changed to accommodate gcc folks. */
  	buf->f_type = REISERFS_SUPER_MAGIC;
651d06230   Coly Li   fs/reiserfs: retu...
2003
2004
2005
  	buf->f_fsid.val[0] = (u32)crc32_le(0, rs->s_uuid, sizeof(rs->s_uuid)/2);
  	buf->f_fsid.val[1] = (u32)crc32_le(0, rs->s_uuid + sizeof(rs->s_uuid)/2,
  				sizeof(rs->s_uuid)/2);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2006
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2007
2008
2009
  }
  
  #ifdef CONFIG_QUOTA
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2010
2011
  static int reiserfs_write_dquot(struct dquot *dquot)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
  	struct reiserfs_transaction_handle th;
  	int ret, err;
  
  	reiserfs_write_lock(dquot->dq_sb);
  	ret =
  	    journal_begin(&th, dquot->dq_sb,
  			  REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
  	if (ret)
  		goto out;
  	ret = dquot_commit(dquot);
  	err =
  	    journal_end(&th, dquot->dq_sb,
  			REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
  	if (!ret && err)
  		ret = err;
        out:
  	reiserfs_write_unlock(dquot->dq_sb);
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2030
2031
2032
2033
  }
  
  static int reiserfs_acquire_dquot(struct dquot *dquot)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
  	struct reiserfs_transaction_handle th;
  	int ret, err;
  
  	reiserfs_write_lock(dquot->dq_sb);
  	ret =
  	    journal_begin(&th, dquot->dq_sb,
  			  REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
  	if (ret)
  		goto out;
  	ret = dquot_acquire(dquot);
  	err =
  	    journal_end(&th, dquot->dq_sb,
  			REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
  	if (!ret && err)
  		ret = err;
        out:
  	reiserfs_write_unlock(dquot->dq_sb);
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2052
2053
2054
2055
  }
  
  static int reiserfs_release_dquot(struct dquot *dquot)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2056
2057
2058
2059
2060
2061
2062
  	struct reiserfs_transaction_handle th;
  	int ret, err;
  
  	reiserfs_write_lock(dquot->dq_sb);
  	ret =
  	    journal_begin(&th, dquot->dq_sb,
  			  REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
9c3013e9b   Jan Kara   quota: fix infini...
2063
2064
2065
  	if (ret) {
  		/* Release dquot anyway to avoid endless cycle in dqput() */
  		dquot_release(dquot);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2066
  		goto out;
9c3013e9b   Jan Kara   quota: fix infini...
2067
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2068
2069
2070
2071
2072
2073
2074
2075
2076
  	ret = dquot_release(dquot);
  	err =
  	    journal_end(&th, dquot->dq_sb,
  			REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
  	if (!ret && err)
  		ret = err;
        out:
  	reiserfs_write_unlock(dquot->dq_sb);
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2077
2078
2079
2080
  }
  
  static int reiserfs_mark_dquot_dirty(struct dquot *dquot)
  {
4506567b2   Jan Kara   reiserfs: fix typ...
2081
  	/* Are we journaling quotas? */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2082
2083
2084
2085
2086
2087
  	if (REISERFS_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] ||
  	    REISERFS_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) {
  		dquot_mark_dquot_dirty(dquot);
  		return reiserfs_write_dquot(dquot);
  	} else
  		return dquot_mark_dquot_dirty(dquot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2088
2089
2090
2091
  }
  
  static int reiserfs_write_info(struct super_block *sb, int type)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
  	struct reiserfs_transaction_handle th;
  	int ret, err;
  
  	/* Data block + inode block */
  	reiserfs_write_lock(sb);
  	ret = journal_begin(&th, sb, 2);
  	if (ret)
  		goto out;
  	ret = dquot_commit_info(sb, type);
  	err = journal_end(&th, sb, 2);
  	if (!ret && err)
  		ret = err;
        out:
  	reiserfs_write_unlock(sb);
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2107
2108
2109
  }
  
  /*
84de856ed   Christoph Hellwig   [PATCH] quota: co...
2110
   * Turn on quotas during mount time - we need to find the quota file and such...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2111
2112
2113
   */
  static int reiserfs_quota_on_mount(struct super_block *sb, int type)
  {
287a80958   Christoph Hellwig   quota: rename def...
2114
2115
  	return dquot_quota_on_mount(sb, REISERFS_SB(sb)->s_qf_names[type],
  					REISERFS_SB(sb)->s_jquota_fmt, type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2116
2117
2118
2119
2120
  }
  
  /*
   * Standard function to be called on quota_on
   */
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2121
  static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
f00c9e44a   Jan Kara   quota: Fix deadlo...
2122
  			     struct path *path)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2123
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2124
  	int err;
d5dee5c39   Jan Kara   reiserfs: unpack ...
2125
  	struct inode *inode;
5d4f7fddf   Jan Kara   reiserfs: fix syn...
2126
  	struct reiserfs_transaction_handle th;
c3aa07764   Jan Kara   reiserfs: Properl...
2127
  	int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2128

c3aa07764   Jan Kara   reiserfs: Properl...
2129
  	if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt)))
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2130
  		return -EINVAL;
307ae18a5   Christoph Hellwig   quota: drop remou...
2131

bd4c625c0   Linus Torvalds   reiserfs: run scr...
2132
  	/* Quotafile not on the same filesystem? */
d8c9584ea   Al Viro   vfs: prefer ->den...
2133
  	if (path->dentry->d_sb != sb) {
77e69dac3   Al Viro   [PATCH] fix races...
2134
2135
  		err = -EXDEV;
  		goto out;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2136
  	}
f00c9e44a   Jan Kara   quota: Fix deadlo...
2137
  	inode = path->dentry->d_inode;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2138
  	/* We must not pack tails for quota files on reiserfs for quota IO to work */
d5dee5c39   Jan Kara   reiserfs: unpack ...
2139
2140
2141
  	if (!(REISERFS_I(inode)->i_flags & i_nopack_mask)) {
  		err = reiserfs_unpack(inode, NULL);
  		if (err) {
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2142
2143
  			reiserfs_warning(sb, "super-6520",
  				"Unpacking tail of quota file failed"
d5dee5c39   Jan Kara   reiserfs: unpack ...
2144
  				" (%d). Cannot turn on quotas.", err);
77e69dac3   Al Viro   [PATCH] fix races...
2145
2146
  			err = -EINVAL;
  			goto out;
d5dee5c39   Jan Kara   reiserfs: unpack ...
2147
2148
  		}
  		mark_inode_dirty(inode);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2149
  	}
5d4f7fddf   Jan Kara   reiserfs: fix syn...
2150
2151
2152
  	/* Journaling quota? */
  	if (REISERFS_SB(sb)->s_qf_names[type]) {
  		/* Quotafile not of fs root? */
f00c9e44a   Jan Kara   quota: Fix deadlo...
2153
  		if (path->dentry->d_parent != sb->s_root)
45b03d5e8   Jeff Mahoney   reiserfs: rework ...
2154
2155
  			reiserfs_warning(sb, "super-6521",
  				 "Quota file not on filesystem root. "
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2156
  				 "Journalled quota will not work.");
5d4f7fddf   Jan Kara   reiserfs: fix syn...
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
  	}
  
  	/*
  	 * When we journal data on quota file, we have to flush journal to see
  	 * all updates to the file when we bypass pagecache...
  	 */
  	if (reiserfs_file_data_log(inode)) {
  		/* Just start temporary transaction and finish it */
  		err = journal_begin(&th, sb, 1);
  		if (err)
77e69dac3   Al Viro   [PATCH] fix races...
2167
  			goto out;
5d4f7fddf   Jan Kara   reiserfs: fix syn...
2168
2169
  		err = journal_end_sync(&th, sb, 1);
  		if (err)
77e69dac3   Al Viro   [PATCH] fix races...
2170
  			goto out;
5d4f7fddf   Jan Kara   reiserfs: fix syn...
2171
  	}
f00c9e44a   Jan Kara   quota: Fix deadlo...
2172
  	err = dquot_quota_on(sb, type, format_id, path);
77e69dac3   Al Viro   [PATCH] fix races...
2173
  out:
77e69dac3   Al Viro   [PATCH] fix races...
2174
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2175
2176
2177
2178
  }
  
  /* Read data from quotafile - avoid pagecache and such because we cannot afford
   * acquiring the locks... As quota files are never truncated and quota code
25985edce   Lucas De Marchi   Fix common misspe...
2179
   * itself serializes the operations (and no one else should touch the files)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2180
2181
2182
2183
   * we don't have to be afraid of races */
  static ssize_t reiserfs_quota_read(struct super_block *sb, int type, char *data,
  				   size_t len, loff_t off)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
  	struct inode *inode = sb_dqopt(sb)->files[type];
  	unsigned long blk = off >> sb->s_blocksize_bits;
  	int err = 0, offset = off & (sb->s_blocksize - 1), tocopy;
  	size_t toread;
  	struct buffer_head tmp_bh, *bh;
  	loff_t i_size = i_size_read(inode);
  
  	if (off > i_size)
  		return 0;
  	if (off + len > i_size)
  		len = i_size - off;
  	toread = len;
  	while (toread > 0) {
  		tocopy =
  		    sb->s_blocksize - offset <
  		    toread ? sb->s_blocksize - offset : toread;
  		tmp_bh.b_state = 0;
  		/* Quota files are without tails so we can safely use this function */
  		reiserfs_write_lock(sb);
  		err = reiserfs_get_block(inode, blk, &tmp_bh, 0);
  		reiserfs_write_unlock(sb);
  		if (err)
  			return err;
  		if (!buffer_mapped(&tmp_bh))	/* A hole? */
  			memset(data, 0, tocopy);
  		else {
  			bh = sb_bread(sb, tmp_bh.b_blocknr);
  			if (!bh)
  				return -EIO;
  			memcpy(data, bh->b_data + offset, tocopy);
  			brelse(bh);
  		}
  		offset = 0;
  		toread -= tocopy;
  		data += tocopy;
  		blk++;
  	}
  	return len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2222
2223
2224
2225
2226
2227
2228
  }
  
  /* Write to quotafile (we know the transaction is already started and has
   * enough credits) */
  static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
  				    const char *data, size_t len, loff_t off)
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2229
2230
2231
2232
2233
2234
  	struct inode *inode = sb_dqopt(sb)->files[type];
  	unsigned long blk = off >> sb->s_blocksize_bits;
  	int err = 0, offset = off & (sb->s_blocksize - 1), tocopy;
  	int journal_quota = REISERFS_SB(sb)->s_qf_names[type] != NULL;
  	size_t towrite = len;
  	struct buffer_head tmp_bh, *bh;
9c3013e9b   Jan Kara   quota: fix infini...
2235
2236
2237
2238
2239
2240
2241
  	if (!current->journal_info) {
  		printk(KERN_WARNING "reiserfs: Quota write (off=%Lu, len=%Lu)"
  			" cancelled because transaction is not started.
  ",
  			(unsigned long long)off, (unsigned long long)len);
  		return -EIO;
  	}
5c81a4197   Arjan van de Ven   [PATCH] lockdep: ...
2242
  	mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
  	while (towrite > 0) {
  		tocopy = sb->s_blocksize - offset < towrite ?
  		    sb->s_blocksize - offset : towrite;
  		tmp_bh.b_state = 0;
  		err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE);
  		if (err)
  			goto out;
  		if (offset || tocopy != sb->s_blocksize)
  			bh = sb_bread(sb, tmp_bh.b_blocknr);
  		else
  			bh = sb_getblk(sb, tmp_bh.b_blocknr);
  		if (!bh) {
  			err = -EIO;
  			goto out;
  		}
  		lock_buffer(bh);
  		memcpy(bh->b_data + offset, data, tocopy);
  		flush_dcache_page(bh->b_page);
  		set_buffer_uptodate(bh);
  		unlock_buffer(bh);
  		reiserfs_prepare_for_journal(sb, bh, 1);
  		journal_mark_dirty(current->journal_info, sb, bh);
  		if (!journal_quota)
  			reiserfs_add_ordered_list(inode, bh);
  		brelse(bh);
  		offset = 0;
  		towrite -= tocopy;
  		data += tocopy;
  		blk++;
  	}
9c3013e9b   Jan Kara   quota: fix infini...
2273
  out:
10dd08dc0   Jan Kara   reiserfs: add mis...
2274
2275
  	if (len == towrite) {
  		mutex_unlock(&inode->i_mutex);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2276
  		return err;
10dd08dc0   Jan Kara   reiserfs: add mis...
2277
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2278
2279
2280
2281
2282
  	if (inode->i_size < off + len - towrite)
  		i_size_write(inode, off + len - towrite);
  	inode->i_version++;
  	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  	mark_inode_dirty(inode);
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
2283
  	mutex_unlock(&inode->i_mutex);
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2284
  	return len - towrite;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2285
2286
2287
  }
  
  #endif
152a08366   Al Viro   new helper: mount...
2288
  static struct dentry *get_super_block(struct file_system_type *fs_type,
454e2398b   David Howells   [PATCH] VFS: Perm...
2289
  			   int flags, const char *dev_name,
152a08366   Al Viro   new helper: mount...
2290
  			   void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2291
  {
152a08366   Al Viro   new helper: mount...
2292
  	return mount_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2293
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2294
  static int __init init_reiserfs_fs(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2295
2296
  {
  	int ret;
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2297
  	if ((ret = init_inodecache())) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2298
2299
  		return ret;
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2300
  	reiserfs_proc_info_global_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2301

bd4c625c0   Linus Torvalds   reiserfs: run scr...
2302
  	ret = register_filesystem(&reiserfs_fs_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2303
2304
2305
2306
  
  	if (ret == 0) {
  		return 0;
  	}
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2307
2308
  	reiserfs_proc_info_global_done();
  	destroy_inodecache();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2309
2310
2311
  
  	return ret;
  }
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2312
  static void __exit exit_reiserfs_fs(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2313
  {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2314
2315
2316
  	reiserfs_proc_info_global_done();
  	unregister_filesystem(&reiserfs_fs_type);
  	destroy_inodecache();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2317
2318
2319
  }
  
  struct file_system_type reiserfs_fs_type = {
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2320
2321
  	.owner = THIS_MODULE,
  	.name = "reiserfs",
152a08366   Al Viro   new helper: mount...
2322
  	.mount = get_super_block,
edc666e2f   David Howells   [PATCH] ReiserFS:...
2323
  	.kill_sb = reiserfs_kill_sb,
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2324
  	.fs_flags = FS_REQUIRES_DEV,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2325
  };
bd4c625c0   Linus Torvalds   reiserfs: run scr...
2326
2327
2328
  MODULE_DESCRIPTION("ReiserFS journaled filesystem");
  MODULE_AUTHOR("Hans Reiser <reiser@namesys.com>");
  MODULE_LICENSE("GPL");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2329

bd4c625c0   Linus Torvalds   reiserfs: run scr...
2330
2331
  module_init(init_reiserfs_fs);
  module_exit(exit_reiserfs_fs);