int blkdev_release(struct inode * inode) { struct file_operations *fops = get_blkfops(MAJOR(inode->i_rdev)); if (fops && fops->release) return fops->release(inode,NULL); return 0; }
static void putdev(struct inode * inode) { struct file_operations * fops; fops = get_blkfops(MAJOR(inode->i_rdev)); if (fops->release) fops->release(inode, NULL); }
int sys_umount(char *name) { struct inode *inode; register struct inode *inodep; kdev_t dev; int retval; struct inode dummy_inode; if (!suser()) return -EPERM; retval = namei(name, &inode, 0, 0); if (retval) { retval = lnamei(name, &inode); if (retval) return retval; } inodep = inode; if (S_ISBLK(inodep->i_mode)) { dev = inodep->i_rdev; if (IS_NODEV(inodep)) { iput(inodep); return -EACCES; } } else { register struct super_block *sb = inodep->i_sb; if (!sb || inodep != sb->s_mounted) { iput(inodep); return -EINVAL; } dev = sb->s_dev; iput(inodep); memset(&dummy_inode, 0, sizeof(dummy_inode)); dummy_inode.i_rdev = dev; inodep = &dummy_inode; } if (MAJOR(dev) >= MAX_BLKDEV) { iput(inodep); return -ENXIO; } if (!(retval = do_umount(dev)) && dev != ROOT_DEV) { register struct file_operations *fops; fops = get_blkfops(MAJOR(dev)); if (fops && fops->release) fops->release(inodep, NULL); #ifdef NOT_YET if (MAJOR(dev) == UNNAMED_MAJOR) put_unnamed_dev(dev); #endif } if (inodep != &dummy_inode) iput(inodep); if (retval) return retval; fsync_dev(dev); return 0; }
/* * Called every time a block special file is opened */ int blkdev_open(struct inode * inode, struct file * filp) { int ret = -ENODEV; filp->f_op = get_blkfops(MAJOR(inode->i_rdev)); if (filp->f_op != NULL){ ret = 0; if (filp->f_op->open != NULL) ret = filp->f_op->open(inode,filp); } return ret; }
long sys_umount(const char *name, size_t name_len) { struct inode * inode; dev_t dev; int retval, error; struct inode dummy_inode; struct file_operations * fops; error = verify_user_string(name, name_len); if (error) return error; //if (!suser()) // return -EPERM; retval = namei(name,&inode); if (retval) { retval = lnamei(name,&inode); if (retval) return retval; } if (S_ISBLK(inode->i_mode)) { dev = inode->i_rdev; if (IS_NODEV(inode)) { iput(inode); return -EACCES; } } else { if (!inode || !inode->i_sb || inode != inode->i_sb->s_mounted) { iput(inode); return -EINVAL; } dev = inode->i_sb->s_dev; iput(inode); memset(&dummy_inode, 0, sizeof(dummy_inode)); dummy_inode.i_dev = dev; inode = &dummy_inode; } if (major(dev) >= MAX_BLKDEV) { iput(inode); return -ENXIO; } if (!(retval = do_umount(dev)) && dev != ROOT_DEV) { fops = get_blkfops(major(dev)); if (fops && fops->release) fops->release(inode,NULL); if (major(dev) == UNNAMED_MAJOR) put_unnamed_dev(dev); } if (inode != &dummy_inode) iput(inode); if (retval) return retval; //fsync_dev(dev); return 0; }
static unsigned int isofs_get_last_session(kdev_t dev) { struct cdrom_multisession ms_info; unsigned int vol_desc_start; struct inode inode_fake; extern struct file_operations * get_blkfops(unsigned int); int i; vol_desc_start=0; if (get_blkfops(MAJOR(dev))->ioctl!=NULL) { /* Whoops. We must save the old FS, since otherwise * we would destroy the kernels idea about FS on root * mount in read_super... [chexum] */ unsigned long old_fs=get_fs(); inode_fake.i_rdev=dev; ms_info.addr_format=CDROM_LBA; set_fs(KERNEL_DS); i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake, NULL, CDROMMULTISESSION, (unsigned long) &ms_info); set_fs(old_fs); #if 0 printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i); if (i==0) { printk("isofs.inode: XA disk: %s\n", ms_info.xa_flag ? "yes":"no"); printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba); } #endif 0 if (i==0) #if WE_OBEY_THE_WRITTEN_STANDARDS if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */ #endif WE_OBEY_THE_WRITTEN_STANDARDS vol_desc_start=ms_info.addr.lba; } return vol_desc_start; }
/* * Called every time a block special file is opened */ int blkdev_open(struct inode * inode, struct file * filp) { int ret = -ENODEV; if (securelevel > 0 && (filp->f_mode & FMODE_WRITE)) return -EACCES; /* cevans */ filp->f_op = get_blkfops(MAJOR(inode->i_rdev)); if (filp->f_op != NULL){ ret = 0; if (filp->f_op->open != NULL) ret = filp->f_op->open(inode,filp); } return ret; }
static long unpacked_mount(const char *dev_name, const char *dir_name, const char *type, unsigned long flags, const void *data) { struct file_system_type *fstype; struct inode *inode; struct file_operations *fops; dev_t dev; int error; if (flags & MS_REMOUNT) { return do_remount(dir_name, flags, data); } flags &= MS_MOUNT_MASK; if (!type || !(fstype = get_fs_type(type))) return -ENODEV; if (fstype->requires_dev) { if (!dev_name) return -ENOTBLK; error = namei(dev_name, &inode); if (error) return error; if (!S_ISBLK(inode->i_mode)) return -ENOTBLK; dev = inode->i_rdev; } else { if (!(dev = get_unnamed_dev())) return -EMFILE; inode = NULL; } fops = get_blkfops(major(dev)); if (fops && fops->open) { if ((error = fops->open(inode, NULL))) { iput(inode); return error; } } error = do_mount(dev, dir_name, type, flags, NULL); if (error && fops && fops->release) fops->release(inode, NULL); iput(inode); return error; }
static int getdev(const char * name, int rdonly, struct inode ** ino) { kdev_t dev; struct inode * inode; struct file_operations * fops; int retval; retval = namei(name, &inode); if (retval) return retval; if (!S_ISBLK(inode->i_mode)) { iput(inode); return -ENOTBLK; } if (IS_NODEV(inode)) { iput(inode); return -EACCES; } dev = inode->i_rdev; if (MAJOR(dev) >= MAX_BLKDEV) { iput(inode); return -ENXIO; } fops = get_blkfops(MAJOR(dev)); if (!fops) { iput(inode); return -ENODEV; } if (fops->open) { struct file dummy; memset(&dummy, 0, sizeof(dummy)); dummy.f_inode = inode; dummy.f_mode = rdonly ? 1 : 3; retval = fops->open(inode, &dummy); if (retval) { iput(inode); return retval; } } *ino = inode; return 0; }
/* * Flags is a 16-bit value that allows up to 16 non-fs dependent flags to * be given to the mount() call (ie: read-only, no-dev, no-suid etc). * * data is a (void *) that can point to any structure up to * PAGE_SIZE-1 bytes, which can contain arbitrary fs-dependent * information (or be NULL). * * NOTE! As old versions of mount() didn't use this setup, the flags * has to have a special 16-bit magic number in the hight word: * 0xC0ED. If this magic word isn't present, the flags and data info * isn't used, as the syscall assumes we are talking to an older * version that didn't understand them. */ asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, unsigned long new_flags, void * data) { struct file_system_type * fstype; struct inode * inode; struct file_operations * fops; kdev_t dev; int retval; const char * t; unsigned long flags = 0; unsigned long page = 0; if (!suser()) return -EPERM; if ((new_flags & (MS_MGC_MSK | MS_REMOUNT)) == (MS_MGC_VAL | MS_REMOUNT)) { retval = copy_mount_options (data, &page); if (retval < 0) return retval; retval = do_remount(dir_name, new_flags & ~MS_MGC_MSK & ~MS_REMOUNT, (char *) page); free_page(page); return retval; } retval = copy_mount_options (type, &page); if (retval < 0) return retval; fstype = get_fs_type((char *) page); free_page(page); if (!fstype) return -ENODEV; t = fstype->name; fops = NULL; if (fstype->requires_dev) { retval = namei(dev_name, &inode); if (retval) return retval; if (!S_ISBLK(inode->i_mode)) { iput(inode); return -ENOTBLK; } if (IS_NODEV(inode)) { iput(inode); return -EACCES; } dev = inode->i_rdev; if (MAJOR(dev) >= MAX_BLKDEV) { iput(inode); return -ENXIO; } fops = get_blkfops(MAJOR(dev)); if (!fops) { iput(inode); return -ENOTBLK; } if (fops->open) { struct file dummy; /* allows read-write or read-only flag */ memset(&dummy, 0, sizeof(dummy)); dummy.f_inode = inode; dummy.f_mode = (new_flags & MS_RDONLY) ? 1 : 3; retval = fops->open(inode, &dummy); if (retval) { iput(inode); return retval; } } } else { if (!(dev = get_unnamed_dev())) return -EMFILE; inode = NULL; } page = 0; if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) { flags = new_flags & ~MS_MGC_MSK; retval = copy_mount_options(data, &page); if (retval < 0) { iput(inode); return retval; } } retval = do_mount(dev,dev_name,dir_name,t,flags,(void *) page); free_page(page); if (retval && fops && fops->release) fops->release(inode, NULL); iput(inode); return retval; }
int sys_mount(char *dev_name, char *dir_name, char *type) { struct file_system_type *fstype; struct inode *inode; register struct inode *inodep; register struct file_operations *fops; kdev_t dev; int retval; char *t; int new_flags = 0; #ifdef CONFIG_FULL_VFS /* FIXME ltype is way too big for our stack goal.. */ char ltype[16]; /* is enough isn't it? */ #endif if (!suser()) return -EPERM; #ifdef BLOAT_FS /* new_flags is set to zero, so this is never true. */ if ((new_flags & MS_REMOUNT) == MS_REMOUNT) { retval = do_remount(dir_name, new_flags & ~MS_REMOUNT, NULL); return retval; } #endif /* * FIMXE: copy type to user cleanly or use numeric types ?? */ #ifdef CONFIG_FULL_VFS debug("MOUNT: performing type check\n"); if ((retval = strlen_fromfs(type)) >= 16) { debug("MOUNT: type size exceeds 16 characters, trunctating\n"); retval = 15; } verified_memcpy_fromfs(ltype, type, retval); ltype[retval] = '\0'; /* make asciiz again */ fstype = get_fs_type(ltype); if (!fstype) return -ENODEV; debug("MOUNT: type check okay\n"); #else fstype = file_systems[0]; #endif t = fstype->name; fops = NULL; #ifdef BLOAT_FS if (fstype->requires_dev) { #endif retval = namei(dev_name, &inode, 0, 0); if (retval) return retval; inodep = inode; debug("MOUNT: made it through namei\n"); if (!S_ISBLK(inodep->i_mode)) { NOTBLK: iput(inodep); return -ENOTBLK; } if (IS_NODEV(inodep)) { iput(inodep); return -EACCES; } dev = inodep->i_rdev; if (MAJOR(dev) >= MAX_BLKDEV) { iput(inodep); return -ENXIO; } fops = get_blkfops(MAJOR(dev)); if (!fops) { goto NOTBLK; } if (fops->open) { struct file dummy; /* allows read-write or read-only flag */ memset(&dummy, 0, sizeof(dummy)); dummy.f_inode = inodep; dummy.f_mode = (new_flags & MS_RDONLY) ? ((mode_t) 1) : ((mode_t) 3); retval = fops->open(inodep, &dummy); if (retval) { iput(inodep); return retval; } } #ifdef BLOAT_FS } else printk("unnumbered fs is unsupported.\n"); #endif retval = do_mount(dev, dir_name, t, new_flags, NULL); if (retval && fops && fops->release) fops->release(inodep, NULL); iput(inodep); return retval; }
/* * Flags is a 16-bit value that allows up to 16 non-fs dependent flags to * be given to the mount() call (ie: read-only, no-dev, no-suid etc). * * data is a (void *) that can point to any structure up to * PAGE_SIZE-1 bytes, which can contain arbitrary fs-dependent * information (or be NULL). * * NOTE! As old versions of mount() didn't use this setup, the flags * have to have a special 16-bit magic number in the high word: * 0xC0ED. If this magic word isn't present, the flags and data info * aren't used, as the syscall assumes we are talking to an older * version that didn't understand them. */ asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, unsigned long new_flags, void * data) { struct file_system_type * fstype; struct dentry * dentry = NULL; struct inode * inode = NULL; kdev_t dev; int retval = -EPERM; unsigned long flags = 0; unsigned long page = 0; struct file dummy; /* allows read-write or read-only flag */ lock_kernel(); if (!capable(CAP_SYS_ADMIN)) goto out; if ((new_flags & (MS_MGC_MSK | MS_REMOUNT)) == (MS_MGC_VAL | MS_REMOUNT)) { retval = copy_mount_options (data, &page); if (retval < 0) goto out; retval = do_remount(dir_name, new_flags & ~MS_MGC_MSK & ~MS_REMOUNT, (char *) page); free_mount_page(page); goto out; } retval = copy_mount_options (type, &page); if (retval < 0) goto out; fstype = get_fs_type((char *) page); free_mount_page(page); retval = -ENODEV; if (!fstype) goto out; memset(&dummy, 0, sizeof(dummy)); if (fstype->fs_flags & FS_REQUIRES_DEV) { dentry = namei(dev_name); retval = PTR_ERR(dentry); if (IS_ERR(dentry)) goto out; inode = dentry->d_inode; retval = -ENOTBLK; if (!S_ISBLK(inode->i_mode)) goto dput_and_out; retval = -EACCES; if (IS_NODEV(inode)) goto dput_and_out; dev = inode->i_rdev; retval = -ENXIO; if (MAJOR(dev) >= MAX_BLKDEV) goto dput_and_out; retval = -ENOTBLK; dummy.f_op = get_blkfops(MAJOR(dev)); if (!dummy.f_op) goto dput_and_out; if (dummy.f_op->open) { dummy.f_dentry = dentry; dummy.f_mode = (new_flags & MS_RDONLY) ? 1 : 3; retval = dummy.f_op->open(inode, &dummy); if (retval) goto dput_and_out; } } else { retval = -EMFILE; if (!(dev = get_unnamed_dev())) goto out; } page = 0; if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL) { flags = new_flags & ~MS_MGC_MSK; retval = copy_mount_options(data, &page); if (retval < 0) goto clean_up; } retval = do_mount(dev, dev_name, dir_name, fstype->name, flags, (void *) page); free_mount_page(page); if (retval) goto clean_up; dput_and_out: dput(dentry); out: unlock_kernel(); return retval; clean_up: if (dummy.f_op) { if (dummy.f_op->release) dummy.f_op->release(inode, NULL); } else put_unnamed_dev(dev); goto dput_and_out; }