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
00025 typedef struct x_open_undo_args_s x_open_undo_args_t;
00026
00027 struct x_open_undo_args_s {
00028 int fd;
00029 txc_koa_t *koa;
00030 };
00031
00032
00033 static
00034 void
00035 x_open_undo(void *args, int *result)
00036 {
00037 int local_errno = 0;
00038 x_open_undo_args_t *myargs = (x_open_undo_args_t *) args;
00039 txc_koamgr_t *koamgr;
00040
00041 koamgr = txc_koa_get_koamgr(myargs->koa);
00042 txc_koa_lock_alias_cache(koamgr);
00043 txc_koa_lock_fd(koamgr, myargs->fd);
00044 txc_koa_detach_fd(myargs->koa, myargs->fd, 0);
00045 if (txc_libc_close(myargs->fd) < 0) {
00046 local_errno = errno;
00047 }
00048 txc_koa_unlock_fd(koamgr, myargs->fd);
00049 txc_koa_unlock_alias_cache(koamgr);
00050 if (result) {
00051 *result = local_errno;
00052 }
00053 }
00054
00055
00068 int
00069 XCALL_DEF(x_open)(const char *pathname, int flags, mode_t mode, int *result)
00070 {
00071 txc_tx_t *txd;
00072 txc_koamgr_t *koamgr = txc_g_koamgr;
00073 txc_koa_t *koa;
00074 txc_sentinel_t *sentinel;
00075 txc_result_t xret;
00076 int fildes;
00077 int ret;
00078 ino_t inode;
00079 x_open_undo_args_t *args_undo;
00080 int open_flags = O_RDWR | flags;
00081 int local_result = 0;
00082
00083 txd = txc_tx_get_txd();
00084
00085 switch(txc_tx_get_xactstate(txd)) {
00086 case TXC_XACTSTATE_TRANSACTIONAL_RETRYABLE:
00087
00088 txc_koa_lock_alias_cache(koamgr);
00089 txc_koa_path2inode(pathname, &inode);
00090 if (inode == 0) {
00091
00092 txc_koa_unlock_alias_cache(koamgr);
00093 local_result = EACCES;
00094 ret = -1;
00095 goto done;
00096 } else {
00097 if ((ret = fildes = txc_libc_open(pathname, open_flags, mode)) < 0) {
00098 txc_koa_unlock_alias_cache(koamgr);
00099 local_result = errno;
00100 goto done;
00101 }
00102 if (txc_koa_alias_cache_lookup_inode(koamgr, inode, &koa)
00103 == TXC_R_SUCCESS)
00104 {
00105
00106
00107
00108
00109
00110 txc_koa_lock_fds_refby_koa(koa);
00111 txc_koa_lock_fd(koamgr, fildes);
00112 txc_koa_attach_fd(koa, fildes, 0);
00113 sentinel = txc_koa_get_sentinel(koa);
00114 xret = txc_sentinel_tryacquire(txd, sentinel, 0);
00115 if (xret == TXC_R_BUSYSENTINEL) {
00116 txc_libc_close(fildes);
00117 txc_koa_detach_fd(koa, fildes, 0);
00118
00119
00120
00121
00122 txc_koa_unlock_fd(koamgr, fildes);
00123 txc_koa_unlock_fds_refby_koa(koa);
00124 txc_koa_unlock_alias_cache(koamgr);
00125 txc_tx_abort_transaction(txd, TXC_ABORTREASON_BUSYSENTINEL);
00126 TXC_INTERNALERROR("Never gets here. Transaction abort failed.\n");
00127 }
00128
00129 args_undo = (x_open_undo_args_t *)
00130 txc_buffer_linear_malloc(txd->buffer_linear,
00131 sizeof(x_open_undo_args_t));
00132 if (args_undo == NULL) {
00133 TXC_INTERNALERROR("Allocation failed. Linear buffer out of space.\n");
00134 }
00135 args_undo->koa = koa;
00136 args_undo->fd = fildes;
00137
00138 txc_tx_register_undo_action (txd, x_open_undo,
00139 (void *) args_undo, result,
00140 TXC_KOA_CREATE_UNDO_ACTION_ORDER);
00141
00142
00143
00144
00145
00146
00147
00148 txc_koa_unlock_fds_refby_koa(koa);
00149 txc_koa_unlock_alias_cache(koamgr);
00150 ret = fildes;
00151 } else {
00152
00153
00154
00155
00156
00157
00158 txc_koa_create(koamgr, &koa, TXC_KOA_IS_FILE, (void *) inode);
00159 txc_koa_lock_fd(koamgr, fildes);
00160 txc_koa_attach_fd(koa, fildes, 0);
00161 sentinel = txc_koa_get_sentinel(koa);
00162 xret = txc_sentinel_tryacquire(txd, sentinel, 0);
00163 if (xret != TXC_R_SUCCESS) {
00164 TXC_INTERNALERROR("Cannot acquire the sentinel of the KOA I've just created!\n");
00165 }
00166 args_undo = (x_open_undo_args_t *)
00167 txc_buffer_linear_malloc(txd->buffer_linear,
00168 sizeof(x_open_undo_args_t));
00169 if (args_undo == NULL) {
00170 TXC_INTERNALERROR("Allocation failed. Linear buffer out of space.\n");
00171 }
00172 args_undo->koa = koa;
00173 args_undo->fd = fildes;
00174
00175 txc_tx_register_undo_action (txd, x_open_undo,
00176 (void *) args_undo, result,
00177 TXC_KOA_CREATE_UNDO_ACTION_ORDER);
00178
00179 txc_koa_unlock_fd(koamgr, fildes);
00180 txc_koa_unlock_alias_cache(koamgr);
00181 ret = fildes;
00182 }
00183 }
00184 txc_stats_txstat_increment(txd, XCALL, x_open, 1);
00185 break;
00186 case TXC_XACTSTATE_TRANSACTIONAL_IRREVOCABLE:
00187 case TXC_XACTSTATE_NONTRANSACTIONAL:
00188
00189
00190
00191
00192
00193
00194
00195 txc_koa_lock_alias_cache(koamgr);
00196 if ((ret = fildes = txc_libc_open(pathname, open_flags, mode)) < 0) {
00197 txc_koa_unlock_alias_cache(koamgr);
00198 local_result = errno;
00199 goto done;
00200 }
00201 txc_koa_path2inode(pathname, &inode);
00202 if (txc_koa_alias_cache_lookup_inode(koamgr, inode, &koa)
00203 != TXC_R_SUCCESS)
00204 {
00205 txc_koa_create(koamgr, &koa, TXC_KOA_IS_FILE, (void *) inode);
00206 }
00207 txc_koa_lock_fd(koamgr, fildes);
00208 txc_koa_attach_fd(koa, fildes, 0);
00209 sentinel = txc_koa_get_sentinel(koa);
00210 txc_koa_unlock_fd(koamgr, fildes);
00211 txc_koa_unlock_alias_cache(koamgr);
00212 ret = fildes;
00213 }
00214 done:
00215 if (result) {
00216 *result = local_result;
00217 }
00218 return ret;
00219 }