Esempio n. 1
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 */
Esempio n. 2
0
extern int
vnode_shadow_fop_open(
    INODE_T *inode,
    FILE_T *file
)
{
    int err = 0;
    INODE_T *real_inode;
    DENT_T *rdentry = NULL;
    DENT_T *oldent;
    struct file_operations *oldfops;
    struct vfsmount *oldmnt, *newmnt;
    VNODE_T *cvp;

    oldmnt = file->f_vfsmnt;

    oldent = file->f_dentry;
    ASSERT(D_COUNT(oldent));
    /* The Linux kernel has stopped ignoring the O_DIRECT flag.
     * The problem is that they wait until after they call the fop open
     * function to check the inode to see if it will support direct I/O.
     * But they get the inode pointer before they call us and check the
     * inode after we return so they never check the actual inode we open
     * but only the shadow one.  Their error handling never comes back to
     * us and they release their old pointers and not our new ones.  The
     * only choice we have is to not allow O_DIRECT on shadow files.
     */
    if (file->f_flags & O_DIRECT) {
        err = -EINVAL;
        goto out_nolock;
    }
    /* Get the real dentry */
    rdentry = REALDENTRY_LOCKED(oldent, &cvp);
    if (rdentry == NULL) {
        err = -ENOENT;
	goto out_nolock;
    }
    VNODE_DGET(rdentry);                 /* protect rdentry->d_inode */
    if (rdentry->d_inode == NULL) {
        /* delete race */
        err = -ENOENT;
        goto out;
    }
    newmnt = MDKI_MNTGET(REALVFSMNT(oldent));
    if (newmnt == NULL) {
        err = -EOPNOTSUPP;             /* XXX */
        goto out;
    }

    /* Check that we can write to this file.  Clean up the count on the
     * shadow inode.
     */
    if (file->f_mode & FMODE_WRITE) {
        err = get_write_access(rdentry->d_inode);
        if (err) {
            MDKI_MNTPUT(newmnt);
            goto out;
        }
    }
    real_inode = rdentry->d_inode;

    /* 
     * Swap the file structure contents to point at the underlying object.
     */
    /* In Linux 2.6 they added the mapping stuff to the file so we have to set
    ** that up here, too.
    */
    file->f_mapping = real_inode->i_mapping;
    VNLAYER_RA_STATE_INIT(&(file->f_ra), file->f_mapping);
    file->f_dentry = VNODE_DGET(rdentry);
    oldfops = file->f_op;
    file->f_vfsmnt = newmnt;
    file->f_op = fops_get(real_inode->i_fop);
    if (real_inode->i_fop && !file->f_op)
        /* If we failed to get the reference to a non-NULL op, bail out */
        err = -EIO;                     /* XXX? better error code */
    if (!err) {
	/* Move the file to the file list for the real superblock 
	 * and remove it from the shadow list
	 */
        /* It would be better to use file_move() but it's not exported */
	file_list_lock();
        list_del(&file->f_list);
        list_add(&file->f_list, &real_inode->i_sb->s_files);
	file_list_unlock();
	if (file->f_op && file->f_op->open) {
            err = (*file->f_op->open)(real_inode, file);
            if (err) {
	        /* restore our file to the list on our super block */
	        file_list_lock();
	        list_del(&file->f_list);
	        list_add(&file->f_list, &oldent->d_inode->i_sb->s_files);
	        file_list_unlock();
	    }
	}
    }
    if (err) {
        /* MUST put back old dentry/fops to get accounting right in upper
         * layer. */
        put_write_access(rdentry->d_inode);
        if (file->f_dentry)
            VNODE_DPUT(file->f_dentry);
        if (file->f_op)
            fops_put(file->f_op);
        MDKI_MNTPUT(file->f_vfsmnt);
        file->f_vfsmnt = oldmnt;
        file->f_dentry = oldent;
        file->f_op = oldfops;
    } else {
        put_write_access(oldent->d_inode);
        VNODE_DPUT(oldent);
        /* Drop reference now that we've dropped our use of the file ops */
        fops_put(oldfops);
        MDKI_MNTPUT(oldmnt);
    }
  out:
    VNODE_DPUT(rdentry);
    REALDENTRY_UNLOCK(oldent, cvp);
  out_nolock:
    MDKI_TRACE(TRACE_OPEN, "%s: opened vp=%p fp=%p rdent=%p rdcnt=%d fcnt=%d"
              ", err %d\n", __func__,
              inode, file, rdentry, rdentry ? D_COUNT(rdentry) : 0, F_COUNT(file), -err);
    return(err);
}