int swsusp_check(void) { int error; resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ); if (!IS_ERR(resume_bdev)) { set_blocksize(resume_bdev, PAGE_SIZE); memset(&swsusp_header, 0, sizeof(swsusp_header)); if ((error = bio_read_page(0, &swsusp_header))) return error; if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); /* Reset swap signature now */ error = bio_write_page(0, &swsusp_header); } else { return -EINVAL; } if (error) blkdev_put(resume_bdev); else pr_debug("swsusp: Signature found, resuming\n"); } else { error = PTR_ERR(resume_bdev); } if (error) pr_debug("swsusp: Error %d check for resume file\n", error); return error; }
/*===========================================================================* * fs_readsuper_o * *===========================================================================*/ PUBLIC int fs_readsuper_o() { /* This function reads the superblock of the partition, gets the root inode * and sends back the details of them. Note, that the FS process does not * know the index of the vmnt object which refers to it, whenever the pathname * lookup leaves a partition an ELEAVEMOUNT error is transferred back * so that the VFS knows that it has to find the vnode on which this FS * process' partition is mounted on. */ struct super_block *xp; struct inode *root_ip; int r = OK; phys_bytes ph; fs_dev = fs_m_in.REQ_DEV; /* Map the driver endpoint for this major */ driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = fs_m_in.REQ_DRIVER_E; boottime = fs_m_in.REQ_BOOTTIME; vfs_slink_storage = fs_m_in.REQ_SLINK_STORAGE; /* Fill in the super block. */ superblock.s_dev = fs_dev; /* read_super() needs to know which dev */ r = read_super(&superblock); /* Is it recognized as a Minix filesystem? */ if (r != OK) { superblock.s_dev = NO_DEV; return(r); } set_blocksize(superblock.s_block_size); /* Get the root inode of the mounted file system. */ root_ip = NIL_INODE; /* if 'r' not OK, make sure this is defined */ if (r == OK) { if ( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NIL_INODE) r = err_code; } if (root_ip != NIL_INODE && root_ip->i_mode == 0) { put_inode(root_ip); r = EINVAL; } if (r != OK) return r; superblock.s_rd_only = fs_m_in.REQ_READONLY; superblock.s_is_root = fs_m_in.REQ_ISROOT; /* Root inode properties */ fs_m_out.RES_INODE_NR = root_ip->i_num; fs_m_out.RES_MODE = root_ip->i_mode; fs_m_out.RES_FILE_SIZE = root_ip->i_size; /* Partition properties */ fs_m_out.RES_MAXSIZE = superblock.s_max_size; fs_m_out.RES_BLOCKSIZE = superblock.s_block_size; return r; }
void affs_put_super(struct super_block *sb) { int i; pr_debug("affs_put_super()\n"); lock_super(sb); for (i = 0; i < sb->u.affs_sb.s_bm_count; i++) affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh); ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = htonl(1); secs_to_datestamp(CURRENT_TIME,&ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered); affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5); mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1); if (sb->u.affs_sb.s_flags & SF_PREFIX) kfree(sb->u.affs_sb.s_prefix); kfree(sb->u.affs_sb.s_bitmap); affs_brelse(sb->u.affs_sb.s_root_bh); set_blocksize(sb->s_dev,BLOCK_SIZE); sb->s_dev = 0; unlock_super(sb); MOD_DEC_USE_COUNT; return; }
NDAS_SAL_API sal_file sal_file_open(const char * filename, int flags, int mode) { int linux_flags = 0; sal_file nfile; if (flags & SAL_FILE_FLAG_RO) linux_flags |= O_RDONLY; if (flags & SAL_FILE_FLAG_RW) linux_flags |= O_RDWR; if (flags & SAL_FILE_FLAG_DIRECT) { linux_flags |= O_DIRECT; #if 0 /* Envision test code */ int ret; linux_flags |= O_DIRECT; ret = set_blocksize(MKDEV(3,0), 512); /* envision emulator test */ if (ret !=0) { printk("Failed to set blocksize ret=%d\n", ret); } #endif } if(flags & SAL_FILE_FLAG_EXCL) linux_flags |= O_EXCL; nfile = (sal_file) filp_open(filename, linux_flags, mode); if (IS_ERR((void*)nfile)) { printk("SAL: Failed to open file %s\n", filename); return NULL; } return nfile; }
static void affs_put_super(struct super_block *sb) { int i; pr_debug("AFFS: put_super()\n"); for (i = 0; i < sb->u.affs_sb.s_bm_count; i++) affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh); if (!(sb->s_flags & MS_RDONLY)) { ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = be32_to_cpu(1); secs_to_datestamp(CURRENT_TIME, &ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered); affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5); mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1); } if (sb->u.affs_sb.s_prefix) kfree(sb->u.affs_sb.s_prefix); kfree(sb->u.affs_sb.s_bitmap); affs_brelse(sb->u.affs_sb.s_root_bh); /* * Restore the previous value of this device's blksize_size[][] */ set_blocksize(sb->s_dev, sb->u.affs_sb.s_blksize); MOD_DEC_USE_COUNT; return; }
void affs_put_super(struct super_block *sb) { int i; pr_debug("affs_put_super()\n"); lock_super(sb); for (i = 0; i < sb->u.affs_sb.s_bm_count; i++) affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh); if (!(sb->s_flags & MS_RDONLY)) { ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->bm_flag = htonl(1); secs_to_datestamp(CURRENT_TIME, &ROOT_END_S(sb->u.affs_sb.s_root_bh->b_data,sb)->disk_altered); affs_fix_checksum(sb->s_blocksize,sb->u.affs_sb.s_root_bh->b_data,5); mark_buffer_dirty(sb->u.affs_sb.s_root_bh,1); } if (sb->u.affs_sb.s_flags & SF_PREFIX) kfree(sb->u.affs_sb.s_prefix); kfree(sb->u.affs_sb.s_bitmap); affs_brelse(sb->u.affs_sb.s_root_bh); /* I'm not happy with this. It would be better to save the previous * value of this devices blksize_size[][] in the super block and * restore it here, but with the affs superblock being quite large * already ... */ set_blocksize(sb->s_dev,BLOCK_SIZE); sb->s_dev = 0; unlock_super(sb); MOD_DEC_USE_COUNT; return; }
/* * udf_set_blocksize * * PURPOSE * Set the block size to be used in all transfers. * * DESCRIPTION * To allow room for a DMA transfer, it is best to guess big when unsure. * This routine picks 2048 bytes as the blocksize when guessing. This * should be adequate until devices with larger block sizes become common. * * Note that the Linux kernel can currently only deal with blocksizes of * 512, 1024, 2048, 4096, and 8192 bytes. * * PRE-CONDITIONS * sb Pointer to _locked_ superblock. * * POST-CONDITIONS * sb->s_blocksize Blocksize. * sb->s_blocksize_bits log2 of blocksize. * <return> 0 Blocksize is valid. * <return> 1 Blocksize is invalid. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ static int udf_set_blocksize(struct super_block *sb, int bsize) { /* Use specified block size if specified */ if (bsize) sb->s_blocksize = bsize; if (get_hardsect_size(sb->s_dev) > sb->s_blocksize) sb->s_blocksize = get_hardsect_size(sb->s_dev); /* Block size must be an even multiple of 512 */ switch (sb->s_blocksize) { case 512: sb->s_blocksize_bits = 9; break; case 1024: sb->s_blocksize_bits = 10; break; case 2048: sb->s_blocksize_bits = 11; break; case 4096: sb->s_blocksize_bits = 12; break; case 8192: sb->s_blocksize_bits = 13; break; default: { udf_debug("Bad block size (%ld)\n", sb->s_blocksize); printk(KERN_ERR "udf: bad block size (%ld)\n", sb->s_blocksize); return 0; } } /* Set the block size */ set_blocksize(sb->s_dev, sb->s_blocksize); return sb->s_blocksize; }
static int read_super_block (struct super_block * s, int size) { struct buffer_head * bh; struct reiserfs_super_block * rs; int repeat ; repeat = 0 ; bh = bread (s->s_dev, (REISERFS_DISK_OFFSET_IN_BYTES / size), size); if (!bh) { printk("reiserfs_read_super: unable to read superblock on dev %s\n", kdevname(s->s_dev)); return 1; } rs = (struct reiserfs_super_block *)bh->b_data; if (strncmp (rs->s_magic, REISERFS_SUPER_MAGIC_STRING, strlen ( REISERFS_SUPER_MAGIC_STRING))) { brelse (bh); printk ("reiserfs_read_super: can't find a reiserfs filesystem on dev %s.\n", kdevname(s->s_dev)); return 1; } s->s_blocksize = le16_to_cpu (rs->s_blocksize); s->s_blocksize_bits = 0; while ((1 << s->s_blocksize_bits) != s->s_blocksize) s->s_blocksize_bits ++; if (size != rs->s_blocksize) { brelse (bh); set_blocksize (s->s_dev, s->s_blocksize); bh = reiserfs_bread (s->s_dev, (REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize), s->s_blocksize, &repeat); if (!bh) { printk("reiserfs_read_super: unable to read superblock on dev %s\n", kdevname(s->s_dev)); return 1; } rs = (struct reiserfs_super_block *)bh->b_data; if (strncmp (rs->s_magic, REISERFS_SUPER_MAGIC_STRING, strlen ( REISERFS_SUPER_MAGIC_STRING)) || le16_to_cpu (rs->s_blocksize) != s->s_blocksize) { brelse (bh); printk ("reiserfs_read_super: can't find a reiserfs filesystem on dev %s.\n", kdevname(s->s_dev)); return 1; } } /* must check to be sure we haven't pulled an old format super out of the ** old format's log. This is a kludge of a check, but it will work. ** If block we've just read in is inside the journal for that ** super, it can't be valid. */ if (bh->b_blocknr >= rs->s_journal_block && bh->b_blocknr < (rs->s_journal_block + JOURNAL_BLOCK_COUNT)) { brelse(bh) ; printk("super-459: reiserfs_read_super: super found at block %lu is within its own log. It must not be of this format type.\n", bh->b_blocknr) ; return 1 ; } SB_BUFFER_WITH_SB (s) = bh; SB_DISK_SUPER_BLOCK (s) = rs; s->s_op = &reiserfs_sops; return 0; }
int sb_set_blocksize(struct super_block *sb, int size) { int bits; if (set_blocksize(sb->s_dev, size) < 0) return 0; sb->s_blocksize = size; for (bits = 9, size >>= 9; size >>= 1; bits++) ; sb->s_blocksize_bits = bits; return sb->s_blocksize; }
static struct super_block * cramfs_read_super(struct super_block *sb, void *data, int silent) { int i; struct cramfs_super super; unsigned long root_offset; struct super_block * retval = NULL; set_blocksize(sb->s_dev, PAGE_CACHE_SIZE); sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; /* Invalidate the read buffers on mount: think disk change.. */ for (i = 0; i < READ_BUFFERS; i++) buffer_blocknr[i] = -1; /* Read the first block and get the superblock from it */ memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super)); /* Do sanity checks on the superblock */ if (super.magic != CRAMFS_MAGIC) { printk("wrong magic\n"); goto out; } if (memcmp(super.signature, CRAMFS_SIGNATURE, sizeof(super.signature))) { printk("wrong signature\n"); goto out; } if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) { printk("unsupported filesystem features\n"); goto out; } /* Check that the root inode is in a sane state */ if (!S_ISDIR(super.root.mode)) { printk("root is not a directory\n"); goto out; } root_offset = super.root.offset << 2; if (root_offset == 0) printk(KERN_INFO "cramfs: note: empty filesystem"); else if (root_offset != sizeof(struct cramfs_super)) { printk("bad root offset %lu\n", root_offset); goto out; } /* Set it all up.. */ sb->s_op = &cramfs_ops; sb->s_root = d_alloc_root(get_cramfs_inode(sb, &super.root)); retval = sb; out: return retval; }
/* support old disk layout */ static int read_old_super_block (struct super_block * s, int size) { struct buffer_head * bh; struct reiserfs_super_block * rs; int repeat ; printk("reiserfs_read_super: try to find super block in old location\n"); repeat = 0 ; /* there are only 4k-sized blocks in v3.5.10 */ if (size != REISERFS_OLD_BLOCKSIZE) set_blocksize(s->s_dev, REISERFS_OLD_BLOCKSIZE); bh = bread (s->s_dev, REISERFS_OLD_DISK_OFFSET_IN_BYTES / REISERFS_OLD_BLOCKSIZE, REISERFS_OLD_BLOCKSIZE); if (!bh) { printk("reiserfs_read_super: unable to read superblock on dev %s\n", kdevname(s->s_dev)); return 1; } rs = (struct reiserfs_super_block *)bh->b_data; if (strncmp (rs->s_magic, REISERFS_SUPER_MAGIC_STRING, strlen ( REISERFS_SUPER_MAGIC_STRING))) { /* pre-journaling version check */ if(!strncmp((char*)rs + REISERFS_SUPER_MAGIC_STRING_OFFSET_NJ, REISERFS_SUPER_MAGIC_STRING, strlen(REISERFS_SUPER_MAGIC_STRING))) { printk("reiserfs_read_super: a pre-journaling reiserfs filesystem isn't suitable there.\n"); brelse(bh); return 1; } brelse (bh); printk ("reiserfs_read_super: can't find a reiserfs filesystem on dev %s.\n", kdevname(s->s_dev)); return 1; } if(REISERFS_OLD_BLOCKSIZE != le16_to_cpu (rs->s_blocksize)) { printk("reiserfs_read_super: blocksize mismatch, super block corrupted\n"); brelse(bh); return 1; } s->s_blocksize = REISERFS_OLD_BLOCKSIZE; s->s_blocksize_bits = 0; while ((1 << s->s_blocksize_bits) != s->s_blocksize) s->s_blocksize_bits ++; SB_BUFFER_WITH_SB (s) = bh; SB_DISK_SUPER_BLOCK (s) = rs; s->s_op = &reiserfs_sops; return 0; }
/* * hfs_put_super() * * This is the put_super() entry in the super_operations structure for * HFS filesystems. The purpose is to release the resources * associated with the superblock sb. */ static void hfs_put_super(struct super_block *sb) { struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb; if (!(sb->s_flags & MS_RDONLY)) { hfs_mdb_commit(mdb, 0); sb->s_dirt = 0; } /* release the MDB's resources */ hfs_mdb_put(mdb, sb->s_flags & MS_RDONLY); /* restore default blocksize for the device */ set_blocksize(sb->s_dev, BLOCK_SIZE); }
void xfs_setsize_buftarg( xfs_buftarg_t *btp, unsigned int blocksize, unsigned int sectorsize) { btp->pbr_bsize = blocksize; btp->pbr_sshift = ffs(sectorsize) - 1; btp->pbr_smask = sectorsize - 1; if (set_blocksize(btp->pbr_bdev, sectorsize)) { printk(KERN_WARNING "XFS: Cannot set_blocksize to %u on device %s\n", sectorsize, XFS_BUFTARG_NAME(btp)); } }
int dnbd2_open(struct inode *inode, struct file *file) { dnbd2_device_t *dev = inode->i_bdev->bd_disk->private_data; if (down_interruptible(&dev->config_mutex)) return -EBUSY; /* FIXME: How do we put this add/start_device? */ if (set_blocksize(inode->i_bdev, DNBD2_BLOCK_SIZE)) { up(&dev->config_mutex); return -EBUSY; } atomic_inc(&dev->refcnt); up(&dev->config_mutex); return 0; }
static int nbd_size_set(struct nbd_device *nbd, struct block_device *bdev, int blocksize, int nr_blocks) { int ret; ret = set_blocksize(bdev, blocksize); if (ret) return ret; nbd->blksize = blocksize; nbd->bytesize = (loff_t)blocksize * (loff_t)nr_blocks; nbd_size_update(nbd, bdev); return 0; }
/* * Open/close code for raw IO. * * We just rewrite the i_mapping for the /dev/raw/rawN file descriptor to * point at the blockdev's address_space and set the file handle to use * O_DIRECT. * * Set the device's soft blocksize to the minimum possible. This gives the * finest possible alignment and has no adverse impact on performance. */ static int raw_open(struct inode *inode, struct file *filp) { const int minor = iminor(inode); struct block_device *bdev; int err; if (minor == 0) { /* It is the control device */ filp->f_op = &raw_ctl_fops; return 0; } down(&raw_mutex); /* * All we need to do on open is check that the device is bound. */ bdev = raw_devices[minor].binding; err = -ENODEV; if (!bdev) goto out; igrab(bdev->bd_inode); err = blkdev_get(bdev, filp->f_mode, 0); if (err) goto out; err = bd_claim(bdev, raw_open); if (err) goto out1; err = set_blocksize(bdev, bdev_hardsect_size(bdev)); if (err) goto out2; filp->f_flags |= O_DIRECT; filp->f_mapping = bdev->bd_inode->i_mapping; if (++raw_devices[minor].inuse == 1) filp->f_dentry->d_inode->i_mapping = bdev->bd_inode->i_mapping; filp->private_data = bdev; up(&raw_mutex); return 0; out2: bd_release(bdev); out1: blkdev_put(bdev); out: up(&raw_mutex); return err; }
static int read_suspend_image(const char * specialfile, int noresume) { union diskpage *cur; unsigned long scratch_page = 0; int error; char b[BDEVNAME_SIZE]; resume_device = name_to_dev_t(specialfile); scratch_page = get_zeroed_page(GFP_ATOMIC); cur = (void *) scratch_page; if (cur) { struct block_device *bdev; printk("Resuming from device %s\n", __bdevname(resume_device, b)); bdev = open_by_devnum(resume_device, FMODE_READ, BDEV_RAW); if (IS_ERR(bdev)) { error = PTR_ERR(bdev); } else { set_blocksize(bdev, PAGE_SIZE); error = __read_suspend_image(bdev, cur, noresume); blkdev_put(bdev, BDEV_RAW); } } else error = -ENOMEM; if (scratch_page) free_page(scratch_page); switch (error) { case 0: PRINTK("Reading resume file was successful\n"); break; case -EINVAL: break; case -EIO: printk( "%sI/O error\n", name_resume); break; case -ENOENT: printk( "%s%s: No such file or directory\n", name_resume, specialfile); break; case -ENOMEM: printk( "%sNot enough memory\n", name_resume); break; default: printk( "%sError %d resuming\n", name_resume, error ); } MDELAY(1000); return error; }
void set_fsblocksize(struct vnode *vp) { if (vp->v_type == VBLK) { dev_t dev = (dev_t)vp->v_rdev; int maj = major(dev); if ((u_int)maj >= (u_int)nblkdev) return; vnode_lock(vp); set_blocksize(vp, dev); vnode_unlock(vp); } }
static int swsusp_swap_check(void) /* This is called before saving image */ { int res; res = swap_type_of(swsusp_resume_device, swsusp_resume_block, &hib_resume_bdev); if (res < 0) return res; root_swap = res; res = blkdev_get(hib_resume_bdev, FMODE_WRITE); if (res) return res; res = set_blocksize(resume_bdev, PAGE_SIZE); if (res < 0) blkdev_put(hib_resume_bdev, FMODE_WRITE); return res; }
int swsusp_check(void) { int error; hib_resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ); if (!IS_ERR(hib_resume_bdev)) { set_blocksize(hib_resume_bdev, PAGE_SIZE); memset(swsusp_header, 0, PAGE_SIZE); error = hib_bio_read_page(swsusp_resume_block, swsusp_header, NULL); if (error) goto put; if (!memcmp(SWSUSP_SIG, swsusp_header->sig, 10)) { memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10); /* Reset swap signature now */ error = hib_bio_write_page(swsusp_resume_block, swsusp_header, NULL); } else { error = -EINVAL; } put: if (error) blkdev_put(hib_resume_bdev, FMODE_READ); else pr_debug("PM: Signature found, resuming\n"); } else { error = PTR_ERR(hib_resume_bdev); } if (error) pr_debug("PM: Error %d checking image file\n", error); return error; }
int __init pmdisk_read(void) { int error; if (!strlen(resume_file)) return -ENOENT; resume_device = name_to_dev_t(resume_file); pr_debug("pmdisk: Resume From Partition: %s\n", resume_file); resume_bdev = open_by_devnum(resume_device, FMODE_READ); if (!IS_ERR(resume_bdev)) { set_blocksize(resume_bdev, PAGE_SIZE); error = read_suspend_image(); blkdev_put(resume_bdev); } else error = PTR_ERR(resume_bdev); if (!error) pr_debug("Reading resume file was successful\n"); else pr_debug("pmdisk: Error %d resuming\n", error); return error; }
/* * Initialize a new device for device replace target from a given source dev * and path. * * Return 0 and new device in @device_out, otherwise return < 0 */ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info, const char *device_path, struct btrfs_device *srcdev, struct btrfs_device **device_out) { struct btrfs_device *device; struct block_device *bdev; struct list_head *devices; struct rcu_string *name; u64 devid = BTRFS_DEV_REPLACE_DEVID; int ret = 0; *device_out = NULL; if (fs_info->fs_devices->seeding) { btrfs_err(fs_info, "the filesystem is a seed filesystem!"); return -EINVAL; } bdev = blkdev_get_by_path(device_path, FMODE_WRITE | FMODE_EXCL, fs_info->bdev_holder); if (IS_ERR(bdev)) { btrfs_err(fs_info, "target device %s is invalid!", device_path); return PTR_ERR(bdev); } filemap_write_and_wait(bdev->bd_inode->i_mapping); devices = &fs_info->fs_devices->devices; list_for_each_entry(device, devices, dev_list) { if (device->bdev == bdev) { btrfs_err(fs_info, "target device is in the filesystem!"); ret = -EEXIST; goto error; } } if (i_size_read(bdev->bd_inode) < btrfs_device_get_total_bytes(srcdev)) { btrfs_err(fs_info, "target device is smaller than source device!"); ret = -EINVAL; goto error; } device = btrfs_alloc_device(NULL, &devid, NULL); if (IS_ERR(device)) { ret = PTR_ERR(device); goto error; } name = rcu_string_strdup(device_path, GFP_KERNEL); if (!name) { btrfs_free_device(device); ret = -ENOMEM; goto error; } rcu_assign_pointer(device->name, name); mutex_lock(&fs_info->fs_devices->device_list_mutex); set_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state); device->generation = 0; device->io_width = fs_info->sectorsize; device->io_align = fs_info->sectorsize; device->sector_size = fs_info->sectorsize; device->total_bytes = btrfs_device_get_total_bytes(srcdev); device->disk_total_bytes = btrfs_device_get_disk_total_bytes(srcdev); device->bytes_used = btrfs_device_get_bytes_used(srcdev); device->commit_total_bytes = srcdev->commit_total_bytes; device->commit_bytes_used = device->bytes_used; device->fs_info = fs_info; device->bdev = bdev; set_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state); set_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state); device->mode = FMODE_EXCL; device->dev_stats_valid = 1; set_blocksize(device->bdev, BTRFS_BDEV_BLOCKSIZE); device->fs_devices = fs_info->fs_devices; list_add(&device->dev_list, &fs_info->fs_devices->devices); fs_info->fs_devices->num_devices++; fs_info->fs_devices->open_devices++; mutex_unlock(&fs_info->fs_devices->device_list_mutex); *device_out = device; return 0; error: blkdev_put(bdev, FMODE_EXCL); return ret; }
struct super_block *hpfs_read_super(struct super_block *s, void *options, int silent) { struct hpfs_boot_block *bootblock; struct hpfs_super_block *superblock; struct hpfs_spare_block *spareblock; struct hpfs_dirent *de; struct buffer_head *bh0, *bh1, *bh2; struct quad_buffer_head qbh; dnode_secno root_dno; dev_t dev; uid_t uid; gid_t gid; umode_t umask; int lowercase; int conv; int dubious; /* * Get the mount options */ if (!parse_opts(options, &uid, &gid, &umask, &lowercase, &conv)) { printk("HPFS: syntax error in mount options. Not mounted.\n"); s->s_dev = 0; return 0; } /* * Fill in the super block struct */ lock_super(s); dev = s->s_dev; set_blocksize(dev, 512); /* * fetch sectors 0, 16, 17 */ bootblock = map_sector(dev, 0, &bh0); if (!bootblock) goto bail; superblock = map_sector(dev, 16, &bh1); if (!superblock) goto bail0; spareblock = map_sector(dev, 17, &bh2); if (!spareblock) goto bail1; /* * Check that this fs looks enough like a known one that we can find * and read the root directory. */ if (bootblock->magic != 0xaa55 || superblock->magic != SB_MAGIC || spareblock->magic != SP_MAGIC || bootblock->sig_28h != 0x28 || memcmp(&bootblock->sig_hpfs, "HPFS ", 8) || little_ushort(bootblock->bytes_per_sector) != 512) { printk("HPFS: hpfs_read_super: Not HPFS\n"); goto bail2; } /* * Check for inconsistencies -- possibly wrong guesses here, possibly * filesystem problems. */ dubious = 0; dubious |= check_warn(spareblock->dirty != 0, "`Improperly stopped'", "flag is set", "run CHKDSK"); dubious |= check_warn(spareblock->n_spares_used != 0, "Spare blocks", "may be in use", "run CHKDSK"); /* * Above errors mean we could get wrong answers if we proceed, * so don't */ if (dubious) goto bail2; dubious |= check_warn((spareblock->n_dnode_spares != spareblock->n_dnode_spares_free), "Spare dnodes", "may be in use", "run CHKDSK"); dubious |= check_warn(superblock->zero1 != 0, "#1", "unknown word nonzero", "investigate"); dubious |= check_warn(superblock->zero3 != 0, "#3", "unknown word nonzero", "investigate"); dubious |= check_warn(superblock->zero4 != 0, "#4", "unknown word nonzero", "investigate"); dubious |= check_warn(!zerop(superblock->zero5, sizeof superblock->zero5), "#5", "unknown word nonzero", "investigate"); dubious |= check_warn(!zerop(superblock->zero6, sizeof superblock->zero6), "#6", "unknown word nonzero", "investigate"); if (dubious) printk("HPFS: Proceeding, but operation may be unreliable\n"); /* * set fs read only */ s->s_flags |= MS_RDONLY; /* * fill in standard stuff */ s->s_magic = HPFS_SUPER_MAGIC; s->s_blocksize = 512; s->s_blocksize_bits = 9; s->s_op = (struct super_operations *) &hpfs_sops; /* * fill in hpfs stuff */ s->s_hpfs_root = dir_ino(superblock->root); s->s_hpfs_fs_size = superblock->n_sectors; s->s_hpfs_dirband_size = superblock->n_dir_band / 4; s->s_hpfs_dmap = superblock->dir_band_bitmap; s->s_hpfs_bitmaps = superblock->bitmaps; s->s_hpfs_uid = uid; s->s_hpfs_gid = gid; s->s_hpfs_mode = 0777 & ~umask; s->s_hpfs_n_free = -1; s->s_hpfs_n_free_dnodes = -1; s->s_hpfs_lowercase = lowercase; s->s_hpfs_conv = conv; /* * done with the low blocks */ brelse(bh2); brelse(bh1); brelse(bh0); /* * all set. try it out. */ s->s_mounted = iget(s, s->s_hpfs_root); unlock_super(s); if (!s->s_mounted) { printk("HPFS: hpfs_read_super: inode get failed\n"); s->s_dev = 0; return 0; } /* * find the root directory's . pointer & finish filling in the inode */ root_dno = fnode_dno(dev, s->s_hpfs_root); if (root_dno) de = map_dirent(s->s_mounted, root_dno, "\001\001", 2, &qbh); if (!root_dno || !de) { printk("HPFS: " "hpfs_read_super: root dir isn't in the root dir\n"); s->s_dev = 0; return 0; } s->s_mounted->i_atime = local_to_gmt(de->read_date); s->s_mounted->i_mtime = local_to_gmt(de->write_date); s->s_mounted->i_ctime = local_to_gmt(de->creation_date); brelse4(&qbh); return s; bail2: brelse(bh2); bail1: brelse(bh1); bail0: brelse(bh0); bail: s->s_dev = 0; unlock_super(s); return 0; }
/* Called to mount a filesystem by read_super() in fs/super.c * Return a super block, the main structure of a filesystem * * NOTE : Don't store a pointer to an option, as the page containing the * options is freed after ntfs_read_super() returns. * * NOTE : A context switch can happen in kernel code only if the code blocks * (= calls schedule() in kernel/sched.c). */ struct super_block * ntfs_read_super(struct super_block *sb, void *options, int silent) { ntfs_volume *vol; struct buffer_head *bh; int i; ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n"); #ifdef NTFS_IN_LINUX_KERNEL vol = NTFS_SB2VOL(sb); #else if(!(vol = ntfs_malloc(sizeof(ntfs_volume)))) goto ntfs_read_super_dec; NTFS_SB2VOL(sb)=vol; #endif if(!parse_options(vol,(char*)options)) goto ntfs_read_super_vol; #if 0 /* Set to read only, user option might reset it */ sb->s_flags |= MS_RDONLY; #endif /* Assume a 512 bytes block device for now */ set_blocksize(sb->s_dev, 512); /* Read the super block (boot block) */ if(!(bh=bread(sb->s_dev,0,512))) { ntfs_error("Reading super block failed\n"); goto ntfs_read_super_unl; } ntfs_debug(DEBUG_OTHER, "Done reading boot block\n"); /* Check for 'NTFS' magic number */ if(!IS_NTFS_VOLUME(bh->b_data)){ ntfs_debug(DEBUG_OTHER, "Not a NTFS volume\n"); brelse(bh); goto ntfs_read_super_unl; } ntfs_debug(DEBUG_OTHER, "Going to init volume\n"); ntfs_init_volume(vol,bh->b_data); ntfs_debug(DEBUG_OTHER, "MFT record at cluster 0x%X\n",vol->mft_cluster); brelse(bh); NTFS_SB(vol)=sb; ntfs_debug(DEBUG_OTHER, "Done to init volume\n"); /* Inform the kernel that a device block is a NTFS cluster */ sb->s_blocksize=vol->clustersize; for(i=sb->s_blocksize,sb->s_blocksize_bits=0;i != 1;i>>=1) sb->s_blocksize_bits++; set_blocksize(sb->s_dev,sb->s_blocksize); ntfs_debug(DEBUG_OTHER, "set_blocksize\n"); /* Allocate a MFT record (MFT record can be smaller than a cluster) */ if(!(vol->mft=ntfs_malloc(max(vol->mft_recordsize,vol->clustersize)))) goto ntfs_read_super_unl; /* Read at least the MFT record for $MFT */ for(i=0;i<max(vol->mft_clusters_per_record,1);i++){ if(!(bh=bread(sb->s_dev,vol->mft_cluster+i,vol->clustersize))) { ntfs_error("Could not read MFT record 0\n"); goto ntfs_read_super_mft; } ntfs_memcpy(vol->mft+i*vol->clustersize,bh->b_data,vol->clustersize); brelse(bh); ntfs_debug(DEBUG_OTHER, "Read cluster %x\n",vol->mft_cluster+i); } /* Check and fixup this MFT record */ if(!ntfs_check_mft_record(vol,vol->mft)){ ntfs_error("Invalid MFT record 0\n"); goto ntfs_read_super_mft; } /* Inform the kernel about which super operations are available */ sb->s_op = &ntfs_super_operations; sb->s_magic = NTFS_SUPER_MAGIC; ntfs_debug(DEBUG_OTHER, "Reading special files\n"); if(ntfs_load_special_files(vol)){ ntfs_error("Error loading special files\n"); goto ntfs_read_super_mft; } ntfs_debug(DEBUG_OTHER, "Getting RootDir\n"); /* Get the root directory */ if(!(sb->s_root=d_alloc_root(iget(sb,FILE_ROOT)))){ ntfs_error("Could not get root dir inode\n"); goto ntfs_read_super_mft; } ntfs_debug(DEBUG_OTHER, "read_super: done\n"); return sb; ntfs_read_super_mft: ntfs_free(vol->mft); ntfs_read_super_unl: ntfs_read_super_vol: #ifndef NTFS_IN_LINUX_KERNEL ntfs_free(vol); ntfs_read_super_dec: #endif ntfs_debug(DEBUG_OTHER, "read_super: done\n"); return NULL; }
struct super_block *sysv_read_super(struct super_block *sb,void *data, int silent) { struct buffer_head *bh; const char *found; kdev_t dev = sb->s_dev; struct inode *root_inode; unsigned long blocknr; if (1024 != sizeof (struct xenix_super_block)) panic("Xenix FS: bad super-block size"); if ((512 != sizeof (struct sysv4_super_block)) || (512 != sizeof (struct sysv2_super_block))) panic("SystemV FS: bad super-block size"); if (500 != sizeof (struct coh_super_block)) panic("Coherent FS: bad super-block size"); if (64 != sizeof (struct sysv_inode)) panic("sysv fs: bad i-node size"); MOD_INC_USE_COUNT; lock_super(sb); set_blocksize(dev,BLOCK_SIZE); sb->sv_block_base = 0; /* Try to read Xenix superblock */ if ((bh = bread(dev, 1, BLOCK_SIZE)) != NULL) { if ((found = detect_xenix(sb,bh)) != NULL) goto ok; brelse(bh); } if ((bh = bread(dev, 0, BLOCK_SIZE)) != NULL) { /* Try to recognize SystemV superblock */ if ((found = detect_sysv4(sb,bh)) != NULL) goto ok; if ((found = detect_sysv2(sb,bh)) != NULL) goto ok; /* Try to recognize Coherent superblock */ if ((found = detect_coherent(sb,bh)) != NULL) goto ok; brelse(bh); } /* Try to recognize SystemV superblock */ /* Offset by 1 track, i.e. most probably 9, 15, or 18 kilobytes. */ /* 2kB blocks with offset of 9 and 15 kilobytes are not supported. */ /* Maybe we should also check the device geometry ? */ { static int offsets[] = { 9, 15, 18, }; int i; for (i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++) if ((bh = bread(dev, offsets[i], BLOCK_SIZE)) != NULL) { /* Try to recognize SystemV superblock */ if ((found = detect_sysv4(sb,bh)) != NULL) { if (sb->sv_block_size>BLOCK_SIZE && (offsets[i] % 2)) goto bad_shift; sb->sv_block_base = (offsets[i] << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits; goto ok; } if ((found = detect_sysv2(sb,bh)) != NULL) { if (sb->sv_block_size>BLOCK_SIZE && (offsets[i] % 2)) goto bad_shift; sb->sv_block_base = (offsets[i] << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits; goto ok; } brelse(bh); } } bad_shift: sb->s_dev = 0; unlock_super(sb); if (!silent) printk("VFS: unable to read Xenix/SystemV/Coherent superblock on device " "%s\n", kdevname(dev)); failed: MOD_DEC_USE_COUNT; return NULL; ok: if (sb->sv_block_size >= BLOCK_SIZE) { if (sb->sv_block_size != BLOCK_SIZE) { brelse(bh); set_blocksize(dev, sb->sv_block_size); blocknr = (bh->b_blocknr << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits; if ((bh = bread(dev, blocknr, sb->sv_block_size)) == NULL) goto bad_superblock; } switch (sb->sv_type) { case FSTYPE_XENIX: if (!detected_xenix(sb,bh,bh)) goto bad_superblock; break; case FSTYPE_SYSV4: if (!detected_sysv4(sb,bh)) goto bad_superblock; break; case FSTYPE_SYSV2: if (!detected_sysv2(sb,bh)) goto bad_superblock; break; default: goto bad_superblock; goto superblock_ok; bad_superblock: brelse(bh); sb->s_dev = 0; unlock_super(sb); printk("SysV FS: cannot read superblock in %d byte mode\n", sb->sv_block_size); goto failed; superblock_ok: } } else {
/* Called to mount a filesystem by read_super() in fs/super.c. * Return a super block, the main structure of a filesystem. * * NOTE : Don't store a pointer to an option, as the page containing the * options is freed after ntfs_read_super() returns. * * NOTE : A context switch can happen in kernel code only if the code blocks * (= calls schedule() in kernel/sched.c). */ struct super_block *ntfs_read_super(struct super_block *sb, void *options, int silent) { ntfs_volume *vol; struct buffer_head *bh; int i, to_read, blocksize; ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n"); vol = NTFS_SB2VOL(sb); init_ntfs_super_block(vol); if (!parse_options(vol, (char*)options)) goto ntfs_read_super_vol; blocksize = get_hardsect_size(sb->s_dev); if (blocksize < 512) blocksize = 512; if (set_blocksize(sb->s_dev, blocksize) < 0) { ntfs_error("Unable to set blocksize %d.\n", blocksize); goto ntfs_read_super_vol; } sb->s_blocksize = blocksize; /* Read the super block (boot block). */ if (!(bh = sb_bread(sb, 0))) { ntfs_error("Reading super block failed\n"); goto ntfs_read_super_unl; } ntfs_debug(DEBUG_OTHER, "Done reading boot block\n"); /* Check for valid 'NTFS' boot sector. */ if (!is_boot_sector_ntfs(bh->b_data)) { ntfs_debug(DEBUG_OTHER, "Not a NTFS volume\n"); bforget(bh); goto ntfs_read_super_unl; } ntfs_debug(DEBUG_OTHER, "Going to init volume\n"); if (ntfs_init_volume(vol, bh->b_data) < 0) { ntfs_debug(DEBUG_OTHER, "Init volume failed.\n"); bforget(bh); goto ntfs_read_super_unl; } ntfs_debug(DEBUG_OTHER, "$Mft at cluster 0x%lx\n", vol->mft_lcn); brelse(bh); NTFS_SB(vol) = sb; if (vol->cluster_size > PAGE_SIZE) { ntfs_error("Partition cluster size is not supported yet (it " "is > max kernel blocksize).\n"); goto ntfs_read_super_unl; } ntfs_debug(DEBUG_OTHER, "Done to init volume\n"); /* Inform the kernel that a device block is a NTFS cluster. */ sb->s_blocksize = vol->cluster_size; sb->s_blocksize_bits = vol->cluster_size_bits; if (blocksize != vol->cluster_size && set_blocksize(sb->s_dev, sb->s_blocksize) < 0) { ntfs_error("Cluster size too small for device.\n"); goto ntfs_read_super_unl; } ntfs_debug(DEBUG_OTHER, "set_blocksize\n"); /* Allocate an MFT record (MFT record can be smaller than a cluster). */ i = vol->cluster_size; if (i < vol->mft_record_size) i = vol->mft_record_size; if (!(vol->mft = ntfs_malloc(i))) goto ntfs_read_super_unl; /* Read at least the MFT record for $Mft. */ to_read = vol->mft_clusters_per_record; if (to_read < 1) to_read = 1; for (i = 0; i < to_read; i++) { if (!(bh = sb_bread(sb, vol->mft_lcn + i))) { ntfs_error("Could not read $Mft record 0\n"); goto ntfs_read_super_mft; } ntfs_memcpy(vol->mft + ((__s64)i << vol->cluster_size_bits), bh->b_data, vol->cluster_size); brelse(bh); ntfs_debug(DEBUG_OTHER, "Read cluster 0x%x\n", vol->mft_lcn + i); } /* Check and fixup this MFT record */ if (!ntfs_check_mft_record(vol, vol->mft)){ ntfs_error("Invalid $Mft record 0\n"); goto ntfs_read_super_mft; } /* Inform the kernel about which super operations are available. */ sb->s_op = &ntfs_super_operations; sb->s_magic = NTFS_SUPER_MAGIC; sb->s_maxbytes = ~0ULL >> 1; ntfs_debug(DEBUG_OTHER, "Reading special files\n"); if (ntfs_load_special_files(vol)) { ntfs_error("Error loading special files\n"); goto ntfs_read_super_mft; } ntfs_debug(DEBUG_OTHER, "Getting RootDir\n"); /* Get the root directory. */ if (!(sb->s_root = d_alloc_root(iget(sb, FILE_root)))) { ntfs_error("Could not get root dir inode\n"); goto ntfs_read_super_mft; } ntfs_read_super_ret: ntfs_debug(DEBUG_OTHER, "read_super: done\n"); return sb; ntfs_read_super_mft: ntfs_free(vol->mft); ntfs_read_super_unl: ntfs_read_super_vol: sb = NULL; goto ntfs_read_super_ret; }
static struct super_block * cramfs_read_super(struct super_block *sb, void *data, int silent) { #ifndef CONFIG_CRAMFS_LINEAR int i; #else char *p; #endif struct cramfs_super super; unsigned long root_offset; struct super_block * retval = NULL; sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; #ifndef CONFIG_CRAMFS_LINEAR set_blocksize(sb->s_dev, PAGE_CACHE_SIZE); /* Invalidate the read buffers on mount: think disk change.. */ for (i = 0; i < READ_BUFFERS; i++) buffer_blocknr[i] = -1; #else /* * The physical location of the cramfs image is specified as * a mount parameter. This parameter is mandatory for obvious * reasons. Some validation is made on the phys address but this * is not exhaustive and we count on the fact that someone using * this feature is supposed to know what he/she's doing. */ if (!data || !(p = strstr((char *)data, "physaddr="))) { printk(KERN_ERR "cramfs: unknown physical address for linear cramfs image\n"); goto out; } sb->CRAMFS_SB_LINEAR_PHYS_ADDR = simple_strtoul(p + 9, NULL, 0); if (sb->CRAMFS_SB_LINEAR_PHYS_ADDR & (PAGE_SIZE-1)) { printk(KERN_ERR "cramfs: physical address 0x%lx for linear cramfs isn't aligned to a page boundary\n", sb->CRAMFS_SB_LINEAR_PHYS_ADDR); goto out; } if (sb->CRAMFS_SB_LINEAR_PHYS_ADDR == 0) { printk(KERN_ERR "cramfs: physical address for linear cramfs image can't be 0\n"); goto out; } printk(KERN_INFO "cramfs: checking physical address 0x%lx for linear cramfs image\n", sb->CRAMFS_SB_LINEAR_PHYS_ADDR); /* Map only one page for now. Will remap it when fs size is known. */ sb->CRAMFS_SB_LINEAR_VIRT_ADDR = ioremap(sb->CRAMFS_SB_LINEAR_PHYS_ADDR, PAGE_SIZE); if (!sb->CRAMFS_SB_LINEAR_VIRT_ADDR) { printk(KERN_ERR "cramfs: ioremap of the linear cramfs image failed\n"); goto out; } #endif down(&read_mutex); /* Read the first block and get the superblock from it */ memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super)); up(&read_mutex); /* Do sanity checks on the superblock */ if (super.magic != CRAMFS_MAGIC) { /* check at 512 byte offset */ memcpy(&super, cramfs_read(sb, 512, sizeof(super)), sizeof(super)); if (super.magic != CRAMFS_MAGIC) { printk(KERN_ERR "cramfs: wrong magic\n"); goto out; } } /* get feature flags first */ if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) { printk(KERN_ERR "cramfs: unsupported filesystem features\n"); goto out; } /* Check that the root inode is in a sane state */ if (!S_ISDIR(super.root.mode)) { printk(KERN_ERR "cramfs: root is not a directory\n"); goto out; } root_offset = super.root.offset << 2; if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) { sb->CRAMFS_SB_SIZE=super.size; sb->CRAMFS_SB_BLOCKS=super.fsid.blocks; sb->CRAMFS_SB_FILES=super.fsid.files; } else { sb->CRAMFS_SB_SIZE=1<<28; sb->CRAMFS_SB_BLOCKS=0; sb->CRAMFS_SB_FILES=0; } sb->CRAMFS_SB_MAGIC=super.magic; sb->CRAMFS_SB_FLAGS=super.flags; if (root_offset == 0) printk(KERN_INFO "cramfs: empty filesystem"); else if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && ((root_offset != sizeof(struct cramfs_super)) && (root_offset != 512 + sizeof(struct cramfs_super)))) { printk(KERN_ERR "cramfs: bad root offset %lu\n", root_offset); goto out; } /* Set it all up.. */ sb->s_op = &cramfs_ops; sb->s_root = d_alloc_root(get_cramfs_inode(sb, &super.root)); #ifdef CONFIG_CRAMFS_LINEAR /* Remap the whole filesystem now */ iounmap(sb->CRAMFS_SB_LINEAR_VIRT_ADDR); printk(KERN_INFO "cramfs: linear cramfs image appears to be %lu KB in size\n", sb->CRAMFS_SB_SIZE/1024); sb->CRAMFS_SB_LINEAR_VIRT_ADDR = ioremap(sb->CRAMFS_SB_LINEAR_PHYS_ADDR, sb->CRAMFS_SB_SIZE); if (!sb->CRAMFS_SB_LINEAR_VIRT_ADDR) { printk(KERN_ERR "cramfs: ioremap of the linear cramfs image failed\n"); goto out; } #endif retval = sb; out: #ifdef CONFIG_CRAMFS_LINEAR if (!retval && sb->CRAMFS_SB_LINEAR_VIRT_ADDR) iounmap(sb->CRAMFS_SB_LINEAR_VIRT_ADDR); #endif return retval; }
struct super_block * ext2_read_super (struct super_block * sb, void * data, int silent) { struct buffer_head * bh; struct ext2_sb_info * sbi = EXT2_SB(sb); struct ext2_super_block * es; unsigned long sb_block = 1; unsigned short resuid = EXT2_DEF_RESUID; unsigned short resgid = EXT2_DEF_RESGID; unsigned long block; unsigned long logic_sb_block; unsigned long offset = 0; kdev_t dev = sb->s_dev; int blocksize = BLOCK_SIZE; int db_count; int i, j; /* * See what the current blocksize for the device is, and * use that as the blocksize. Otherwise (or if the blocksize * is smaller than the default) use the default. * This is important for devices that have a hardware * sectorsize that is larger than the default. */ blocksize = get_hardsect_size(dev); if(blocksize < BLOCK_SIZE ) blocksize = BLOCK_SIZE; sb->u.ext2_sb.s_mount_opt = 0; if (!parse_options ((char *) data, &sb_block, &resuid, &resgid, &sb->u.ext2_sb.s_mount_opt)) { return NULL; } if (set_blocksize(dev, blocksize) < 0) { printk ("EXT2-fs: unable to set blocksize %d\n", blocksize); return NULL; } sb->s_blocksize = blocksize; /* * If the superblock doesn't start on a sector boundary, * calculate the offset. FIXME(eric) this doesn't make sense * that we would have to do this. */ if (blocksize != BLOCK_SIZE) { logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize; offset = (sb_block*BLOCK_SIZE) % blocksize; } else { logic_sb_block = sb_block; } if (!(bh = sb_bread(sb, logic_sb_block))) { printk ("EXT2-fs: unable to read superblock\n"); return NULL; } /* * Note: s_es must be initialized as soon as possible because * some ext2 macro-instructions depend on its value */ es = (struct ext2_super_block *) (((char *)bh->b_data) + offset); sb->u.ext2_sb.s_es = es; sb->s_magic = le16_to_cpu(es->s_magic); if (sb->s_magic != EXT2_SUPER_MAGIC) { if (!silent) printk ("VFS: Can't find ext2 filesystem on dev %s.\n", bdevname(dev)); goto failed_mount; } if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV && (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) || EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) || EXT2_HAS_INCOMPAT_FEATURE(sb, ~0U))) printk("EXT2-fs warning: feature flags set on rev 0 fs, " "running e2fsck is recommended\n"); /* * Check feature flags regardless of the revision level, since we * previously didn't change the revision level when setting the flags, * so there is a chance incompat flags are set on a rev 0 filesystem. */ if ((i = EXT2_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP))) { printk("EXT2-fs: %s: couldn't mount because of " "unsupported optional features (%x).\n", bdevname(dev), i); goto failed_mount; } if (!(sb->s_flags & MS_RDONLY) && (i = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){ printk("EXT2-fs: %s: couldn't mount RDWR because of " "unsupported optional features (%x).\n", bdevname(dev), i); goto failed_mount; } if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) ext2_warning(sb, __FUNCTION__, "mounting ext3 filesystem as ext2\n"); sb->s_blocksize_bits = le32_to_cpu(EXT2_SB(sb)->s_es->s_log_block_size) + 10; sb->s_blocksize = 1 << sb->s_blocksize_bits; sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits); /* If the blocksize doesn't match, re-read the thing.. */ if (sb->s_blocksize != blocksize) { blocksize = sb->s_blocksize; brelse(bh); if (set_blocksize(dev, blocksize) < 0) { printk(KERN_ERR "EXT2-fs: blocksize too small for device.\n"); return NULL; } logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize; offset = (sb_block*BLOCK_SIZE) % blocksize; bh = sb_bread(sb, logic_sb_block); if(!bh) { printk("EXT2-fs: Couldn't read superblock on " "2nd try.\n"); goto failed_mount; } es = (struct ext2_super_block *) (((char *)bh->b_data) + offset); sb->u.ext2_sb.s_es = es; if (es->s_magic != le16_to_cpu(EXT2_SUPER_MAGIC)) { printk ("EXT2-fs: Magic mismatch, very weird !\n"); goto failed_mount; } } if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) { sbi->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; sbi->s_first_ino = EXT2_GOOD_OLD_FIRST_INO; } else { sbi->s_inode_size = le16_to_cpu(es->s_inode_size); sbi->s_first_ino = le32_to_cpu(es->s_first_ino); if ((sbi->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE) || (sbi->s_inode_size & (sbi->s_inode_size - 1)) || (sbi->s_inode_size > blocksize)) { printk ("EXT2-fs: unsupported inode size: %d\n", sbi->s_inode_size); goto failed_mount; } } sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE << le32_to_cpu(es->s_log_frag_size); if (sb->u.ext2_sb.s_frag_size) sb->u.ext2_sb.s_frags_per_block = sb->s_blocksize / sb->u.ext2_sb.s_frag_size; else sb->s_magic = 0; sb->u.ext2_sb.s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group); sb->u.ext2_sb.s_frags_per_group = le32_to_cpu(es->s_frags_per_group); sb->u.ext2_sb.s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group); sb->u.ext2_sb.s_inodes_per_block = sb->s_blocksize / EXT2_INODE_SIZE(sb); sb->u.ext2_sb.s_itb_per_group = sb->u.ext2_sb.s_inodes_per_group / sb->u.ext2_sb.s_inodes_per_block; sb->u.ext2_sb.s_desc_per_block = sb->s_blocksize / sizeof (struct ext2_group_desc); sb->u.ext2_sb.s_sbh = bh; if (resuid != EXT2_DEF_RESUID) sb->u.ext2_sb.s_resuid = resuid; else sb->u.ext2_sb.s_resuid = le16_to_cpu(es->s_def_resuid); if (resgid != EXT2_DEF_RESGID) sb->u.ext2_sb.s_resgid = resgid; else sb->u.ext2_sb.s_resgid = le16_to_cpu(es->s_def_resgid); sb->u.ext2_sb.s_mount_state = le16_to_cpu(es->s_state); sb->u.ext2_sb.s_addr_per_block_bits = log2 (EXT2_ADDR_PER_BLOCK(sb)); sb->u.ext2_sb.s_desc_per_block_bits = log2 (EXT2_DESC_PER_BLOCK(sb)); if (sb->s_magic != EXT2_SUPER_MAGIC) { if (!silent) printk ("VFS: Can't find an ext2 filesystem on dev " "%s.\n", bdevname(dev)); goto failed_mount; } if (sb->s_blocksize != bh->b_size) { if (!silent) printk ("VFS: Unsupported blocksize on dev " "%s.\n", bdevname(dev)); goto failed_mount; } if (sb->s_blocksize != sb->u.ext2_sb.s_frag_size) { printk ("EXT2-fs: fragsize %lu != blocksize %lu (not supported yet)\n", sb->u.ext2_sb.s_frag_size, sb->s_blocksize); goto failed_mount; } if (sb->u.ext2_sb.s_blocks_per_group > sb->s_blocksize * 8) { printk ("EXT2-fs: #blocks per group too big: %lu\n", sb->u.ext2_sb.s_blocks_per_group); goto failed_mount; } if (sb->u.ext2_sb.s_frags_per_group > sb->s_blocksize * 8) { printk ("EXT2-fs: #fragments per group too big: %lu\n", sb->u.ext2_sb.s_frags_per_group); goto failed_mount; } if (sb->u.ext2_sb.s_inodes_per_group > sb->s_blocksize * 8) { printk ("EXT2-fs: #inodes per group too big: %lu\n", sb->u.ext2_sb.s_inodes_per_group); goto failed_mount; } sb->u.ext2_sb.s_groups_count = (le32_to_cpu(es->s_blocks_count) - le32_to_cpu(es->s_first_data_block) + EXT2_BLOCKS_PER_GROUP(sb) - 1) / EXT2_BLOCKS_PER_GROUP(sb); db_count = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) / EXT2_DESC_PER_BLOCK(sb); sb->u.ext2_sb.s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL); if (sb->u.ext2_sb.s_group_desc == NULL) { printk ("EXT2-fs: not enough memory\n"); goto failed_mount; } for (i = 0; i < db_count; i++) { block = descriptor_loc(sb, logic_sb_block, i); sbi->s_group_desc[i] = sb_bread(sb, block); if (!sbi->s_group_desc[i]) { for (j = 0; j < i; j++) brelse (sbi->s_group_desc[j]); kfree(sbi->s_group_desc); printk ("EXT2-fs: unable to read group descriptors\n"); goto failed_mount; } } if (!ext2_check_descriptors (sb)) { printk ("EXT2-fs: group descriptors corrupted!\n"); db_count = i; goto failed_mount2; } for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) { sb->u.ext2_sb.s_inode_bitmap_number[i] = 0; sb->u.ext2_sb.s_inode_bitmap[i] = NULL; sb->u.ext2_sb.s_block_bitmap_number[i] = 0; sb->u.ext2_sb.s_block_bitmap[i] = NULL; } sb->u.ext2_sb.s_loaded_inode_bitmaps = 0; sb->u.ext2_sb.s_loaded_block_bitmaps = 0; sb->u.ext2_sb.s_gdb_count = db_count; /* * set up enough so that it can read an inode */ sb->s_op = &ext2_sops; sb->s_root = d_alloc_root(iget(sb, EXT2_ROOT_INO)); if (!sb->s_root || !S_ISDIR(sb->s_root->d_inode->i_mode) || !sb->s_root->d_inode->i_blocks || !sb->s_root->d_inode->i_size) { if (sb->s_root) { dput(sb->s_root); sb->s_root = NULL; printk(KERN_ERR "EXT2-fs: corrupt root inode, run e2fsck\n"); } else printk(KERN_ERR "EXT2-fs: get root inode failed\n"); goto failed_mount2; } ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); return sb; failed_mount2: for (i = 0; i < db_count; i++) brelse(sb->u.ext2_sb.s_group_desc[i]); kfree(sb->u.ext2_sb.s_group_desc); failed_mount: brelse(bh); return NULL; }
/*===========================================================================* * fs_readsuper * *===========================================================================*/ PUBLIC int fs_readsuper() { /* This function reads the superblock of the partition, gets the root inode * and sends back the details of them. Note, that the FS process does not * know the index of the vmnt object which refers to it, whenever the pathname * lookup leaves a partition an ELEAVEMOUNT error is transferred back * so that the VFS knows that it has to find the vnode on which this FS * process' partition is mounted on. */ struct inode *root_ip; cp_grant_id_t label_gid; size_t label_len; int r = OK; int readonly, isroot; u32_t mask; fs_dev = fs_m_in.REQ_DEV; label_gid = fs_m_in.REQ_GRANT; label_len = fs_m_in.REQ_PATH_LEN; readonly = (fs_m_in.REQ_FLAGS & REQ_RDONLY) ? 1 : 0; isroot = (fs_m_in.REQ_FLAGS & REQ_ISROOT) ? 1 : 0; if (label_len > sizeof(fs_dev_label)) return(EINVAL); r = sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label, label_len, D); if (r != OK) { printf("%s:%d fs_readsuper: safecopyfrom failed: %d\n", __FILE__, __LINE__, r); return(EINVAL); } /* Map the driver label for this major. */ bdev_driver(fs_dev, fs_dev_label); /* Open the device the file system lives on. */ if (bdev_open(fs_dev, readonly ? R_BIT : (R_BIT|W_BIT)) != OK) { return(EINVAL); } /* Fill in the super block. */ STATICINIT(superblock, 1); if (!superblock) panic("Can't allocate memory for superblock."); superblock->s_dev = fs_dev; /* read_super() needs to know which dev */ r = read_super(superblock); /* Is it recognized as a Minix filesystem? */ if (r != OK) { superblock->s_dev = NO_DEV; bdev_close(fs_dev); return(r); } if (superblock->s_rev_level != EXT2_GOOD_OLD_REV) { struct super_block *sp = superblock; /* just shorter name */ mask = ~SUPPORTED_INCOMPAT_FEATURES; if (HAS_INCOMPAT_FEATURE(sp, mask)) { if (HAS_INCOMPAT_FEATURE(sp, INCOMPAT_COMPRESSION & mask)) printf("ext2: fs compression is not supported by server\n"); if (HAS_INCOMPAT_FEATURE(sp, INCOMPAT_FILETYPE & mask)) printf("ext2: fs in dir filetype is not supported by server\n"); if (HAS_INCOMPAT_FEATURE(sp, INCOMPAT_RECOVER & mask)) printf("ext2: fs recovery is not supported by server\n"); if (HAS_INCOMPAT_FEATURE(sp, INCOMPAT_JOURNAL_DEV & mask)) printf("ext2: fs journal dev is not supported by server\n"); if (HAS_INCOMPAT_FEATURE(sp, INCOMPAT_META_BG & mask)) printf("ext2: fs meta bg is not supported by server\n"); return(EINVAL); } mask = ~SUPPORTED_RO_COMPAT_FEATURES; if (HAS_RO_COMPAT_FEATURE(sp, mask)) { if (HAS_RO_COMPAT_FEATURE(sp, RO_COMPAT_SPARSE_SUPER & mask)) { printf("ext2: sparse super is not supported by server, \ remount read-only\n"); } if (HAS_RO_COMPAT_FEATURE(sp, RO_COMPAT_LARGE_FILE & mask)) { printf("ext2: large files are not supported by server, \ remount read-only\n"); } if (HAS_RO_COMPAT_FEATURE(sp, RO_COMPAT_BTREE_DIR & mask)) { printf("ext2: dir's btree is not supported by server, \ remount read-only\n"); } return(EINVAL); } } if (superblock->s_state == EXT2_ERROR_FS) { printf("ext2: filesystem wasn't cleanly unmounted previous time\n"); superblock->s_dev = NO_DEV; bdev_close(fs_dev); return(EINVAL); } set_blocksize(superblock->s_block_size, superblock->s_blocks_count, superblock->s_free_blocks_count, major(fs_dev)); /* Get the root inode of the mounted file system. */ if ( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NULL) { printf("ext2: couldn't get root inode\n"); superblock->s_dev = NO_DEV; bdev_close(fs_dev); return(EINVAL); } if (root_ip != NULL && root_ip->i_mode == 0) { printf("%s:%d zero mode for root inode?\n", __FILE__, __LINE__); put_inode(root_ip); superblock->s_dev = NO_DEV; bdev_close(fs_dev); return(EINVAL); } if (root_ip != NULL && (root_ip->i_mode & I_TYPE) != I_DIRECTORY) { printf("%s:%d root inode has wrong type, it's not a DIR\n", __FILE__, __LINE__); put_inode(root_ip); superblock->s_dev = NO_DEV; bdev_close(fs_dev); return(EINVAL); } superblock->s_rd_only = readonly; superblock->s_is_root = isroot; if (!readonly) { superblock->s_state = EXT2_ERROR_FS; superblock->s_mnt_count++; superblock->s_mtime = clock_time(); write_super(superblock); /* Commit info, we just set above */ } /* Root inode properties */ fs_m_out.RES_INODE_NR = root_ip->i_num; fs_m_out.RES_MODE = root_ip->i_mode; fs_m_out.RES_FILE_SIZE_LO = root_ip->i_size; fs_m_out.RES_UID = root_ip->i_uid; fs_m_out.RES_GID = root_ip->i_gid; fs_m_out.RES_CONREQS = 1; /* We can handle only 1 request at a time */ return(r); }
struct super_block *efs_read_super(struct super_block *s, void *d, int silent) { kdev_t dev = s->s_dev; struct efs_sb_info *sb; struct buffer_head *bh; sb = SUPER_INFO(s); s->s_magic = EFS_SUPER_MAGIC; s->s_blocksize = EFS_BLOCKSIZE; s->s_blocksize_bits = EFS_BLOCKSIZE_BITS; if( set_blocksize(dev, EFS_BLOCKSIZE) < 0) { printk(KERN_ERR "EFS: device does not support %d byte blocks\n", EFS_BLOCKSIZE); goto out_no_fs_ul; } /* read the vh (volume header) block */ bh = sb_bread(s, 0); if (!bh) { printk(KERN_ERR "EFS: cannot read volume header\n"); goto out_no_fs_ul; } /* * if this returns zero then we didn't find any partition table. * this isn't (yet) an error - just assume for the moment that * the device is valid and go on to search for a superblock. */ sb->fs_start = efs_validate_vh((struct volume_header *) bh->b_data); brelse(bh); if (sb->fs_start == -1) { goto out_no_fs_ul; } bh = sb_bread(s, sb->fs_start + EFS_SUPER); if (!bh) { printk(KERN_ERR "EFS: cannot read superblock\n"); goto out_no_fs_ul; } if (efs_validate_super(sb, (struct efs_super *) bh->b_data)) { #ifdef DEBUG printk(KERN_WARNING "EFS: invalid superblock at block %u\n", sb->fs_start + EFS_SUPER); #endif brelse(bh); goto out_no_fs_ul; } brelse(bh); if (!(s->s_flags & MS_RDONLY)) { #ifdef DEBUG printk(KERN_INFO "EFS: forcing read-only mode\n"); #endif s->s_flags |= MS_RDONLY; } s->s_op = &efs_superblock_operations; s->s_root = d_alloc_root(iget(s, EFS_ROOTINODE)); if (!(s->s_root)) { printk(KERN_ERR "EFS: get root inode failed\n"); goto out_no_fs; } return(s); out_no_fs_ul: out_no_fs: return(NULL); }