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} |