void iput(register struct inode *inode) { if (inode) { wait_on_inode(inode); if (!inode->i_count) { printk("VFS: iput: trying to free free inode\n"); printk("VFS: device %s, inode %lu, mode=0%07o\n", kdevname(inode->i_rdev), inode->i_ino, inode->i_mode); return; } #ifdef NOT_YET if (inode->i_pipe) wake_up_interruptible(&PIPE_WAIT(*inode)); #endif repeat: if (inode->i_count > 1) { inode->i_count--; return; } wake_up(&inode_wait); #ifdef NOT_YET if (inode->i_pipe) { /* Free up any memory allocated to the pipe */ } #endif if (inode->i_sb) { struct super_operations *sop = inode->i_sb->s_op; if (sop && sop->put_inode) { sop->put_inode(inode); if (!inode->i_nlink) return; } } if (inode->i_dirt) { write_inode(inode); /* we can sleep - so do again */ wait_on_inode(inode); goto repeat; } inode->i_count--; nr_free_inodes++; } return; }
/* return 1 if this is not super block */ static int print_super_block (struct buffer_head * bh) { struct reiserfs_super_block * rs = (struct reiserfs_super_block *)(bh->b_data); int skipped, data_blocks; char *version; if (strncmp (rs->s_magic, REISERFS_SUPER_MAGIC_STRING, strlen ( REISERFS_SUPER_MAGIC_STRING)) == 0) { version = "3.5"; } else if( strncmp (rs->s_magic, REISER2FS_SUPER_MAGIC_STRING, strlen ( REISER2FS_SUPER_MAGIC_STRING)) == 0) { version = "3.6"; } else { return 1; } printk ("%s\'s super block in block %ld\n======================\n", kdevname (bh->b_dev), bh->b_blocknr); printk ("Reiserfs version %s\n", version ); printk ("Block count %u\n", sb_block_count(rs)); printk ("Blocksize %d\n", sb_blocksize(rs)); printk ("Free blocks %u\n", sb_free_blocks(rs)); // FIXME: this would be confusing if // someone stores reiserfs super block in some data block ;) // skipped = (bh->b_blocknr * bh->b_size) / sb_blocksize(rs); skipped = bh->b_blocknr; data_blocks = sb_block_count(rs) - skipped - 1 - sb_bmap_nr(rs) - (sb_orig_journal_size(rs) + 1) - sb_free_blocks(rs); printk ("Busy blocks (skipped %d, bitmaps - %d, journal blocks - %d\n" "1 super blocks, %d data blocks\n", skipped, sb_bmap_nr(rs), (sb_orig_journal_size(rs) + 1), data_blocks); printk ("Root block %u\n", sb_root_block(rs)); printk ("Journal block (first) %d\n", sb_journal_block(rs)); printk ("Journal dev %d\n", sb_journal_dev(rs)); printk ("Journal orig size %d\n", sb_orig_journal_size(rs)); printk ("Filesystem state %s\n", (sb_state(rs) == REISERFS_VALID_FS) ? "VALID" : "ERROR"); printk ("Hash function \"%s\"\n", sb_hash_function_code(rs) == TEA_HASH ? "tea" : ( sb_hash_function_code(rs) == YURA_HASH ? "rupasov" : (sb_hash_function_code(rs) == R5_HASH ? "r5" : "unknown"))); printk ("Tree height %d\n", sb_tree_height(rs)); return 0; }
static struct super_block *read_super(kdev_t dev, char *name, int flags, char *data, int silent) { register struct super_block *s; register struct file_system_type *type; if (!dev) return NULL; #ifdef BLOAT_FS check_disk_change(dev); #endif s = get_super(dev); if (s) return s; #if CONFIG_FULL_VFS if (!(type = get_fs_type(name))) { printk("VFS: dev %s: get_fs_type(%s) failed\n", kdevname(dev), name); return NULL; } #else type = file_systems[0]; #endif for (s = super_blocks; s->s_dev; s++) { if (s >= super_blocks + NR_SUPER) return NULL; } s->s_dev = dev; s->s_flags = (unsigned short int) flags; if (!type->read_super(s, data, silent)) { s->s_dev = 0; return NULL; } s->s_dev = dev; s->s_covered = NULL; s->s_dirt = 0; s->s_type = type; #ifdef BLOAT_FS s->s_rd_only = 0; #endif return s; }
static int mcdx_media_changed(struct cdrom_device_info * cdi, int disc_nr) /* Return: 1 if media changed since last call to this function 0 otherwise */ { struct s_drive_stuff *stuffp; xinfo("mcdx_media_changed called for device %s\n", kdevname(cdi->dev)); stuffp = mcdx_stuffp[MINOR(cdi->dev)]; mcdx_getstatus(stuffp, 1); if (stuffp->yyy == 0) return 0; stuffp->yyy = 0; return 1; }
int sysv_unlink(struct inode * dir, struct dentry * dentry) { int retval; struct inode * inode; struct buffer_head * bh; struct sysv_dir_entry * de; repeat: retval = -ENOENT; inode = NULL; bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); if (!bh) goto end_unlink; inode = dentry->d_inode; retval = -EPERM; if (de->inode != inode->i_ino) { brelse(bh); current->counter = 0; schedule(); goto repeat; } if (de->inode != inode->i_ino) { retval = -ENOENT; goto end_unlink; } if (!inode->i_nlink) { printk("Deleting nonexistent file (%s:%lu), %d\n", kdevname(inode->i_dev), inode->i_ino, inode->i_nlink); inode->i_nlink=1; } de->inode = 0; mark_buffer_dirty(bh, 1); dir->i_ctime = dir->i_mtime = CURRENT_TIME; mark_inode_dirty(dir); inode->i_nlink--; inode->i_ctime = dir->i_ctime; mark_inode_dirty(inode); d_delete(dentry); retval = 0; end_unlink: brelse(bh); return retval; }
void invalidate_inodes(kdev_t dev) { register struct inode *inode, *next; int i; next = first_inode; for (i = nr_inodes; i > 0; i--) { inode = next; next = inode->i_next; /* clear_inode() changes the queues.. */ if (inode->i_dev != dev) continue; if (inode->i_count || inode->i_dirt || inode->i_lock) { printk("VFS: inode busy on removed device %s\n", kdevname(dev)); continue; } clear_inode(inode); } }
void put_super(kdev_t dev) { register struct super_block *sb; register struct super_operations *sop; if (dev == ROOT_DEV) { panic("put_super: root\n"); return; } if (!(sb = get_super(dev))) return; if (sb->s_covered) { printk("VFS: Mounted device %s - tssk, tssk\n", kdevname(dev)); return; } sop = sb->s_op; if (sop && sop->put_super) sop->put_super(sb); }
/* * Function: scsi_end_request() * * Purpose: Post-processing of completed commands called from interrupt * handler or a bottom-half handler. * * Arguments: SCpnt - command that is complete. * uptodate - 1 if I/O indicates success, 0 for I/O error. * sectors - number of sectors we want to mark. * requeue - indicates whether we should requeue leftovers. * frequeue - indicates that if we release the command block * that the queue request function should be called. * * Lock status: Assumed that lock is not held upon entry. * * Returns: Nothing * * Notes: This is called for block device requests in order to * mark some number of sectors as complete. * * We are guaranteeing that the request queue will be goosed * at some point during this call. */ static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors, int requeue, int frequeue) { request_queue_t *q = &SCpnt->device->request_queue; struct request *req; struct buffer_head *bh; unsigned long flags; int nsect; ASSERT_LOCK(&io_request_lock, 0); req = &SCpnt->request; req->errors = 0; if (!uptodate) { printk(" I/O error: dev %s, sector %lu\n", kdevname(req->rq_dev), req->sector); } do { if ((bh = req->bh) != NULL) { nsect = bh->b_size >> 9; blk_finished_io(nsect); blk_finished_sectors(req, nsect); req->bh = bh->b_reqnext; bh->b_reqnext = NULL; sectors -= nsect; bh->b_end_io(bh, uptodate); if ((bh = req->bh) != NULL) { req->hard_sector += nsect; req->hard_nr_sectors -= nsect; req->sector += nsect; req->nr_sectors -= nsect; req->current_nr_sectors = bh->b_size >> 9; req->hard_cur_sectors = req->current_nr_sectors; if (req->nr_sectors < req->current_nr_sectors) { req->nr_sectors = req->current_nr_sectors; printk("scsi_end_request: buffer-list destroyed\n"); } } }
void iput(register struct inode *inode) { register struct super_operations *sop; if (inode) { wait_on_inode(inode); if (!inode->i_count) { printk("VFS: iput: trying to free free inode\n"); printk("VFS: device %s, inode %lu, mode=0%07o\n", kdevname(inode->i_rdev), inode->i_ino, inode->i_mode); return; } #ifdef NOT_YET if ((inode->i_mode & S_IFMT) == S_IFIFO) wake_up_interruptible(&PIPE_WAIT(*inode)); #endif goto ini_loop; do { write_inode(inode); /* we can sleep - so do again */ wait_on_inode(inode); ini_loop: if (inode->i_count > 1) { inode->i_count--; return; } wake_up(&inode_wait); if (inode->i_sb) { sop = inode->i_sb->s_op; if (sop && sop->put_inode) { sop->put_inode(inode); if (!inode->i_nlink) return; } } } while (inode->i_dirt); inode->i_count--; nr_free_inodes++; } }
static struct super_block * read_super(kdev_t dev,const char *name,int flags, void *data, int silent) { struct super_block * s; struct file_system_type *type; if (!dev) goto out_null; check_disk_change(dev); s = get_super(dev); if (s) goto out; type = get_fs_type(name); if (!type) { printk("VFS: on device %s: get_fs_type(%s) failed\n", kdevname(dev), name); goto out; } s = get_empty_super(); if (!s) goto out; s->s_dev = dev; s->s_flags = flags; s->s_dirt = 0; sema_init(&s->s_vfs_rename_sem,1); /* N.B. Should lock superblock now ... */ if (!type->read_super(s, data, silent)) goto out_fail; s->s_dev = dev; /* N.B. why do this again?? */ s->s_rd_only = 0; s->s_type = type; out: return s; /* N.B. s_dev should be cleared in type->read_super */ out_fail: s->s_dev = 0; out_null: s = NULL; goto out; }
NORET_TYPE void ext2_panic (struct super_block * sb, const char * function, const char * fmt, ...) { va_list args; if (!(sb->s_flags & MS_RDONLY)) { sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS; sb->u.ext2_sb.s_es->s_state |= EXT2_ERROR_FS; mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); sb->s_dirt = 1; } va_start (args, fmt); vsprintf (error_buf, fmt, args); va_end (args); /* this is to prevent panic from syncing this filesystem */ if (sb->s_lock) sb->s_lock=0; sb->s_flags |= MS_RDONLY; panic ("EXT2-fs panic (device %s): %s: %s\n", kdevname(sb->s_dev), function, error_buf); }
/* * Swap partitions are now read via brw_page. ll_rw_page is an * asynchronous function now --- we must call wait_on_page afterwards * if synchronous IO is required. */ void ll_rw_page(int rw, kdev_t dev, unsigned long page, char * buffer) { int block = page; switch (rw) { case READ: break; case WRITE: if (is_read_only(dev)) { printk("Can't page to read-only device %s\n", kdevname(dev)); return; } break; default: panic("ll_rw_page: bad block dev cmd, must be R/W"); } if (set_bit(PG_locked, &mem_map[MAP_NR(buffer)].flags)) panic ("ll_rw_page: page already locked"); brw_page(rw, (unsigned long) buffer, dev, &block, PAGE_SIZE, 0); }
/* do_emergency_sync helper function */ static void go_sync(struct super_block *sb, int remount_flag) { int orig_loglevel; orig_loglevel = console_loglevel; console_loglevel = 7; printk(KERN_INFO "%sing device %s ... ", remount_flag ? "Remount" : "Sync", kdevname(sb->s_dev)); if (remount_flag) { /* Remount R/O */ int ret, flags; struct list_head *p; if (sb->s_flags & MS_RDONLY) { printk("R/O\n"); return; } file_list_lock(); for (p = sb->s_files.next; p != &sb->s_files; p = p->next) { struct file *file = list_entry(p, struct file, f_list); if (file->f_dentry && file_count(file) && S_ISREG(file->f_dentry->d_inode->i_mode)) file->f_mode &= ~2; } file_list_unlock(); DQUOT_OFF(sb); fsync_dev(sb->s_dev); flags = MS_RDONLY; if (sb->s_op && sb->s_op->remount_fs) { ret = sb->s_op->remount_fs(sb, &flags, NULL); if (ret) printk("error %d\n", ret); else { sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); printk("OK\n"); } } else printk("nothing to do\n"); } else { /* Sync only */
void ufs_panic (struct super_block * sb, const char * function, const char * fmt, ...) { struct ufs_sb_private_info * uspi; struct ufs_super_block_first * usb1; va_list args; uspi = sb->u.ufs_sb.s_uspi; usb1 = ubh_get_usb_first(USPI_UBH); if (!(sb->s_flags & MS_RDONLY)) { usb1->fs_clean = UFS_FSBAD; ubh_mark_buffer_dirty(USPI_UBH); sb->s_dirt = 1; } va_start (args, fmt); vsprintf (error_buf, fmt, args); va_end (args); sb->s_flags |= MS_RDONLY; printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n", kdevname(sb->s_dev), function, error_buf); }
static void go_sync(kdev_t dev, int remount_flag) { printk(KERN_INFO "%sing device %s ... ", remount_flag ? "Remount" : "Sync", kdevname(dev)); if (remount_flag) { /* Remount R/O */ struct super_block *sb = get_super(dev); struct vfsmount *vfsmnt; int ret, flags; if (!sb) { printk("Superblock not found\n"); return; } if (sb->s_flags & MS_RDONLY) { printk("R/O\n"); return; } DQUOT_OFF(dev); fsync_dev(dev); flags = MS_RDONLY; if (sb->s_op && sb->s_op->remount_fs) { ret = sb->s_op->remount_fs(sb, &flags, NULL); if (ret) printk("error %d\n", ret); else { sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); if ((vfsmnt = lookup_vfsmnt(sb->s_dev))) vfsmnt->mnt_flags = sb->s_flags; printk("OK\n"); } } else printk("nothing to do\n"); } else { fsync_dev(dev); /* Sync only */ printk("OK\n"); } }
static char *lock_get_status(struct file_lock *fl, char *p, int id, char *pfx) { struct wait_queue *wt; p += sprintf(p, "%d:%s ", id, pfx); if (fl->fl_flags & F_POSIX) { #ifdef CONFIG_LOCK_MANDATORY p += sprintf(p, "%s %s ", (fl->fl_flags & F_BROKEN) ? "BROKEN" : "POSIX ", ((fl->fl_file->f_inode->i_mode & (S_IXGRP | S_ISGID)) == S_ISGID) ? "MANDATORY" : "ADVISORY "); #else p += sprintf(p, "%s ADVISORY ", (fl->fl_flags & F_BROKEN) ? "BROKEN" : "POSIX "); #endif } else { p += sprintf(p, "FLOCK ADVISORY "); } p += sprintf(p, "%s ", (fl->fl_type == F_RDLCK) ? "READ " : "WRITE"); p += sprintf(p, "%d %s:%ld %ld %ld ", fl->fl_owner ? fl->fl_owner->pid : 0, kdevname(fl->fl_file->f_inode->i_dev), fl->fl_file->f_inode->i_ino, fl->fl_start, fl->fl_end); p += sprintf(p, "%08lx %08lx %08lx %08lx %08lx\n%d:%s", (long)fl, (long)fl->fl_prevlink, (long)fl->fl_nextlink, (long)fl->fl_next, (long)fl->fl_block, id, pfx); if ((wt = fl->fl_wait) != NULL) { do { p += sprintf(p, " %d", wt->task->pid); wt = wt->next; } while (wt != fl->fl_wait); } p += sprintf(p, "\n"); return (p); }
static struct super_block * read_super(kdev_t dev,const char *name,int flags, void *data, int silent) { struct super_block * s; struct file_system_type *type; if (!dev) return NULL; check_disk_change(dev); s = get_super(dev); if (s) return s; if (!(type = get_fs_type(name))) { printk("VFS: on device %s: get_fs_type(%s) failed\n", kdevname(dev), name); return NULL; } for (s = 0+super_blocks ;; s++) { if (s >= NR_SUPER+super_blocks) return NULL; if (!(s->s_dev)) break; } s->s_dev = dev; s->s_flags = flags; if (!type->read_super(s,data, silent)) { s->s_dev = 0; return NULL; } s->s_dev = dev; s->s_covered = NULL; s->s_rd_only = 0; s->s_dirt = 0; s->s_type = type; return s; }
/* * This routine checks whether a removable media has been changed, * and invalidates all buffer-cache-entries in that case. This * is a relatively slow routine, so we have to try to minimize using * it. Thus it is called only upon a 'mount' or 'open'. This * is the best way of combining speed and utility, I think. * People changing diskettes in the middle of an operation deserve * to lose :-) */ int check_disk_change(kdev_t dev) { register struct file_operations *fops; int i; i = MAJOR(dev); if (i >= MAX_BLKDEV || (fops = blkdevs[i].ds_fops) == NULL) return 0; if (fops->check_media_change == NULL) return 0; if (!fops->check_media_change(dev)) return 0; printk("VFS: Disk change detected on device %s\n", kdevname(dev)); for (i = 0; i < NR_SUPER; i++) if (super_blocks[i].s_dev == dev) put_super(super_blocks[i].s_dev); invalidate_inodes(dev); invalidate_buffers(dev); if (fops->revalidate) fops->revalidate(dev); return 1; }
/* This function is called when the file system is umounted. */ static void jffs_put_super(struct super_block *sb) { struct jffs_control *c = (struct jffs_control *) sb->u.generic_sbp; D1(kdev_t dev = sb->s_dev); D2(printk("jffs_put_super()\n")); #ifdef CONFIG_JFFS_PROC_FS jffs_unregister_jffs_proc_dir(c); #endif if (c->gc_task) { D1(printk (KERN_NOTICE "jffs_put_super(): Telling gc thread to die.\n")); send_sig(SIGKILL, c->gc_task, 1); } wait_for_completion(&c->gc_thread_comp); D1(printk (KERN_NOTICE "jffs_put_super(): Successfully waited on thread.\n")); jffs_cleanup_control((struct jffs_control *)sb->u.generic_sbp); D1(printk(KERN_NOTICE "JFFS: Successfully unmounted device %s.\n", kdevname(dev))); }
void nftl_request(RQFUNC_ARG) { unsigned int dev, block, nsect; struct NFTLrecord *nftl; char *buffer; struct request *req; int res; while (1) { INIT_REQUEST; /* blk.h */ req = CURRENT; /* We can do this because the generic code knows not to touch the request at the head of the queue */ spin_unlock_irq(&io_request_lock); DEBUG(MTD_DEBUG_LEVEL2, "NFTL_request\n"); DEBUG(MTD_DEBUG_LEVEL3, "NFTL %s request, from sector 0x%04lx for 0x%04lx sectors\n", (req->cmd == READ) ? "Read " : "Write", req->sector, req->current_nr_sectors); dev = MINOR(req->rq_dev); block = req->sector; nsect = req->current_nr_sectors; buffer = req->buffer; res = 1; /* succeed */ if (dev >= MAX_NFTLS * (1<<NFTL_PARTN_BITS)) { /* there is no such partition */ printk("nftl: bad minor number: device = %s\n", kdevname(req->rq_dev)); res = 0; /* fail */ goto repeat; } nftl = NFTLs[dev / (1<<NFTL_PARTN_BITS)]; DEBUG(MTD_DEBUG_LEVEL3, "Waiting for mutex\n"); down(&nftl->mutex); DEBUG(MTD_DEBUG_LEVEL3, "Got mutex\n"); if (block + nsect > part_table[dev].nr_sects) { /* access past the end of device */ printk("nftl%c%d: bad access: block = %d, count = %d\n", (MINOR(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect); up(&nftl->mutex); res = 0; /* fail */ goto repeat; } block += part_table[dev].start_sect; if (req->cmd == READ) { DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request of 0x%x sectors @ %x " "(req->nr_sectors == %lx)\n", nsect, block, req->nr_sectors); for ( ; nsect > 0; nsect-- , block++, buffer += 512) { /* Read a single sector to req->buffer + (512 * i) */ if (NFTL_readblock(nftl, block, buffer)) { DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request failed\n"); up(&nftl->mutex); res = 0; goto repeat; } } DEBUG(MTD_DEBUG_LEVEL2,"NFTL read request completed OK\n"); up(&nftl->mutex); goto repeat; } else if (req->cmd == WRITE) { DEBUG(MTD_DEBUG_LEVEL2, "NFTL write request of 0x%x sectors @ %x " "(req->nr_sectors == %lx)\n", nsect, block, req->nr_sectors); #ifdef CONFIG_NFTL_RW for ( ; nsect > 0; nsect-- , block++, buffer += 512) { /* Read a single sector to req->buffer + (512 * i) */ if (NFTL_writeblock(nftl, block, buffer)) { DEBUG(MTD_DEBUG_LEVEL1,"NFTL write request failed\n"); up(&nftl->mutex); res = 0; goto repeat; } } DEBUG(MTD_DEBUG_LEVEL2,"NFTL write request completed OK\n"); #else res = 0; /* Writes always fail */ #endif /* CONFIG_NFTL_RW */ up(&nftl->mutex); goto repeat; } else { DEBUG(MTD_DEBUG_LEVEL0, "NFTL unknown request\n"); up(&nftl->mutex); res = 0; goto repeat; } repeat: DEBUG(MTD_DEBUG_LEVEL3, "end_request(%d)\n", res); spin_lock_irq(&io_request_lock); end_request(res); }
int reiserfs_unlink (struct inode * dir, struct dentry *dentry) { int retval; struct inode * inode; struct reiserfs_dir_entry de; struct path path; int windex ; int call_journal_end = 1 ; struct reiserfs_transaction_handle th ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; init_path (&path); retval = -ENOENT; journal_begin(&th, dir->i_sb, jbegin_count) ; windex = push_journal_writer("reiserfs_unlink") ; /* free preserve list if we should */ /* maybe_free_preserve_list (dir->i_sb);*/ de.de_gen_number_bit_string = 0; if (reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path, &de) == POSITION_NOT_FOUND) { goto end_unlink; } inode = dentry->d_inode; reiserfs_update_inode_transaction(inode) ; reiserfs_update_inode_transaction(dir) ; retval = -EPERM; if (S_ISDIR (inode->i_mode)) { goto end_unlink; } if ((dir->i_mode & S_ISVTX) && !fsuser() && current->fsuid != inode->i_uid && current->fsuid != dir->i_uid) { goto end_unlink; } retval = -ENOENT; if (comp_short_keys ((struct key *)&(de.de_dir_id), INODE_PKEY (inode))) { goto end_unlink; } if (!inode->i_nlink) { printk("reiserfs_unlink: deleting nonexistent file (%s:%lu), %d\n", kdevname(inode->i_dev), inode->i_ino, inode->i_nlink); inode->i_nlink = 1; } if (reiserfs_cut_from_item (&th, dir, dir->i_sb, &path, &(de.de_entry_num), &(de.de_entry_key), 0, NOTHING_SPECIAL) == 0) { retval = -ENOENT; goto end_unlink; } inode->i_nlink--; inode->i_ctime = CURRENT_TIME; if_in_ram_update_sd (&th, inode); dir->i_size -= (de.de_entrylen + DEH_SIZE); dir->i_ctime = dir->i_mtime = CURRENT_TIME; if_in_ram_update_sd (&th, dir) ; pop_journal_writer(windex) ; journal_end(&th, dir->i_sb, jbegin_count) ; call_journal_end = 0 ; d_delete(dentry); retval = 0; end_unlink: pathrelse (&path); pop_journal_writer(windex) ; if (call_journal_end) journal_end(&th, dir->i_sb, jbegin_count) ; return retval; }
static void do_mount_root(void) { struct file_system_type * fs_type; struct super_block * sb; struct vfsmount *vfsmnt; struct inode * inode, d_inode; struct file filp; int retval; #ifdef CONFIG_ROOT_NFS if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) if (nfs_root_init(nfs_root_name, nfs_root_addrs) < 0) { printk(KERN_ERR "Root-NFS: Unable to contact NFS " "server for root fs, using /dev/fd0 instead\n"); ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0); } if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) { ROOT_DEV = 0; if ((fs_type = get_fs_type("nfs"))) { sb = &super_blocks[0]; while (sb->s_dev) sb++; sb->s_dev = get_unnamed_dev(); sb->s_flags = root_mountflags & ~MS_RDONLY; if (nfs_root_mount(sb) >= 0) { inode = sb->s_mounted; inode->i_count += 3 ; sb->s_covered = inode; sb->s_rd_only = 0; sb->s_dirt = 0; sb->s_type = fs_type; current->fs->pwd = inode; current->fs->root = inode; ROOT_DEV = sb->s_dev; printk (KERN_NOTICE "VFS: Mounted root (nfs filesystem).\n"); vfsmnt = add_vfsmnt(ROOT_DEV, "rootfs", "/"); if (!vfsmnt) panic("VFS: add_vfsmnt failed for NFS root.\n"); vfsmnt->mnt_sb = sb; vfsmnt->mnt_flags = sb->s_flags; return; } sb->s_dev = 0; } if (!ROOT_DEV) { printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n"); ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0); } } #endif #ifdef CONFIG_BLK_DEV_FD if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { floppy_eject(); printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n"); wait_for_keypress(); } #endif memset(&filp, 0, sizeof(filp)); memset(&d_inode, 0, sizeof(d_inode)); d_inode.i_rdev = ROOT_DEV; filp.f_inode = &d_inode; if ( root_mountflags & MS_RDONLY) filp.f_mode = 1; /* read only */ else filp.f_mode = 3; /* read write */ retval = blkdev_open(&d_inode, &filp); if (retval == -EROFS) { root_mountflags |= MS_RDONLY; filp.f_mode = 1; retval = blkdev_open(&d_inode, &filp); } if (retval) /* * Allow the user to distinguish between failed open * and bad superblock on root device. */ printk("VFS: Cannot open root device %s\n", kdevname(ROOT_DEV)); else for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) { if (!fs_type->requires_dev) continue; sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1); if (sb) { inode = sb->s_mounted; inode->i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */ sb->s_covered = inode; sb->s_flags = root_mountflags; current->fs->pwd = inode; current->fs->root = inode; printk ("VFS: Mounted root (%s filesystem)%s.\n", fs_type->name, (sb->s_flags & MS_RDONLY) ? " readonly" : ""); vfsmnt = add_vfsmnt(ROOT_DEV, "rootfs", "/"); if (!vfsmnt) panic("VFS: add_vfsmnt failed for root fs"); vfsmnt->mnt_sb = sb; vfsmnt->mnt_flags = root_mountflags; return; } } panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV)); }
int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_part_minor) { struct buffer_head *bh; int blk, blocks_in_map; int dev_bsize, dev_pos, pos; unsigned secsize; #ifdef CONFIG_PPC int found_root = 0; int found_root_goodness = 0; #endif struct mac_partition *part; struct mac_driver_desc *md; dev_bsize = get_ptable_blocksize(dev); dev_pos = 0; /* Get 0th block and look at the first partition map entry. */ if ((bh = bread(dev, 0, dev_bsize)) == 0) { printk("%s: error reading partition table\n", kdevname(dev)); return -1; } md = (struct mac_driver_desc *) bh->b_data; if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) { brelse(bh); return 0; } secsize = be16_to_cpu(md->block_size); if (secsize >= dev_bsize) { brelse(bh); dev_pos = secsize; if ((bh = bread(dev, secsize/dev_bsize, dev_bsize)) == 0) { printk("%s: error reading partition table\n", kdevname(dev)); return -1; } } part = (struct mac_partition *) (bh->b_data + secsize - dev_pos); if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) { brelse(bh); return 0; /* not a MacOS disk */ } blocks_in_map = be32_to_cpu(part->map_count); for (blk = 1; blk <= blocks_in_map; ++blk) { pos = blk * secsize; if (pos >= dev_pos + dev_bsize) { brelse(bh); dev_pos = pos; if ((bh = bread(dev, pos/dev_bsize, dev_bsize)) == 0) { printk("%s: error reading partition table\n", kdevname(dev)); return -1; } } part = (struct mac_partition *) (bh->b_data + pos - dev_pos); if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) break; blocks_in_map = be32_to_cpu(part->map_count); add_gd_partition(hd, first_part_minor, fsec + be32_to_cpu(part->start_block) * (secsize/512), be32_to_cpu(part->block_count) * (secsize/512), 0); #ifdef CONFIG_PPC /* * If this is the first bootable partition, tell the * setup code, in case it wants to make this the root. */ if (_machine == _MACH_Pmac) { int goodness = 0; if ((be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE) && strcasecmp(part->processor, "powerpc") == 0) goodness++; if (strcasecmp(part->type, "Apple_UNIX_SVR2") == 0) { goodness++; if ((strcmp(part->name, "/") == 0) || (strstr(part->name, "root") != 0)) { goodness++; } if (strncmp(part->name, "swap", 4) == 0) goodness--; } if (goodness > found_root_goodness) { found_root = blk; found_root_goodness = goodness; } } #endif /* CONFIG_PPC */ ++first_part_minor; } #ifdef CONFIG_PPC if (found_root_goodness) note_bootable_part(dev, found_root); #endif brelse(bh); printk("\n"); return 1; }
static int read_super_block (struct super_block * s, int size, int offset) { struct buffer_head * bh; struct reiserfs_super_block * rs; bh = bread (s->s_dev, offset / size, size); if (!bh) { printk ("read_super_block: " "bread failed (dev %s, block %d, size %d)\n", kdevname (s->s_dev), offset / size, size); return 1; } rs = (struct reiserfs_super_block *)bh->b_data; if (!is_reiserfs_magic_string (rs)) { printk ("read_super_block: " "can't find a reiserfs filesystem on (dev %s, block %lu, size %d)\n", kdevname(s->s_dev), bh->b_blocknr, size); brelse (bh); return 1; } // // ok, reiserfs signature (old or new) found in at the given offset // s->s_blocksize = sb_blocksize(rs); s->s_blocksize_bits = 0; while ((1 << s->s_blocksize_bits) != s->s_blocksize) s->s_blocksize_bits ++; brelse (bh); if (s->s_blocksize != size) set_blocksize (s->s_dev, s->s_blocksize); bh = reiserfs_bread (s, offset / s->s_blocksize, s->s_blocksize); if (!bh) { printk("read_super_block: " "bread failed (dev %s, block %d, size %d)\n", kdevname (s->s_dev), offset / size, size); return 1; } rs = (struct reiserfs_super_block *)bh->b_data; if (!is_reiserfs_magic_string (rs) || sb_blocksize(rs) != s->s_blocksize) { printk ("read_super_block: " "can't find a reiserfs filesystem on (dev %s, block %lu, size %d)\n", kdevname(s->s_dev), bh->b_blocknr, size); brelse (bh); printk ("read_super_block: 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 >= sb_journal_block(rs) && bh->b_blocknr < (sb_journal_block(rs) + JOURNAL_BLOCK_COUNT)) { brelse(bh) ; printk("super-459: read_super_block: " "super found at block %lu is within its own log. " "It must not be of this format type.\n", bh->b_blocknr) ; return 1 ; } if ( rs->s_root_block == -1 ) { brelse(bh) ; printk("dev %s: Unfinished reiserfsck --rebuild-tree run detected. Please run\n" "reiserfsck --rebuild-tree and wait for a completion. If that fails\n" "get newer reiserfsprogs package\n", kdevname (s->s_dev)); return 1; } SB_BUFFER_WITH_SB (s) = bh; SB_DISK_SUPER_BLOCK (s) = rs; s->s_op = &reiserfs_sops; /* new format is limited by the 32 bit wide i_blocks field, want to ** be one full block below that. */ s->s_maxbytes = (512LL << 32) - s->s_blocksize ; return 0; }
struct super_block * affs_read_super(struct super_block *s,void *data, int silent) { struct buffer_head *bh = NULL; struct buffer_head *bb; kdev_t dev = s->s_dev; int root_block; int size; __u32 chksum; __u32 *bm; int ptype, stype; int mapidx; int num_bm; int i, j; int key; int blocksize; uid_t uid; gid_t gid; int reserved; int az_no; unsigned long mount_flags; unsigned long offset; pr_debug("affs_read_super(%s)\n",data ? (const char *)data : "no options"); MOD_INC_USE_COUNT; if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, &blocksize,&s->u.affs_sb.s_prefix,s->u.affs_sb.s_volume,&mount_flags)) { s->s_dev = 0; printk("AFFS: error parsing options.\n"); MOD_DEC_USE_COUNT; return NULL; } lock_super(s); /* Get the size of the device in 512-byte blocks. * If we later see that the partition uses bigger * blocks, we will have to change it. */ size = blksize_size[MAJOR(dev)][MINOR(dev)]; size = (size ? size : BLOCK_SIZE) / 512 * blk_size[MAJOR(dev)][MINOR(dev)]; s->u.affs_sb.s_bitmap = NULL; s->u.affs_sb.s_root_bh = NULL; s->u.affs_sb.s_flags = mount_flags; s->u.affs_sb.s_mode = i; s->u.affs_sb.s_uid = uid; s->u.affs_sb.s_gid = gid; if (size == 0) { s->s_dev = 0; unlock_super(s); printk("affs_read_super: could not determine device size\n"); goto out; } s->u.affs_sb.s_partition_size = size; s->u.affs_sb.s_reserved = reserved; /* Try to find root block. Its location may depend on the block size. */ s->u.affs_sb.s_hashsize = 0; if (blocksize > 0) { i = blocksize; j = blocksize; } else { i = 512; j = 4096; } for (blocksize = i, key = 0; blocksize <= j; blocksize <<= 1, size >>= 1) { if (root_block < 0) s->u.affs_sb.s_root_block = (reserved + size - 1) / 2; else s->u.affs_sb.s_root_block = root_block; set_blocksize(dev,blocksize); /* The root block location that was calculated above is not * correct if the partition size is an odd number of 512- * byte blocks, which will be rounded down to a number of * 1024-byte blocks, and if there were an even number of * reserved blocks. Ideally, all partition checkers should * report the real number of blocks of the real blocksize, * but since this just cannot be done, we have to try to * find the root block anyways. In the above case, it is one * block behind the calculated one. So we check this one, too. */ for (num_bm = 0; num_bm < 2; num_bm++) { pr_debug("AFFS: Dev %s - trying bs=%d bytes, root at %d, " "size=%d blocks, %d reserved\n",kdevname(dev),blocksize, s->u.affs_sb.s_root_block + num_bm,size,reserved); bh = affs_bread(dev,s->u.affs_sb.s_root_block + num_bm,blocksize); if (!bh) { printk("AFFS: unable to read root block\n"); goto out; } if (!affs_checksum_block(blocksize,bh->b_data,&ptype,&stype) && ptype == T_SHORT && stype == ST_ROOT) { s->s_blocksize = blocksize; s->u.affs_sb.s_hashsize = blocksize / 4 - 56; s->u.affs_sb.s_root_block += num_bm; key = 1; break; } } if (key) break; affs_brelse(bh); bh = NULL; } if (!key) { affs_brelse(bh); if (!silent) printk("AFFS: Can't find a valid root block on device %s\n",kdevname(dev)); goto out; } root_block = s->u.affs_sb.s_root_block; s->u.affs_sb.s_partition_size = size; s->s_blocksize_bits = blocksize == 512 ? 9 : blocksize == 1024 ? 10 : blocksize == 2048 ? 11 : 12; /* Find out which kind of FS we have */ bb = affs_bread(dev,0,s->s_blocksize); if (bb) { chksum = htonl(*(__u32 *)bb->b_data); switch (chksum) { case MUFS_FS: case MUFS_INTLFFS: s->u.affs_sb.s_flags |= SF_MUFS; /* fall thru */ case FS_INTLFFS: s->u.affs_sb.s_flags |= SF_INTL; break; case MUFS_DCFFS: case MUFS_FFS: s->u.affs_sb.s_flags |= SF_MUFS; break; case FS_DCFFS: case FS_FFS: break; case MUFS_OFS: s->u.affs_sb.s_flags |= SF_MUFS; /* fall thru */ case FS_OFS: s->u.affs_sb.s_flags |= SF_OFS; break; case MUFS_DCOFS: if (!(s->s_flags & MS_RDONLY)) { printk("AFFS: Dircache FS - mounting %s read only.\n", kdevname(dev)); } /* fall thru */ case MUFS_INTLOFS: s->u.affs_sb.s_flags |= SF_MUFS; if (0) /* fall thru */ case FS_DCOFS: if (!(s->s_flags & MS_RDONLY)) { printk("AFFS: Dircache FS - mounting %s read only.\n", kdevname(dev)); } /* fall thru */ case FS_INTLOFS: s->u.affs_sb.s_flags |= SF_INTL | SF_OFS; break; default: printk("AFFS: Unknown filesystem on device %s: %08X\n", kdevname(dev),chksum); affs_brelse(bb); goto out; } affs_brelse(bb); } else { printk("AFFS: Can't get boot block.\n"); goto out; } if (mount_flags & SF_VERBOSE) { chksum = ntohl(chksum); printk("AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n", GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0], &GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1], (char *)&chksum,((char *)&chksum)[3] + '0',blocksize); }
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 by the VFS at mount time to initialize the whole file system. */ static struct super_block * jffs_read_super(struct super_block *sb, void *data, int silent) { kdev_t dev = sb->s_dev; struct inode *root_inode; struct jffs_control *c; D1(printk(KERN_NOTICE "JFFS: Trying to mount device %s.\n", kdevname(dev))); if (MAJOR(dev) != MTD_BLOCK_MAJOR) { printk(KERN_WARNING "JFFS: Trying to mount a " "non-mtd device.\n"); return 0; } sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->u.generic_sbp = (void *) 0; sb->s_maxbytes = 0xFFFFFFFF; /* Build the file system. */ if (jffs_build_fs(sb) < 0) { goto jffs_sb_err1; } /* * set up enough so that we can read an inode */ sb->s_magic = JFFS_MAGIC_SB_BITMASK; sb->s_op = &jffs_ops; root_inode = iget(sb, JFFS_MIN_INO); if (!root_inode) goto jffs_sb_err2; /* Get the root directory of this file system. */ if (!(sb->s_root = d_alloc_root(root_inode))) { goto jffs_sb_err3; } c = (struct jffs_control *) sb->u.generic_sbp; #ifdef CONFIG_JFFS_PROC_FS /* Set up the jffs proc file system. */ if (jffs_register_jffs_proc_dir(dev, c) < 0) { printk(KERN_WARNING "JFFS: Failed to initialize the JFFS " "proc file system for device %s.\n", kdevname(dev)); } #endif /* Set the Garbage Collection thresholds */ /* GC if free space goes below 5% of the total size */ c->gc_minfree_threshold = c->fmc->flash_size / 20; if (c->gc_minfree_threshold < c->fmc->sector_size) c->gc_minfree_threshold = c->fmc->sector_size; /* GC if dirty space exceeds 33% of the total size. */ c->gc_maxdirty_threshold = c->fmc->flash_size / 3; if (c->gc_maxdirty_threshold < c->fmc->sector_size) c->gc_maxdirty_threshold = c->fmc->sector_size; c->thread_pid = kernel_thread (jffs_garbage_collect_thread, (void *) c, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); D1(printk(KERN_NOTICE "JFFS: GC thread pid=%d.\n", (int) c->thread_pid)); D1(printk(KERN_NOTICE "JFFS: Successfully mounted device %s.\n", kdevname(dev))); return sb; jffs_sb_err3: iput(root_inode); jffs_sb_err2: jffs_cleanup_control((struct jffs_control *)sb->u.generic_sbp); jffs_sb_err1: printk(KERN_WARNING "JFFS: Failed to mount device %s.\n", kdevname(dev)); return 0; }
/* * hfs_read_super() * * This is the function that is responsible for mounting an HFS * filesystem. It performs all the tasks necessary to get enough data * from the disk to read the root inode. This includes parsing the * mount options, dealing with Macintosh partitions, reading the * superblock and the allocation bitmap blocks, calling * hfs_btree_init() to get the necessary data about the extents and * catalog B-trees and, finally, reading the root inode into memory. */ struct super_block *hfs_read_super(struct super_block *s, void *data, int silent) { struct hfs_mdb *mdb; struct hfs_cat_key key; kdev_t dev = s->s_dev; hfs_s32 part_size, part_start; struct inode *root_inode; int part; if (!parse_options((char *)data, HFS_SB(s), &part)) { hfs_warn("hfs_fs: unable to parse mount options.\n"); goto bail3; } /* set the device driver to 512-byte blocks */ set_blocksize(dev, HFS_SECTOR_SIZE); s->s_blocksize_bits = HFS_SECTOR_SIZE_BITS; s->s_blocksize = HFS_SECTOR_SIZE; #ifdef CONFIG_MAC_PARTITION /* check to see if we're in a partition */ mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, 0); /* erk. try parsing the partition table ourselves */ if (!mdb) { if (hfs_part_find(s, part, silent, &part_size, &part_start)) { goto bail2; } mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start); } #else if (hfs_part_find(s, part, silent, &part_size, &part_start)) { goto bail2; } mdb = hfs_mdb_get(s, s->s_flags & MS_RDONLY, part_start); #endif if (!mdb) { if (!silent) { hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n", kdevname(dev)); } goto bail2; } HFS_SB(s)->s_mdb = mdb; if (HFS_ITYPE(mdb->next_id) != 0) { hfs_warn("hfs_fs: too many files.\n"); goto bail1; } s->s_magic = HFS_SUPER_MAGIC; s->s_op = &hfs_super_operations; /* try to get the root inode */ hfs_cat_build_key(htonl(HFS_POR_CNID), (struct hfs_name *)(mdb->vname), &key); root_inode = hfs_iget(hfs_cat_get(mdb, &key), HFS_ITYPE_NORM, NULL); if (!root_inode) goto bail_no_root; s->s_root = d_alloc_root(root_inode); if (!s->s_root) goto bail_no_root; /* fix up pointers. */ HFS_I(root_inode)->entry->sys_entry[HFS_ITYPE_TO_INT(HFS_ITYPE_NORM)] = s->s_root; s->s_root->d_op = &hfs_dentry_operations; /* everything's okay */ return s; bail_no_root: hfs_warn("hfs_fs: get root inode failed.\n"); iput(root_inode); bail1: hfs_mdb_put(mdb, s->s_flags & MS_RDONLY); bail2: set_blocksize(dev, BLOCK_SIZE); bail3: return NULL; }
int dosetopt(int minor, struct psdev_opt *opt) { int retval = 0; int newval = opt->optval; ENTRY; switch(opt->optname) { case PSDEV_TIMEOUT: izo_channels[minor].uc_timeout = newval; break; case PSDEV_HARD: izo_channels[minor].uc_hard = newval; break; case PSDEV_NO_FILTER: izo_channels[minor].uc_no_filter = newval; break; case PSDEV_NO_JOURNAL: izo_channels[minor].uc_no_journal = newval; break; case PSDEV_NO_UPCALL: izo_channels[minor].uc_no_upcall = newval; break; #ifdef PRESTO_DEBUG case PSDEV_ERRORVAL: { /* If we have a positive arg, set a breakpoint for that * value. If we have a negative arg, make that device * read-only. FIXME It would be much better to only * allow setting the underlying device read-only for the * current presto cache. */ int errorval = izo_channels[minor].uc_errorval; if (errorval < 0) { if (newval == 0) set_device_ro(-errorval, 0); else CERROR("device %s already read only\n", kdevname(-errorval)); } else { if (newval < 0) set_device_ro(-newval, 1); izo_channels[minor].uc_errorval = newval; CDEBUG(D_PSDEV, "setting errorval to %d\n", newval); } break; } #endif case PSDEV_TRACE: case PSDEV_DEBUG: case PSDEV_BYTES_TO_CLOSE: default: CDEBUG(D_PSDEV, "ioctl: dosetopt: minor %d, bad optname 0x%x, \n", minor, opt->optname); retval = -EINVAL; } EXIT; return retval; }
static struct super_block * affs_read_super(struct super_block *sb, void *data, int silent) { struct buffer_head *root_bh = NULL; struct buffer_head *boot_bh; struct inode *root_inode = NULL; kdev_t dev = sb->s_dev; s32 root_block; int blocks, size, blocksize; u32 chksum; int num_bm; int i, j; s32 key; uid_t uid; gid_t gid; int reserved; unsigned long mount_flags; pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options"); sb->s_magic = AFFS_SUPER_MAGIC; sb->s_op = &affs_sops; memset(AFFS_SB, 0, sizeof(struct affs_sb_info)); init_MUTEX(&AFFS_SB->s_bmlock); if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, &blocksize,&AFFS_SB->s_prefix, AFFS_SB->s_volume, &mount_flags)) { printk(KERN_ERR "AFFS: Error parsing options\n"); return NULL; } /* N.B. after this point s_prefix must be released */ AFFS_SB->s_flags = mount_flags; AFFS_SB->s_mode = i; AFFS_SB->s_uid = uid; AFFS_SB->s_gid = gid; AFFS_SB->s_reserved= reserved; /* Get the size of the device in 512-byte blocks. * If we later see that the partition uses bigger * blocks, we will have to change it. */ blocks = blk_size[MAJOR(dev)] ? blk_size[MAJOR(dev)][MINOR(dev)] : 0; if (!blocks) { printk(KERN_ERR "AFFS: Could not determine device size\n"); goto out_error; } size = (BLOCK_SIZE / 512) * blocks; pr_debug("AFFS: initial blksize=%d, blocks=%d\n", 512, blocks); affs_set_blocksize(sb, PAGE_SIZE); /* Try to find root block. Its location depends on the block size. */ i = 512; j = 4096; if (blocksize > 0) { i = j = blocksize; size = size / (blocksize / 512); } for (blocksize = i, key = 0; blocksize <= j; blocksize <<= 1, size >>= 1) { AFFS_SB->s_root_block = root_block; if (root_block < 0) AFFS_SB->s_root_block = (reserved + size - 1) / 2; pr_debug("AFFS: setting blocksize to %d\n", blocksize); affs_set_blocksize(sb, blocksize); AFFS_SB->s_partition_size = size; /* The root block location that was calculated above is not * correct if the partition size is an odd number of 512- * byte blocks, which will be rounded down to a number of * 1024-byte blocks, and if there were an even number of * reserved blocks. Ideally, all partition checkers should * report the real number of blocks of the real blocksize, * but since this just cannot be done, we have to try to * find the root block anyways. In the above case, it is one * block behind the calculated one. So we check this one, too. */ for (num_bm = 0; num_bm < 2; num_bm++) { pr_debug("AFFS: Dev %s, trying root=%u, bs=%d, " "size=%d, reserved=%d\n", kdevname(dev), AFFS_SB->s_root_block + num_bm, blocksize, size, reserved); root_bh = affs_bread(sb, AFFS_SB->s_root_block + num_bm); if (!root_bh) continue; if (!affs_checksum_block(sb, root_bh) && be32_to_cpu(AFFS_ROOT_HEAD(root_bh)->ptype) == T_SHORT && be32_to_cpu(AFFS_ROOT_TAIL(sb, root_bh)->stype) == ST_ROOT) { AFFS_SB->s_hashsize = blocksize / 4 - 56; AFFS_SB->s_root_block += num_bm; key = 1; goto got_root; } affs_brelse(root_bh); root_bh = NULL; } } if (!silent) printk(KERN_ERR "AFFS: No valid root block on device %s\n", kdevname(dev)); goto out_error; /* N.B. after this point bh must be released */ got_root: root_block = AFFS_SB->s_root_block; sb->s_blocksize_bits = blocksize == 512 ? 9 : blocksize == 1024 ? 10 : blocksize == 2048 ? 11 : 12; /* Find out which kind of FS we have */ boot_bh = bread(sb->s_dev, 0, sb->s_blocksize); if (!boot_bh) { printk(KERN_ERR "AFFS: Cannot read boot block\n"); goto out_error; } chksum = be32_to_cpu(*(u32 *)boot_bh->b_data); brelse(boot_bh); /* Dircache filesystems are compatible with non-dircache ones * when reading. As long as they aren't supported, writing is * not recommended. */ if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS || chksum == MUFS_DCOFS) && !(sb->s_flags & MS_RDONLY)) { printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n", kdevname(dev)); sb->s_flags |= MS_RDONLY; AFFS_SB->s_flags |= SF_READONLY; } switch (chksum) { case MUFS_FS: case MUFS_INTLFFS: case MUFS_DCFFS: AFFS_SB->s_flags |= SF_MUFS; /* fall thru */ case FS_INTLFFS: case FS_DCFFS: AFFS_SB->s_flags |= SF_INTL; break; case MUFS_FFS: AFFS_SB->s_flags |= SF_MUFS; break; case FS_FFS: break; case MUFS_OFS: AFFS_SB->s_flags |= SF_MUFS; /* fall thru */ case FS_OFS: AFFS_SB->s_flags |= SF_OFS; sb->s_flags |= MS_NOEXEC; break; case MUFS_DCOFS: case MUFS_INTLOFS: AFFS_SB->s_flags |= SF_MUFS; case FS_DCOFS: case FS_INTLOFS: AFFS_SB->s_flags |= SF_INTL | SF_OFS; sb->s_flags |= MS_NOEXEC; break; default: printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n", kdevname(dev), chksum); goto out_error; } if (mount_flags & SF_VERBOSE) { chksum = cpu_to_be32(chksum); printk(KERN_NOTICE "AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n", AFFS_ROOT_TAIL(sb, root_bh)->disk_name[0], AFFS_ROOT_TAIL(sb, root_bh)->disk_name + 1, (char *)&chksum,((char *)&chksum)[3] + '0',blocksize); } sb->s_flags |= MS_NODEV | MS_NOSUID; AFFS_SB->s_data_blksize = sb->s_blocksize; if (AFFS_SB->s_flags & SF_OFS) AFFS_SB->s_data_blksize -= 24; /* Keep super block in cache */ AFFS_SB->s_root_bh = root_bh; /* N.B. after this point s_root_bh must be released */ if (affs_init_bitmap(sb)) goto out_error; /* set up enough so that it can read an inode */ root_inode = iget(sb, root_block); sb->s_root = d_alloc_root(root_inode); if (!sb->s_root) { printk(KERN_ERR "AFFS: Get root inode failed\n"); goto out_error; } sb->s_root->d_op = &affs_dentry_operations; pr_debug("AFFS: s_flags=%lX\n",sb->s_flags); return sb; /* * Begin the cascaded cleanup ... */ out_error: if (root_inode) iput(root_inode); if (AFFS_SB->s_bitmap) kfree(AFFS_SB->s_bitmap); affs_brelse(root_bh); if (AFFS_SB->s_prefix) kfree(AFFS_SB->s_prefix); return NULL; }