]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/xfs_mount.c
Sync user and kernel code, make xfs_io -f option useful.
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_mount.c
CommitLineData
2bd0ea18 1/*
0d3e0b37 2 * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved.
2bd0ea18
NS
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
5000d01d 14 * or the like. Any license provided herein, whether implied or
2bd0ea18
NS
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33#include <xfs.h>
34
35/*
36 * Mount initialization code establishing various mount
37 * fields from the superblock associated with the given
38 * mount structure.
39 */
40void
41xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
42{
43 int i;
44
45 mp->m_agfrotor = mp->m_agirotor = 0;
321717ae 46 spinlock_init(&mp->m_agirotor_lock, "m_agirotor_lock");
34317449 47 mp->m_maxagi = mp->m_sb.sb_agcount;
2bd0ea18
NS
48 mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG;
49 mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
9440d84d 50 mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
2bd0ea18
NS
51 mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1;
52 mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog;
53 mp->m_litino = sbp->sb_inodesize -
54 ((uint)sizeof(xfs_dinode_core_t) + (uint)sizeof(xfs_agino_t));
55 mp->m_blockmask = sbp->sb_blocksize - 1;
56 mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
57 mp->m_blockwmask = mp->m_blockwsize - 1;
58
73bf5988
SL
59
60 if (XFS_SB_VERSION_HASLOGV2(sbp)) {
61 if (sbp->sb_logsunit <= 1) {
62 mp->m_lstripemask = 1;
63 } else {
64 mp->m_lstripemask =
65 1 << xfs_highbit32(sbp->sb_logsunit >> BBSHIFT);
66 }
67 }
68
2bd0ea18
NS
69 /*
70 * Setup for attributes, in case they get created.
71 * This value is for inodes getting attributes for the first time,
72 * the per-inode value is for old attribute values.
73 */
74 ASSERT(sbp->sb_inodesize >= 256 && sbp->sb_inodesize <= 2048);
75 switch (sbp->sb_inodesize) {
76 case 256:
77 mp->m_attroffset = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(2);
78 break;
79 case 512:
80 case 1024:
81 case 2048:
82 mp->m_attroffset = XFS_BMDR_SPACE_CALC(12);
83 break;
84 default:
85 ASSERT(0);
86 }
87 ASSERT(mp->m_attroffset < XFS_LITINO(mp));
88
89 for (i = 0; i < 2; i++) {
90 mp->m_alloc_mxr[i] = XFS_BTREE_BLOCK_MAXRECS(sbp->sb_blocksize,
91 xfs_alloc, i == 0);
92 mp->m_alloc_mnr[i] = XFS_BTREE_BLOCK_MINRECS(sbp->sb_blocksize,
93 xfs_alloc, i == 0);
94 }
95 for (i = 0; i < 2; i++) {
96 mp->m_bmap_dmxr[i] = XFS_BTREE_BLOCK_MAXRECS(sbp->sb_blocksize,
97 xfs_bmbt, i == 0);
98 mp->m_bmap_dmnr[i] = XFS_BTREE_BLOCK_MINRECS(sbp->sb_blocksize,
99 xfs_bmbt, i == 0);
100 }
101 for (i = 0; i < 2; i++) {
102 mp->m_inobt_mxr[i] = XFS_BTREE_BLOCK_MAXRECS(sbp->sb_blocksize,
103 xfs_inobt, i == 0);
104 mp->m_inobt_mnr[i] = XFS_BTREE_BLOCK_MINRECS(sbp->sb_blocksize,
105 xfs_inobt, i == 0);
106 }
107
108 mp->m_bsize = XFS_FSB_TO_BB(mp, 1);
7dcc1612
NS
109 mp->m_ialloc_inos = (int)MAX((__uint16_t)XFS_INODES_PER_CHUNK,
110 sbp->sb_inopblock);
2bd0ea18
NS
111 mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog;
112}
113
114static struct {
115 short offset;
5000d01d
SL
116 short type; /* 0 = integer
117 * 1 = binary / string (no translation)
118 */
2bd0ea18 119} xfs_sb_info[] = {
5000d01d
SL
120 { offsetof(xfs_sb_t, sb_magicnum), 0 },
121 { offsetof(xfs_sb_t, sb_blocksize), 0 },
122 { offsetof(xfs_sb_t, sb_dblocks), 0 },
123 { offsetof(xfs_sb_t, sb_rblocks), 0 },
124 { offsetof(xfs_sb_t, sb_rextents), 0 },
125 { offsetof(xfs_sb_t, sb_uuid), 1 },
126 { offsetof(xfs_sb_t, sb_logstart), 0 },
127 { offsetof(xfs_sb_t, sb_rootino), 0 },
128 { offsetof(xfs_sb_t, sb_rbmino), 0 },
129 { offsetof(xfs_sb_t, sb_rsumino), 0 },
130 { offsetof(xfs_sb_t, sb_rextsize), 0 },
131 { offsetof(xfs_sb_t, sb_agblocks), 0 },
132 { offsetof(xfs_sb_t, sb_agcount), 0 },
133 { offsetof(xfs_sb_t, sb_rbmblocks), 0 },
134 { offsetof(xfs_sb_t, sb_logblocks), 0 },
2bd0ea18 135 { offsetof(xfs_sb_t, sb_versionnum), 0 },
5000d01d
SL
136 { offsetof(xfs_sb_t, sb_sectsize), 0 },
137 { offsetof(xfs_sb_t, sb_inodesize), 0 },
138 { offsetof(xfs_sb_t, sb_inopblock), 0 },
139 { offsetof(xfs_sb_t, sb_fname[0]), 1 },
140 { offsetof(xfs_sb_t, sb_blocklog), 0 },
141 { offsetof(xfs_sb_t, sb_sectlog), 0 },
142 { offsetof(xfs_sb_t, sb_inodelog), 0 },
143 { offsetof(xfs_sb_t, sb_inopblog), 0 },
144 { offsetof(xfs_sb_t, sb_agblklog), 0 },
145 { offsetof(xfs_sb_t, sb_rextslog), 0 },
2bd0ea18 146 { offsetof(xfs_sb_t, sb_inprogress), 0 },
5000d01d
SL
147 { offsetof(xfs_sb_t, sb_imax_pct), 0 },
148 { offsetof(xfs_sb_t, sb_icount), 0 },
149 { offsetof(xfs_sb_t, sb_ifree), 0 },
150 { offsetof(xfs_sb_t, sb_fdblocks), 0 },
151 { offsetof(xfs_sb_t, sb_frextents), 0 },
152 { offsetof(xfs_sb_t, sb_uquotino), 0 },
153 { offsetof(xfs_sb_t, sb_gquotino), 0 },
154 { offsetof(xfs_sb_t, sb_qflags), 0 },
155 { offsetof(xfs_sb_t, sb_flags), 0 },
156 { offsetof(xfs_sb_t, sb_shared_vn), 0 },
2bd0ea18 157 { offsetof(xfs_sb_t, sb_inoalignmt), 0 },
5000d01d
SL
158 { offsetof(xfs_sb_t, sb_unit), 0 },
159 { offsetof(xfs_sb_t, sb_width), 0 },
160 { offsetof(xfs_sb_t, sb_dirblklog), 0 },
9440d84d
NS
161 { offsetof(xfs_sb_t, sb_logsectlog), 0 },
162 { offsetof(xfs_sb_t, sb_logsectsize),0 },
5000d01d
SL
163 { offsetof(xfs_sb_t, sb_logsunit), 0 },
164 { sizeof(xfs_sb_t), 0 }
2bd0ea18
NS
165};
166
167/*
168 * xfs_xlatesb
5000d01d
SL
169 * data - on disk version of sb
170 * sb - a superblock
171 * dir - conversion direction: <0 - convert sb to buf
172 * >0 - convert buf to sb
173 * arch - architecture to read/write from/to buf
174 * fields - which fields to copy (bitmask)
2bd0ea18
NS
175 */
176void
b391b7cd
NS
177xfs_xlatesb(
178 void *data,
179 xfs_sb_t *sb,
180 int dir,
181 xfs_arch_t arch,
182 __int64_t fields)
2bd0ea18 183{
b391b7cd
NS
184 xfs_caddr_t buf_ptr;
185 xfs_caddr_t mem_ptr;
186 xfs_sb_field_t f;
187 int first;
188 int size;
5000d01d 189
b391b7cd
NS
190 ASSERT(dir);
191 ASSERT(fields);
2bd0ea18 192
b391b7cd
NS
193 if (!fields)
194 return;
5000d01d 195
b391b7cd
NS
196 buf_ptr = (xfs_caddr_t)data;
197 mem_ptr = (xfs_caddr_t)sb;
5000d01d 198
b391b7cd
NS
199 while (fields) {
200 f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
201 first = xfs_sb_info[f].offset;
202 size = xfs_sb_info[f + 1].offset - first;
2bd0ea18 203
b391b7cd 204 ASSERT(xfs_sb_info[f].type == 0 || xfs_sb_info[f].type == 1);
5000d01d 205
b391b7cd
NS
206 if (arch == ARCH_NOCONVERT ||
207 size == 1 ||
208 xfs_sb_info[f].type == 1) {
209 if (dir > 0) {
32181a02 210 memcpy(mem_ptr + first, buf_ptr + first, size);
b391b7cd 211 } else {
32181a02 212 memcpy(buf_ptr + first, mem_ptr + first, size);
b391b7cd
NS
213 }
214 } else {
215 switch (size) {
216 case 2:
217 INT_XLATE(*(__uint16_t*)(buf_ptr+first),
218 *(__uint16_t*)(mem_ptr+first),
219 dir, arch);
220 break;
221 case 4:
222 INT_XLATE(*(__uint32_t*)(buf_ptr+first),
223 *(__uint32_t*)(mem_ptr+first),
224 dir, arch);
225 break;
226 case 8:
227 INT_XLATE(*(__uint64_t*)(buf_ptr+first),
228 *(__uint64_t*)(mem_ptr+first), dir, arch);
229 break;
230 default:
231 ASSERT(0);
232 }
233 }
234
235 fields &= ~(1LL << f);
236 }
2bd0ea18 237}
a33a9e62
NS
238
239void
240xfs_initialize_perag(xfs_mount_t *mp, int agcount)
241{
242 int index, max_metadata;
243 xfs_perag_t *pag;
244 xfs_agino_t agino;
245 xfs_ino_t ino;
246 xfs_sb_t *sbp = &mp->m_sb;
247 xfs_ino_t max_inum = XFS_MAXINUMBER_32;
248
249 /* Check to see if the filesystem can overflow 32 bit inodes */
250 agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
251 ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
252
253 /* Clear the mount flag if no inode can overflow 32 bits
254 * on this filesystem.
255 */
256 if (ino <= max_inum) {
257 mp->m_flags &= ~XFS_MOUNT_32BITINODES;
258 }
259
260 /* If we can overflow then setup the ag headers accordingly */
261 if (mp->m_flags & XFS_MOUNT_32BITINODES) {
262 /* Calculate how much should be reserved for inodes to
263 * meet the max inode percentage.
264 */
265 if (mp->m_maxicount) {
266 __uint64_t icount;
267
268 icount = sbp->sb_dblocks * sbp->sb_imax_pct;
269 do_div(icount, 100);
270 icount += sbp->sb_agblocks - 1;
271 do_div(icount, mp->m_ialloc_blks);
272 max_metadata = icount;
273 } else {
274 max_metadata = agcount;
275 }
276 for (index = 0; index < agcount; index++) {
277 ino = XFS_AGINO_TO_INO(mp, index, agino);
278 if (ino > max_inum) {
279 index++;
280 break;
281 }
282
283 /* This ag is prefered for inodes */
284 pag = &mp->m_perag[index];
285 pag->pagi_inodeok = 1;
286 if (index < max_metadata)
287 pag->pagf_metadata = 1;
288 }
289 } else {
290 /* Setup default behavior for smaller filesystems */
291 for (index = 0; index < agcount; index++) {
292 pag = &mp->m_perag[index];
293 pag->pagi_inodeok = 1;
294 }
295 }
296 mp->m_maxagi = index;
297}
298