Deleted Added
full compact
ext2_vfsops.c (193628) ext2_vfsops.c (202283)
1/*-
2 * modified for EXT2FS support in Lites 1.1
3 *
4 * Aug 1995, Godmar Back (gback@cs.utah.edu)
5 * University of Utah, Department of Computer Science
6 */
7/*-
8 * Copyright (c) 1989, 1991, 1993, 1994

--- 19 unchanged lines hidden (view full) ---

28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94
1/*-
2 * modified for EXT2FS support in Lites 1.1
3 *
4 * Aug 1995, Godmar Back (gback@cs.utah.edu)
5 * University of Utah, Department of Computer Science
6 */
7/*-
8 * Copyright (c) 1989, 1991, 1993, 1994

--- 19 unchanged lines hidden (view full) ---

28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94
36 * $FreeBSD: head/sys/gnu/fs/ext2fs/ext2_vfsops.c 193628 2009-06-07 08:42:26Z stas $
36 * $FreeBSD: head/sys/fs/ext2fs/ext2_vfsops.c 202283 2010-01-14 14:30:54Z lulf $
37 */
38
37 */
38
39/*-
40 * COPYRIGHT.INFO says this has some GPL'd code from ext2_super.c in it
41 *
42 * This program is free software; you can redistribute it and/or modify
43 * it under the terms of the GNU General Public License as published by
44 * the Free Software Foundation; either version 2 of the License.
45 *
46 * This program is distributed in the hope that it will be useful,
47 * but WITHOUT ANY WARRANTY; without even the implied warranty of
48 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49 * GNU General Public License for more details.
50 *
51 * You should have received a copy of the GNU General Public License
52 * along with this program; if not, write to the Free Software
53 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
54 *
55 */
56
57#include <sys/param.h>
58#include <sys/systm.h>
59#include <sys/namei.h>
60#include <sys/priv.h>
61#include <sys/proc.h>
62#include <sys/kernel.h>
63#include <sys/vnode.h>
64#include <sys/mount.h>
65#include <sys/bio.h>
66#include <sys/buf.h>
67#include <sys/conf.h>
68#include <sys/fcntl.h>
69#include <sys/malloc.h>
70#include <sys/stat.h>
71#include <sys/mutex.h>
72
73#include <geom/geom.h>
74#include <geom/geom_vfs.h>
75
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/namei.h>
42#include <sys/priv.h>
43#include <sys/proc.h>
44#include <sys/kernel.h>
45#include <sys/vnode.h>
46#include <sys/mount.h>
47#include <sys/bio.h>
48#include <sys/buf.h>
49#include <sys/conf.h>
50#include <sys/fcntl.h>
51#include <sys/malloc.h>
52#include <sys/stat.h>
53#include <sys/mutex.h>
54
55#include <geom/geom.h>
56#include <geom/geom_vfs.h>
57
76#include <gnu/fs/ext2fs/ext2_mount.h>
77#include <gnu/fs/ext2fs/inode.h>
58#include
59#include
78
60
79#include <gnu/fs/ext2fs/fs.h>
80#include <gnu/fs/ext2fs/ext2_extern.h>
81#include <gnu/fs/ext2fs/ext2_fs_sb.h>
82#include <gnu/fs/ext2fs/ext2_fs.h>
61#include
62#include
63#include <fs/ext2fs/ext2fs.h>
83
84static int ext2_flushfiles(struct mount *mp, int flags, struct thread *td);
85static int ext2_mountfs(struct vnode *, struct mount *);
86static int ext2_reload(struct mount *mp, struct thread *td);
87static int ext2_sbupdate(struct ext2mount *, int);
64
65static int ext2_flushfiles(struct mount *mp, int flags, struct thread *td);
66static int ext2_mountfs(struct vnode *, struct mount *);
67static int ext2_reload(struct mount *mp, struct thread *td);
68static int ext2_sbupdate(struct ext2mount *, int);
88
69static int ext2_cgupdate(struct ext2mount *, int);
89static vfs_unmount_t ext2_unmount;
90static vfs_root_t ext2_root;
91static vfs_statfs_t ext2_statfs;
92static vfs_sync_t ext2_sync;
93static vfs_vget_t ext2_vget;
94static vfs_fhtovp_t ext2_fhtovp;
95static vfs_mount_t ext2_mount;
96

--- 7 unchanged lines hidden (view full) ---

104 .vfs_statfs = ext2_statfs,
105 .vfs_sync = ext2_sync,
106 .vfs_unmount = ext2_unmount,
107 .vfs_vget = ext2_vget,
108};
109
110VFS_SET(ext2fs_vfsops, ext2fs, 0);
111
70static vfs_unmount_t ext2_unmount;
71static vfs_root_t ext2_root;
72static vfs_statfs_t ext2_statfs;
73static vfs_sync_t ext2_sync;
74static vfs_vget_t ext2_vget;
75static vfs_fhtovp_t ext2_fhtovp;
76static vfs_mount_t ext2_mount;
77

--- 7 unchanged lines hidden (view full) ---

85 .vfs_statfs = ext2_statfs,
86 .vfs_sync = ext2_sync,
87 .vfs_unmount = ext2_unmount,
88 .vfs_vget = ext2_vget,
89};
90
91VFS_SET(ext2fs_vfsops, ext2fs, 0);
92
112static int ext2_check_sb_compat(struct ext2_super_block *es, struct cdev *dev,
93static int ext2_check_sb_compat(struct ext2fs *es, struct cdev *dev,
113 int ronly);
114static int compute_sb_data(struct vnode * devvp,
94 int ronly);
95static int compute_sb_data(struct vnode * devvp,
115 struct ext2_super_block * es, struct ext2_sb_info * fs);
96 struct ext2fs * es, struct m_ext2fs * fs);
116
117static const char *ext2_opts[] = { "from", "export", "acls", "noexec",
118 "noatime", "union", "suiddir", "multilabel", "nosymfollow",
119 "noclusterr", "noclusterw", "force", NULL };
120
121/*
122 * VFS Operations.
123 *
124 * mount system call
125 */
126static int
127ext2_mount(struct mount *mp)
128{
129 struct vfsoptlist *opts;
130 struct vnode *devvp;
131 struct thread *td;
132 struct ext2mount *ump = 0;
97
98static const char *ext2_opts[] = { "from", "export", "acls", "noexec",
99 "noatime", "union", "suiddir", "multilabel", "nosymfollow",
100 "noclusterr", "noclusterw", "force", NULL };
101
102/*
103 * VFS Operations.
104 *
105 * mount system call
106 */
107static int
108ext2_mount(struct mount *mp)
109{
110 struct vfsoptlist *opts;
111 struct vnode *devvp;
112 struct thread *td;
113 struct ext2mount *ump = 0;
133 struct ext2_sb_info *fs;
114 struct m_ext2fs *fs;
134 struct nameidata nd, *ndp = &nd;
135 accmode_t accmode;
136 char *path, *fspec;
137 int error, flags, len;
138
139 td = curthread;
140 opts = mp->mnt_optnew;
141

--- 11 unchanged lines hidden (view full) ---

153 return (EINVAL);
154
155 /*
156 * If updating, check whether changing from read-only to
157 * read/write; if there is no device name, that's all we do.
158 */
159 if (mp->mnt_flag & MNT_UPDATE) {
160 ump = VFSTOEXT2(mp);
115 struct nameidata nd, *ndp = &nd;
116 accmode_t accmode;
117 char *path, *fspec;
118 int error, flags, len;
119
120 td = curthread;
121 opts = mp->mnt_optnew;
122

--- 11 unchanged lines hidden (view full) ---

134 return (EINVAL);
135
136 /*
137 * If updating, check whether changing from read-only to
138 * read/write; if there is no device name, that's all we do.
139 */
140 if (mp->mnt_flag & MNT_UPDATE) {
141 ump = VFSTOEXT2(mp);
161 fs = ump->um_e2fs;
142 fs = ump->um_e2fs;
162 error = 0;
143 error = 0;
163 if (fs->s_rd_only == 0 &&
144 if (fs->e2fs_ronly == 0 &&
164 vfs_flagopt(opts, "ro", NULL, 0)) {
165 error = VFS_SYNC(mp, MNT_WAIT);
166 if (error)
167 return (error);
168 flags = WRITECLOSE;
169 if (mp->mnt_flag & MNT_FORCE)
170 flags |= FORCECLOSE;
145 vfs_flagopt(opts, "ro", NULL, 0)) {
146 error = VFS_SYNC(mp, MNT_WAIT);
147 if (error)
148 return (error);
149 flags = WRITECLOSE;
150 if (mp->mnt_flag & MNT_FORCE)
151 flags |= FORCECLOSE;
171 if (vfs_busy(mp, MBF_NOWAIT))
172 return (EBUSY);
173 error = ext2_flushfiles(mp, flags, td);
152 error = ext2_flushfiles(mp, flags, td);
174 vfs_unbusy(mp);
175 if (!error && fs->s_wasvalid) {
176 fs->s_es->s_state |= EXT2_VALID_FS;
153 if ( error == 0 && fs->e2fs_wasvalid && ext2_cgupdate(ump, MNT_WAIT) == 0) {
154 fs->e2fs->e2fs_state |= E2FS_ISCLEAN;
177 ext2_sbupdate(ump, MNT_WAIT);
178 }
155 ext2_sbupdate(ump, MNT_WAIT);
156 }
179 fs->s_rd_only = 1;
157 fs->e2fs_ronly = 1;
180 vfs_flagopt(opts, "ro", &mp->mnt_flag, MNT_RDONLY);
181 DROP_GIANT();
182 g_topology_lock();
183 g_access(ump->um_cp, 0, -1, 0);
184 g_topology_unlock();
185 PICKUP_GIANT();
186 }
187 if (!error && (mp->mnt_flag & MNT_RELOAD))
188 error = ext2_reload(mp, td);
189 if (error)
190 return (error);
191 devvp = ump->um_devvp;
158 vfs_flagopt(opts, "ro", &mp->mnt_flag, MNT_RDONLY);
159 DROP_GIANT();
160 g_topology_lock();
161 g_access(ump->um_cp, 0, -1, 0);
162 g_topology_unlock();
163 PICKUP_GIANT();
164 }
165 if (!error && (mp->mnt_flag & MNT_RELOAD))
166 error = ext2_reload(mp, td);
167 if (error)
168 return (error);
169 devvp = ump->um_devvp;
192 if (fs->s_rd_only && !vfs_flagopt(opts, "ro", NULL, 0)) {
193 if (ext2_check_sb_compat(fs->s_es, devvp->v_rdev, 0))
170 if (fs->e2fs_ronly && !vfs_flagopt(opts, "ro", NULL, 0)) {
171 if (ext2_check_sb_compat(fs->e2fs, devvp->v_rdev, 0))
194 return (EPERM);
195
196 /*
197 * If upgrade to read-write by non-root, then verify
198 * that user has necessary permissions on the device.
199 */
200 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
201 error = VOP_ACCESS(devvp, VREAD | VWRITE,

--- 8 unchanged lines hidden (view full) ---

210 DROP_GIANT();
211 g_topology_lock();
212 error = g_access(ump->um_cp, 0, 1, 0);
213 g_topology_unlock();
214 PICKUP_GIANT();
215 if (error)
216 return (error);
217
172 return (EPERM);
173
174 /*
175 * If upgrade to read-write by non-root, then verify
176 * that user has necessary permissions on the device.
177 */
178 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
179 error = VOP_ACCESS(devvp, VREAD | VWRITE,

--- 8 unchanged lines hidden (view full) ---

188 DROP_GIANT();
189 g_topology_lock();
190 error = g_access(ump->um_cp, 0, 1, 0);
191 g_topology_unlock();
192 PICKUP_GIANT();
193 if (error)
194 return (error);
195
218 if ((fs->s_es->s_state & EXT2_VALID_FS) == 0 ||
219 (fs->s_es->s_state & EXT2_ERROR_FS)) {
196 if ((fs->e2fs->e2fs_state & E2FS_ISCLEAN) == 0 ||
197 (fs->e2fs->e2fs_state & E2FS_ERRORS)) {
220 if (mp->mnt_flag & MNT_FORCE) {
221 printf(
198 if (mp->mnt_flag & MNT_FORCE) {
199 printf(
222"WARNING: %s was not properly dismounted\n", fs->fs_fsmnt);
200"WARNING: %s was not properly dismounted\n", fs->e2fs_fsmnt);
223 } else {
224 printf(
225"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
201 } else {
202 printf(
203"WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n",
226 fs->fs_fsmnt);
204 fs->e2fs_fsmnt);
227 return (EPERM);
228 }
229 }
205 return (EPERM);
206 }
207 }
230 fs->s_es->s_state &= ~EXT2_VALID_FS;
231 ext2_sbupdate(ump, MNT_WAIT);
232 fs->s_rd_only = 0;
208 fs->e2fs->e2fs_state &= ~E2FS_ISCLEAN;
209 (void)ext2_cgupdate(ump, MNT_WAIT);
210 fs->e2fs_ronly = 0;
233 MNT_ILOCK(mp);
234 mp->mnt_flag &= ~MNT_RDONLY;
235 MNT_IUNLOCK(mp);
236 }
237 if (vfs_flagopt(opts, "export", NULL, 0)) {
238 /* Process export requests in vfs_mount.c. */
239 return (error);
240 }

--- 48 unchanged lines hidden (view full) ---

289 }
290 ump = VFSTOEXT2(mp);
291 fs = ump->um_e2fs;
292
293 /*
294 * Note that this strncpy() is ok because of a check at the start
295 * of ext2_mount().
296 */
211 MNT_ILOCK(mp);
212 mp->mnt_flag &= ~MNT_RDONLY;
213 MNT_IUNLOCK(mp);
214 }
215 if (vfs_flagopt(opts, "export", NULL, 0)) {
216 /* Process export requests in vfs_mount.c. */
217 return (error);
218 }

--- 48 unchanged lines hidden (view full) ---

267 }
268 ump = VFSTOEXT2(mp);
269 fs = ump->um_e2fs;
270
271 /*
272 * Note that this strncpy() is ok because of a check at the start
273 * of ext2_mount().
274 */
297 strncpy(fs->fs_fsmnt, path, MAXMNTLEN);
298 fs->fs_fsmnt[MAXMNTLEN - 1] = '\0';
275 strncpy(fs->e2fs_fsmnt, path, MAXMNTLEN);
276 fs->e2fs_fsmnt[MAXMNTLEN - 1] = '\0';
299 vfs_mountedfrom(mp, fspec);
300 return (0);
301}
302
277 vfs_mountedfrom(mp, fspec);
278 return (0);
279}
280
303/*
304 * Checks that the data in the descriptor blocks make sense
305 * this is taken from ext2/super.c.
306 */
307static int
281static int
308ext2_check_descriptors(struct ext2_sb_info *sb)
282ext2_check_sb_compat(struct ext2fs *es, struct cdev *dev, int ronly)
309{
283{
310 struct ext2_group_desc *gdp = NULL;
311 unsigned long block = sb->s_es->s_first_data_block;
312 int desc_block = 0;
313 int i;
314
284
315 for (i = 0; i < sb->s_groups_count; i++) {
316 /* examine next descriptor block */
317 if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0)
318 gdp = (struct ext2_group_desc *)
319 sb->s_group_desc[desc_block++]->b_data;
320 if (gdp->bg_block_bitmap < block ||
321 gdp->bg_block_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb)) {
322 printf ("ext2_check_descriptors: "
323 "Block bitmap for group %d"
324 " not in group (block %lu)!\n",
325 i, (unsigned long) gdp->bg_block_bitmap);
326 return (0);
327 }
328 if (gdp->bg_inode_bitmap < block ||
329 gdp->bg_inode_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb)) {
330 printf ("ext2_check_descriptors: "
331 "Inode bitmap for group %d"
332 " not in group (block %lu)!\n",
333 i, (unsigned long) gdp->bg_inode_bitmap);
334 return (0);
335 }
336 if (gdp->bg_inode_table < block ||
337 gdp->bg_inode_table + sb->s_itb_per_group >=
338 block + EXT2_BLOCKS_PER_GROUP(sb)) {
339 printf ("ext2_check_descriptors: "
340 "Inode table for group %d"
341 " not in group (block %lu)!\n",
342 i, (unsigned long) gdp->bg_inode_table);
343 return (0);
344 }
345 block += EXT2_BLOCKS_PER_GROUP(sb);
346 gdp++;
347 }
348 return (1);
349}
350
351static int
352ext2_check_sb_compat(struct ext2_super_block *es, struct cdev *dev, int ronly)
353{
354
355 if (es->s_magic != EXT2_SUPER_MAGIC) {
285 if (es->e2fs_magic != E2FS_MAGIC) {
356 printf("ext2fs: %s: wrong magic number %#x (expected %#x)\n",
286 printf("ext2fs: %s: wrong magic number %#x (expected %#x)\n",
357 devtoname(dev), es->s_magic, EXT2_SUPER_MAGIC);
287 devtoname(dev), es->e2fs_magic, E2FS_MAGIC);
358 return (1);
359 }
288 return (1);
289 }
360 if (es->s_rev_level > EXT2_GOOD_OLD_REV) {
361 if (es->s_feature_incompat & ~EXT2_FEATURE_INCOMPAT_SUPP) {
290 if (es->e2fs_rev > E2FS_REV0) {
291 if (es->e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP) {
362 printf(
363"WARNING: mount of %s denied due to unsupported optional features\n",
364 devtoname(dev));
365 return (1);
366 }
367 if (!ronly &&
292 printf(
293"WARNING: mount of %s denied due to unsupported optional features\n",
294 devtoname(dev));
295 return (1);
296 }
297 if (!ronly &&
368 (es->s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPP)) {
298 (es->e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP)) {
369 printf("WARNING: R/W mount of %s denied due to "
370 "unsupported optional features\n", devtoname(dev));
371 return (1);
372 }
373 }
374 return (0);
375}
376
377/*
378 * This computes the fields of the ext2_sb_info structure from the
379 * data in the ext2_super_block structure read in.
380 */
381static int
299 printf("WARNING: R/W mount of %s denied due to "
300 "unsupported optional features\n", devtoname(dev));
301 return (1);
302 }
303 }
304 return (0);
305}
306
307/*
308 * This computes the fields of the ext2_sb_info structure from the
309 * data in the ext2_super_block structure read in.
310 */
311static int
382compute_sb_data(struct vnode *devvp, struct ext2_super_block *es,
383 struct ext2_sb_info *fs)
312compute_sb_data(struct vnode *devvp, struct ext2fs *es,
313 struct m_ext2fs *fs)
384{
385 int db_count, error;
314{
315 int db_count, error;
386 int i, j;
316 int i;
387 int logic_sb_block = 1; /* XXX for now */
317 int logic_sb_block = 1; /* XXX for now */
318 struct buf *bp;
388
319
389 fs->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size;
390 fs->s_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->s_log_block_size;
391 fs->s_fsbtodb = es->s_log_block_size + 1;
392 fs->s_qbmask = fs->s_blocksize - 1;
393 fs->s_blocksize_bits = es->s_log_block_size + 10;
394 fs->s_frag_size = EXT2_MIN_FRAG_SIZE << es->s_log_frag_size;
395 if (fs->s_frag_size)
396 fs->s_frags_per_block = fs->s_blocksize / fs->s_frag_size;
397 fs->s_blocks_per_group = es->s_blocks_per_group;
398 fs->s_frags_per_group = es->s_frags_per_group;
399 fs->s_inodes_per_group = es->s_inodes_per_group;
400 if (es->s_rev_level == EXT2_GOOD_OLD_REV) {
401 fs->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
402 fs->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
320 fs->e2fs_bsize = EXT2_MIN_BLOCK_SIZE << es->e2fs_log_bsize;
321 fs->e2fs_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->e2fs_log_bsize;
322 fs->e2fs_fsbtodb = es->e2fs_log_bsize + 1;
323 fs->e2fs_qbmask = fs->e2fs_bsize - 1;
324 fs->e2fs_blocksize_bits = es->e2fs_log_bsize + 10;
325 fs->e2fs_fsize = EXT2_MIN_FRAG_SIZE << es->e2fs_log_fsize;
326 if (fs->e2fs_fsize)
327 fs->e2fs_fpb = fs->e2fs_bsize / fs->e2fs_fsize;
328 fs->e2fs_bpg = es->e2fs_bpg;
329 fs->e2fs_fpg = es->e2fs_fpg;
330 fs->e2fs_ipg = es->e2fs_ipg;
331 if (es->e2fs_rev == E2FS_REV0) {
332 fs->e2fs_first_inode = E2FS_REV0_FIRST_INO;
333 fs->e2fs_isize = E2FS_REV0_INODE_SIZE ;
403 } else {
334 } else {
404 fs->s_first_ino = es->s_first_ino;
405 fs->s_inode_size = es->s_inode_size;
335 fs->e2fs_first_inode = es->e2fs_first_ino;
336 fs->e2fs_isize = es->e2fs_inode_size;
406
407 /*
408 * Simple sanity check for superblock inode size value.
409 */
337
338 /*
339 * Simple sanity check for superblock inode size value.
340 */
410 if (fs->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE ||
411 fs->s_inode_size > fs->s_blocksize ||
412 (fs->s_inode_size & (fs->s_inode_size - 1)) != 0) {
341 if (fs->e2fs_isize < E2FS_REV0_INODE_SIZE ||
342 fs->e2fs_isize > fs->e2fs_bsize ||
343 (fs->e2fs_isize & (fs->e2fs_isize - 1)) != 0) {
413 printf("EXT2-fs: invalid inode size %d\n",
344 printf("EXT2-fs: invalid inode size %d\n",
414 fs->s_inode_size);
345 fs->e2fs_isize);
415 return (EIO);
416 }
417 }
346 return (EIO);
347 }
348 }
418 fs->s_inodes_per_block = fs->s_blocksize / EXT2_INODE_SIZE(fs);
419 fs->s_itb_per_group = fs->s_inodes_per_group /fs->s_inodes_per_block;
420 fs->s_desc_per_block = fs->s_blocksize / sizeof (struct ext2_group_desc);
349 fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs);
350 fs->e2fs_itpg = fs->e2fs_ipg /fs->e2fs_ipb;
351 fs->e2fs_descpb = fs->e2fs_bsize / sizeof (struct ext2_gd);
421 /* s_resuid / s_resgid ? */
352 /* s_resuid / s_resgid ? */
422 fs->s_groups_count = (es->s_blocks_count - es->s_first_data_block +
353 fs->e2fs_gcount = (es->e2fs_bcount - es->e2fs_first_dblock +
423 EXT2_BLOCKS_PER_GROUP(fs) - 1) / EXT2_BLOCKS_PER_GROUP(fs);
354 EXT2_BLOCKS_PER_GROUP(fs) - 1) / EXT2_BLOCKS_PER_GROUP(fs);
424 db_count = (fs->s_groups_count + EXT2_DESC_PER_BLOCK(fs) - 1) /
355 db_count = (fs->e2fs_gcount + EXT2_DESC_PER_BLOCK(fs) - 1) /
425 EXT2_DESC_PER_BLOCK(fs);
356 EXT2_DESC_PER_BLOCK(fs);
426 fs->s_gdb_count = db_count;
427 fs->s_group_desc = malloc(db_count * sizeof (struct buf *),
357 fs->e2fs_gdbcount = db_count;
358 fs->e2fs_gd = malloc(db_count * fs->e2fs_bsize,
428 M_EXT2MNT, M_WAITOK);
359 M_EXT2MNT, M_WAITOK);
360 fs->e2fs_contigdirs = malloc(fs->e2fs_gcount * sizeof(*fs->e2fs_contigdirs),
361 M_EXT2MNT, M_WAITOK);
429
430 /*
431 * Adjust logic_sb_block.
432 * Godmar thinks: if the blocksize is greater than 1024, then
433 * the superblock is logically part of block zero.
434 */
362
363 /*
364 * Adjust logic_sb_block.
365 * Godmar thinks: if the blocksize is greater than 1024, then
366 * the superblock is logically part of block zero.
367 */
435 if(fs->s_blocksize > SBSIZE)
368 if(fs->e2fs_bsize > SBSIZE)
436 logic_sb_block = 0;
369 logic_sb_block = 0;
437
438 for (i = 0; i < db_count; i++) {
370 for (i = 0; i < db_count; i++) {
439 error = bread(devvp , fsbtodb(fs, logic_sb_block + i + 1),
440 fs->s_blocksize, NOCRED, &fs->s_group_desc[i]);
441 if(error) {
442 for (j = 0; j < i; j++)
443 brelse(fs->s_group_desc[j]);
444 free(fs->s_group_desc, M_EXT2MNT);
445 printf("EXT2-fs: unable to read group descriptors"
446 " (%d)\n", error);
447 return (EIO);
371 error = bread(devvp ,
372 fsbtodb(fs, logic_sb_block + i + 1 ),
373 fs->e2fs_bsize, NOCRED, &bp);
374 if (error) {
375 free(fs->e2fs_gd, M_EXT2MNT);
376 brelse(bp);
377 return (error);
448 }
378 }
449 LCK_BUF(fs->s_group_desc[i])
379 e2fs_cgload((struct ext2_gd *)bp->b_data,
380 &fs->e2fs_gd[
381 i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
382 fs->e2fs_bsize);
383 brelse(bp);
384 bp = NULL;
450 }
385 }
451 if(!ext2_check_descriptors(fs)) {
452 for (j = 0; j < db_count; j++)
453 ULCK_BUF(fs->s_group_desc[j])
454 free(fs->s_group_desc, M_EXT2MNT);
455 printf("EXT2-fs: (ext2_check_descriptors failure) "
456 "unable to read group descriptors\n");
457 return (EIO);
386 fs->e2fs_total_dir = 0;
387 for (i=0; i < fs->e2fs_gcount; i++){
388 fs->e2fs_total_dir += fs->e2fs_gd[i].ext2bgd_ndirs;
389 fs->e2fs_contigdirs[i] = 0;
458 }
390 }
459 for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) {
460 fs->s_inode_bitmap_number[i] = 0;
461 fs->s_inode_bitmap[i] = NULL;
462 fs->s_block_bitmap_number[i] = 0;
463 fs->s_block_bitmap[i] = NULL;
464 }
465 fs->s_loaded_inode_bitmaps = 0;
466 fs->s_loaded_block_bitmaps = 0;
467 if (es->s_rev_level == EXT2_GOOD_OLD_REV ||
468 (es->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_LARGE_FILE) == 0)
469 fs->fs_maxfilesize = 0x7fffffff;
391 if (es->e2fs_rev == E2FS_REV0 ||
392 (es->e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE) == 0)
393 fs->e2fs_maxfilesize = 0x7fffffff;
470 else
394 else
471 fs->fs_maxfilesize = 0x7fffffffffffffff;
395 fs->e2fs_maxfilesize = 0x7fffffffffffffff;
472 return (0);
473}
474
475/*
476 * Reload all incore data for a filesystem (used after running fsck on
477 * the root filesystem and finding things to fix). The filesystem must
478 * be mounted read-only.
479 *
480 * Things to do to update the mount:
481 * 1) invalidate all cached meta-data.
482 * 2) re-read superblock from disk.
483 * 3) re-read summary information from disk.
484 * 4) invalidate all inactive vnodes.
485 * 5) invalidate all cached file data.
486 * 6) re-read inode data for all active vnodes.
396 return (0);
397}
398
399/*
400 * Reload all incore data for a filesystem (used after running fsck on
401 * the root filesystem and finding things to fix). The filesystem must
402 * be mounted read-only.
403 *
404 * Things to do to update the mount:
405 * 1) invalidate all cached meta-data.
406 * 2) re-read superblock from disk.
407 * 3) re-read summary information from disk.
408 * 4) invalidate all inactive vnodes.
409 * 5) invalidate all cached file data.
410 * 6) re-read inode data for all active vnodes.
411 * XXX we are missing some steps, in particular # 3, this has to be reviewed.
487 */
488static int
489ext2_reload(struct mount *mp, struct thread *td)
490{
491 struct vnode *vp, *mvp, *devvp;
492 struct inode *ip;
493 struct buf *bp;
412 */
413static int
414ext2_reload(struct mount *mp, struct thread *td)
415{
416 struct vnode *vp, *mvp, *devvp;
417 struct inode *ip;
418 struct buf *bp;
494 struct ext2_super_block *es;
495 struct ext2_sb_info *fs;
419 struct ext2fs *es;
420 struct m_ext2fs *fs;
496 int error;
497
498 if ((mp->mnt_flag & MNT_RDONLY) == 0)
499 return (EINVAL);
500 /*
501 * Step 1: invalidate all cached meta-data.
502 */
503 devvp = VFSTOEXT2(mp)->um_devvp;
504 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
505 if (vinvalbuf(devvp, 0, 0, 0) != 0)
506 panic("ext2_reload: dirty1");
507 VOP_UNLOCK(devvp, 0);
508
509 /*
510 * Step 2: re-read superblock from disk.
511 * constants have been adjusted for ext2
512 */
513 if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
514 return (error);
421 int error;
422
423 if ((mp->mnt_flag & MNT_RDONLY) == 0)
424 return (EINVAL);
425 /*
426 * Step 1: invalidate all cached meta-data.
427 */
428 devvp = VFSTOEXT2(mp)->um_devvp;
429 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
430 if (vinvalbuf(devvp, 0, 0, 0) != 0)
431 panic("ext2_reload: dirty1");
432 VOP_UNLOCK(devvp, 0);
433
434 /*
435 * Step 2: re-read superblock from disk.
436 * constants have been adjusted for ext2
437 */
438 if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
439 return (error);
515 es = (struct ext2_super_block *)bp->b_data;
440 es = (struct ext2fs *)bp->b_data;
516 if (ext2_check_sb_compat(es, devvp->v_rdev, 0) != 0) {
517 brelse(bp);
518 return (EIO); /* XXX needs translation */
519 }
520 fs = VFSTOEXT2(mp)->um_e2fs;
441 if (ext2_check_sb_compat(es, devvp->v_rdev, 0) != 0) {
442 brelse(bp);
443 return (EIO); /* XXX needs translation */
444 }
445 fs = VFSTOEXT2(mp)->um_e2fs;
521 bcopy(bp->b_data, fs->s_es, sizeof(struct ext2_super_block));
446 bcopy(bp->b_data, fs->e2fs, sizeof(struct ext2fs));
522
523 if((error = compute_sb_data(devvp, es, fs)) != 0) {
524 brelse(bp);
525 return (error);
526 }
527#ifdef UNKLAR
528 if (fs->fs_sbsize < SBSIZE)
529 bp->b_flags |= B_INVAL;

--- 19 unchanged lines hidden (view full) ---

549 if (vinvalbuf(vp, 0, 0, 0))
550 panic("ext2_reload: dirty2");
551
552 /*
553 * Step 5: re-read inode data for all active vnodes.
554 */
555 ip = VTOI(vp);
556 error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
447
448 if((error = compute_sb_data(devvp, es, fs)) != 0) {
449 brelse(bp);
450 return (error);
451 }
452#ifdef UNKLAR
453 if (fs->fs_sbsize < SBSIZE)
454 bp->b_flags |= B_INVAL;

--- 19 unchanged lines hidden (view full) ---

474 if (vinvalbuf(vp, 0, 0, 0))
475 panic("ext2_reload: dirty2");
476
477 /*
478 * Step 5: re-read inode data for all active vnodes.
479 */
480 ip = VTOI(vp);
481 error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
557 (int)fs->s_blocksize, NOCRED, &bp);
482 (int)fs->e2fs_bsize, NOCRED, &bp);
558 if (error) {
559 VOP_UNLOCK(vp, 0);
560 vrele(vp);
561 MNT_VNODE_FOREACH_ABORT(mp, mvp);
562 return (error);
563 }
483 if (error) {
484 VOP_UNLOCK(vp, 0);
485 vrele(vp);
486 MNT_VNODE_FOREACH_ABORT(mp, mvp);
487 return (error);
488 }
564 ext2_ei2i((struct ext2_inode *) ((char *)bp->b_data +
489 ext2_ei2i((struct ext2fs_dinode *) ((char *)bp->b_data +
565 EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number)), ip);
566 brelse(bp);
567 VOP_UNLOCK(vp, 0);
568 vrele(vp);
569 MNT_ILOCK(mp);
570 }
571 MNT_IUNLOCK(mp);
572 return (0);
573}
574
575/*
576 * Common code for mount and mountroot.
577 */
578static int
579ext2_mountfs(struct vnode *devvp, struct mount *mp)
580{
581 struct ext2mount *ump;
582 struct buf *bp;
490 EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number)), ip);
491 brelse(bp);
492 VOP_UNLOCK(vp, 0);
493 vrele(vp);
494 MNT_ILOCK(mp);
495 }
496 MNT_IUNLOCK(mp);
497 return (0);
498}
499
500/*
501 * Common code for mount and mountroot.
502 */
503static int
504ext2_mountfs(struct vnode *devvp, struct mount *mp)
505{
506 struct ext2mount *ump;
507 struct buf *bp;
583 struct ext2_sb_info *fs;
584 struct ext2_super_block *es;
508 struct m_ext2fs *fs;
509 struct ext2fs *es;
585 struct cdev *dev = devvp->v_rdev;
586 struct g_consumer *cp;
587 struct bufobj *bo;
588 int error;
589 int ronly;
590
591 ronly = vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0);
592 /* XXX: use VOP_ACESS to check FS perms */

--- 24 unchanged lines hidden (view full) ---

617 mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
618 if (mp->mnt_iosize_max > MAXPHYS)
619 mp->mnt_iosize_max = MAXPHYS;
620
621 bp = NULL;
622 ump = NULL;
623 if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
624 goto out;
510 struct cdev *dev = devvp->v_rdev;
511 struct g_consumer *cp;
512 struct bufobj *bo;
513 int error;
514 int ronly;
515
516 ronly = vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0);
517 /* XXX: use VOP_ACESS to check FS perms */

--- 24 unchanged lines hidden (view full) ---

542 mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
543 if (mp->mnt_iosize_max > MAXPHYS)
544 mp->mnt_iosize_max = MAXPHYS;
545
546 bp = NULL;
547 ump = NULL;
548 if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
549 goto out;
625 es = (struct ext2_super_block *)bp->b_data;
550 es = (struct ext2fs *)bp->b_data;
626 if (ext2_check_sb_compat(es, dev, ronly) != 0) {
627 error = EINVAL; /* XXX needs translation */
628 goto out;
629 }
551 if (ext2_check_sb_compat(es, dev, ronly) != 0) {
552 error = EINVAL; /* XXX needs translation */
553 goto out;
554 }
630 if ((es->s_state & EXT2_VALID_FS) == 0 ||
631 (es->s_state & EXT2_ERROR_FS)) {
555 if ((es->e2fs_state & E2FS_ISCLEAN) == 0 ||
556 (es->e2fs_state & E2FS_ERRORS)) {
632 if (ronly || (mp->mnt_flag & MNT_FORCE)) {
633 printf(
634"WARNING: Filesystem was not properly dismounted\n");
635 } else {
636 printf(
637"WARNING: R/W mount denied. Filesystem is not clean - run fsck\n");
638 error = EPERM;
639 goto out;
640 }
641 }
642 ump = malloc(sizeof *ump, M_EXT2MNT, M_WAITOK);
643 bzero((caddr_t)ump, sizeof *ump);
644
645 /*
646 * I don't know whether this is the right strategy. Note that
647 * we dynamically allocate both an ext2_sb_info and an ext2_super_block
648 * while Linux keeps the super block in a locked buffer.
649 */
557 if (ronly || (mp->mnt_flag & MNT_FORCE)) {
558 printf(
559"WARNING: Filesystem was not properly dismounted\n");
560 } else {
561 printf(
562"WARNING: R/W mount denied. Filesystem is not clean - run fsck\n");
563 error = EPERM;
564 goto out;
565 }
566 }
567 ump = malloc(sizeof *ump, M_EXT2MNT, M_WAITOK);
568 bzero((caddr_t)ump, sizeof *ump);
569
570 /*
571 * I don't know whether this is the right strategy. Note that
572 * we dynamically allocate both an ext2_sb_info and an ext2_super_block
573 * while Linux keeps the super block in a locked buffer.
574 */
650 ump->um_e2fs = malloc(sizeof(struct ext2_sb_info),
575 ump->um_e2fs = malloc(sizeof(struct m_ext2fs),
651 M_EXT2MNT, M_WAITOK);
576 M_EXT2MNT, M_WAITOK);
652 ump->um_e2fs->s_es = malloc(sizeof(struct ext2_super_block),
577 ump->um_e2fs->e2fs = malloc(sizeof(struct ext2fs),
653 M_EXT2MNT, M_WAITOK);
578 M_EXT2MNT, M_WAITOK);
654 bcopy(es, ump->um_e2fs->s_es, (u_int)sizeof(struct ext2_super_block));
655 if ((error = compute_sb_data(devvp, ump->um_e2fs->s_es, ump->um_e2fs)))
579 mtx_init(EXT2_MTX(ump), "EXT2FS", "EXT2FS Lock", MTX_DEF);
580 bcopy(es, ump->um_e2fs->e2fs, (u_int)sizeof(struct ext2fs));
581 if ((error = compute_sb_data(devvp, ump->um_e2fs->e2fs, ump->um_e2fs)))
656 goto out;
657
582 goto out;
583
658 /*
659 * We don't free the group descriptors allocated by compute_sb_data()
660 * until ext2_unmount(). This is OK since the mount will succeed.
661 */
662 brelse(bp);
663 bp = NULL;
664 fs = ump->um_e2fs;
584 brelse(bp);
585 bp = NULL;
586 fs = ump->um_e2fs;
665 fs->s_rd_only = ronly; /* ronly is set according to mnt_flags */
587 fs->e2fs_ronly = ronly; /* ronly is set according to mnt_flags */
666
667 /*
668 * If the fs is not mounted read-only, make sure the super block is
669 * always written back on a sync().
670 */
588
589 /*
590 * If the fs is not mounted read-only, make sure the super block is
591 * always written back on a sync().
592 */
671 fs->s_wasvalid = fs->s_es->s_state & EXT2_VALID_FS ? 1 : 0;
593 fs->e2fs_wasvalid = fs->e2fs->e2fs_state & E2FS_ISCLEAN ? 1 : 0;
672 if (ronly == 0) {
594 if (ronly == 0) {
673 fs->s_dirt = 1; /* mark it modified */
674 fs->s_es->s_state &= ~EXT2_VALID_FS; /* set fs invalid */
595 fs->e2fs_fmod = 1; /* mark it modified */
596 fs->e2fs->e2fs_state &= ~E2FS_ISCLEAN; /* set fs invalid */
675 }
676 mp->mnt_data = ump;
677 mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
678 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
679 mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN;
680 MNT_ILOCK(mp);
681 mp->mnt_flag |= MNT_LOCAL;
682 MNT_IUNLOCK(mp);
683 ump->um_mountp = mp;
684 ump->um_dev = dev;
685 ump->um_devvp = devvp;
686 ump->um_bo = &devvp->v_bufobj;
687 ump->um_cp = cp;
688
689 /*
690 * Setting those two parameters allowed us to use
691 * ufs_bmap w/o changse!
692 */
693 ump->um_nindir = EXT2_ADDR_PER_BLOCK(fs);
597 }
598 mp->mnt_data = ump;
599 mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
600 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
601 mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN;
602 MNT_ILOCK(mp);
603 mp->mnt_flag |= MNT_LOCAL;
604 MNT_IUNLOCK(mp);
605 ump->um_mountp = mp;
606 ump->um_dev = dev;
607 ump->um_devvp = devvp;
608 ump->um_bo = &devvp->v_bufobj;
609 ump->um_cp = cp;
610
611 /*
612 * Setting those two parameters allowed us to use
613 * ufs_bmap w/o changse!
614 */
615 ump->um_nindir = EXT2_ADDR_PER_BLOCK(fs);
694 ump->um_bptrtodb = fs->s_es->s_log_block_size + 1;
616 ump->um_bptrtodb = fs->e2fs->e2fs_log_bsize + 1;
695 ump->um_seqinc = EXT2_FRAGS_PER_BLOCK(fs);
696 if (ronly == 0)
697 ext2_sbupdate(ump, MNT_WAIT);
617 ump->um_seqinc = EXT2_FRAGS_PER_BLOCK(fs);
618 if (ronly == 0)
619 ext2_sbupdate(ump, MNT_WAIT);
620 /*
621 * Initialize filesystem stat information in mount struct.
622 */
623 MNT_ILOCK(mp);
624 mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED |
625 MNTK_EXTENDED_SHARED;
626 MNT_IUNLOCK(mp);
698 return (0);
699out:
700 if (bp)
701 brelse(bp);
702 if (cp != NULL) {
703 DROP_GIANT();
704 g_topology_lock();
705 g_vfs_close(cp);
706 g_topology_unlock();
707 PICKUP_GIANT();
708 }
709 if (ump) {
627 return (0);
628out:
629 if (bp)
630 brelse(bp);
631 if (cp != NULL) {
632 DROP_GIANT();
633 g_topology_lock();
634 g_vfs_close(cp);
635 g_topology_unlock();
636 PICKUP_GIANT();
637 }
638 if (ump) {
710 free(ump->um_e2fs->s_es, M_EXT2MNT);
639 mtx_destroy(EXT2_MTX(ump));
640 free(ump->um_e2fs->e2fs_gd, M_EXT2MNT);
641 free(ump->um_e2fs->e2fs_contigdirs, M_EXT2MNT);
642 free(ump->um_e2fs->e2fs, M_EXT2MNT);
711 free(ump->um_e2fs, M_EXT2MNT);
712 free(ump, M_EXT2MNT);
713 mp->mnt_data = NULL;
714 }
715 return (error);
716}
717
718/*
719 * Unmount system call.
720 */
721static int
722ext2_unmount(struct mount *mp, int mntflags)
723{
724 struct ext2mount *ump;
643 free(ump->um_e2fs, M_EXT2MNT);
644 free(ump, M_EXT2MNT);
645 mp->mnt_data = NULL;
646 }
647 return (error);
648}
649
650/*
651 * Unmount system call.
652 */
653static int
654ext2_unmount(struct mount *mp, int mntflags)
655{
656 struct ext2mount *ump;
725 struct ext2_sb_info *fs;
726 int error, flags, ronly, i;
657 struct m_ext2fs *fs;
658 int error, flags, ronly;
727
728 flags = 0;
729 if (mntflags & MNT_FORCE) {
730 if (mp->mnt_flag & MNT_ROOTFS)
731 return (EINVAL);
732 flags |= FORCECLOSE;
733 }
734 if ((error = ext2_flushfiles(mp, flags, curthread)) != 0)
735 return (error);
736 ump = VFSTOEXT2(mp);
737 fs = ump->um_e2fs;
659
660 flags = 0;
661 if (mntflags & MNT_FORCE) {
662 if (mp->mnt_flag & MNT_ROOTFS)
663 return (EINVAL);
664 flags |= FORCECLOSE;
665 }
666 if ((error = ext2_flushfiles(mp, flags, curthread)) != 0)
667 return (error);
668 ump = VFSTOEXT2(mp);
669 fs = ump->um_e2fs;
738 ronly = fs->s_rd_only;
739 if (ronly == 0) {
740 if (fs->s_wasvalid)
741 fs->s_es->s_state |= EXT2_VALID_FS;
742 ext2_sbupdate(ump, MNT_WAIT);
670 ronly = fs->e2fs_ronly;
671 if (ronly == 0 && ext2_cgupdate(ump, MNT_WAIT) == 0) {
672 if (fs->e2fs_wasvalid)
673 fs->e2fs->e2fs_state |= E2FS_ISCLEAN;
674 ext2_sbupdate(ump, MNT_WAIT);
743 }
744
675 }
676
745 /* release buffers containing group descriptors */
746 for(i = 0; i < fs->s_gdb_count; i++)
747 ULCK_BUF(fs->s_group_desc[i])
748 free(fs->s_group_desc, M_EXT2MNT);
749
750 /* release cached inode/block bitmaps */
751 for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
752 if (fs->s_inode_bitmap[i])
753 ULCK_BUF(fs->s_inode_bitmap[i])
754 for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
755 if (fs->s_block_bitmap[i])
756 ULCK_BUF(fs->s_block_bitmap[i])
757
758 DROP_GIANT();
759 g_topology_lock();
760 g_vfs_close(ump->um_cp);
761 g_topology_unlock();
762 PICKUP_GIANT();
763 vrele(ump->um_devvp);
677 DROP_GIANT();
678 g_topology_lock();
679 g_vfs_close(ump->um_cp);
680 g_topology_unlock();
681 PICKUP_GIANT();
682 vrele(ump->um_devvp);
764 free(fs->s_es, M_EXT2MNT);
683 free(fs->e2fs_gd, M_EXT2MNT);
684 free(fs->e2fs_contigdirs, M_EXT2MNT);
685 free(fs->e2fs, M_EXT2MNT);
765 free(fs, M_EXT2MNT);
766 free(ump, M_EXT2MNT);
767 mp->mnt_data = NULL;
768 MNT_ILOCK(mp);
769 mp->mnt_flag &= ~MNT_LOCAL;
770 MNT_IUNLOCK(mp);
771 return (error);
772}

--- 4 unchanged lines hidden (view full) ---

777static int
778ext2_flushfiles(struct mount *mp, int flags, struct thread *td)
779{
780 int error;
781
782 error = vflush(mp, 0, flags, td);
783 return (error);
784}
686 free(fs, M_EXT2MNT);
687 free(ump, M_EXT2MNT);
688 mp->mnt_data = NULL;
689 MNT_ILOCK(mp);
690 mp->mnt_flag &= ~MNT_LOCAL;
691 MNT_IUNLOCK(mp);
692 return (error);
693}

--- 4 unchanged lines hidden (view full) ---

698static int
699ext2_flushfiles(struct mount *mp, int flags, struct thread *td)
700{
701 int error;
702
703 error = vflush(mp, 0, flags, td);
704 return (error);
705}
785
786/*
787 * Get file system statistics.
706/*
707 * Get file system statistics.
788 * taken from ext2/super.c ext2_statfs.
789 */
708 */
790static int
709int
791ext2_statfs(struct mount *mp, struct statfs *sbp)
792{
793 struct ext2mount *ump;
710ext2_statfs(struct mount *mp, struct statfs *sbp)
711{
712 struct ext2mount *ump;
794 struct ext2_sb_info *fs;
795 struct ext2_super_block *es;
796 unsigned long overhead;
797 int i, nsb;
713 struct m_ext2fs *fs;
714 uint32_t overhead, overhead_per_group, ngdb;
715 int i, ngroups;
798
799 ump = VFSTOEXT2(mp);
800 fs = ump->um_e2fs;
716
717 ump = VFSTOEXT2(mp);
718 fs = ump->um_e2fs;
801 es = fs->s_es;
719 if (fs->e2fs->e2fs_magic != E2FS_MAGIC)
720 panic("ext2fs_statvfs");
802
721
803 if (es->s_magic != EXT2_SUPER_MAGIC)
804 panic("ext2_statfs - magic number spoiled");
805
806 /*
807 * Compute the overhead (FS structures)
808 */
722 /*
723 * Compute the overhead (FS structures)
724 */
809 if (es->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) {
810 nsb = 0;
811 for (i = 0 ; i < fs->s_groups_count; i++)
812 if (ext2_group_sparse(i))
813 nsb++;
814 } else
815 nsb = fs->s_groups_count;
816 overhead = es->s_first_data_block +
817 /* Superblocks and block group descriptors: */
818 nsb * (1 + fs->s_gdb_count) +
819 /* Inode bitmap, block bitmap, and inode table: */
820 fs->s_groups_count * (1 + 1 + fs->s_itb_per_group);
725 overhead_per_group =
726 1 /* block bitmap */ +
727 1 /* inode bitmap */ +
728 fs->e2fs_itpg;
729 overhead = fs->e2fs->e2fs_first_dblock +
730 fs->e2fs_gcount * overhead_per_group;
731 if (fs->e2fs->e2fs_rev > E2FS_REV0 &&
732 fs->e2fs->e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) {
733 for (i = 0, ngroups = 0; i < fs->e2fs_gcount; i++) {
734 if (cg_has_sb(i))
735 ngroups++;
736 }
737 } else {
738 ngroups = fs->e2fs_gcount;
739 }
740 ngdb = fs->e2fs_gdbcount;
741 if (fs->e2fs->e2fs_rev > E2FS_REV0 &&
742 fs->e2fs->e2fs_features_compat & EXT2F_COMPAT_RESIZE)
743 ngdb += fs->e2fs->e2fs_reserved_ngdb;
744 overhead += ngroups * (1 /* superblock */ + ngdb);
821
822 sbp->f_bsize = EXT2_FRAG_SIZE(fs);
823 sbp->f_iosize = EXT2_BLOCK_SIZE(fs);
745
746 sbp->f_bsize = EXT2_FRAG_SIZE(fs);
747 sbp->f_iosize = EXT2_BLOCK_SIZE(fs);
824 sbp->f_blocks = es->s_blocks_count - overhead;
825 sbp->f_bfree = es->s_free_blocks_count;
826 sbp->f_bavail = sbp->f_bfree - es->s_r_blocks_count;
827 sbp->f_files = es->s_inodes_count;
828 sbp->f_ffree = es->s_free_inodes_count;
748 sbp->f_blocks = fs->e2fs->e2fs_bcount - overhead;
749 sbp->f_bfree = fs->e2fs->e2fs_fbcount;
750 sbp->f_bavail = sbp->f_bfree - fs->e2fs->e2fs_rbcount;
751 sbp->f_files = fs->e2fs->e2fs_icount;
752 sbp->f_ffree = fs->e2fs->e2fs_ficount;
829 return (0);
830}
831
832/*
833 * Go through the disk queues to initiate sandbagged IO;
834 * go through the inodes to write those that have been modified;
835 * initiate the writing of the super block if it has been modified.
836 *
837 * Note: we are always called with the filesystem marked `MPBUSY'.
838 */
839static int
840ext2_sync(struct mount *mp, int waitfor)
841{
842 struct vnode *mvp, *vp;
843 struct thread *td;
844 struct inode *ip;
845 struct ext2mount *ump = VFSTOEXT2(mp);
753 return (0);
754}
755
756/*
757 * Go through the disk queues to initiate sandbagged IO;
758 * go through the inodes to write those that have been modified;
759 * initiate the writing of the super block if it has been modified.
760 *
761 * Note: we are always called with the filesystem marked `MPBUSY'.
762 */
763static int
764ext2_sync(struct mount *mp, int waitfor)
765{
766 struct vnode *mvp, *vp;
767 struct thread *td;
768 struct inode *ip;
769 struct ext2mount *ump = VFSTOEXT2(mp);
846 struct ext2_sb_info *fs;
770 struct m_ext2fs *fs;
847 int error, allerror = 0;
848
849 td = curthread;
850 fs = ump->um_e2fs;
771 int error, allerror = 0;
772
773 td = curthread;
774 fs = ump->um_e2fs;
851 if (fs->s_dirt != 0 && fs->s_rd_only != 0) { /* XXX */
852 printf("fs = %s\n", fs->fs_fsmnt);
775 if (fs->e2fs_fmod != 0 && fs->e2fs_ronly != 0) { /* XXX */
776 printf("fs = %s\n", fs->e2fs_fsmnt);
853 panic("ext2_sync: rofs mod");
854 }
855
856 /*
857 * Write back each (modified) inode.
858 */
859 MNT_ILOCK(mp);
860loop:

--- 38 unchanged lines hidden (view full) ---

899 if ((error = VOP_FSYNC(ump->um_devvp, waitfor, td)) != 0)
900 allerror = error;
901 VOP_UNLOCK(ump->um_devvp, 0);
902 }
903
904 /*
905 * Write back modified superblock.
906 */
777 panic("ext2_sync: rofs mod");
778 }
779
780 /*
781 * Write back each (modified) inode.
782 */
783 MNT_ILOCK(mp);
784loop:

--- 38 unchanged lines hidden (view full) ---

823 if ((error = VOP_FSYNC(ump->um_devvp, waitfor, td)) != 0)
824 allerror = error;
825 VOP_UNLOCK(ump->um_devvp, 0);
826 }
827
828 /*
829 * Write back modified superblock.
830 */
907 if (fs->s_dirt != 0) {
908 fs->s_dirt = 0;
909 fs->s_es->s_wtime = time_second;
910 if ((error = ext2_sbupdate(ump, waitfor)) != 0)
831 if (fs->e2fs_fmod != 0) {
832 fs->e2fs_fmod = 0;
833 fs->e2fs->e2fs_wtime = time_second;
834 if ((error = ext2_cgupdate(ump, waitfor)) != 0)
911 allerror = error;
912 }
913 return (allerror);
914}
915
916/*
917 * Look up an EXT2FS dinode number to find its incore vnode, otherwise read it
918 * in from disk. If it is in core, wait for the lock bit to clear, then
919 * return the inode locked. Detection and handling of mount points must be
920 * done by the calling routine.
921 */
922static int
923ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
924{
835 allerror = error;
836 }
837 return (allerror);
838}
839
840/*
841 * Look up an EXT2FS dinode number to find its incore vnode, otherwise read it
842 * in from disk. If it is in core, wait for the lock bit to clear, then
843 * return the inode locked. Detection and handling of mount points must be
844 * done by the calling routine.
845 */
846static int
847ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
848{
925 struct ext2_sb_info *fs;
849 struct m_ext2fs *fs;
926 struct inode *ip;
927 struct ext2mount *ump;
928 struct buf *bp;
929 struct vnode *vp;
930 struct cdev *dev;
931 struct thread *td;
932 int i, error;
933 int used_blocks;

--- 19 unchanged lines hidden (view full) ---

953 if ((error = getnewvnode("ext2fs", mp, &ext2_vnodeops, &vp)) != 0) {
954 *vpp = NULL;
955 free(ip, M_EXT2NODE);
956 return (error);
957 }
958 vp->v_data = ip;
959 ip->i_vnode = vp;
960 ip->i_e2fs = fs = ump->um_e2fs;
850 struct inode *ip;
851 struct ext2mount *ump;
852 struct buf *bp;
853 struct vnode *vp;
854 struct cdev *dev;
855 struct thread *td;
856 int i, error;
857 int used_blocks;

--- 19 unchanged lines hidden (view full) ---

877 if ((error = getnewvnode("ext2fs", mp, &ext2_vnodeops, &vp)) != 0) {
878 *vpp = NULL;
879 free(ip, M_EXT2NODE);
880 return (error);
881 }
882 vp->v_data = ip;
883 ip->i_vnode = vp;
884 ip->i_e2fs = fs = ump->um_e2fs;
885 ip->i_ump = ump;
961 ip->i_number = ino;
962
963 lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL);
964 error = insmntque(vp, mp);
965 if (error != 0) {
966 free(ip, M_EXT2NODE);
967 *vpp = NULL;
968 return (error);
969 }
970 error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL);
971 if (error || *vpp != NULL)
972 return (error);
973
974 /* Read in the disk contents for the inode, copy into the inode. */
975 if ((error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
886 ip->i_number = ino;
887
888 lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL);
889 error = insmntque(vp, mp);
890 if (error != 0) {
891 free(ip, M_EXT2NODE);
892 *vpp = NULL;
893 return (error);
894 }
895 error = vfs_hash_insert(vp, ino, flags, td, vpp, NULL, NULL);
896 if (error || *vpp != NULL)
897 return (error);
898
899 /* Read in the disk contents for the inode, copy into the inode. */
900 if ((error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
976 (int)fs->s_blocksize, NOCRED, &bp)) != 0) {
901 (int)fs->e2fs_bsize, NOCRED, &bp)) != 0) {
977 /*
978 * The inode does not contain anything useful, so it would
979 * be misleading to leave it on its hash chain. With mode
980 * still zero, it will be unlinked and returned to the free
981 * list by vput().
982 */
902 /*
903 * The inode does not contain anything useful, so it would
904 * be misleading to leave it on its hash chain. With mode
905 * still zero, it will be unlinked and returned to the free
906 * list by vput().
907 */
983 vput(vp);
984 brelse(bp);
908 brelse(bp);
909 vput(vp);
985 *vpp = NULL;
986 return (error);
987 }
988 /* convert ext2 inode to dinode */
910 *vpp = NULL;
911 return (error);
912 }
913 /* convert ext2 inode to dinode */
989 ext2_ei2i((struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE(fs) *
914 ext2_ei2i((struct ext2fs_dinode *) ((char *)bp->b_data + EXT2_INODE_SIZE(fs) *
990 ino_to_fsbo(fs, ino)), ip);
991 ip->i_block_group = ino_to_cg(fs, ino);
992 ip->i_next_alloc_block = 0;
993 ip->i_next_alloc_goal = 0;
994 ip->i_prealloc_count = 0;
995 ip->i_prealloc_block = 0;
996
997 /*
998 * Now we want to make sure that block pointers for unused
999 * blocks are zeroed out - ext2_balloc depends on this
1000 * although for regular files and directories only
1001 */
1002 if(S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode)) {
915 ino_to_fsbo(fs, ino)), ip);
916 ip->i_block_group = ino_to_cg(fs, ino);
917 ip->i_next_alloc_block = 0;
918 ip->i_next_alloc_goal = 0;
919 ip->i_prealloc_count = 0;
920 ip->i_prealloc_block = 0;
921
922 /*
923 * Now we want to make sure that block pointers for unused
924 * blocks are zeroed out - ext2_balloc depends on this
925 * although for regular files and directories only
926 */
927 if(S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode)) {
1003 used_blocks = (ip->i_size+fs->s_blocksize-1) / fs->s_blocksize;
928 used_blocks = (ip->i_size+fs->e2fs_bsize-1) / fs->e2fs_bsize;
1004 for(i = used_blocks; i < EXT2_NDIR_BLOCKS; i++)
1005 ip->i_db[i] = 0;
1006 }
1007/*
1008 ext2_print_inode(ip);
1009*/
929 for(i = used_blocks; i < EXT2_NDIR_BLOCKS; i++)
930 ip->i_db[i] = 0;
931 }
932/*
933 ext2_print_inode(ip);
934*/
1010 brelse(bp);
935 bqrelse(bp);
1011
1012 /*
1013 * Initialize the vnode from the inode, check for aliases.
1014 * Note that the underlying vnode may have changed.
1015 */
1016 if ((error = ext2_vinit(mp, &ext2_fifoops, &vp)) != 0) {
1017 vput(vp);
1018 *vpp = NULL;

--- 29 unchanged lines hidden (view full) ---

1048 * those rights via. exflagsp and credanonp
1049 */
1050static int
1051ext2_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
1052{
1053 struct inode *ip;
1054 struct ufid *ufhp;
1055 struct vnode *nvp;
936
937 /*
938 * Initialize the vnode from the inode, check for aliases.
939 * Note that the underlying vnode may have changed.
940 */
941 if ((error = ext2_vinit(mp, &ext2_fifoops, &vp)) != 0) {
942 vput(vp);
943 *vpp = NULL;

--- 29 unchanged lines hidden (view full) ---

973 * those rights via. exflagsp and credanonp
974 */
975static int
976ext2_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
977{
978 struct inode *ip;
979 struct ufid *ufhp;
980 struct vnode *nvp;
1056 struct ext2_sb_info *fs;
981 struct m_ext2fs *fs;
1057 int error;
1058
1059 ufhp = (struct ufid *)fhp;
1060 fs = VFSTOEXT2(mp)->um_e2fs;
1061 if (ufhp->ufid_ino < ROOTINO ||
982 int error;
983
984 ufhp = (struct ufid *)fhp;
985 fs = VFSTOEXT2(mp)->um_e2fs;
986 if (ufhp->ufid_ino < ROOTINO ||
1062 ufhp->ufid_ino > fs->s_groups_count * fs->s_es->s_inodes_per_group)
987 ufhp->ufid_ino > fs->e2fs_gcount * fs->e2fs->e2fs_ipg)
1063 return (ESTALE);
1064
1065 error = VFS_VGET(mp, ufhp->ufid_ino, LK_EXCLUSIVE, &nvp);
1066 if (error) {
1067 *vpp = NULLVP;
1068 return (error);
1069 }
1070 ip = VTOI(nvp);

--- 9 unchanged lines hidden (view full) ---

1080}
1081
1082/*
1083 * Write a superblock and associated information back to disk.
1084 */
1085static int
1086ext2_sbupdate(struct ext2mount *mp, int waitfor)
1087{
988 return (ESTALE);
989
990 error = VFS_VGET(mp, ufhp->ufid_ino, LK_EXCLUSIVE, &nvp);
991 if (error) {
992 *vpp = NULLVP;
993 return (error);
994 }
995 ip = VTOI(nvp);

--- 9 unchanged lines hidden (view full) ---

1005}
1006
1007/*
1008 * Write a superblock and associated information back to disk.
1009 */
1010static int
1011ext2_sbupdate(struct ext2mount *mp, int waitfor)
1012{
1088 struct ext2_sb_info *fs = mp->um_e2fs;
1089 struct ext2_super_block *es = fs->s_es;
1013 struct m_ext2fs *fs = mp->um_e2fs;
1014 struct ext2fs *es = fs->e2fs;
1090 struct buf *bp;
1091 int error = 0;
1092
1093 bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0, 0);
1015 struct buf *bp;
1016 int error = 0;
1017
1018 bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0, 0);
1094 bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2_super_block));
1019 bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2fs));
1095 if (waitfor == MNT_WAIT)
1096 error = bwrite(bp);
1097 else
1098 bawrite(bp);
1099
1100 /*
1101 * The buffers for group descriptors, inode bitmaps and block bitmaps
1102 * are not busy at this point and are (hopefully) written by the
1103 * usual sync mechanism. No need to write them here.
1104 */
1105 return (error);
1106}
1020 if (waitfor == MNT_WAIT)
1021 error = bwrite(bp);
1022 else
1023 bawrite(bp);
1024
1025 /*
1026 * The buffers for group descriptors, inode bitmaps and block bitmaps
1027 * are not busy at this point and are (hopefully) written by the
1028 * usual sync mechanism. No need to write them here.
1029 */
1030 return (error);
1031}
1032int
1033ext2_cgupdate(struct ext2mount *mp, int waitfor)
1034{
1035 struct m_ext2fs *fs = mp->um_e2fs;
1036 struct buf *bp;
1037 int i, error = 0, allerror = 0;
1107
1038
1039 allerror = ext2_sbupdate(mp, waitfor);
1040 for (i = 0; i < fs->e2fs_gdbcount; i++) {
1041 bp = getblk(mp->um_devvp, fsbtodb(fs,
1042 fs->e2fs->e2fs_first_dblock +
1043 1 /* superblock */ + i), fs->e2fs_bsize, 0, 0, 0);
1044 e2fs_cgsave(&fs->e2fs_gd[
1045 i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
1046 (struct ext2_gd *)bp->b_data, fs->e2fs_bsize);
1047 if (waitfor == MNT_WAIT)
1048 error = bwrite(bp);
1049 else
1050 bawrite(bp);
1051 }
1052
1053 if (!allerror && error)
1054 allerror = error;
1055 return (allerror);
1056}
1108/*
1109 * Return the root of a filesystem.
1110 */
1111static int
1112ext2_root(struct mount *mp, int flags, struct vnode **vpp)
1113{
1114 struct vnode *nvp;
1115 int error;
1116
1117 error = VFS_VGET(mp, (ino_t)ROOTINO, LK_EXCLUSIVE, &nvp);
1118 if (error)
1119 return (error);
1120 *vpp = nvp;
1121 return (0);
1122}
1057/*
1058 * Return the root of a filesystem.
1059 */
1060static int
1061ext2_root(struct mount *mp, int flags, struct vnode **vpp)
1062{
1063 struct vnode *nvp;
1064 int error;
1065
1066 error = VFS_VGET(mp, (ino_t)ROOTINO, LK_EXCLUSIVE, &nvp);
1067 if (error)
1068 return (error);
1069 *vpp = nvp;
1070 return (0);
1071}