Blame view

fs/xfs/xfs_mount.c 66.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
7b7187698   Nathan Scott   [XFS] Update lice...
2
3
   * Copyright (c) 2000-2005 Silicon Graphics, Inc.
   * All Rights Reserved.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
   *
7b7187698   Nathan Scott   [XFS] Update lice...
5
6
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
   * published by the Free Software Foundation.
   *
7b7187698   Nathan Scott   [XFS] Update lice...
9
10
11
12
   * This program is distributed in the hope that it would be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
   *
7b7187698   Nathan Scott   [XFS] Update lice...
14
15
16
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write the Free Software Foundation,
   * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include "xfs.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
19
  #include "xfs_fs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #include "xfs_types.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
21
  #include "xfs_bit.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #include "xfs_log.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
23
  #include "xfs_inum.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
  #include "xfs_trans.h"
  #include "xfs_sb.h"
  #include "xfs_ag.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  #include "xfs_dir2.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  #include "xfs_mount.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  #include "xfs_bmap_btree.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
30
  #include "xfs_alloc_btree.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
  #include "xfs_ialloc_btree.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
  #include "xfs_dinode.h"
  #include "xfs_inode.h"
a844f4510   Nathan Scott   [XFS] Remove xfs_...
34
35
  #include "xfs_btree.h"
  #include "xfs_ialloc.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
  #include "xfs_alloc.h"
  #include "xfs_rtalloc.h"
  #include "xfs_bmap.h"
  #include "xfs_error.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
  #include "xfs_rw.h"
  #include "xfs_quota.h"
  #include "xfs_fsops.h"
433550990   Christoph Hellwig   [XFS] remove most...
43
  #include "xfs_utils.h"
0b1b213fc   Christoph Hellwig   xfs: event tracin...
44
  #include "xfs_trace.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45

ba0f32d46   Christoph Hellwig   [XFS] mark variou...
46
  STATIC void	xfs_unmountfs_wait(xfs_mount_t *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47

8d280b98c   David Chinner   [XFS] On machines...
48
49
  
  #ifdef HAVE_PERCPU_SB
20f4ebf2b   David Chinner   [XFS] Make growfs...
50
  STATIC void	xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
45af6c6de   Christoph Hellwig   [XFS] split xfs_i...
51
52
53
  						int);
  STATIC void	xfs_icsb_balance_counter_locked(xfs_mount_t *, xfs_sb_field_t,
  						int);
36fbe6e6b   David Chinner   [XFS] xfs_icsb_co...
54
  STATIC void	xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
8d280b98c   David Chinner   [XFS] On machines...
55
  #else
45af6c6de   Christoph Hellwig   [XFS] split xfs_i...
56
57
  #define xfs_icsb_balance_counter(mp, a, b)		do { } while (0)
  #define xfs_icsb_balance_counter_locked(mp, a, b)	do { } while (0)
8d280b98c   David Chinner   [XFS] On machines...
58
  #endif
1df84c930   Christoph Hellwig   [XFS] Mark some l...
59
  static const struct {
8d280b98c   David Chinner   [XFS] On machines...
60
61
62
63
  	short offset;
  	short type;	/* 0 = integer
  			 * 1 = binary / string (no translation)
  			 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
  } xfs_sb_info[] = {
      { offsetof(xfs_sb_t, sb_magicnum),   0 },
      { offsetof(xfs_sb_t, sb_blocksize),  0 },
      { offsetof(xfs_sb_t, sb_dblocks),    0 },
      { offsetof(xfs_sb_t, sb_rblocks),    0 },
      { offsetof(xfs_sb_t, sb_rextents),   0 },
      { offsetof(xfs_sb_t, sb_uuid),       1 },
      { offsetof(xfs_sb_t, sb_logstart),   0 },
      { offsetof(xfs_sb_t, sb_rootino),    0 },
      { offsetof(xfs_sb_t, sb_rbmino),     0 },
      { offsetof(xfs_sb_t, sb_rsumino),    0 },
      { offsetof(xfs_sb_t, sb_rextsize),   0 },
      { offsetof(xfs_sb_t, sb_agblocks),   0 },
      { offsetof(xfs_sb_t, sb_agcount),    0 },
      { offsetof(xfs_sb_t, sb_rbmblocks),  0 },
      { offsetof(xfs_sb_t, sb_logblocks),  0 },
      { offsetof(xfs_sb_t, sb_versionnum), 0 },
      { offsetof(xfs_sb_t, sb_sectsize),   0 },
      { offsetof(xfs_sb_t, sb_inodesize),  0 },
      { offsetof(xfs_sb_t, sb_inopblock),  0 },
      { offsetof(xfs_sb_t, sb_fname[0]),   1 },
      { offsetof(xfs_sb_t, sb_blocklog),   0 },
      { offsetof(xfs_sb_t, sb_sectlog),    0 },
      { offsetof(xfs_sb_t, sb_inodelog),   0 },
      { offsetof(xfs_sb_t, sb_inopblog),   0 },
      { offsetof(xfs_sb_t, sb_agblklog),   0 },
      { offsetof(xfs_sb_t, sb_rextslog),   0 },
      { offsetof(xfs_sb_t, sb_inprogress), 0 },
      { offsetof(xfs_sb_t, sb_imax_pct),   0 },
      { offsetof(xfs_sb_t, sb_icount),     0 },
      { offsetof(xfs_sb_t, sb_ifree),      0 },
      { offsetof(xfs_sb_t, sb_fdblocks),   0 },
      { offsetof(xfs_sb_t, sb_frextents),  0 },
      { offsetof(xfs_sb_t, sb_uquotino),   0 },
      { offsetof(xfs_sb_t, sb_gquotino),   0 },
      { offsetof(xfs_sb_t, sb_qflags),     0 },
      { offsetof(xfs_sb_t, sb_flags),      0 },
      { offsetof(xfs_sb_t, sb_shared_vn),  0 },
      { offsetof(xfs_sb_t, sb_inoalignmt), 0 },
      { offsetof(xfs_sb_t, sb_unit),	 0 },
      { offsetof(xfs_sb_t, sb_width),	 0 },
      { offsetof(xfs_sb_t, sb_dirblklog),	 0 },
      { offsetof(xfs_sb_t, sb_logsectlog), 0 },
      { offsetof(xfs_sb_t, sb_logsectsize),0 },
      { offsetof(xfs_sb_t, sb_logsunit),	 0 },
      { offsetof(xfs_sb_t, sb_features2),	 0 },
ee1c09082   David Chinner   [XFS] Fix superbl...
110
      { offsetof(xfs_sb_t, sb_bad_features2), 0 },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
      { sizeof(xfs_sb_t),			 0 }
  };
27174203f   Christoph Hellwig   xfs: cleanup uuid...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
  static DEFINE_MUTEX(xfs_uuid_table_mutex);
  static int xfs_uuid_table_size;
  static uuid_t *xfs_uuid_table;
  
  /*
   * See if the UUID is unique among mounted XFS filesystems.
   * Mount fails if UUID is nil or a FS with the same UUID is already mounted.
   */
  STATIC int
  xfs_uuid_mount(
  	struct xfs_mount	*mp)
  {
  	uuid_t			*uuid = &mp->m_sb.sb_uuid;
  	int			hole, i;
  
  	if (mp->m_flags & XFS_MOUNT_NOUUID)
  		return 0;
  
  	if (uuid_is_nil(uuid)) {
0b932cccb   Dave Chinner   xfs: Convert rema...
132
  		xfs_warn(mp, "Filesystem has nil UUID - can't mount");
27174203f   Christoph Hellwig   xfs: cleanup uuid...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  		return XFS_ERROR(EINVAL);
  	}
  
  	mutex_lock(&xfs_uuid_table_mutex);
  	for (i = 0, hole = -1; i < xfs_uuid_table_size; i++) {
  		if (uuid_is_nil(&xfs_uuid_table[i])) {
  			hole = i;
  			continue;
  		}
  		if (uuid_equal(uuid, &xfs_uuid_table[i]))
  			goto out_duplicate;
  	}
  
  	if (hole < 0) {
  		xfs_uuid_table = kmem_realloc(xfs_uuid_table,
  			(xfs_uuid_table_size + 1) * sizeof(*xfs_uuid_table),
  			xfs_uuid_table_size  * sizeof(*xfs_uuid_table),
  			KM_SLEEP);
  		hole = xfs_uuid_table_size++;
  	}
  	xfs_uuid_table[hole] = *uuid;
  	mutex_unlock(&xfs_uuid_table_mutex);
  
  	return 0;
  
   out_duplicate:
  	mutex_unlock(&xfs_uuid_table_mutex);
0b932cccb   Dave Chinner   xfs: Convert rema...
160
  	xfs_warn(mp, "Filesystem has duplicate UUID - can't mount");
27174203f   Christoph Hellwig   xfs: cleanup uuid...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  	return XFS_ERROR(EINVAL);
  }
  
  STATIC void
  xfs_uuid_unmount(
  	struct xfs_mount	*mp)
  {
  	uuid_t			*uuid = &mp->m_sb.sb_uuid;
  	int			i;
  
  	if (mp->m_flags & XFS_MOUNT_NOUUID)
  		return;
  
  	mutex_lock(&xfs_uuid_table_mutex);
  	for (i = 0; i < xfs_uuid_table_size; i++) {
  		if (uuid_is_nil(&xfs_uuid_table[i]))
  			continue;
  		if (!uuid_equal(uuid, &xfs_uuid_table[i]))
  			continue;
  		memset(&xfs_uuid_table[i], 0, sizeof(uuid_t));
  		break;
  	}
  	ASSERT(i < xfs_uuid_table_size);
  	mutex_unlock(&xfs_uuid_table_mutex);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
  /*
0fa800fbd   Dave Chinner   xfs: Add trace po...
187
   * Reference counting access wrappers to the perag structures.
e176579e7   Dave Chinner   xfs: lockless per...
188
189
   * Because we never free per-ag structures, the only thing we
   * have to protect against changes is the tree structure itself.
0fa800fbd   Dave Chinner   xfs: Add trace po...
190
191
192
193
194
195
   */
  struct xfs_perag *
  xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno)
  {
  	struct xfs_perag	*pag;
  	int			ref = 0;
e176579e7   Dave Chinner   xfs: lockless per...
196
  	rcu_read_lock();
0fa800fbd   Dave Chinner   xfs: Add trace po...
197
198
199
  	pag = radix_tree_lookup(&mp->m_perag_tree, agno);
  	if (pag) {
  		ASSERT(atomic_read(&pag->pag_ref) >= 0);
0fa800fbd   Dave Chinner   xfs: Add trace po...
200
201
  		ref = atomic_inc_return(&pag->pag_ref);
  	}
e176579e7   Dave Chinner   xfs: lockless per...
202
  	rcu_read_unlock();
0fa800fbd   Dave Chinner   xfs: Add trace po...
203
204
205
  	trace_xfs_perag_get(mp, agno, ref, _RET_IP_);
  	return pag;
  }
65d0f2053   Dave Chinner   xfs: split inode ...
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
  /*
   * search from @first to find the next perag with the given tag set.
   */
  struct xfs_perag *
  xfs_perag_get_tag(
  	struct xfs_mount	*mp,
  	xfs_agnumber_t		first,
  	int			tag)
  {
  	struct xfs_perag	*pag;
  	int			found;
  	int			ref;
  
  	rcu_read_lock();
  	found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
  					(void **)&pag, first, 1, tag);
  	if (found <= 0) {
  		rcu_read_unlock();
  		return NULL;
  	}
  	ref = atomic_inc_return(&pag->pag_ref);
  	rcu_read_unlock();
  	trace_xfs_perag_get_tag(mp, pag->pag_agno, ref, _RET_IP_);
  	return pag;
  }
0fa800fbd   Dave Chinner   xfs: Add trace po...
231
232
233
234
235
236
237
238
239
  void
  xfs_perag_put(struct xfs_perag *pag)
  {
  	int	ref;
  
  	ASSERT(atomic_read(&pag->pag_ref) > 0);
  	ref = atomic_dec_return(&pag->pag_ref);
  	trace_xfs_perag_put(pag->pag_mount, pag->pag_agno, ref, _RET_IP_);
  }
e176579e7   Dave Chinner   xfs: lockless per...
240
241
242
243
244
245
246
247
248
  STATIC void
  __xfs_free_perag(
  	struct rcu_head	*head)
  {
  	struct xfs_perag *pag = container_of(head, struct xfs_perag, rcu_head);
  
  	ASSERT(atomic_read(&pag->pag_ref) == 0);
  	kmem_free(pag);
  }
0fa800fbd   Dave Chinner   xfs: Add trace po...
249
  /*
e176579e7   Dave Chinner   xfs: lockless per...
250
   * Free up the per-ag resources associated with the mount structure.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
   */
c962fb790   Christoph Hellwig   [XFS] kill xfs_mo...
252
  STATIC void
ff4f038c6   Christoph Hellwig   [XFS] refactor xf...
253
  xfs_free_perag(
745f69191   Christoph Hellwig   [XFS] call common...
254
  	xfs_mount_t	*mp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
  {
1c1c6ebcf   Dave Chinner   xfs: Replace per-...
256
257
258
259
260
261
262
  	xfs_agnumber_t	agno;
  	struct xfs_perag *pag;
  
  	for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
  		spin_lock(&mp->m_perag_lock);
  		pag = radix_tree_delete(&mp->m_perag_tree, agno);
  		spin_unlock(&mp->m_perag_lock);
e176579e7   Dave Chinner   xfs: lockless per...
263
  		ASSERT(pag);
f83282a8e   Dave Chinner   xfs: fix per-ag r...
264
  		ASSERT(atomic_read(&pag->pag_ref) == 0);
e176579e7   Dave Chinner   xfs: lockless per...
265
  		call_rcu(&pag->rcu_head, __xfs_free_perag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  }
4cc929ee3   Nathan Scott   [XFS] Don't grow ...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  /*
   * Check size of device based on the (data/realtime) block count.
   * Note: this check is used by the growfs code as well as mount.
   */
  int
  xfs_sb_validate_fsb_count(
  	xfs_sb_t	*sbp,
  	__uint64_t	nblocks)
  {
  	ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);
  	ASSERT(sbp->sb_blocklog >= BBSHIFT);
  
  #if XFS_BIG_BLKNOS     /* Limited by ULONG_MAX of page cache index */
  	if (nblocks >> (PAGE_CACHE_SHIFT - sbp->sb_blocklog) > ULONG_MAX)
657a4cffd   Eric Sandeen   xfs: replace E2BI...
282
  		return EFBIG;
4cc929ee3   Nathan Scott   [XFS] Don't grow ...
283
284
  #else                  /* Limited by UINT_MAX of sectors */
  	if (nblocks << (sbp->sb_blocklog - BBSHIFT) > UINT_MAX)
657a4cffd   Eric Sandeen   xfs: replace E2BI...
285
  		return EFBIG;
4cc929ee3   Nathan Scott   [XFS] Don't grow ...
286
287
288
  #endif
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
290
291
292
293
294
295
  
  /*
   * Check the validity of the SB found.
   */
  STATIC int
  xfs_mount_validate_sb(
  	xfs_mount_t	*mp,
764d1f89a   Nathan Scott   [XFS] Implement t...
296
297
  	xfs_sb_t	*sbp,
  	int		flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
  {
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
299
  	int		loud = !(flags & XFS_MFSI_QUIET);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
301
302
303
304
305
306
307
  	/*
  	 * If the log device and data device have the
  	 * same device number, the log is internal.
  	 * Consequently, the sb_logstart should be non-zero.  If
  	 * we have a zero sb_logstart in this case, we may be trying to mount
  	 * a volume filesystem in a non-volume manner.
  	 */
  	if (sbp->sb_magicnum != XFS_SB_MAGIC) {
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
308
309
  		if (loud)
  			xfs_warn(mp, "bad magic number");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
311
  		return XFS_ERROR(EWRONGFS);
  	}
621187099   Eric Sandeen   [XFS] remove shou...
312
  	if (!xfs_sb_good_version(sbp)) {
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
313
314
  		if (loud)
  			xfs_warn(mp, "bad version");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
316
317
318
319
  		return XFS_ERROR(EWRONGFS);
  	}
  
  	if (unlikely(
  	    sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
320
321
322
323
  		if (loud)
  			xfs_warn(mp,
  		"filesystem is marked as having an external log; "
  		"specify logdev on the mount command line.");
764d1f89a   Nathan Scott   [XFS] Implement t...
324
  		return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
327
328
  	}
  
  	if (unlikely(
  	    sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
329
330
331
332
  		if (loud)
  			xfs_warn(mp,
  		"filesystem is marked as having an internal log; "
  		"do not specify logdev on the mount command line.");
764d1f89a   Nathan Scott   [XFS] Implement t...
333
  		return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
336
337
338
339
340
341
342
343
344
345
  	}
  
  	/*
  	 * More sanity checking. These were stolen directly from
  	 * xfs_repair.
  	 */
  	if (unlikely(
  	    sbp->sb_agcount <= 0					||
  	    sbp->sb_sectsize < XFS_MIN_SECTORSIZE			||
  	    sbp->sb_sectsize > XFS_MAX_SECTORSIZE			||
  	    sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG			||
  	    sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG			||
2ac00af7a   Olaf Weber   xfs: add more che...
346
  	    sbp->sb_sectsize != (1 << sbp->sb_sectlog)			||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
348
349
350
  	    sbp->sb_blocksize < XFS_MIN_BLOCKSIZE			||
  	    sbp->sb_blocksize > XFS_MAX_BLOCKSIZE			||
  	    sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG			||
  	    sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG			||
2ac00af7a   Olaf Weber   xfs: add more che...
351
  	    sbp->sb_blocksize != (1 << sbp->sb_blocklog)		||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
353
  	    sbp->sb_inodesize < XFS_DINODE_MIN_SIZE			||
  	    sbp->sb_inodesize > XFS_DINODE_MAX_SIZE			||
9f989c945   Nathan Scott   [XFS] Additional ...
354
355
  	    sbp->sb_inodelog < XFS_DINODE_MIN_LOG			||
  	    sbp->sb_inodelog > XFS_DINODE_MAX_LOG			||
2ac00af7a   Olaf Weber   xfs: add more che...
356
  	    sbp->sb_inodesize != (1 << sbp->sb_inodelog)		||
9f989c945   Nathan Scott   [XFS] Additional ...
357
  	    (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog)	||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
359
  	    (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE)	||
  	    (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)	||
e50bd16fe   Nathan Scott   [XFS] Fix superbl...
360
  	    (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */))) {
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
361
362
  		if (loud)
  			xfs_warn(mp, "SB sanity check 1 failed");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
365
366
367
368
369
370
371
372
373
374
  		return XFS_ERROR(EFSCORRUPTED);
  	}
  
  	/*
  	 * Sanity check AG count, size fields against data size field
  	 */
  	if (unlikely(
  	    sbp->sb_dblocks == 0 ||
  	    sbp->sb_dblocks >
  	     (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks ||
  	    sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) *
  			      sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) {
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
375
376
  		if (loud)
  			xfs_warn(mp, "SB sanity check 2 failed");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
378
  		return XFS_ERROR(EFSCORRUPTED);
  	}
2edbddd5f   Lachlan McIlroy   [XFS] Don't asser...
379
380
381
382
  	/*
  	 * Until this is fixed only page-sized or smaller data blocks work.
  	 */
  	if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
383
384
385
386
387
388
  		if (loud) {
  			xfs_warn(mp,
  		"File system with blocksize %d bytes. "
  		"Only pagesize (%ld) or less will currently work.",
  				sbp->sb_blocksize, PAGE_SIZE);
  		}
2edbddd5f   Lachlan McIlroy   [XFS] Don't asser...
389
390
  		return XFS_ERROR(ENOSYS);
  	}
1a5902c5d   Christoph Hellwig   xfs: remove m_att...
391
392
393
394
395
396
397
398
399
400
  	/*
  	 * Currently only very few inode sizes are supported.
  	 */
  	switch (sbp->sb_inodesize) {
  	case 256:
  	case 512:
  	case 1024:
  	case 2048:
  		break;
  	default:
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
401
402
403
  		if (loud)
  			xfs_warn(mp, "inode size of %d bytes not supported",
  				sbp->sb_inodesize);
1a5902c5d   Christoph Hellwig   xfs: remove m_att...
404
405
  		return XFS_ERROR(ENOSYS);
  	}
4cc929ee3   Nathan Scott   [XFS] Don't grow ...
406
407
  	if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) ||
  	    xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
408
409
410
  		if (loud)
  			xfs_warn(mp,
  		"file system too large to be mounted on this system.");
657a4cffd   Eric Sandeen   xfs: replace E2BI...
411
  		return XFS_ERROR(EFBIG);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
413
414
  	}
  
  	if (unlikely(sbp->sb_inprogress)) {
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
415
416
  		if (loud)
  			xfs_warn(mp, "file system busy");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
418
419
420
  		return XFS_ERROR(EFSCORRUPTED);
  	}
  
  	/*
de20614b3   Nathan Scott   [XFS] Block mount...
421
422
  	 * Version 1 directory format has never worked on Linux.
  	 */
621187099   Eric Sandeen   [XFS] remove shou...
423
  	if (unlikely(!xfs_sb_version_hasdirv2(sbp))) {
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
424
425
426
  		if (loud)
  			xfs_warn(mp,
  				"file system using version 1 directory format");
de20614b3   Nathan Scott   [XFS] Block mount...
427
428
  		return XFS_ERROR(ENOSYS);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
430
  	return 0;
  }
1c1c6ebcf   Dave Chinner   xfs: Replace per-...
431
  int
c11e2c369   Nathan Scott   [XFS] Rework fid ...
432
  xfs_initialize_perag(
c11e2c369   Nathan Scott   [XFS] Rework fid ...
433
  	xfs_mount_t	*mp,
1c1c6ebcf   Dave Chinner   xfs: Replace per-...
434
435
  	xfs_agnumber_t	agcount,
  	xfs_agnumber_t	*maxagi)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
437
  {
  	xfs_agnumber_t	index, max_metadata;
8b26c5825   Dave Chinner   xfs: handle ENOME...
438
  	xfs_agnumber_t	first_initialised = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
440
441
442
  	xfs_perag_t	*pag;
  	xfs_agino_t	agino;
  	xfs_ino_t	ino;
  	xfs_sb_t	*sbp = &mp->m_sb;
8b26c5825   Dave Chinner   xfs: handle ENOME...
443
  	int		error = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444

1c1c6ebcf   Dave Chinner   xfs: Replace per-...
445
446
447
448
449
450
451
452
453
454
455
  	/*
  	 * Walk the current per-ag tree so we don't try to initialise AGs
  	 * that already exist (growfs case). Allocate and insert all the
  	 * AGs we don't find ready for initialisation.
  	 */
  	for (index = 0; index < agcount; index++) {
  		pag = xfs_perag_get(mp, index);
  		if (pag) {
  			xfs_perag_put(pag);
  			continue;
  		}
8b26c5825   Dave Chinner   xfs: handle ENOME...
456
457
  		if (!first_initialised)
  			first_initialised = index;
fb3b504ad   Christoph Hellwig   xfs: fix access t...
458

1c1c6ebcf   Dave Chinner   xfs: Replace per-...
459
460
  		pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL);
  		if (!pag)
8b26c5825   Dave Chinner   xfs: handle ENOME...
461
  			goto out_unwind;
fb3b504ad   Christoph Hellwig   xfs: fix access t...
462
463
  		pag->pag_agno = index;
  		pag->pag_mount = mp;
1a427ab0c   Dave Chinner   xfs: convert pag_...
464
  		spin_lock_init(&pag->pag_ici_lock);
69b491c21   Dave Chinner   xfs: serialise in...
465
  		mutex_init(&pag->pag_ici_reclaim_lock);
fb3b504ad   Christoph Hellwig   xfs: fix access t...
466
  		INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
74f75a0cb   Dave Chinner   xfs: convert buff...
467
468
  		spin_lock_init(&pag->pag_buf_lock);
  		pag->pag_buf_tree = RB_ROOT;
fb3b504ad   Christoph Hellwig   xfs: fix access t...
469

1c1c6ebcf   Dave Chinner   xfs: Replace per-...
470
  		if (radix_tree_preload(GFP_NOFS))
8b26c5825   Dave Chinner   xfs: handle ENOME...
471
  			goto out_unwind;
fb3b504ad   Christoph Hellwig   xfs: fix access t...
472

1c1c6ebcf   Dave Chinner   xfs: Replace per-...
473
474
475
476
  		spin_lock(&mp->m_perag_lock);
  		if (radix_tree_insert(&mp->m_perag_tree, index, pag)) {
  			BUG();
  			spin_unlock(&mp->m_perag_lock);
8b26c5825   Dave Chinner   xfs: handle ENOME...
477
478
479
  			radix_tree_preload_end();
  			error = -EEXIST;
  			goto out_unwind;
1c1c6ebcf   Dave Chinner   xfs: Replace per-...
480
481
482
483
  		}
  		spin_unlock(&mp->m_perag_lock);
  		radix_tree_preload_end();
  	}
fb3b504ad   Christoph Hellwig   xfs: fix access t...
484
485
486
  	/*
  	 * If we mount with the inode64 option, or no inode overflows
  	 * the legacy 32-bit address space clear the inode32 option.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
  	 */
fb3b504ad   Christoph Hellwig   xfs: fix access t...
488
489
490
491
  	agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
  	ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
  
  	if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
  		mp->m_flags |= XFS_MOUNT_32BITINODES;
fb3b504ad   Christoph Hellwig   xfs: fix access t...
493
  	else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
  		mp->m_flags &= ~XFS_MOUNT_32BITINODES;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
  	if (mp->m_flags & XFS_MOUNT_32BITINODES) {
fb3b504ad   Christoph Hellwig   xfs: fix access t...
497
498
499
  		/*
  		 * Calculate how much should be reserved for inodes to meet
  		 * the max inode percentage.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
502
503
504
505
506
  		 */
  		if (mp->m_maxicount) {
  			__uint64_t	icount;
  
  			icount = sbp->sb_dblocks * sbp->sb_imax_pct;
  			do_div(icount, 100);
  			icount += sbp->sb_agblocks - 1;
a749ee861   Eric Sandeen   [XFS] Fix calcula...
507
  			do_div(icount, sbp->sb_agblocks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
509
510
511
  			max_metadata = icount;
  		} else {
  			max_metadata = agcount;
  		}
fb3b504ad   Christoph Hellwig   xfs: fix access t...
512

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
514
  		for (index = 0; index < agcount; index++) {
  			ino = XFS_AGINO_TO_INO(mp, index, agino);
fb3b504ad   Christoph Hellwig   xfs: fix access t...
515
  			if (ino > XFS_MAXINUMBER_32) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
518
  				index++;
  				break;
  			}
44b56e0a1   Dave Chinner   xfs: convert rema...
519
  			pag = xfs_perag_get(mp, index);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
522
  			pag->pagi_inodeok = 1;
  			if (index < max_metadata)
  				pag->pagf_metadata = 1;
44b56e0a1   Dave Chinner   xfs: convert rema...
523
  			xfs_perag_put(pag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524
525
  		}
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
  		for (index = 0; index < agcount; index++) {
44b56e0a1   Dave Chinner   xfs: convert rema...
527
  			pag = xfs_perag_get(mp, index);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528
  			pag->pagi_inodeok = 1;
44b56e0a1   Dave Chinner   xfs: convert rema...
529
  			xfs_perag_put(pag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
531
  		}
  	}
fb3b504ad   Christoph Hellwig   xfs: fix access t...
532

1c1c6ebcf   Dave Chinner   xfs: Replace per-...
533
534
535
  	if (maxagi)
  		*maxagi = index;
  	return 0;
8b26c5825   Dave Chinner   xfs: handle ENOME...
536
537
538
539
540
541
542
543
  
  out_unwind:
  	kmem_free(pag);
  	for (; index > first_initialised; index--) {
  		pag = radix_tree_delete(&mp->m_perag_tree, index);
  		kmem_free(pag);
  	}
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
  }
2bdf7cd0b   Christoph Hellwig   [XFS] superblock ...
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
  void
  xfs_sb_from_disk(
  	xfs_sb_t	*to,
  	xfs_dsb_t	*from)
  {
  	to->sb_magicnum = be32_to_cpu(from->sb_magicnum);
  	to->sb_blocksize = be32_to_cpu(from->sb_blocksize);
  	to->sb_dblocks = be64_to_cpu(from->sb_dblocks);
  	to->sb_rblocks = be64_to_cpu(from->sb_rblocks);
  	to->sb_rextents = be64_to_cpu(from->sb_rextents);
  	memcpy(&to->sb_uuid, &from->sb_uuid, sizeof(to->sb_uuid));
  	to->sb_logstart = be64_to_cpu(from->sb_logstart);
  	to->sb_rootino = be64_to_cpu(from->sb_rootino);
  	to->sb_rbmino = be64_to_cpu(from->sb_rbmino);
  	to->sb_rsumino = be64_to_cpu(from->sb_rsumino);
  	to->sb_rextsize = be32_to_cpu(from->sb_rextsize);
  	to->sb_agblocks = be32_to_cpu(from->sb_agblocks);
  	to->sb_agcount = be32_to_cpu(from->sb_agcount);
  	to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks);
  	to->sb_logblocks = be32_to_cpu(from->sb_logblocks);
  	to->sb_versionnum = be16_to_cpu(from->sb_versionnum);
  	to->sb_sectsize = be16_to_cpu(from->sb_sectsize);
  	to->sb_inodesize = be16_to_cpu(from->sb_inodesize);
  	to->sb_inopblock = be16_to_cpu(from->sb_inopblock);
  	memcpy(&to->sb_fname, &from->sb_fname, sizeof(to->sb_fname));
  	to->sb_blocklog = from->sb_blocklog;
  	to->sb_sectlog = from->sb_sectlog;
  	to->sb_inodelog = from->sb_inodelog;
  	to->sb_inopblog = from->sb_inopblog;
  	to->sb_agblklog = from->sb_agblklog;
  	to->sb_rextslog = from->sb_rextslog;
  	to->sb_inprogress = from->sb_inprogress;
  	to->sb_imax_pct = from->sb_imax_pct;
  	to->sb_icount = be64_to_cpu(from->sb_icount);
  	to->sb_ifree = be64_to_cpu(from->sb_ifree);
  	to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks);
  	to->sb_frextents = be64_to_cpu(from->sb_frextents);
  	to->sb_uquotino = be64_to_cpu(from->sb_uquotino);
  	to->sb_gquotino = be64_to_cpu(from->sb_gquotino);
  	to->sb_qflags = be16_to_cpu(from->sb_qflags);
  	to->sb_flags = from->sb_flags;
  	to->sb_shared_vn = from->sb_shared_vn;
  	to->sb_inoalignmt = be32_to_cpu(from->sb_inoalignmt);
  	to->sb_unit = be32_to_cpu(from->sb_unit);
  	to->sb_width = be32_to_cpu(from->sb_width);
  	to->sb_dirblklog = from->sb_dirblklog;
  	to->sb_logsectlog = from->sb_logsectlog;
  	to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize);
  	to->sb_logsunit = be32_to_cpu(from->sb_logsunit);
  	to->sb_features2 = be32_to_cpu(from->sb_features2);
ee1c09082   David Chinner   [XFS] Fix superbl...
595
  	to->sb_bad_features2 = be32_to_cpu(from->sb_bad_features2);
2bdf7cd0b   Christoph Hellwig   [XFS] superblock ...
596
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
  /*
2bdf7cd0b   Christoph Hellwig   [XFS] superblock ...
598
   * Copy in core superblock to ondisk one.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
   *
2bdf7cd0b   Christoph Hellwig   [XFS] superblock ...
600
   * The fields argument is mask of superblock fields to copy.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
602
   */
  void
2bdf7cd0b   Christoph Hellwig   [XFS] superblock ...
603
604
605
  xfs_sb_to_disk(
  	xfs_dsb_t	*to,
  	xfs_sb_t	*from,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
607
  	__int64_t	fields)
  {
2bdf7cd0b   Christoph Hellwig   [XFS] superblock ...
608
609
  	xfs_caddr_t	to_ptr = (xfs_caddr_t)to;
  	xfs_caddr_t	from_ptr = (xfs_caddr_t)from;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
611
612
  	xfs_sb_field_t	f;
  	int		first;
  	int		size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
  	ASSERT(fields);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
615
  	if (!fields)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
617
618
619
620
621
622
623
  	while (fields) {
  		f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
  		first = xfs_sb_info[f].offset;
  		size = xfs_sb_info[f + 1].offset - first;
  
  		ASSERT(xfs_sb_info[f].type == 0 || xfs_sb_info[f].type == 1);
  
  		if (size == 1 || xfs_sb_info[f].type == 1) {
2bdf7cd0b   Christoph Hellwig   [XFS] superblock ...
624
  			memcpy(to_ptr + first, from_ptr + first, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
626
627
  		} else {
  			switch (size) {
  			case 2:
2bdf7cd0b   Christoph Hellwig   [XFS] superblock ...
628
629
  				*(__be16 *)(to_ptr + first) =
  					cpu_to_be16(*(__u16 *)(from_ptr + first));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
631
  				break;
  			case 4:
2bdf7cd0b   Christoph Hellwig   [XFS] superblock ...
632
633
  				*(__be32 *)(to_ptr + first) =
  					cpu_to_be32(*(__u32 *)(from_ptr + first));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
635
  				break;
  			case 8:
2bdf7cd0b   Christoph Hellwig   [XFS] superblock ...
636
637
  				*(__be64 *)(to_ptr + first) =
  					cpu_to_be64(*(__u64 *)(from_ptr + first));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
  				break;
  			default:
  				ASSERT(0);
  			}
  		}
  
  		fields &= ~(1LL << f);
  	}
  }
  
  /*
   * xfs_readsb
   *
   * Does the initial read of the superblock.
   */
  int
764d1f89a   Nathan Scott   [XFS] Implement t...
654
  xfs_readsb(xfs_mount_t *mp, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
656
  {
  	unsigned int	sector_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
  	xfs_buf_t	*bp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
  	int		error;
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
659
  	int		loud = !(flags & XFS_MFSI_QUIET);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
660
661
662
663
664
665
666
667
668
669
  
  	ASSERT(mp->m_sb_bp == NULL);
  	ASSERT(mp->m_ddev_targp != NULL);
  
  	/*
  	 * Allocate a (locked) buffer to hold the superblock.
  	 * This will be kept around at all times to optimize
  	 * access to the superblock.
  	 */
  	sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
26af65523   Dave Chinner   xfs: kill XBF_FS_...
670
671
672
673
674
  
  reread:
  	bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp,
  					XFS_SB_DADDR, sector_size, 0);
  	if (!bp) {
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
675
676
  		if (loud)
  			xfs_warn(mp, "SB buffer read failed");
26af65523   Dave Chinner   xfs: kill XBF_FS_...
677
  		return EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
680
681
682
683
  
  	/*
  	 * Initialize the mount structure from the superblock.
  	 * But first do some basic consistency checking.
  	 */
2bdf7cd0b   Christoph Hellwig   [XFS] superblock ...
684
  	xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));
764d1f89a   Nathan Scott   [XFS] Implement t...
685
  	error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
  	if (error) {
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
687
688
  		if (loud)
  			xfs_warn(mp, "SB validate failed");
26af65523   Dave Chinner   xfs: kill XBF_FS_...
689
  		goto release_buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
690
691
692
693
694
695
  	}
  
  	/*
  	 * We must be able to do sector-sized and sector-aligned IO.
  	 */
  	if (sector_size > mp->m_sb.sb_sectsize) {
af34e09da   Dave Chinner   xfs: kill xfs_fs_...
696
697
698
  		if (loud)
  			xfs_warn(mp, "device supports %u byte sectors (not %u)",
  				sector_size, mp->m_sb.sb_sectsize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
  		error = ENOSYS;
26af65523   Dave Chinner   xfs: kill XBF_FS_...
700
  		goto release_buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
702
703
704
705
706
707
  	}
  
  	/*
  	 * If device sector size is smaller than the superblock size,
  	 * re-read the superblock so the buffer is correctly sized.
  	 */
  	if (sector_size < mp->m_sb.sb_sectsize) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708
709
  		xfs_buf_relse(bp);
  		sector_size = mp->m_sb.sb_sectsize;
26af65523   Dave Chinner   xfs: kill XBF_FS_...
710
  		goto reread;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711
  	}
5478eead8   Lachlan McIlroy   [XFS] Re-initiali...
712
713
  	/* Initialize per-cpu counters */
  	xfs_icsb_reinit_counters(mp);
8d280b98c   David Chinner   [XFS] On machines...
714

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
  	mp->m_sb_bp = bp;
26af65523   Dave Chinner   xfs: kill XBF_FS_...
716
  	xfs_buf_unlock(bp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
  	return 0;
26af65523   Dave Chinner   xfs: kill XBF_FS_...
718
719
  release_buf:
  	xfs_buf_relse(bp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
721
722
723
724
725
726
727
728
729
730
  	return error;
  }
  
  
  /*
   * xfs_mount_common
   *
   * Mount initialization code establishing various mount
   * fields from the superblock associated with the given
   * mount structure
   */
ba0f32d46   Christoph Hellwig   [XFS] mark variou...
731
  STATIC void
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
733
  xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
  	mp->m_agfrotor = mp->m_agirotor = 0;
007c61c68   Eric Sandeen   [XFS] Remove spin.h
735
  	spin_lock_init(&mp->m_agirotor_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
737
738
739
740
741
  	mp->m_maxagi = mp->m_sb.sb_agcount;
  	mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG;
  	mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
  	mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
  	mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1;
  	mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
744
  	mp->m_blockmask = sbp->sb_blocksize - 1;
  	mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
  	mp->m_blockwmask = mp->m_blockwsize - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745

60197e8df   Christoph Hellwig   [XFS] Cleanup max...
746
747
748
749
750
751
752
753
754
755
756
757
758
759
  	mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1);
  	mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0);
  	mp->m_alloc_mnr[0] = mp->m_alloc_mxr[0] / 2;
  	mp->m_alloc_mnr[1] = mp->m_alloc_mxr[1] / 2;
  
  	mp->m_inobt_mxr[0] = xfs_inobt_maxrecs(mp, sbp->sb_blocksize, 1);
  	mp->m_inobt_mxr[1] = xfs_inobt_maxrecs(mp, sbp->sb_blocksize, 0);
  	mp->m_inobt_mnr[0] = mp->m_inobt_mxr[0] / 2;
  	mp->m_inobt_mnr[1] = mp->m_inobt_mxr[1] / 2;
  
  	mp->m_bmap_dmxr[0] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, 1);
  	mp->m_bmap_dmxr[1] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, 0);
  	mp->m_bmap_dmnr[0] = mp->m_bmap_dmxr[0] / 2;
  	mp->m_bmap_dmnr[1] = mp->m_bmap_dmxr[1] / 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
761
762
763
764
765
  
  	mp->m_bsize = XFS_FSB_TO_BB(mp, 1);
  	mp->m_ialloc_inos = (int)MAX((__uint16_t)XFS_INODES_PER_CHUNK,
  					sbp->sb_inopblock);
  	mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog;
  }
92821e2ba   David Chinner   [XFS] Lazy Superb...
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
  
  /*
   * xfs_initialize_perag_data
   *
   * Read in each per-ag structure so we can count up the number of
   * allocated inodes, free inodes and used filesystem blocks as this
   * information is no longer persistent in the superblock. Once we have
   * this information, write it into the in-core superblock structure.
   */
  STATIC int
  xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount)
  {
  	xfs_agnumber_t	index;
  	xfs_perag_t	*pag;
  	xfs_sb_t	*sbp = &mp->m_sb;
  	uint64_t	ifree = 0;
  	uint64_t	ialloc = 0;
  	uint64_t	bfree = 0;
  	uint64_t	bfreelst = 0;
  	uint64_t	btree = 0;
  	int		error;
92821e2ba   David Chinner   [XFS] Lazy Superb...
787
788
789
790
  
  	for (index = 0; index < agcount; index++) {
  		/*
  		 * read the agf, then the agi. This gets us
9da096fd1   Malcolm Parsons   xfs: fix various ...
791
  		 * all the information we need and populates the
92821e2ba   David Chinner   [XFS] Lazy Superb...
792
793
794
795
796
797
798
799
800
  		 * per-ag structures for us.
  		 */
  		error = xfs_alloc_pagf_init(mp, NULL, index, 0);
  		if (error)
  			return error;
  
  		error = xfs_ialloc_pagi_init(mp, NULL, index);
  		if (error)
  			return error;
44b56e0a1   Dave Chinner   xfs: convert rema...
801
  		pag = xfs_perag_get(mp, index);
92821e2ba   David Chinner   [XFS] Lazy Superb...
802
803
804
805
806
  		ifree += pag->pagi_freecount;
  		ialloc += pag->pagi_count;
  		bfree += pag->pagf_freeblks;
  		bfreelst += pag->pagf_flcount;
  		btree += pag->pagf_btreeblks;
44b56e0a1   Dave Chinner   xfs: convert rema...
807
  		xfs_perag_put(pag);
92821e2ba   David Chinner   [XFS] Lazy Superb...
808
809
810
811
  	}
  	/*
  	 * Overwrite incore superblock counters with just-read data
  	 */
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
812
  	spin_lock(&mp->m_sb_lock);
92821e2ba   David Chinner   [XFS] Lazy Superb...
813
814
815
  	sbp->sb_ifree = ifree;
  	sbp->sb_icount = ialloc;
  	sbp->sb_fdblocks = bfree + bfreelst + btree;
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
816
  	spin_unlock(&mp->m_sb_lock);
92821e2ba   David Chinner   [XFS] Lazy Superb...
817
818
819
820
821
822
  
  	/* Fixup the per-cpu counters as well. */
  	xfs_icsb_reinit_counters(mp);
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
  /*
0771fb451   Eric Sandeen   [XFS] Refactor xf...
824
   * Update alignment values based on mount options and sb values
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
825
   */
0771fb451   Eric Sandeen   [XFS] Refactor xf...
826
  STATIC int
7884bc861   Christoph Hellwig   xfs: fix bad_feat...
827
  xfs_update_alignment(xfs_mount_t *mp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829
  	xfs_sb_t	*sbp = &(mp->m_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830

4249023a5   Christoph Hellwig   [XFS] cleanup xfs...
831
  	if (mp->m_dalign) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832
833
834
835
836
837
838
  		/*
  		 * If stripe unit and stripe width are not multiples
  		 * of the fs blocksize turn off alignment.
  		 */
  		if ((BBTOB(mp->m_dalign) & mp->m_blockmask) ||
  		    (BBTOB(mp->m_swidth) & mp->m_blockmask)) {
  			if (mp->m_flags & XFS_MOUNT_RETERR) {
0b932cccb   Dave Chinner   xfs: Convert rema...
839
  				xfs_warn(mp, "alignment check 1 failed");
0771fb451   Eric Sandeen   [XFS] Refactor xf...
840
  				return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841
842
843
844
845
846
847
848
849
  			}
  			mp->m_dalign = mp->m_swidth = 0;
  		} else {
  			/*
  			 * Convert the stripe unit and width to FSBs.
  			 */
  			mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign);
  			if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) {
  				if (mp->m_flags & XFS_MOUNT_RETERR) {
0771fb451   Eric Sandeen   [XFS] Refactor xf...
850
  					return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
851
  				}
534877869   Dave Chinner   xfs: convert xfs_...
852
853
854
  				xfs_warn(mp,
  		"stripe alignment turned off: sunit(%d)/swidth(%d) "
  		"incompatible with agsize(%d)",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
856
857
858
859
860
861
862
863
  					mp->m_dalign, mp->m_swidth,
  					sbp->sb_agblocks);
  
  				mp->m_dalign = 0;
  				mp->m_swidth = 0;
  			} else if (mp->m_dalign) {
  				mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth);
  			} else {
  				if (mp->m_flags & XFS_MOUNT_RETERR) {
534877869   Dave Chinner   xfs: convert xfs_...
864
865
866
  					xfs_warn(mp,
  		"stripe alignment turned off: sunit(%d) less than bsize(%d)",
  						mp->m_dalign,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867
  						mp->m_blockmask +1);
0771fb451   Eric Sandeen   [XFS] Refactor xf...
868
  					return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869
870
871
872
873
874
875
876
877
  				}
  				mp->m_swidth = 0;
  			}
  		}
  
  		/*
  		 * Update superblock with new values
  		 * and log changes
  		 */
621187099   Eric Sandeen   [XFS] remove shou...
878
  		if (xfs_sb_version_hasdalign(sbp)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
880
  			if (sbp->sb_unit != mp->m_dalign) {
  				sbp->sb_unit = mp->m_dalign;
7884bc861   Christoph Hellwig   xfs: fix bad_feat...
881
  				mp->m_update_flags |= XFS_SB_UNIT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
883
884
  			}
  			if (sbp->sb_width != mp->m_swidth) {
  				sbp->sb_width = mp->m_swidth;
7884bc861   Christoph Hellwig   xfs: fix bad_feat...
885
  				mp->m_update_flags |= XFS_SB_WIDTH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886
887
888
  			}
  		}
  	} else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN &&
621187099   Eric Sandeen   [XFS] remove shou...
889
  		    xfs_sb_version_hasdalign(&mp->m_sb)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
890
891
892
  			mp->m_dalign = sbp->sb_unit;
  			mp->m_swidth = sbp->sb_width;
  	}
0771fb451   Eric Sandeen   [XFS] Refactor xf...
893
894
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
895

0771fb451   Eric Sandeen   [XFS] Refactor xf...
896
897
898
899
900
901
902
903
  /*
   * Set the maximum inode count for this filesystem
   */
  STATIC void
  xfs_set_maxicount(xfs_mount_t *mp)
  {
  	xfs_sb_t	*sbp = &(mp->m_sb);
  	__uint64_t	icount;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
904

0771fb451   Eric Sandeen   [XFS] Refactor xf...
905
906
907
908
  	if (sbp->sb_imax_pct) {
  		/*
  		 * Make sure the maximum inode count is a multiple
  		 * of the units we allocate inodes in.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
909
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
910
911
912
913
914
  		icount = sbp->sb_dblocks * sbp->sb_imax_pct;
  		do_div(icount, 100);
  		do_div(icount, mp->m_ialloc_blks);
  		mp->m_maxicount = (icount * mp->m_ialloc_blks)  <<
  				   sbp->sb_inopblog;
0771fb451   Eric Sandeen   [XFS] Refactor xf...
915
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916
  		mp->m_maxicount = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
  	}
0771fb451   Eric Sandeen   [XFS] Refactor xf...
918
919
920
921
922
923
924
925
926
927
928
929
930
  }
  
  /*
   * Set the default minimum read and write sizes unless
   * already specified in a mount option.
   * We use smaller I/O sizes when the file system
   * is being used for NFS service (wsync mount option).
   */
  STATIC void
  xfs_set_rw_sizes(xfs_mount_t *mp)
  {
  	xfs_sb_t	*sbp = &(mp->m_sb);
  	int		readio_log, writeio_log;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932
933
934
935
936
937
938
939
940
941
942
943
  	if (!(mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)) {
  		if (mp->m_flags & XFS_MOUNT_WSYNC) {
  			readio_log = XFS_WSYNC_READIO_LOG;
  			writeio_log = XFS_WSYNC_WRITEIO_LOG;
  		} else {
  			readio_log = XFS_READIO_LOG_LARGE;
  			writeio_log = XFS_WRITEIO_LOG_LARGE;
  		}
  	} else {
  		readio_log = mp->m_readio_log;
  		writeio_log = mp->m_writeio_log;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
944
945
946
947
948
949
950
951
952
953
954
955
  	if (sbp->sb_blocklog > readio_log) {
  		mp->m_readio_log = sbp->sb_blocklog;
  	} else {
  		mp->m_readio_log = readio_log;
  	}
  	mp->m_readio_blocks = 1 << (mp->m_readio_log - sbp->sb_blocklog);
  	if (sbp->sb_blocklog > writeio_log) {
  		mp->m_writeio_log = sbp->sb_blocklog;
  	} else {
  		mp->m_writeio_log = writeio_log;
  	}
  	mp->m_writeio_blocks = 1 << (mp->m_writeio_log - sbp->sb_blocklog);
0771fb451   Eric Sandeen   [XFS] Refactor xf...
956
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957

0771fb451   Eric Sandeen   [XFS] Refactor xf...
958
  /*
055388a31   Dave Chinner   xfs: dynamic spec...
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
   * precalculate the low space thresholds for dynamic speculative preallocation.
   */
  void
  xfs_set_low_space_thresholds(
  	struct xfs_mount	*mp)
  {
  	int i;
  
  	for (i = 0; i < XFS_LOWSP_MAX; i++) {
  		__uint64_t space = mp->m_sb.sb_dblocks;
  
  		do_div(space, 100);
  		mp->m_low_space[i] = space * (i + 1);
  	}
  }
  
  
  /*
0771fb451   Eric Sandeen   [XFS] Refactor xf...
977
978
979
980
981
   * Set whether we're using inode alignment.
   */
  STATIC void
  xfs_set_inoalignment(xfs_mount_t *mp)
  {
621187099   Eric Sandeen   [XFS] remove shou...
982
  	if (xfs_sb_version_hasalign(&mp->m_sb) &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
984
985
986
987
988
989
990
991
992
993
994
995
996
  	    mp->m_sb.sb_inoalignmt >=
  	    XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size))
  		mp->m_inoalign_mask = mp->m_sb.sb_inoalignmt - 1;
  	else
  		mp->m_inoalign_mask = 0;
  	/*
  	 * If we are using stripe alignment, check whether
  	 * the stripe unit is a multiple of the inode alignment
  	 */
  	if (mp->m_dalign && mp->m_inoalign_mask &&
  	    !(mp->m_dalign & mp->m_inoalign_mask))
  		mp->m_sinoalign = mp->m_dalign;
  	else
  		mp->m_sinoalign = 0;
0771fb451   Eric Sandeen   [XFS] Refactor xf...
997
998
999
1000
1001
1002
  }
  
  /*
   * Check that the data (and log if separate) are an ok size.
   */
  STATIC int
4249023a5   Christoph Hellwig   [XFS] cleanup xfs...
1003
  xfs_check_sizes(xfs_mount_t *mp)
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1004
1005
1006
  {
  	xfs_buf_t	*bp;
  	xfs_daddr_t	d;
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1007

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1008
1009
  	d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
  	if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1010
  		xfs_warn(mp, "filesystem size mismatch detected");
657a4cffd   Eric Sandeen   xfs: replace E2BI...
1011
  		return XFS_ERROR(EFBIG);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1012
  	}
1922c949c   Dave Chinner   xfs: use unhashed...
1013
1014
1015
1016
  	bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp,
  					d - XFS_FSS_TO_BB(mp, 1),
  					BBTOB(XFS_FSS_TO_BB(mp, 1)), 0);
  	if (!bp) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1017
  		xfs_warn(mp, "last sector read failed");
1922c949c   Dave Chinner   xfs: use unhashed...
1018
  		return EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
  	}
1922c949c   Dave Chinner   xfs: use unhashed...
1020
  	xfs_buf_relse(bp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1021

4249023a5   Christoph Hellwig   [XFS] cleanup xfs...
1022
  	if (mp->m_logdev_targp != mp->m_ddev_targp) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
1024
  		d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
  		if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1025
  			xfs_warn(mp, "log size mismatch detected");
657a4cffd   Eric Sandeen   xfs: replace E2BI...
1026
  			return XFS_ERROR(EFBIG);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027
  		}
1922c949c   Dave Chinner   xfs: use unhashed...
1028
1029
1030
1031
  		bp = xfs_buf_read_uncached(mp, mp->m_logdev_targp,
  					d - XFS_FSB_TO_BB(mp, 1),
  					XFS_FSB_TO_B(mp, 1), 0);
  		if (!bp) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1032
  			xfs_warn(mp, "log device read failed");
1922c949c   Dave Chinner   xfs: use unhashed...
1033
  			return EIO;
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1034
  		}
1922c949c   Dave Chinner   xfs: use unhashed...
1035
  		xfs_buf_relse(bp);
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1036
1037
1038
1039
1040
  	}
  	return 0;
  }
  
  /*
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
   * Clear the quotaflags in memory and in the superblock.
   */
  int
  xfs_mount_reset_sbqflags(
  	struct xfs_mount	*mp)
  {
  	int			error;
  	struct xfs_trans	*tp;
  
  	mp->m_qflags = 0;
  
  	/*
  	 * It is OK to look at sb_qflags here in mount path,
  	 * without m_sb_lock.
  	 */
  	if (mp->m_sb.sb_qflags == 0)
  		return 0;
  	spin_lock(&mp->m_sb_lock);
  	mp->m_sb.sb_qflags = 0;
  	spin_unlock(&mp->m_sb_lock);
  
  	/*
  	 * If the fs is readonly, let the incore superblock run
  	 * with quotas off but don't flush the update out to disk
  	 */
  	if (mp->m_flags & XFS_MOUNT_RDONLY)
  		return 0;
  
  #ifdef QUOTADEBUG
534877869   Dave Chinner   xfs: convert xfs_...
1070
  	xfs_notice(mp, "Writing superblock quota changes");
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1071
1072
1073
1074
1075
1076
1077
  #endif
  
  	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);
  	error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
  				      XFS_DEFAULT_LOG_COUNT);
  	if (error) {
  		xfs_trans_cancel(tp, 0);
534877869   Dave Chinner   xfs: convert xfs_...
1078
  		xfs_alert(mp, "%s: Superblock update failed!", __func__);
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1079
1080
1081
1082
1083
1084
  		return error;
  	}
  
  	xfs_mod_sb(tp, XFS_SB_QFLAGS);
  	return xfs_trans_commit(tp, 0);
  }
d5db0f97f   Eric Sandeen   xfs: more reserve...
1085
1086
1087
1088
1089
1090
  __uint64_t
  xfs_default_resblks(xfs_mount_t *mp)
  {
  	__uint64_t resblks;
  
  	/*
8babd8a2e   Dave Chinner   xfs: Increase the...
1091
1092
1093
1094
1095
  	 * We default to 5% or 8192 fsbs of space reserved, whichever is
  	 * smaller.  This is intended to cover concurrent allocation
  	 * transactions when we initially hit enospc. These each require a 4
  	 * block reservation. Hence by default we cover roughly 2000 concurrent
  	 * allocation reservations.
d5db0f97f   Eric Sandeen   xfs: more reserve...
1096
1097
1098
  	 */
  	resblks = mp->m_sb.sb_dblocks;
  	do_div(resblks, 20);
8babd8a2e   Dave Chinner   xfs: Increase the...
1099
  	resblks = min_t(__uint64_t, resblks, 8192);
d5db0f97f   Eric Sandeen   xfs: more reserve...
1100
1101
  	return resblks;
  }
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1102
  /*
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
   * This function does the following on an initial mount of a file system:
   *	- reads the superblock from disk and init the mount struct
   *	- if we're a 32-bit kernel, do a size check on the superblock
   *		so we don't mount terabyte filesystems
   *	- init mount struct realtime fields
   *	- allocate inode hash table for fs
   *	- init directory manager
   *	- perform recovery and init the log manager
   */
  int
  xfs_mountfs(
4249023a5   Christoph Hellwig   [XFS] cleanup xfs...
1114
  	xfs_mount_t	*mp)
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1115
1116
1117
  {
  	xfs_sb_t	*sbp = &(mp->m_sb);
  	xfs_inode_t	*rip;
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1118
  	__uint64_t	resblks;
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1119
1120
  	uint		quotamount = 0;
  	uint		quotaflags = 0;
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1121
  	int		error = 0;
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1122
1123
1124
  	xfs_mount_common(mp, sbp);
  
  	/*
e6957ea48   Eric Sandeen   [XFS] Ensure "bot...
1125
1126
1127
1128
1129
  	 * Check for a mismatched features2 values.  Older kernels
  	 * read & wrote into the wrong sb offset for sb_features2
  	 * on some platforms due to xfs_sb_t not being 64bit size aligned
  	 * when sb_features2 was added, which made older superblock
  	 * reading/writing routines swap it as a 64-bit value.
ee1c09082   David Chinner   [XFS] Fix superbl...
1130
  	 *
e6957ea48   Eric Sandeen   [XFS] Ensure "bot...
1131
1132
1133
1134
1135
1136
1137
1138
  	 * For backwards compatibility, we make both slots equal.
  	 *
  	 * If we detect a mismatched field, we OR the set bits into the
  	 * existing features2 field in case it has already been modified; we
  	 * don't want to lose any features.  We then update the bad location
  	 * with the ORed value so that older kernels will see any features2
  	 * flags, and mark the two fields as needing updates once the
  	 * transaction subsystem is online.
ee1c09082   David Chinner   [XFS] Fix superbl...
1139
  	 */
e6957ea48   Eric Sandeen   [XFS] Ensure "bot...
1140
  	if (xfs_sb_has_mismatched_features2(sbp)) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1141
  		xfs_warn(mp, "correcting sb_features alignment problem");
ee1c09082   David Chinner   [XFS] Fix superbl...
1142
  		sbp->sb_features2 |= sbp->sb_bad_features2;
e6957ea48   Eric Sandeen   [XFS] Ensure "bot...
1143
  		sbp->sb_bad_features2 = sbp->sb_features2;
7884bc861   Christoph Hellwig   xfs: fix bad_feat...
1144
  		mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2;
e6957ea48   Eric Sandeen   [XFS] Ensure "bot...
1145
1146
1147
1148
1149
  
  		/*
  		 * Re-check for ATTR2 in case it was found in bad_features2
  		 * slot.
  		 */
7c12f2965   Tim Shimmin   [XFS] Fix up noat...
1150
1151
  		if (xfs_sb_version_hasattr2(&mp->m_sb) &&
  		   !(mp->m_flags & XFS_MOUNT_NOATTR2))
e6957ea48   Eric Sandeen   [XFS] Ensure "bot...
1152
  			mp->m_flags |= XFS_MOUNT_ATTR2;
7c12f2965   Tim Shimmin   [XFS] Fix up noat...
1153
1154
1155
1156
1157
  	}
  
  	if (xfs_sb_version_hasattr2(&mp->m_sb) &&
  	   (mp->m_flags & XFS_MOUNT_NOATTR2)) {
  		xfs_sb_version_removeattr2(&mp->m_sb);
7884bc861   Christoph Hellwig   xfs: fix bad_feat...
1158
  		mp->m_update_flags |= XFS_SB_FEATURES2;
e6957ea48   Eric Sandeen   [XFS] Ensure "bot...
1159

7c12f2965   Tim Shimmin   [XFS] Fix up noat...
1160
1161
  		/* update sb_versionnum for the clearing of the morebits */
  		if (!sbp->sb_features2)
7884bc861   Christoph Hellwig   xfs: fix bad_feat...
1162
  			mp->m_update_flags |= XFS_SB_VERSIONNUM;
ee1c09082   David Chinner   [XFS] Fix superbl...
1163
1164
1165
  	}
  
  	/*
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1166
1167
1168
1169
1170
  	 * Check if sb_agblocks is aligned at stripe boundary
  	 * If sb_agblocks is NOT aligned turn off m_dalign since
  	 * allocator alignment is within an ag, therefore ag has
  	 * to be aligned at stripe boundary.
  	 */
7884bc861   Christoph Hellwig   xfs: fix bad_feat...
1171
  	error = xfs_update_alignment(mp);
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1172
  	if (error)
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1173
  		goto out;
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1174
1175
1176
1177
1178
1179
1180
1181
1182
  
  	xfs_alloc_compute_maxlevels(mp);
  	xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK);
  	xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
  	xfs_ialloc_compute_maxlevels(mp);
  
  	xfs_set_maxicount(mp);
  
  	mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog);
27174203f   Christoph Hellwig   xfs: cleanup uuid...
1183
1184
1185
  	error = xfs_uuid_mount(mp);
  	if (error)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186
1187
  
  	/*
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1188
1189
1190
  	 * Set the minimum read and write sizes
  	 */
  	xfs_set_rw_sizes(mp);
055388a31   Dave Chinner   xfs: dynamic spec...
1191
1192
  	/* set the low space thresholds for dynamic preallocation */
  	xfs_set_low_space_thresholds(mp);
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
  	/*
  	 * Set the inode cluster size.
  	 * This may still be overridden by the file system
  	 * block size if it is larger than the chosen cluster size.
  	 */
  	mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
  
  	/*
  	 * Set inode alignment fields
  	 */
  	xfs_set_inoalignment(mp);
  
  	/*
  	 * Check that the data (and log if separate) are an ok size.
  	 */
4249023a5   Christoph Hellwig   [XFS] cleanup xfs...
1208
  	error = xfs_check_sizes(mp);
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1209
  	if (error)
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1210
  		goto out_remove_uuid;
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1211
1212
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1213
1214
  	 * Initialize realtime fields in the mount structure
  	 */
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1215
1216
  	error = xfs_rtmount_init(mp);
  	if (error) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1217
  		xfs_warn(mp, "RT mount failed");
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1218
  		goto out_remove_uuid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1219
1220
1221
  	}
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1222
1223
1224
1225
  	 *  Copies the low order bits of the timestamp and the randomly
  	 *  set "sequence" number out of a UUID.
  	 */
  	uuid_getnodeuniq(&sbp->sb_uuid, mp->m_fixedfsid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226
  	mp->m_dmevmask = 0;	/* not persistent; set after each mount */
f6c2d1fa6   Nathan Scott   [XFS] Remove vers...
1227
  	xfs_dir_mount(mp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
  
  	/*
  	 * Initialize the attribute manager's entries.
  	 */
  	mp->m_attr_magicpct = (mp->m_sb.sb_blocksize * 37) / 100;
  
  	/*
  	 * Initialize the precomputed transaction reservations values.
  	 */
  	xfs_trans_init(mp);
  
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1240
1241
  	 * Allocate and initialize the per-ag data.
  	 */
1c1c6ebcf   Dave Chinner   xfs: Replace per-...
1242
  	spin_lock_init(&mp->m_perag_lock);
9b98b6f3e   Dave Chinner   xfs: fix might_sl...
1243
  	INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
1c1c6ebcf   Dave Chinner   xfs: Replace per-...
1244
1245
  	error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
  	if (error) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1246
  		xfs_warn(mp, "Failed per-ag init: %d", error);
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1247
  		goto out_remove_uuid;
1c1c6ebcf   Dave Chinner   xfs: Replace per-...
1248
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1249

f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1250
  	if (!sbp->sb_logblocks) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1251
  		xfs_warn(mp, "no log defined");
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1252
1253
1254
1255
  		XFS_ERROR_REPORT("xfs_mountfs", XFS_ERRLEVEL_LOW, mp);
  		error = XFS_ERROR(EFSCORRUPTED);
  		goto out_free_perag;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1256
1257
1258
  	/*
  	 * log's mount-time initialization. Perform 1st part recovery if needed
  	 */
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1259
1260
1261
1262
  	error = xfs_log_mount(mp, mp->m_logdev_targp,
  			      XFS_FSB_TO_DADDR(mp, sbp->sb_logstart),
  			      XFS_FSB_TO_BB(mp, sbp->sb_logblocks));
  	if (error) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1263
  		xfs_warn(mp, "log mount failed");
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1264
  		goto out_free_perag;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1265
1266
1267
  	}
  
  	/*
92821e2ba   David Chinner   [XFS] Lazy Superb...
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
  	 * Now the log is mounted, we know if it was an unclean shutdown or
  	 * not. If it was, with the first phase of recovery has completed, we
  	 * have consistent AG blocks on disk. We have not recovered EFIs yet,
  	 * but they are recovered transactionally in the second recovery phase
  	 * later.
  	 *
  	 * Hence we can safely re-initialise incore superblock counters from
  	 * the per-ag data. These may not be correct if the filesystem was not
  	 * cleanly unmounted, so we need to wait for recovery to finish before
  	 * doing this.
  	 *
  	 * If the filesystem was cleanly unmounted, then we can trust the
  	 * values in the superblock to be correct and we don't need to do
  	 * anything here.
  	 *
  	 * If we are currently making the filesystem, the initialisation will
  	 * fail as the perag data is in an undefined state.
  	 */
92821e2ba   David Chinner   [XFS] Lazy Superb...
1286
1287
1288
1289
  	if (xfs_sb_version_haslazysbcount(&mp->m_sb) &&
  	    !XFS_LAST_UNMOUNT_WAS_CLEAN(mp) &&
  	     !mp->m_sb.sb_inprogress) {
  		error = xfs_initialize_perag_data(mp, sbp->sb_agcount);
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1290
1291
  		if (error)
  			goto out_free_perag;
92821e2ba   David Chinner   [XFS] Lazy Superb...
1292
  	}
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1293

92821e2ba   David Chinner   [XFS] Lazy Superb...
1294
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1295
1296
1297
  	 * Get and sanity-check the root inode.
  	 * Save the pointer to it in the mount structure.
  	 */
7b6259e7a   Dave Chinner   xfs: remove block...
1298
  	error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1299
  	if (error) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1300
  		xfs_warn(mp, "failed to read root inode");
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1301
  		goto out_log_dealloc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1302
1303
1304
  	}
  
  	ASSERT(rip != NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1305
1306
  
  	if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1307
  		xfs_warn(mp, "corrupted root inode %llu: not a directory",
b65745205   Nathan Scott   [XFS] Portability...
1308
  			(unsigned long long)rip->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1309
1310
1311
1312
  		xfs_iunlock(rip, XFS_ILOCK_EXCL);
  		XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW,
  				 mp);
  		error = XFS_ERROR(EFSCORRUPTED);
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1313
  		goto out_rele_rip;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1314
1315
1316
1317
1318
1319
1320
1321
  	}
  	mp->m_rootip = rip;	/* save it */
  
  	xfs_iunlock(rip, XFS_ILOCK_EXCL);
  
  	/*
  	 * Initialize realtime inode pointers in the mount structure
  	 */
0771fb451   Eric Sandeen   [XFS] Refactor xf...
1322
1323
  	error = xfs_rtmount_inodes(mp);
  	if (error) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1324
1325
1326
  		/*
  		 * Free up the root inode.
  		 */
0b932cccb   Dave Chinner   xfs: Convert rema...
1327
  		xfs_warn(mp, "failed to read RT inodes");
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1328
  		goto out_rele_rip;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1329
1330
1331
  	}
  
  	/*
7884bc861   Christoph Hellwig   xfs: fix bad_feat...
1332
1333
1334
  	 * If this is a read-only mount defer the superblock updates until
  	 * the next remount into writeable mode.  Otherwise we would never
  	 * perform the update e.g. for the root filesystem.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335
  	 */
7884bc861   Christoph Hellwig   xfs: fix bad_feat...
1336
1337
  	if (mp->m_update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) {
  		error = xfs_mount_log_sb(mp, mp->m_update_flags);
e5720eec0   David Chinner   [XFS] Propagate e...
1338
  		if (error) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1339
  			xfs_warn(mp, "failed to write sb changes");
b93b6e434   Christoph Hellwig   xfs: make sure to...
1340
  			goto out_rtunmount;
e5720eec0   David Chinner   [XFS] Propagate e...
1341
1342
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1343
1344
1345
1346
  
  	/*
  	 * Initialise the XFS quota management subsystem for this mount
  	 */
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
  	if (XFS_IS_QUOTA_RUNNING(mp)) {
  		error = xfs_qm_newmount(mp, &quotamount, &quotaflags);
  		if (error)
  			goto out_rtunmount;
  	} else {
  		ASSERT(!XFS_IS_QUOTA_ON(mp));
  
  		/*
  		 * If a file system had quotas running earlier, but decided to
  		 * mount without -o uquota/pquota/gquota options, revoke the
  		 * quotachecked license.
  		 */
  		if (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1360
  			xfs_notice(mp, "resetting quota flags");
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1361
1362
1363
1364
1365
  			error = xfs_mount_reset_sbqflags(mp);
  			if (error)
  				return error;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1366
1367
1368
1369
1370
1371
  
  	/*
  	 * Finish recovering the file system.  This part needed to be
  	 * delayed until after the root and real-time bitmap inodes
  	 * were consistently read in.
  	 */
4249023a5   Christoph Hellwig   [XFS] cleanup xfs...
1372
  	error = xfs_log_mount_finish(mp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1373
  	if (error) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1374
  		xfs_warn(mp, "log mount finish failed");
b93b6e434   Christoph Hellwig   xfs: make sure to...
1375
  		goto out_rtunmount;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1376
1377
1378
1379
1380
  	}
  
  	/*
  	 * Complete the quota initialisation, post-log-replay component.
  	 */
7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1381
1382
1383
1384
1385
1386
  	if (quotamount) {
  		ASSERT(mp->m_qflags == 0);
  		mp->m_qflags = quotaflags;
  
  		xfs_qm_mount_quotas(mp);
  	}
84e1e99f1   David Chinner   [XFS] Prevent ENO...
1387
1388
1389
1390
1391
1392
1393
  	/*
  	 * Now we are mounted, reserve a small amount of unused space for
  	 * privileged transactions. This is needed so that transaction
  	 * space required for critical operations can dip into this pool
  	 * when at ENOSPC. This is needed for operations like create with
  	 * attr, unwritten extent conversion at ENOSPC, etc. Data allocations
  	 * are not allowed to use this reserved space.
8babd8a2e   Dave Chinner   xfs: Increase the...
1394
1395
1396
  	 *
  	 * This may drive us straight to ENOSPC on mount, but that implies
  	 * we were already there on the last unmount. Warn if this occurs.
84e1e99f1   David Chinner   [XFS] Prevent ENO...
1397
  	 */
d5db0f97f   Eric Sandeen   xfs: more reserve...
1398
1399
1400
1401
  	if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
  		resblks = xfs_default_resblks(mp);
  		error = xfs_reserve_blocks(mp, &resblks, NULL);
  		if (error)
0b932cccb   Dave Chinner   xfs: Convert rema...
1402
1403
  			xfs_warn(mp,
  	"Unable to allocate reserve blocks. Continuing without reserve pool.");
d5db0f97f   Eric Sandeen   xfs: more reserve...
1404
  	}
84e1e99f1   David Chinner   [XFS] Prevent ENO...
1405

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1406
  	return 0;
b93b6e434   Christoph Hellwig   xfs: make sure to...
1407
1408
   out_rtunmount:
  	xfs_rtunmount_inodes(mp);
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1409
   out_rele_rip:
433550990   Christoph Hellwig   [XFS] remove most...
1410
  	IRELE(rip);
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1411
   out_log_dealloc:
21b699c89   Christoph Hellwig   xfs: cleanup log ...
1412
  	xfs_log_unmount(mp);
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1413
   out_free_perag:
ff4f038c6   Christoph Hellwig   [XFS] refactor xf...
1414
  	xfs_free_perag(mp);
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1415
   out_remove_uuid:
27174203f   Christoph Hellwig   xfs: cleanup uuid...
1416
  	xfs_uuid_unmount(mp);
f9057e3da   Christoph Hellwig   xfs: cleanup erro...
1417
   out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1418
1419
1420
1421
  	return error;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1422
1423
1424
   * This flushes out the inodes,dquots and the superblock, unmounts the
   * log and makes sure that incore structures are freed.
   */
41b5c2e77   Christoph Hellwig   [XFS] xfs_unmount...
1425
1426
1427
  void
  xfs_unmountfs(
  	struct xfs_mount	*mp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1428
  {
41b5c2e77   Christoph Hellwig   [XFS] xfs_unmount...
1429
1430
  	__uint64_t		resblks;
  	int			error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1431

7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1432
  	xfs_qm_unmount_quotas(mp);
b93b6e434   Christoph Hellwig   xfs: make sure to...
1433
  	xfs_rtunmount_inodes(mp);
77508ec8e   Christoph Hellwig   [XFS] move root i...
1434
  	IRELE(mp->m_rootip);
641c56fbf   David Chinner   [XFS] Prevent dea...
1435
1436
  	/*
  	 * We can potentially deadlock here if we have an inode cluster
9da096fd1   Malcolm Parsons   xfs: fix various ...
1437
  	 * that has been freed has its buffer still pinned in memory because
641c56fbf   David Chinner   [XFS] Prevent dea...
1438
1439
1440
1441
1442
1443
1444
  	 * the transaction is still sitting in a iclog. The stale inodes
  	 * on that buffer will have their flush locks held until the
  	 * transaction hits the disk and the callbacks run. the inode
  	 * flush takes the flush lock unconditionally and with nothing to
  	 * push out the iclog we will never get that unlocked. hence we
  	 * need to force the log first.
  	 */
a14a348bf   Christoph Hellwig   xfs: cleanup up x...
1445
  	xfs_log_force(mp, XFS_LOG_SYNC);
c854363e8   Dave Chinner   xfs: Use delayed ...
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
  
  	/*
  	 * Do a delwri reclaim pass first so that as many dirty inodes are
  	 * queued up for IO as possible. Then flush the buffers before making
  	 * a synchronous path to catch all the remaining inodes are reclaimed.
  	 * This makes the reclaim process as quick as possible by avoiding
  	 * synchronous writeout and blocking on inodes already in the delwri
  	 * state as much as possible.
  	 */
  	xfs_reclaim_inodes(mp, 0);
  	XFS_bflush(mp->m_ddev_targp);
  	xfs_reclaim_inodes(mp, SYNC_WAIT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1458

7d095257e   Christoph Hellwig   xfs: kill xfs_qmops
1459
  	xfs_qm_unmount(mp);
a357a1215   Lachlan McIlroy   [XFS] Fix use-aft...
1460

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1461
1462
1463
1464
1465
  	/*
  	 * Flush out the log synchronously so that we know for sure
  	 * that nothing is pinned.  This is important because bflush()
  	 * will skip pinned buffers.
  	 */
a14a348bf   Christoph Hellwig   xfs: cleanup up x...
1466
  	xfs_log_force(mp, XFS_LOG_SYNC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1467
1468
1469
1470
1471
  
  	xfs_binval(mp->m_ddev_targp);
  	if (mp->m_rtdev_targp) {
  		xfs_binval(mp->m_rtdev_targp);
  	}
84e1e99f1   David Chinner   [XFS] Prevent ENO...
1472
1473
1474
1475
  	/*
  	 * Unreserve any blocks we have so that when we unmount we don't account
  	 * the reserved free space as used. This is really only necessary for
  	 * lazy superblock counting because it trusts the incore superblock
9da096fd1   Malcolm Parsons   xfs: fix various ...
1476
  	 * counters to be absolutely correct on clean unmount.
84e1e99f1   David Chinner   [XFS] Prevent ENO...
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
  	 *
  	 * We don't bother correcting this elsewhere for lazy superblock
  	 * counting because on mount of an unclean filesystem we reconstruct the
  	 * correct counter value and this is irrelevant.
  	 *
  	 * For non-lazy counter filesystems, this doesn't matter at all because
  	 * we only every apply deltas to the superblock and hence the incore
  	 * value does not matter....
  	 */
  	resblks = 0;
714082bc1   David Chinner   [XFS] Report erro...
1487
1488
  	error = xfs_reserve_blocks(mp, &resblks, NULL);
  	if (error)
0b932cccb   Dave Chinner   xfs: Convert rema...
1489
  		xfs_warn(mp, "Unable to free reserved block pool. "
714082bc1   David Chinner   [XFS] Report erro...
1490
  				"Freespace may not be correct on next mount.");
e5720eec0   David Chinner   [XFS] Propagate e...
1491
1492
  	error = xfs_log_sbcount(mp, 1);
  	if (error)
0b932cccb   Dave Chinner   xfs: Convert rema...
1493
  		xfs_warn(mp, "Unable to update superblock counters. "
e5720eec0   David Chinner   [XFS] Propagate e...
1494
  				"Freespace may not be correct on next mount.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1495
  	xfs_unmountfs_writesb(mp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1496
  	xfs_unmountfs_wait(mp); 		/* wait for async bufs */
21b699c89   Christoph Hellwig   xfs: cleanup log ...
1497
1498
  	xfs_log_unmount_write(mp);
  	xfs_log_unmount(mp);
27174203f   Christoph Hellwig   xfs: cleanup uuid...
1499
  	xfs_uuid_unmount(mp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1500

1550d0b0b   Christoph Hellwig   [XFS] kill INDUCE...
1501
  #if defined(DEBUG)
0ce4cfd4f   Christoph Hellwig   [XFS] kill the vf...
1502
  	xfs_errortag_clearall(mp, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1503
  #endif
ff4f038c6   Christoph Hellwig   [XFS] refactor xf...
1504
  	xfs_free_perag(mp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1505
  }
ba0f32d46   Christoph Hellwig   [XFS] mark variou...
1506
  STATIC void
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
  xfs_unmountfs_wait(xfs_mount_t *mp)
  {
  	if (mp->m_logdev_targp != mp->m_ddev_targp)
  		xfs_wait_buftarg(mp->m_logdev_targp);
  	if (mp->m_rtdev_targp)
  		xfs_wait_buftarg(mp->m_rtdev_targp);
  	xfs_wait_buftarg(mp->m_ddev_targp);
  }
  
  int
92821e2ba   David Chinner   [XFS] Lazy Superb...
1517
1518
  xfs_fs_writable(xfs_mount_t *mp)
  {
b267ce995   Christoph Hellwig   [XFS] kill struct...
1519
  	return !(xfs_test_for_freeze(mp) || XFS_FORCED_SHUTDOWN(mp) ||
bd186aa90   Christoph Hellwig   [XFS] kill the vf...
1520
  		(mp->m_flags & XFS_MOUNT_RDONLY));
92821e2ba   David Chinner   [XFS] Lazy Superb...
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
  }
  
  /*
   * xfs_log_sbcount
   *
   * Called either periodically to keep the on disk superblock values
   * roughly up to date or from unmount to make sure the values are
   * correct on a clean unmount.
   *
   * Note this code can be called during the process of freezing, so
   * we may need to use the transaction allocator which does not not
   * block when the transaction subsystem is in its frozen state.
   */
  int
  xfs_log_sbcount(
  	xfs_mount_t	*mp,
  	uint		sync)
  {
  	xfs_trans_t	*tp;
  	int		error;
  
  	if (!xfs_fs_writable(mp))
  		return 0;
d4d90b577   Christoph Hellwig   [XFS] Add xfs_ics...
1544
  	xfs_icsb_sync_counters(mp, 0);
92821e2ba   David Chinner   [XFS] Lazy Superb...
1545
1546
1547
1548
1549
1550
1551
  
  	/*
  	 * we don't need to do this if we are updating the superblock
  	 * counters on every modification.
  	 */
  	if (!xfs_sb_version_haslazysbcount(&mp->m_sb))
  		return 0;
80641dc66   Christoph Hellwig   xfs: I/O completi...
1552
  	tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT, KM_SLEEP);
92821e2ba   David Chinner   [XFS] Lazy Superb...
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
  	error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
  					XFS_DEFAULT_LOG_COUNT);
  	if (error) {
  		xfs_trans_cancel(tp, 0);
  		return error;
  	}
  
  	xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS);
  	if (sync)
  		xfs_trans_set_sync(tp);
e5720eec0   David Chinner   [XFS] Propagate e...
1563
1564
  	error = xfs_trans_commit(tp, 0);
  	return error;
92821e2ba   David Chinner   [XFS] Lazy Superb...
1565
1566
1567
  }
  
  int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1568
1569
1570
  xfs_unmountfs_writesb(xfs_mount_t *mp)
  {
  	xfs_buf_t	*sbp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1571
1572
1573
1574
1575
1576
  	int		error = 0;
  
  	/*
  	 * skip superblock write if fs is read-only, or
  	 * if we are doing a forced umount.
  	 */
bd186aa90   Christoph Hellwig   [XFS] kill the vf...
1577
  	if (!((mp->m_flags & XFS_MOUNT_RDONLY) ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1578
  		XFS_FORCED_SHUTDOWN(mp))) {
8d280b98c   David Chinner   [XFS] On machines...
1579

92821e2ba   David Chinner   [XFS] Lazy Superb...
1580
  		sbp = xfs_getsb(mp, 0);
8d280b98c   David Chinner   [XFS] On machines...
1581

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1582
1583
1584
1585
1586
1587
1588
  		XFS_BUF_UNDONE(sbp);
  		XFS_BUF_UNREAD(sbp);
  		XFS_BUF_UNDELAYWRITE(sbp);
  		XFS_BUF_WRITE(sbp);
  		XFS_BUF_UNASYNC(sbp);
  		ASSERT(XFS_BUF_TARGET(sbp) == mp->m_ddev_targp);
  		xfsbdstrat(mp, sbp);
1a1a3e97b   Christoph Hellwig   xfs: remove xfs_b...
1589
  		error = xfs_buf_iowait(sbp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1590
1591
1592
  		if (error)
  			xfs_ioerror_alert("xfs_unmountfs_writesb",
  					  mp, sbp, XFS_BUF_ADDR(sbp));
92821e2ba   David Chinner   [XFS] Lazy Superb...
1593
  		xfs_buf_relse(sbp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1594
  	}
014c2544e   Jesper Juhl   return statement ...
1595
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
  }
  
  /*
   * xfs_mod_sb() can be used to copy arbitrary changes to the
   * in-core superblock into the superblock buffer to be logged.
   * It does not provide the higher level of locking that is
   * needed to protect the in-core superblock from concurrent
   * access.
   */
  void
  xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
  {
  	xfs_buf_t	*bp;
  	int		first;
  	int		last;
  	xfs_mount_t	*mp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1612
1613
1614
1615
1616
1617
1618
  	xfs_sb_field_t	f;
  
  	ASSERT(fields);
  	if (!fields)
  		return;
  	mp = tp->t_mountp;
  	bp = xfs_trans_getsb(tp, mp, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1619
1620
1621
1622
  	first = sizeof(xfs_sb_t);
  	last = 0;
  
  	/* translate/copy */
2bdf7cd0b   Christoph Hellwig   [XFS] superblock ...
1623
  	xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, fields);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1624
1625
  
  	/* find modified range */
587aa0feb   Dave Chinner   xfs: rearrange xf...
1626
1627
1628
  	f = (xfs_sb_field_t)xfs_highbit64((__uint64_t)fields);
  	ASSERT((1LL << f) & XFS_SB_MOD_BITS);
  	last = xfs_sb_info[f + 1].offset - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1629
1630
1631
1632
  
  	f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
  	ASSERT((1LL << f) & XFS_SB_MOD_BITS);
  	first = xfs_sb_info[f].offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1633
1634
  	xfs_trans_log_buf(tp, bp, first, last);
  }
d210a28cd   Yingping Lu   [XFS] In actual a...
1635

d210a28cd   Yingping Lu   [XFS] In actual a...
1636

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1637
1638
1639
1640
1641
1642
1643
  /*
   * xfs_mod_incore_sb_unlocked() is a utility routine common used to apply
   * a delta to a specified field in the in-core superblock.  Simply
   * switch on the field indicated and apply the delta to that field.
   * Fields are not allowed to dip below zero, so if the delta would
   * do this do not apply it and return EINVAL.
   *
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
1644
   * The m_sb_lock must be held when this routine is called.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1645
   */
d96f8f891   Eric Sandeen   xfs: add more sta...
1646
  STATIC int
20f4ebf2b   David Chinner   [XFS] Make growfs...
1647
1648
1649
1650
1651
  xfs_mod_incore_sb_unlocked(
  	xfs_mount_t	*mp,
  	xfs_sb_field_t	field,
  	int64_t		delta,
  	int		rsvd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
  {
  	int		scounter;	/* short counter for 32 bit fields */
  	long long	lcounter;	/* long counter for 64 bit fields */
  	long long	res_used, rem;
  
  	/*
  	 * With the in-core superblock spin lock held, switch
  	 * on the indicated field.  Apply the delta to the
  	 * proper field.  If the fields value would dip below
  	 * 0, then do not apply the delta and return EINVAL.
  	 */
  	switch (field) {
  	case XFS_SBS_ICOUNT:
  		lcounter = (long long)mp->m_sb.sb_icount;
  		lcounter += delta;
  		if (lcounter < 0) {
  			ASSERT(0);
014c2544e   Jesper Juhl   return statement ...
1669
  			return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1670
1671
  		}
  		mp->m_sb.sb_icount = lcounter;
014c2544e   Jesper Juhl   return statement ...
1672
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1673
1674
1675
1676
1677
  	case XFS_SBS_IFREE:
  		lcounter = (long long)mp->m_sb.sb_ifree;
  		lcounter += delta;
  		if (lcounter < 0) {
  			ASSERT(0);
014c2544e   Jesper Juhl   return statement ...
1678
  			return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1679
1680
  		}
  		mp->m_sb.sb_ifree = lcounter;
014c2544e   Jesper Juhl   return statement ...
1681
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1682
  	case XFS_SBS_FDBLOCKS:
4be536deb   David Chinner   [XFS] Prevent fre...
1683
1684
  		lcounter = (long long)
  			mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
  		res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
  
  		if (delta > 0) {		/* Putting blocks back */
  			if (res_used > delta) {
  				mp->m_resblks_avail += delta;
  			} else {
  				rem = delta - res_used;
  				mp->m_resblks_avail = mp->m_resblks;
  				lcounter += rem;
  			}
  		} else {				/* Taking blocks away */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1696
  			lcounter += delta;
8babd8a2e   Dave Chinner   xfs: Increase the...
1697
1698
1699
1700
1701
  			if (lcounter >= 0) {
  				mp->m_sb.sb_fdblocks = lcounter +
  							XFS_ALLOC_SET_ASIDE(mp);
  				return 0;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1702

8babd8a2e   Dave Chinner   xfs: Increase the...
1703
1704
1705
1706
1707
1708
  			/*
  			 * We are out of blocks, use any available reserved
  			 * blocks if were allowed to.
  			 */
  			if (!rsvd)
  				return XFS_ERROR(ENOSPC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1709

8babd8a2e   Dave Chinner   xfs: Increase the...
1710
1711
1712
1713
  			lcounter = (long long)mp->m_resblks_avail + delta;
  			if (lcounter >= 0) {
  				mp->m_resblks_avail = lcounter;
  				return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1714
  			}
8babd8a2e   Dave Chinner   xfs: Increase the...
1715
1716
1717
1718
1719
  			printk_once(KERN_WARNING
  				"Filesystem \"%s\": reserve blocks depleted! "
  				"Consider increasing reserve pool size.",
  				mp->m_fsname);
  			return XFS_ERROR(ENOSPC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1720
  		}
4be536deb   David Chinner   [XFS] Prevent fre...
1721
  		mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
014c2544e   Jesper Juhl   return statement ...
1722
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1723
1724
1725
1726
  	case XFS_SBS_FREXTENTS:
  		lcounter = (long long)mp->m_sb.sb_frextents;
  		lcounter += delta;
  		if (lcounter < 0) {
014c2544e   Jesper Juhl   return statement ...
1727
  			return XFS_ERROR(ENOSPC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1728
1729
  		}
  		mp->m_sb.sb_frextents = lcounter;
014c2544e   Jesper Juhl   return statement ...
1730
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1731
1732
1733
1734
1735
  	case XFS_SBS_DBLOCKS:
  		lcounter = (long long)mp->m_sb.sb_dblocks;
  		lcounter += delta;
  		if (lcounter < 0) {
  			ASSERT(0);
014c2544e   Jesper Juhl   return statement ...
1736
  			return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1737
1738
  		}
  		mp->m_sb.sb_dblocks = lcounter;
014c2544e   Jesper Juhl   return statement ...
1739
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1740
1741
1742
1743
1744
  	case XFS_SBS_AGCOUNT:
  		scounter = mp->m_sb.sb_agcount;
  		scounter += delta;
  		if (scounter < 0) {
  			ASSERT(0);
014c2544e   Jesper Juhl   return statement ...
1745
  			return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1746
1747
  		}
  		mp->m_sb.sb_agcount = scounter;
014c2544e   Jesper Juhl   return statement ...
1748
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1749
1750
1751
1752
1753
  	case XFS_SBS_IMAX_PCT:
  		scounter = mp->m_sb.sb_imax_pct;
  		scounter += delta;
  		if (scounter < 0) {
  			ASSERT(0);
014c2544e   Jesper Juhl   return statement ...
1754
  			return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1755
1756
  		}
  		mp->m_sb.sb_imax_pct = scounter;
014c2544e   Jesper Juhl   return statement ...
1757
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1758
1759
1760
1761
1762
  	case XFS_SBS_REXTSIZE:
  		scounter = mp->m_sb.sb_rextsize;
  		scounter += delta;
  		if (scounter < 0) {
  			ASSERT(0);
014c2544e   Jesper Juhl   return statement ...
1763
  			return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1764
1765
  		}
  		mp->m_sb.sb_rextsize = scounter;
014c2544e   Jesper Juhl   return statement ...
1766
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1767
1768
1769
1770
1771
  	case XFS_SBS_RBMBLOCKS:
  		scounter = mp->m_sb.sb_rbmblocks;
  		scounter += delta;
  		if (scounter < 0) {
  			ASSERT(0);
014c2544e   Jesper Juhl   return statement ...
1772
  			return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1773
1774
  		}
  		mp->m_sb.sb_rbmblocks = scounter;
014c2544e   Jesper Juhl   return statement ...
1775
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1776
1777
1778
1779
1780
  	case XFS_SBS_RBLOCKS:
  		lcounter = (long long)mp->m_sb.sb_rblocks;
  		lcounter += delta;
  		if (lcounter < 0) {
  			ASSERT(0);
014c2544e   Jesper Juhl   return statement ...
1781
  			return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1782
1783
  		}
  		mp->m_sb.sb_rblocks = lcounter;
014c2544e   Jesper Juhl   return statement ...
1784
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1785
1786
1787
1788
1789
  	case XFS_SBS_REXTENTS:
  		lcounter = (long long)mp->m_sb.sb_rextents;
  		lcounter += delta;
  		if (lcounter < 0) {
  			ASSERT(0);
014c2544e   Jesper Juhl   return statement ...
1790
  			return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1791
1792
  		}
  		mp->m_sb.sb_rextents = lcounter;
014c2544e   Jesper Juhl   return statement ...
1793
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1794
1795
1796
1797
1798
  	case XFS_SBS_REXTSLOG:
  		scounter = mp->m_sb.sb_rextslog;
  		scounter += delta;
  		if (scounter < 0) {
  			ASSERT(0);
014c2544e   Jesper Juhl   return statement ...
1799
  			return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1800
1801
  		}
  		mp->m_sb.sb_rextslog = scounter;
014c2544e   Jesper Juhl   return statement ...
1802
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1803
1804
  	default:
  		ASSERT(0);
014c2544e   Jesper Juhl   return statement ...
1805
  		return XFS_ERROR(EINVAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1806
1807
1808
1809
1810
1811
  	}
  }
  
  /*
   * xfs_mod_incore_sb() is used to change a field in the in-core
   * superblock structure by the specified delta.  This modification
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
1812
   * is protected by the m_sb_lock.  Just use the xfs_mod_incore_sb_unlocked()
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1813
1814
1815
   * routine to do the work.
   */
  int
20f4ebf2b   David Chinner   [XFS] Make growfs...
1816
  xfs_mod_incore_sb(
96540c785   Christoph Hellwig   xfs: do not use x...
1817
1818
1819
1820
  	struct xfs_mount	*mp,
  	xfs_sb_field_t		field,
  	int64_t			delta,
  	int			rsvd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1821
  {
96540c785   Christoph Hellwig   xfs: do not use x...
1822
  	int			status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1823

8d280b98c   David Chinner   [XFS] On machines...
1824
  #ifdef HAVE_PERCPU_SB
96540c785   Christoph Hellwig   xfs: do not use x...
1825
  	ASSERT(field < XFS_SBS_ICOUNT || field > XFS_SBS_FDBLOCKS);
8d280b98c   David Chinner   [XFS] On machines...
1826
  #endif
96540c785   Christoph Hellwig   xfs: do not use x...
1827
1828
1829
  	spin_lock(&mp->m_sb_lock);
  	status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
  	spin_unlock(&mp->m_sb_lock);
8d280b98c   David Chinner   [XFS] On machines...
1830

014c2544e   Jesper Juhl   return statement ...
1831
  	return status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1832
1833
1834
  }
  
  /*
1b0407125   Christoph Hellwig   xfs: do not use x...
1835
   * Change more than one field in the in-core superblock structure at a time.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1836
   *
1b0407125   Christoph Hellwig   xfs: do not use x...
1837
1838
1839
1840
1841
1842
1843
1844
   * The fields and changes to those fields are specified in the array of
   * xfs_mod_sb structures passed in.  Either all of the specified deltas
   * will be applied or none of them will.  If any modified field dips below 0,
   * then all modifications will be backed out and EINVAL will be returned.
   *
   * Note that this function may not be used for the superblock values that
   * are tracked with the in-memory per-cpu counters - a direct call to
   * xfs_icsb_modify_counters is required for these.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1845
1846
   */
  int
1b0407125   Christoph Hellwig   xfs: do not use x...
1847
1848
1849
1850
1851
  xfs_mod_incore_sb_batch(
  	struct xfs_mount	*mp,
  	xfs_mod_sb_t		*msb,
  	uint			nmsb,
  	int			rsvd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1852
  {
1b0407125   Christoph Hellwig   xfs: do not use x...
1853
1854
  	xfs_mod_sb_t		*msbp = &msb[0];
  	int			error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1855
1856
  
  	/*
1b0407125   Christoph Hellwig   xfs: do not use x...
1857
1858
1859
1860
  	 * Loop through the array of mod structures and apply each individually.
  	 * If any fail, then back out all those which have already been applied.
  	 * Do all of this within the scope of the m_sb_lock so that all of the
  	 * changes will be atomic.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1861
  	 */
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
1862
  	spin_lock(&mp->m_sb_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1863
  	for (msbp = &msbp[0]; msbp < (msb + nmsb); msbp++) {
1b0407125   Christoph Hellwig   xfs: do not use x...
1864
1865
  		ASSERT(msbp->msb_field < XFS_SBS_ICOUNT ||
  		       msbp->msb_field > XFS_SBS_FDBLOCKS);
8d280b98c   David Chinner   [XFS] On machines...
1866

1b0407125   Christoph Hellwig   xfs: do not use x...
1867
1868
1869
1870
  		error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
  						   msbp->msb_delta, rsvd);
  		if (error)
  			goto unwind;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1871
  	}
1b0407125   Christoph Hellwig   xfs: do not use x...
1872
1873
  	spin_unlock(&mp->m_sb_lock);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1874

1b0407125   Christoph Hellwig   xfs: do not use x...
1875
1876
1877
1878
1879
  unwind:
  	while (--msbp >= msb) {
  		error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
  						   -msbp->msb_delta, rsvd);
  		ASSERT(error == 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1880
  	}
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
1881
  	spin_unlock(&mp->m_sb_lock);
1b0407125   Christoph Hellwig   xfs: do not use x...
1882
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
  }
  
  /*
   * xfs_getsb() is called to obtain the buffer for the superblock.
   * The buffer is returned locked and read in from disk.
   * The buffer should be released with a call to xfs_brelse().
   *
   * If the flags parameter is BUF_TRYLOCK, then we'll only return
   * the superblock buffer if it can be locked without sleeping.
   * If it can't then we'll return NULL.
   */
  xfs_buf_t *
  xfs_getsb(
  	xfs_mount_t	*mp,
  	int		flags)
  {
  	xfs_buf_t	*bp;
  
  	ASSERT(mp->m_sb_bp != NULL);
  	bp = mp->m_sb_bp;
0cadda1c5   Christoph Hellwig   xfs: remove dupli...
1903
  	if (flags & XBF_TRYLOCK) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1904
1905
1906
1907
1908
1909
1910
1911
  		if (!XFS_BUF_CPSEMA(bp)) {
  			return NULL;
  		}
  	} else {
  		XFS_BUF_PSEMA(bp, PRIBIO);
  	}
  	XFS_BUF_HOLD(bp);
  	ASSERT(XFS_BUF_ISDONE(bp));
014c2544e   Jesper Juhl   return statement ...
1912
  	return bp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1913
1914
1915
1916
1917
1918
1919
  }
  
  /*
   * Used to free the superblock along various error paths.
   */
  void
  xfs_freesb(
26af65523   Dave Chinner   xfs: kill XBF_FS_...
1920
  	struct xfs_mount	*mp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1921
  {
26af65523   Dave Chinner   xfs: kill XBF_FS_...
1922
  	struct xfs_buf		*bp = mp->m_sb_bp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1923

26af65523   Dave Chinner   xfs: kill XBF_FS_...
1924
  	xfs_buf_lock(bp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1925
  	mp->m_sb_bp = NULL;
26af65523   Dave Chinner   xfs: kill XBF_FS_...
1926
  	xfs_buf_relse(bp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1927
1928
1929
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1930
   * Used to log changes to the superblock unit and width fields which could
e6957ea48   Eric Sandeen   [XFS] Ensure "bot...
1931
1932
   * be altered by the mount options, as well as any potential sb_features2
   * fixup. Only the first superblock is updated.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1933
   */
7884bc861   Christoph Hellwig   xfs: fix bad_feat...
1934
  int
ee1c09082   David Chinner   [XFS] Fix superbl...
1935
  xfs_mount_log_sb(
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1936
1937
1938
1939
  	xfs_mount_t	*mp,
  	__int64_t	fields)
  {
  	xfs_trans_t	*tp;
e5720eec0   David Chinner   [XFS] Propagate e...
1940
  	int		error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1941

ee1c09082   David Chinner   [XFS] Fix superbl...
1942
  	ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID |
4b166de0a   David Chinner   [XFS] Update vali...
1943
1944
  			 XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2 |
  			 XFS_SB_VERSIONNUM));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1945
1946
  
  	tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT);
e5720eec0   David Chinner   [XFS] Propagate e...
1947
1948
1949
  	error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
  				XFS_DEFAULT_LOG_COUNT);
  	if (error) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1950
  		xfs_trans_cancel(tp, 0);
e5720eec0   David Chinner   [XFS] Propagate e...
1951
  		return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1952
1953
  	}
  	xfs_mod_sb(tp, fields);
e5720eec0   David Chinner   [XFS] Propagate e...
1954
1955
  	error = xfs_trans_commit(tp, 0);
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1956
  }
8d280b98c   David Chinner   [XFS] On machines...
1957

dda35b8f8   Christoph Hellwig   xfs: merge xfs_lr...
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
  /*
   * If the underlying (data/log/rt) device is readonly, there are some
   * operations that cannot proceed.
   */
  int
  xfs_dev_is_read_only(
  	struct xfs_mount	*mp,
  	char			*message)
  {
  	if (xfs_readonly_buftarg(mp->m_ddev_targp) ||
  	    xfs_readonly_buftarg(mp->m_logdev_targp) ||
  	    (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) {
0b932cccb   Dave Chinner   xfs: Convert rema...
1970
1971
  		xfs_notice(mp, "%s required on read-only device.", message);
  		xfs_notice(mp, "write access unavailable, cannot proceed.");
dda35b8f8   Christoph Hellwig   xfs: merge xfs_lr...
1972
1973
1974
1975
  		return EROFS;
  	}
  	return 0;
  }
8d280b98c   David Chinner   [XFS] On machines...
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
  
  #ifdef HAVE_PERCPU_SB
  /*
   * Per-cpu incore superblock counters
   *
   * Simple concept, difficult implementation
   *
   * Basically, replace the incore superblock counters with a distributed per cpu
   * counter for contended fields (e.g.  free block count).
   *
   * Difficulties arise in that the incore sb is used for ENOSPC checking, and
   * hence needs to be accurately read when we are running low on space. Hence
   * there is a method to enable and disable the per-cpu counters based on how
   * much "stuff" is available in them.
   *
   * Basically, a counter is enabled if there is enough free resource to justify
   * running a per-cpu fast-path. If the per-cpu counter runs out (i.e. a local
   * ENOSPC), then we disable the counters to synchronise all callers and
   * re-distribute the available resources.
   *
   * If, once we redistributed the available resources, we still get a failure,
   * we disable the per-cpu counter and go through the slow path.
   *
   * The slow path is the current xfs_mod_incore_sb() function.  This means that
9da096fd1   Malcolm Parsons   xfs: fix various ...
2000
   * when we disable a per-cpu counter, we need to drain its resources back to
8d280b98c   David Chinner   [XFS] On machines...
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
   * the global superblock. We do this after disabling the counter to prevent
   * more threads from queueing up on the counter.
   *
   * Essentially, this means that we still need a lock in the fast path to enable
   * synchronisation between the global counters and the per-cpu counters. This
   * is not a problem because the lock will be local to a CPU almost all the time
   * and have little contention except when we get to ENOSPC conditions.
   *
   * Basically, this lock becomes a barrier that enables us to lock out the fast
   * path while we do things like enabling and disabling counters and
   * synchronising the counters.
   *
   * Locking rules:
   *
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
2015
   * 	1. m_sb_lock before picking up per-cpu locks
8d280b98c   David Chinner   [XFS] On machines...
2016
   * 	2. per-cpu locks always picked up via for_each_online_cpu() order
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
2017
   * 	3. accurate counter sync requires m_sb_lock + per cpu locks
8d280b98c   David Chinner   [XFS] On machines...
2018
   * 	4. modifying per-cpu counters requires holding per-cpu lock
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
2019
2020
   * 	5. modifying global counters requires holding m_sb_lock
   *	6. enabling or disabling a counter requires holding the m_sb_lock 
8d280b98c   David Chinner   [XFS] On machines...
2021
2022
2023
2024
2025
2026
2027
   *	   and _none_ of the per-cpu locks.
   *
   * Disabled counters are only ever re-enabled by a balance operation
   * that results in more free resources per CPU than a given threshold.
   * To ensure counters don't remain disabled, they are rebalanced when
   * the global resource goes above a higher threshold (i.e. some hysteresis
   * is present to prevent thrashing).
e8234a687   David Chinner   [XFS] Add support...
2028
   */
5a67e4c5b   Chandra Seetharaman   [PATCH] cpu hotpl...
2029
  #ifdef CONFIG_HOTPLUG_CPU
e8234a687   David Chinner   [XFS] Add support...
2030
2031
  /*
   * hot-plug CPU notifier support.
8d280b98c   David Chinner   [XFS] On machines...
2032
   *
5a67e4c5b   Chandra Seetharaman   [PATCH] cpu hotpl...
2033
2034
2035
2036
   * We need a notifier per filesystem as we need to be able to identify
   * the filesystem to balance the counters out. This is achieved by
   * having a notifier block embedded in the xfs_mount_t and doing pointer
   * magic to get the mount pointer from the notifier block address.
8d280b98c   David Chinner   [XFS] On machines...
2037
   */
e8234a687   David Chinner   [XFS] Add support...
2038
2039
2040
2041
2042
2043
2044
2045
  STATIC int
  xfs_icsb_cpu_notify(
  	struct notifier_block *nfb,
  	unsigned long action,
  	void *hcpu)
  {
  	xfs_icsb_cnts_t *cntp;
  	xfs_mount_t	*mp;
e8234a687   David Chinner   [XFS] Add support...
2046
2047
2048
2049
2050
2051
  
  	mp = (xfs_mount_t *)container_of(nfb, xfs_mount_t, m_icsb_notifier);
  	cntp = (xfs_icsb_cnts_t *)
  			per_cpu_ptr(mp->m_sb_cnts, (unsigned long)hcpu);
  	switch (action) {
  	case CPU_UP_PREPARE:
8bb784428   Rafael J. Wysocki   Add suspend-relat...
2052
  	case CPU_UP_PREPARE_FROZEN:
e8234a687   David Chinner   [XFS] Add support...
2053
2054
  		/* Easy Case - initialize the area and locks, and
  		 * then rebalance when online does everything else for us. */
01e1b69cf   David Chinner   [XFS] using a spi...
2055
  		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
e8234a687   David Chinner   [XFS] Add support...
2056
2057
  		break;
  	case CPU_ONLINE:
8bb784428   Rafael J. Wysocki   Add suspend-relat...
2058
  	case CPU_ONLINE_FROZEN:
03135cf72   David Chinner   [XFS] Fix UP buil...
2059
  		xfs_icsb_lock(mp);
45af6c6de   Christoph Hellwig   [XFS] split xfs_i...
2060
2061
2062
  		xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
  		xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
  		xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
03135cf72   David Chinner   [XFS] Fix UP buil...
2063
  		xfs_icsb_unlock(mp);
e8234a687   David Chinner   [XFS] Add support...
2064
2065
  		break;
  	case CPU_DEAD:
8bb784428   Rafael J. Wysocki   Add suspend-relat...
2066
  	case CPU_DEAD_FROZEN:
e8234a687   David Chinner   [XFS] Add support...
2067
2068
2069
  		/* Disable all the counters, then fold the dead cpu's
  		 * count into the total on the global superblock and
  		 * re-enable the counters. */
03135cf72   David Chinner   [XFS] Fix UP buil...
2070
  		xfs_icsb_lock(mp);
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
2071
  		spin_lock(&mp->m_sb_lock);
e8234a687   David Chinner   [XFS] Add support...
2072
2073
2074
2075
2076
2077
2078
  		xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT);
  		xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
  		xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
  
  		mp->m_sb.sb_icount += cntp->icsb_icount;
  		mp->m_sb.sb_ifree += cntp->icsb_ifree;
  		mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
01e1b69cf   David Chinner   [XFS] using a spi...
2079
  		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
e8234a687   David Chinner   [XFS] Add support...
2080

45af6c6de   Christoph Hellwig   [XFS] split xfs_i...
2081
2082
2083
  		xfs_icsb_balance_counter_locked(mp, XFS_SBS_ICOUNT, 0);
  		xfs_icsb_balance_counter_locked(mp, XFS_SBS_IFREE, 0);
  		xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0);
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
2084
  		spin_unlock(&mp->m_sb_lock);
03135cf72   David Chinner   [XFS] Fix UP buil...
2085
  		xfs_icsb_unlock(mp);
e8234a687   David Chinner   [XFS] Add support...
2086
2087
2088
2089
2090
  		break;
  	}
  
  	return NOTIFY_OK;
  }
5a67e4c5b   Chandra Seetharaman   [PATCH] cpu hotpl...
2091
  #endif /* CONFIG_HOTPLUG_CPU */
e8234a687   David Chinner   [XFS] Add support...
2092

8d280b98c   David Chinner   [XFS] On machines...
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
  int
  xfs_icsb_init_counters(
  	xfs_mount_t	*mp)
  {
  	xfs_icsb_cnts_t *cntp;
  	int		i;
  
  	mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
  	if (mp->m_sb_cnts == NULL)
  		return -ENOMEM;
5a67e4c5b   Chandra Seetharaman   [PATCH] cpu hotpl...
2103
  #ifdef CONFIG_HOTPLUG_CPU
e8234a687   David Chinner   [XFS] Add support...
2104
2105
  	mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify;
  	mp->m_icsb_notifier.priority = 0;
5a67e4c5b   Chandra Seetharaman   [PATCH] cpu hotpl...
2106
2107
  	register_hotcpu_notifier(&mp->m_icsb_notifier);
  #endif /* CONFIG_HOTPLUG_CPU */
e8234a687   David Chinner   [XFS] Add support...
2108

8d280b98c   David Chinner   [XFS] On machines...
2109
2110
  	for_each_online_cpu(i) {
  		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
01e1b69cf   David Chinner   [XFS] using a spi...
2111
  		memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
8d280b98c   David Chinner   [XFS] On machines...
2112
  	}
20b642858   David Chinner   [XFS] Reduction g...
2113
2114
  
  	mutex_init(&mp->m_icsb_mutex);
8d280b98c   David Chinner   [XFS] On machines...
2115
2116
2117
2118
2119
2120
2121
  	/*
  	 * start with all counters disabled so that the
  	 * initial balance kicks us off correctly
  	 */
  	mp->m_icsb_counters = -1;
  	return 0;
  }
5478eead8   Lachlan McIlroy   [XFS] Re-initiali...
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
  void
  xfs_icsb_reinit_counters(
  	xfs_mount_t	*mp)
  {
  	xfs_icsb_lock(mp);
  	/*
  	 * start with all counters disabled so that the
  	 * initial balance kicks us off correctly
  	 */
  	mp->m_icsb_counters = -1;
45af6c6de   Christoph Hellwig   [XFS] split xfs_i...
2132
2133
2134
  	xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
  	xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
  	xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
5478eead8   Lachlan McIlroy   [XFS] Re-initiali...
2135
2136
  	xfs_icsb_unlock(mp);
  }
c962fb790   Christoph Hellwig   [XFS] kill xfs_mo...
2137
  void
8d280b98c   David Chinner   [XFS] On machines...
2138
2139
2140
  xfs_icsb_destroy_counters(
  	xfs_mount_t	*mp)
  {
e8234a687   David Chinner   [XFS] Add support...
2141
  	if (mp->m_sb_cnts) {
5a67e4c5b   Chandra Seetharaman   [PATCH] cpu hotpl...
2142
  		unregister_hotcpu_notifier(&mp->m_icsb_notifier);
8d280b98c   David Chinner   [XFS] On machines...
2143
  		free_percpu(mp->m_sb_cnts);
e8234a687   David Chinner   [XFS] Add support...
2144
  	}
03135cf72   David Chinner   [XFS] Fix UP buil...
2145
  	mutex_destroy(&mp->m_icsb_mutex);
8d280b98c   David Chinner   [XFS] On machines...
2146
  }
b8f82a4a6   Christoph Hellwig   xfs: kill the STA...
2147
  STATIC void
01e1b69cf   David Chinner   [XFS] using a spi...
2148
2149
2150
2151
2152
2153
2154
  xfs_icsb_lock_cntr(
  	xfs_icsb_cnts_t	*icsbp)
  {
  	while (test_and_set_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags)) {
  		ndelay(1000);
  	}
  }
b8f82a4a6   Christoph Hellwig   xfs: kill the STA...
2155
  STATIC void
01e1b69cf   David Chinner   [XFS] using a spi...
2156
2157
2158
2159
2160
  xfs_icsb_unlock_cntr(
  	xfs_icsb_cnts_t	*icsbp)
  {
  	clear_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags);
  }
8d280b98c   David Chinner   [XFS] On machines...
2161

b8f82a4a6   Christoph Hellwig   xfs: kill the STA...
2162
  STATIC void
8d280b98c   David Chinner   [XFS] On machines...
2163
2164
2165
2166
2167
2168
2169
2170
  xfs_icsb_lock_all_counters(
  	xfs_mount_t	*mp)
  {
  	xfs_icsb_cnts_t *cntp;
  	int		i;
  
  	for_each_online_cpu(i) {
  		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
01e1b69cf   David Chinner   [XFS] using a spi...
2171
  		xfs_icsb_lock_cntr(cntp);
8d280b98c   David Chinner   [XFS] On machines...
2172
2173
  	}
  }
b8f82a4a6   Christoph Hellwig   xfs: kill the STA...
2174
  STATIC void
8d280b98c   David Chinner   [XFS] On machines...
2175
2176
2177
2178
2179
2180
2181
2182
  xfs_icsb_unlock_all_counters(
  	xfs_mount_t	*mp)
  {
  	xfs_icsb_cnts_t *cntp;
  	int		i;
  
  	for_each_online_cpu(i) {
  		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
01e1b69cf   David Chinner   [XFS] using a spi...
2183
  		xfs_icsb_unlock_cntr(cntp);
8d280b98c   David Chinner   [XFS] On machines...
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
  	}
  }
  
  STATIC void
  xfs_icsb_count(
  	xfs_mount_t	*mp,
  	xfs_icsb_cnts_t	*cnt,
  	int		flags)
  {
  	xfs_icsb_cnts_t *cntp;
  	int		i;
  
  	memset(cnt, 0, sizeof(xfs_icsb_cnts_t));
  
  	if (!(flags & XFS_ICSB_LAZY_COUNT))
  		xfs_icsb_lock_all_counters(mp);
  
  	for_each_online_cpu(i) {
  		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
  		cnt->icsb_icount += cntp->icsb_icount;
  		cnt->icsb_ifree += cntp->icsb_ifree;
  		cnt->icsb_fdblocks += cntp->icsb_fdblocks;
  	}
  
  	if (!(flags & XFS_ICSB_LAZY_COUNT))
  		xfs_icsb_unlock_all_counters(mp);
  }
  
  STATIC int
  xfs_icsb_counter_disabled(
  	xfs_mount_t	*mp,
  	xfs_sb_field_t	field)
  {
  	ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
  	return test_bit(field, &mp->m_icsb_counters);
  }
36fbe6e6b   David Chinner   [XFS] xfs_icsb_co...
2220
  STATIC void
8d280b98c   David Chinner   [XFS] On machines...
2221
2222
2223
2224
2225
2226
2227
  xfs_icsb_disable_counter(
  	xfs_mount_t	*mp,
  	xfs_sb_field_t	field)
  {
  	xfs_icsb_cnts_t	cnt;
  
  	ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
20b642858   David Chinner   [XFS] Reduction g...
2228
2229
2230
2231
2232
2233
2234
2235
2236
  	/*
  	 * If we are already disabled, then there is nothing to do
  	 * here. We check before locking all the counters to avoid
  	 * the expensive lock operation when being called in the
  	 * slow path and the counter is already disabled. This is
  	 * safe because the only time we set or clear this state is under
  	 * the m_icsb_mutex.
  	 */
  	if (xfs_icsb_counter_disabled(mp, field))
36fbe6e6b   David Chinner   [XFS] xfs_icsb_co...
2237
  		return;
20b642858   David Chinner   [XFS] Reduction g...
2238

8d280b98c   David Chinner   [XFS] On machines...
2239
2240
2241
  	xfs_icsb_lock_all_counters(mp);
  	if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
  		/* drain back to superblock */
ce46193bc   Christoph Hellwig   [XFS] kill XFS_IC...
2242
  		xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
8d280b98c   David Chinner   [XFS] On machines...
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
  		switch(field) {
  		case XFS_SBS_ICOUNT:
  			mp->m_sb.sb_icount = cnt.icsb_icount;
  			break;
  		case XFS_SBS_IFREE:
  			mp->m_sb.sb_ifree = cnt.icsb_ifree;
  			break;
  		case XFS_SBS_FDBLOCKS:
  			mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
  			break;
  		default:
  			BUG();
  		}
  	}
  
  	xfs_icsb_unlock_all_counters(mp);
8d280b98c   David Chinner   [XFS] On machines...
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
  }
  
  STATIC void
  xfs_icsb_enable_counter(
  	xfs_mount_t	*mp,
  	xfs_sb_field_t	field,
  	uint64_t	count,
  	uint64_t	resid)
  {
  	xfs_icsb_cnts_t	*cntp;
  	int		i;
  
  	ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
  
  	xfs_icsb_lock_all_counters(mp);
  	for_each_online_cpu(i) {
  		cntp = per_cpu_ptr(mp->m_sb_cnts, i);
  		switch (field) {
  		case XFS_SBS_ICOUNT:
  			cntp->icsb_icount = count + resid;
  			break;
  		case XFS_SBS_IFREE:
  			cntp->icsb_ifree = count + resid;
  			break;
  		case XFS_SBS_FDBLOCKS:
  			cntp->icsb_fdblocks = count + resid;
  			break;
  		default:
  			BUG();
  			break;
  		}
  		resid = 0;
  	}
  	clear_bit(field, &mp->m_icsb_counters);
  	xfs_icsb_unlock_all_counters(mp);
  }
dbcabad19   David Chinner   [XFS] Fix block r...
2295
  void
d4d90b577   Christoph Hellwig   [XFS] Add xfs_ics...
2296
  xfs_icsb_sync_counters_locked(
8d280b98c   David Chinner   [XFS] On machines...
2297
2298
2299
2300
  	xfs_mount_t	*mp,
  	int		flags)
  {
  	xfs_icsb_cnts_t	cnt;
8d280b98c   David Chinner   [XFS] On machines...
2301

8d280b98c   David Chinner   [XFS] On machines...
2302
  	xfs_icsb_count(mp, &cnt, flags);
8d280b98c   David Chinner   [XFS] On machines...
2303
2304
2305
2306
2307
2308
  	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_ICOUNT))
  		mp->m_sb.sb_icount = cnt.icsb_icount;
  	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE))
  		mp->m_sb.sb_ifree = cnt.icsb_ifree;
  	if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
  		mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
8d280b98c   David Chinner   [XFS] On machines...
2309
2310
2311
2312
2313
  }
  
  /*
   * Accurate update of per-cpu counters to incore superblock
   */
d4d90b577   Christoph Hellwig   [XFS] Add xfs_ics...
2314
  void
8d280b98c   David Chinner   [XFS] On machines...
2315
  xfs_icsb_sync_counters(
d4d90b577   Christoph Hellwig   [XFS] Add xfs_ics...
2316
2317
  	xfs_mount_t	*mp,
  	int		flags)
8d280b98c   David Chinner   [XFS] On machines...
2318
  {
d4d90b577   Christoph Hellwig   [XFS] Add xfs_ics...
2319
2320
2321
  	spin_lock(&mp->m_sb_lock);
  	xfs_icsb_sync_counters_locked(mp, flags);
  	spin_unlock(&mp->m_sb_lock);
8d280b98c   David Chinner   [XFS] On machines...
2322
2323
2324
2325
2326
  }
  
  /*
   * Balance and enable/disable counters as necessary.
   *
20b642858   David Chinner   [XFS] Reduction g...
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
   * Thresholds for re-enabling counters are somewhat magic.  inode counts are
   * chosen to be the same number as single on disk allocation chunk per CPU, and
   * free blocks is something far enough zero that we aren't going thrash when we
   * get near ENOSPC. We also need to supply a minimum we require per cpu to
   * prevent looping endlessly when xfs_alloc_space asks for more than will
   * be distributed to a single CPU but each CPU has enough blocks to be
   * reenabled.
   *
   * Note that we can be called when counters are already disabled.
   * xfs_icsb_disable_counter() optimises the counter locking in this case to
   * prevent locking every per-cpu counter needlessly.
8d280b98c   David Chinner   [XFS] On machines...
2338
   */
20b642858   David Chinner   [XFS] Reduction g...
2339
2340
  
  #define XFS_ICSB_INO_CNTR_REENABLE	(uint64_t)64
4be536deb   David Chinner   [XFS] Prevent fre...
2341
  #define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \
20b642858   David Chinner   [XFS] Reduction g...
2342
  		(uint64_t)(512 + XFS_ALLOC_SET_ASIDE(mp))
8d280b98c   David Chinner   [XFS] On machines...
2343
  STATIC void
45af6c6de   Christoph Hellwig   [XFS] split xfs_i...
2344
  xfs_icsb_balance_counter_locked(
8d280b98c   David Chinner   [XFS] On machines...
2345
2346
  	xfs_mount_t	*mp,
  	xfs_sb_field_t  field,
20b642858   David Chinner   [XFS] Reduction g...
2347
  	int		min_per_cpu)
8d280b98c   David Chinner   [XFS] On machines...
2348
  {
6fdf8ccc0   Nathan Scott   [XFS] Rework code...
2349
  	uint64_t	count, resid;
8d280b98c   David Chinner   [XFS] On machines...
2350
  	int		weight = num_online_cpus();
20b642858   David Chinner   [XFS] Reduction g...
2351
  	uint64_t	min = (uint64_t)min_per_cpu;
8d280b98c   David Chinner   [XFS] On machines...
2352

8d280b98c   David Chinner   [XFS] On machines...
2353
2354
2355
2356
2357
2358
2359
2360
  	/* disable counter and sync counter */
  	xfs_icsb_disable_counter(mp, field);
  
  	/* update counters  - first CPU gets residual*/
  	switch (field) {
  	case XFS_SBS_ICOUNT:
  		count = mp->m_sb.sb_icount;
  		resid = do_div(count, weight);
20b642858   David Chinner   [XFS] Reduction g...
2361
  		if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
45af6c6de   Christoph Hellwig   [XFS] split xfs_i...
2362
  			return;
8d280b98c   David Chinner   [XFS] On machines...
2363
2364
2365
2366
  		break;
  	case XFS_SBS_IFREE:
  		count = mp->m_sb.sb_ifree;
  		resid = do_div(count, weight);
20b642858   David Chinner   [XFS] Reduction g...
2367
  		if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
45af6c6de   Christoph Hellwig   [XFS] split xfs_i...
2368
  			return;
8d280b98c   David Chinner   [XFS] On machines...
2369
2370
2371
2372
  		break;
  	case XFS_SBS_FDBLOCKS:
  		count = mp->m_sb.sb_fdblocks;
  		resid = do_div(count, weight);
20b642858   David Chinner   [XFS] Reduction g...
2373
  		if (count < max(min, XFS_ICSB_FDBLK_CNTR_REENABLE(mp)))
45af6c6de   Christoph Hellwig   [XFS] split xfs_i...
2374
  			return;
8d280b98c   David Chinner   [XFS] On machines...
2375
2376
2377
  		break;
  	default:
  		BUG();
6fdf8ccc0   Nathan Scott   [XFS] Rework code...
2378
  		count = resid = 0;	/* quiet, gcc */
8d280b98c   David Chinner   [XFS] On machines...
2379
2380
2381
2382
  		break;
  	}
  
  	xfs_icsb_enable_counter(mp, field, count, resid);
45af6c6de   Christoph Hellwig   [XFS] split xfs_i...
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
  }
  
  STATIC void
  xfs_icsb_balance_counter(
  	xfs_mount_t	*mp,
  	xfs_sb_field_t  fields,
  	int		min_per_cpu)
  {
  	spin_lock(&mp->m_sb_lock);
  	xfs_icsb_balance_counter_locked(mp, fields, min_per_cpu);
  	spin_unlock(&mp->m_sb_lock);
8d280b98c   David Chinner   [XFS] On machines...
2394
  }
1b0407125   Christoph Hellwig   xfs: do not use x...
2395
  int
20b642858   David Chinner   [XFS] Reduction g...
2396
  xfs_icsb_modify_counters(
8d280b98c   David Chinner   [XFS] On machines...
2397
2398
  	xfs_mount_t	*mp,
  	xfs_sb_field_t	field,
20f4ebf2b   David Chinner   [XFS] Make growfs...
2399
  	int64_t		delta,
20b642858   David Chinner   [XFS] Reduction g...
2400
  	int		rsvd)
8d280b98c   David Chinner   [XFS] On machines...
2401
2402
2403
  {
  	xfs_icsb_cnts_t	*icsbp;
  	long long	lcounter;	/* long counter for 64 bit fields */
7a9e02d6b   Christoph Lameter   this_cpu: xfs_ics...
2404
  	int		ret = 0;
8d280b98c   David Chinner   [XFS] On machines...
2405

20b642858   David Chinner   [XFS] Reduction g...
2406
  	might_sleep();
8d280b98c   David Chinner   [XFS] On machines...
2407
  again:
7a9e02d6b   Christoph Lameter   this_cpu: xfs_ics...
2408
2409
  	preempt_disable();
  	icsbp = this_cpu_ptr(mp->m_sb_cnts);
20b642858   David Chinner   [XFS] Reduction g...
2410
2411
2412
2413
  
  	/*
  	 * if the counter is disabled, go to slow path
  	 */
8d280b98c   David Chinner   [XFS] On machines...
2414
2415
  	if (unlikely(xfs_icsb_counter_disabled(mp, field)))
  		goto slow_path;
20b642858   David Chinner   [XFS] Reduction g...
2416
2417
2418
2419
2420
  	xfs_icsb_lock_cntr(icsbp);
  	if (unlikely(xfs_icsb_counter_disabled(mp, field))) {
  		xfs_icsb_unlock_cntr(icsbp);
  		goto slow_path;
  	}
8d280b98c   David Chinner   [XFS] On machines...
2421
2422
2423
2424
2425
2426
  
  	switch (field) {
  	case XFS_SBS_ICOUNT:
  		lcounter = icsbp->icsb_icount;
  		lcounter += delta;
  		if (unlikely(lcounter < 0))
20b642858   David Chinner   [XFS] Reduction g...
2427
  			goto balance_counter;
8d280b98c   David Chinner   [XFS] On machines...
2428
2429
2430
2431
2432
2433
2434
  		icsbp->icsb_icount = lcounter;
  		break;
  
  	case XFS_SBS_IFREE:
  		lcounter = icsbp->icsb_ifree;
  		lcounter += delta;
  		if (unlikely(lcounter < 0))
20b642858   David Chinner   [XFS] Reduction g...
2435
  			goto balance_counter;
8d280b98c   David Chinner   [XFS] On machines...
2436
2437
2438
2439
2440
  		icsbp->icsb_ifree = lcounter;
  		break;
  
  	case XFS_SBS_FDBLOCKS:
  		BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0);
4be536deb   David Chinner   [XFS] Prevent fre...
2441
  		lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
8d280b98c   David Chinner   [XFS] On machines...
2442
2443
  		lcounter += delta;
  		if (unlikely(lcounter < 0))
20b642858   David Chinner   [XFS] Reduction g...
2444
  			goto balance_counter;
4be536deb   David Chinner   [XFS] Prevent fre...
2445
  		icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
8d280b98c   David Chinner   [XFS] On machines...
2446
2447
2448
2449
2450
  		break;
  	default:
  		BUG();
  		break;
  	}
01e1b69cf   David Chinner   [XFS] using a spi...
2451
  	xfs_icsb_unlock_cntr(icsbp);
7a9e02d6b   Christoph Lameter   this_cpu: xfs_ics...
2452
  	preempt_enable();
8d280b98c   David Chinner   [XFS] On machines...
2453
  	return 0;
8d280b98c   David Chinner   [XFS] On machines...
2454
  slow_path:
7a9e02d6b   Christoph Lameter   this_cpu: xfs_ics...
2455
  	preempt_enable();
8d280b98c   David Chinner   [XFS] On machines...
2456

20b642858   David Chinner   [XFS] Reduction g...
2457
2458
2459
2460
2461
  	/*
  	 * serialise with a mutex so we don't burn lots of cpu on
  	 * the superblock lock. We still need to hold the superblock
  	 * lock, however, when we modify the global structures.
  	 */
03135cf72   David Chinner   [XFS] Fix UP buil...
2462
  	xfs_icsb_lock(mp);
20b642858   David Chinner   [XFS] Reduction g...
2463
2464
2465
2466
2467
2468
2469
2470
  
  	/*
  	 * Now running atomically.
  	 *
  	 * If the counter is enabled, someone has beaten us to rebalancing.
  	 * Drop the lock and try again in the fast path....
  	 */
  	if (!(xfs_icsb_counter_disabled(mp, field))) {
03135cf72   David Chinner   [XFS] Fix UP buil...
2471
  		xfs_icsb_unlock(mp);
8d280b98c   David Chinner   [XFS] On machines...
2472
  		goto again;
8d280b98c   David Chinner   [XFS] On machines...
2473
  	}
20b642858   David Chinner   [XFS] Reduction g...
2474
2475
2476
2477
2478
  	/*
  	 * The counter is currently disabled. Because we are
  	 * running atomically here, we know a rebalance cannot
  	 * be in progress. Hence we can go straight to operating
  	 * on the global superblock. We do not call xfs_mod_incore_sb()
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
2479
  	 * here even though we need to get the m_sb_lock. Doing so
20b642858   David Chinner   [XFS] Reduction g...
2480
  	 * will cause us to re-enter this function and deadlock.
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
2481
  	 * Hence we get the m_sb_lock ourselves and then call
20b642858   David Chinner   [XFS] Reduction g...
2482
2483
2484
  	 * xfs_mod_incore_sb_unlocked() as the unlocked path operates
  	 * directly on the global counters.
  	 */
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
2485
  	spin_lock(&mp->m_sb_lock);
8d280b98c   David Chinner   [XFS] On machines...
2486
  	ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
3685c2a1d   Eric Sandeen   [XFS] Unwrap XFS_...
2487
  	spin_unlock(&mp->m_sb_lock);
8d280b98c   David Chinner   [XFS] On machines...
2488

20b642858   David Chinner   [XFS] Reduction g...
2489
2490
2491
2492
2493
2494
2495
  	/*
  	 * Now that we've modified the global superblock, we
  	 * may be able to re-enable the distributed counters
  	 * (e.g. lots of space just got freed). After that
  	 * we are done.
  	 */
  	if (ret != ENOSPC)
45af6c6de   Christoph Hellwig   [XFS] split xfs_i...
2496
  		xfs_icsb_balance_counter(mp, field, 0);
03135cf72   David Chinner   [XFS] Fix UP buil...
2497
  	xfs_icsb_unlock(mp);
8d280b98c   David Chinner   [XFS] On machines...
2498
  	return ret;
8d280b98c   David Chinner   [XFS] On machines...
2499

20b642858   David Chinner   [XFS] Reduction g...
2500
2501
  balance_counter:
  	xfs_icsb_unlock_cntr(icsbp);
7a9e02d6b   Christoph Lameter   this_cpu: xfs_ics...
2502
  	preempt_enable();
8d280b98c   David Chinner   [XFS] On machines...
2503

20b642858   David Chinner   [XFS] Reduction g...
2504
2505
2506
2507
2508
2509
  	/*
  	 * We may have multiple threads here if multiple per-cpu
  	 * counters run dry at the same time. This will mean we can
  	 * do more balances than strictly necessary but it is not
  	 * the common slowpath case.
  	 */
03135cf72   David Chinner   [XFS] Fix UP buil...
2510
  	xfs_icsb_lock(mp);
20b642858   David Chinner   [XFS] Reduction g...
2511
2512
2513
2514
2515
2516
2517
2518
2519
  
  	/*
  	 * running atomically.
  	 *
  	 * This will leave the counter in the correct state for future
  	 * accesses. After the rebalance, we simply try again and our retry
  	 * will either succeed through the fast path or slow path without
  	 * another balance operation being required.
  	 */
45af6c6de   Christoph Hellwig   [XFS] split xfs_i...
2520
  	xfs_icsb_balance_counter(mp, field, delta);
03135cf72   David Chinner   [XFS] Fix UP buil...
2521
  	xfs_icsb_unlock(mp);
20b642858   David Chinner   [XFS] Reduction g...
2522
  	goto again;
8d280b98c   David Chinner   [XFS] On machines...
2523
  }
20b642858   David Chinner   [XFS] Reduction g...
2524

8d280b98c   David Chinner   [XFS] On machines...
2525
  #endif