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 ssize_t write_chan(struct tty_struct * tty, struct file * file, const unsigned char * buf, size_t nr) { const unsigned char *b = buf; DECLARE_WAITQUEUE(wait, current); int c; ssize_t retval = 0; int transaction_commit = committing_transaction(); /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */ if ((!transaction_commit) && L_TOSTOP(tty) && file->f_op->write != redirected_tty_write) { retval = tty_check_change(tty); if (retval) return retval; } add_wait_queue(&tty->write_wait, &wait); while (1) { set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } if ((!transaction_commit) && (tty_hung_up_p(file) || (tty->link && !tty->link->count))) { retval = -EIO; break; } if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) { while (nr > 0) { ssize_t num = opost_block(tty, b, nr); if (num < 0) { if (num == -EAGAIN) break; retval = num; goto break_out; } b += num; nr -= num; if (nr == 0) break; c = *b; if (opost(c, tty) < 0) break; b++; nr--; } if (tty->driver->flush_chars) tty->driver->flush_chars(tty); } else { while (nr > 0) { c = tty->driver->write(tty, b, nr); if (c < 0) { retval = c; goto break_out; } if (!c) break; b += c; nr -= c; } } if (!nr) break; if ((!transaction_commit) && (tx_cache_get_file_ro(file)->f_flags & O_NONBLOCK)) { retval = -EAGAIN; break; } schedule(); } break_out: __set_current_state(TASK_RUNNING); remove_wait_queue(&tty->write_wait, &wait); return (b - buf) ? b - buf : retval; }