/* 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 */
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); }