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