long do_fsync(struct file *file, int datasync) { int ret; int err; struct address_space *mapping = file->f_mapping; if (live_transaction()){ /* DEP 5/27/10 - Defer fsync until commit. */ struct deferred_object_operation *def_op; txobj_thread_list_node_t *list_node = workset_has_object(&file->f_mapping->host->xobj); if (!list_node) { tx_cache_get_file_ro(file); tx_cache_get_inode_ro(file->f_mapping->host); list_node = workset_has_object(&file->f_mapping->host->xobj); } def_op = alloc_deferred_object_operation(); INIT_LIST_HEAD(&def_op->list); def_op->type = DEFERRED_TYPE_FSYNC; def_op->u.fsync.datasync = datasync; def_op->u.fsync.file = file; /* DEP: Pin the file until the sync is executed */ tx_atomic_inc_not_zero(&file->f_count); // XXX: Could probably use something finer grained here. WORKSET_LOCK(current->transaction); list_add(&def_op->list, &list_node->deferred_operations); WORKSET_UNLOCK(current->transaction); return 0; } if (!file->f_op || !file->f_op->fsync) { /* Why? We can still call filemap_fdatawrite */ ret = -EINVAL; goto out; } ret = filemap_fdatawrite(mapping); /* * We need to protect against concurrent writers, which could cause * livelocks in fsync_buffers_list(). */ if (!committing_transaction()) mutex_lock(&mapping->host->i_mutex); err = file->f_op->fsync(file, file_get_dentry(file), datasync); if (!ret) ret = err; if (!committing_transaction()) mutex_unlock(&mapping->host->i_mutex); err = filemap_fdatawait(mapping); if (!ret) ret = err; out: return ret; }
static long do_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int error = -ENOTTY; void *f; /* Whitelist check */ if(live_transaction()){ switch(cmd){ case FIOCLEX: case FIONCLEX: case FIONBIO: case FIOASYNC: case FIOQSIZE: case TCGETS: break; default: if(current->transaction->unsupported_operation_action == UNSUPPORTED_ABORT){ // Don't leap out of the stack printk(KERN_ERR "Aborting on unsupported ioctl in tx: %u\n", cmd); abort_self(NULL, 0); } else if(current->transaction->unsupported_operation_action == UNSUPPORTED_ERROR_CODE){ printk(KERN_ERR "Warning: Stopped execution of unsupported ioctl in tx: %u\n", cmd); return -ENOTXSUPPORT; } else { #ifdef CONFIG_TX_KSTM_WARNINGS printk(KERN_ERR "Warning: Executing unsupported ioctl in tx: %u\n", cmd); #endif } } } if (!filp->f_op) goto out; if (filp->f_op->unlocked_ioctl) { error = filp->f_op->unlocked_ioctl(filp, cmd, arg); if (error == -ENOIOCTLCMD) error = -EINVAL; goto out; } else if ((f = filp->f_op->ioctl)) { lock_kernel(); if (!filp->f_op->ioctl) { printk("%s: ioctl %p disappeared\n", __FUNCTION__, f); print_symbol("symbol: %s\n", (unsigned long)f); dump_stack(); } else { error = filp->f_op->ioctl((file_get_dentry(filp)->d_inode), filp, cmd, arg); } unlock_kernel(); } out: return error; }
static struct file *__dentry_open(struct _dentry *dentry, struct vfsmount *mnt, int flags, struct file *f, int (*open)(struct _inode *, struct file *)) { struct _inode *inode; int error; struct super_block *sb; struct _file *_f = tx_cache_get_file(f); _f->f_flags = flags; _f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE; inode = d_get_inode(dentry); sb = inode->i_sb; if (_f->f_mode & FMODE_WRITE) { error = get_write_access(parent(inode)); if (error) goto cleanup_file; } f->f_mapping = inode->i_mapping; _f->f_path.dentry = parent(dentry); _f->f_path.mnt = mnt; _f->f_pos = 0; f->f_op = fops_get(inode->i_fop); file_move(f, &sb->s_files); if (!open && f->f_op) open = f->f_op->open; if (open) { error = open(inode, f); if (error) goto cleanup_all; } _f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); file_ra_state_init(&f->f_ra, tx_cache_get_inode(f->f_mapping->host)->i_mapping); /* NB: we're sure to have correct a_ops only after f_op->open */ if (_f->f_flags & O_DIRECT) { if (!f->f_mapping->a_ops || ((!f->f_mapping->a_ops->direct_IO) && (!f->f_mapping->a_ops->get_xip_page))) { fput(f); f = ERR_PTR(-EINVAL); } } return f; cleanup_all: fops_put(f->f_op); if (_f->f_mode & FMODE_WRITE) put_write_access(parent(inode)); file_kill(f); _f->f_path.dentry = NULL; _f->f_path.mnt = NULL; cleanup_file: /* Avoid issues if we recycle this object */ if(live_transaction()) early_release(&f->xobj, 1); put_filp(f); dput(parent(dentry)); mntput(mnt); return ERR_PTR(error); }
/* * When you add any new common ioctls to the switches above and below * please update compat_sys_ioctl() too. * * vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d. * It's just a simple helper for sys_ioctl and compat_sys_ioctl. */ int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg) { unsigned int flag; int on, error = 0; umode_t mode; struct _file *_filp = tx_cache_get_file(filp); /* Patch up ioctl for bad tx cases*/ if((!_filp) || !_filp->f_dentry ){ #ifdef CONFIG_TX_KSTM_WARNINGS printk(KERN_ERR "Fixing up ioctl\n"); #endif return 0; } mode = d_get_inode_ro(f_get_dentry(_filp))->i_mode; switch (cmd) { case FIOCLEX: set_close_on_exec(fd, 1); break; case FIONCLEX: set_close_on_exec(fd, 0); break; case FIONBIO: if ((error = get_user(on, (int __user *)arg)) != 0) break; flag = O_NONBLOCK; #ifdef __sparc__ /* SunOS compatibility item. */ if(O_NONBLOCK != O_NDELAY) flag |= O_NDELAY; #endif if (on) _filp->f_flags |= flag; else _filp->f_flags &= ~flag; break; case FIOASYNC: if ((error = get_user(on, (int __user *)arg)) != 0) break; flag = on ? FASYNC : 0; /* Did FASYNC state change ? */ if ((flag ^ _filp->f_flags) & FASYNC) { if (filp->f_op && filp->f_op->fasync) { lock_kernel(); error = filp->f_op->fasync(fd, filp, on); unlock_kernel(); } else error = -ENOTTY; } if (error != 0) break; if (on) _filp->f_flags |= FASYNC; else _filp->f_flags &= ~FASYNC; break; case FIOQSIZE: if (S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) { loff_t res = inode_get_bytes(f_get_dentry(_filp)->d_inode); error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0; } else error = -ENOTTY; break; default: if(live_transaction()){ /* Short circuit this stupid ioctl */ if(cmd == TIOCGWINSZ){ #ifdef CONFIG_TX_KSTM_WARNINGS printk(KERN_ERR "Warning: some bozo wants to know the terminal width in a transaction.\n"); #endif error = -EINVAL; break; } else if(cmd != TCGETS) BUG(); } if (S_ISREG(mode)) error = file_ioctl(filp, cmd, arg); else error = do_ioctl(filp, cmd, arg); break; } return error; }