00001
00007 #include <fcntl.h>
00008 #include <unistd.h>
00009 #include <errno.h>
00010 #include <string.h>
00011 #include <stdlib.h>
00012 #include <misc/debug.h>
00013 #include <misc/errno.h>
00014 #include <core/tx.h>
00015 #include <core/config.h>
00016 #include <core/koa.h>
00017 #include <core/buffer.h>
00018 #include <core/txdesc.h>
00019 #include <core/stats.h>
00020 #include <libc/syscalls.h>
00021 #include <xcalls/xcalls.h>
00022
00023
00024 typedef struct x_lseek_undo_args_s x_lseek_undo_args_t;
00025
00026 struct x_lseek_undo_args_s {
00027 int fd;
00028 off_t old_position;
00029 };
00030
00031
00032 static
00033 void
00034 x_lseek_undo(void *args, int *result)
00035 {
00036 x_lseek_undo_args_t *args_undo = (x_lseek_undo_args_t *) args;
00037 int local_result = 0;
00038
00039 if (txc_libc_lseek(args_undo->fd,
00040 args_undo->old_position, SEEK_SET) < 0)
00041 {
00042 local_result = errno;
00043 goto done;
00044 }
00045 done:
00046 if (result) {
00047 *result = local_result;
00048 }
00049 }
00050
00051
00071 off_t
00072 XCALL_DEF(x_lseek)(int fd, off_t offset, int whence, int *result)
00073 {
00074 txc_tx_t *txd;
00075 txc_koamgr_t *koamgr = txc_g_koamgr;
00076 txc_koa_t *koa;
00077 txc_sentinel_t *sentinel;
00078 txc_result_t xret;
00079 int ret;
00080 x_lseek_undo_args_t *args_undo;
00081 int local_result;
00082
00083
00084 txd = txc_tx_get_txd();
00085
00086 switch(txc_tx_get_xactstate(txd)) {
00087 case TXC_XACTSTATE_TRANSACTIONAL_IRREVOCABLE:
00088 case TXC_XACTSTATE_NONTRANSACTIONAL:
00089 if ((ret = txc_libc_lseek(fd, offset, whence)) < 0) {
00090 local_result = errno;
00091 } else {
00092 local_result = 0;
00093 }
00094 goto done;
00095
00096 case TXC_XACTSTATE_TRANSACTIONAL_RETRYABLE:
00097 txc_koa_lock_fd(koamgr, fd);
00098 xret = txc_koa_lookup_fd2koa(koamgr, fd, &koa);
00099 if (xret == TXC_R_FAILURE) {
00100
00101
00102
00103
00104 txc_koa_unlock_fd(koamgr, fd);
00105 local_result = EBADF;
00106 ret = -1;
00107 goto done;
00108 }
00109 sentinel = txc_koa_get_sentinel(koa);
00110 xret = txc_sentinel_tryacquire(txd, sentinel,
00111 TXC_SENTINEL_ACQUIREONRETRY);
00112 txc_koa_unlock_fd(koamgr, fd);
00113 if (xret == TXC_R_BUSYSENTINEL) {
00114 txc_tx_abort_transaction(txd, TXC_ABORTREASON_BUSYSENTINEL);
00115 TXC_INTERNALERROR("Never gets here. Transaction abort failed.\n");
00116 }
00117
00118
00119
00120 if ((args_undo = (x_lseek_undo_args_t *)
00121 txc_buffer_linear_malloc(txd->buffer_linear,
00122 sizeof(x_lseek_undo_args_t)))
00123 == NULL)
00124 {
00125 local_result = ENOMEM;
00126 ret = -1;
00127 goto error_handler_0;
00128 }
00129 args_undo->fd = fd;
00130
00131
00132
00133
00134
00135
00136 if (whence == SEEK_CUR) {
00137 if ((ret = txc_libc_lseek(fd, offset, whence)) < 0) {
00138 local_result = errno;
00139 goto error_handler_1;
00140 }
00141 args_undo->old_position = ret - offset;
00142 } else {
00143 args_undo->old_position = txc_libc_lseek(fd, 0, SEEK_CUR);
00144 if ((ret = txc_libc_lseek(fd, offset, whence)) < 0) {
00145 local_result = errno;
00146 goto error_handler_1;
00147 }
00148 }
00149 txc_tx_register_undo_action(txd, x_lseek_undo,
00150 (void *) args_undo, result,
00151 TXC_TX_REGULAR_UNDO_ACTION_ORDER);
00152 local_result = 0;
00153
00154
00155
00156
00157 txc_stats_txstat_increment(txd, XCALL, x_lseek, 1);
00158 goto done;
00159
00160 default:
00161 TXC_INTERNALERROR("Unknown transaction state\n");
00162 }
00163
00164 error_handler_1:
00165 txc_buffer_linear_free(txd->buffer_linear,
00166 sizeof(x_lseek_undo_args_t));
00167 error_handler_0:
00168 done:
00169 if (result) {
00170 *result = local_result;
00171 }
00172 return ret;
00173 }