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/stats.h>
00019 #include <libc/syscalls.h>
00020 #include <core/txdesc.h>
00021 #include <xcalls/xcalls.h>
00022
00023
00030 typedef struct x_create_case1_commit_undo_args_s x_create_case1_commit_undo_args_t;
00031
00032 struct x_create_case1_commit_undo_args_s {
00033 int fd;
00034 txc_koa_t *koa;
00035 char pathname[TXC_MAX_LEN_PATHNAME];
00036 };
00037
00038
00039 static
00040 void
00041 x_create_case1_undo(void *args, int *result)
00042 {
00043 int ret1;
00044 int local_result = 0;
00045 x_create_case1_commit_undo_args_t *myargs = (x_create_case1_commit_undo_args_t *) args;
00046 txc_koamgr_t *koamgr;
00047
00048 koamgr = txc_koa_get_koamgr(myargs->koa);
00049 txc_koa_lock_alias_cache(koamgr);
00050 if ((ret1 = txc_libc_unlink(myargs->pathname)) < 0) {
00051 local_result = errno;
00052 }
00053 txc_koa_detach_fd(myargs->koa, myargs->fd, 1);
00054 if (txc_libc_close(myargs->fd) < 0) {
00055 if (ret1 == 0) {
00056 local_result = errno;
00057 }
00058 }
00059 txc_koa_unlock_alias_cache(koamgr);
00060 if (result) {
00061 *result = local_result;
00062 }
00063 }
00064
00065
00066
00067
00068
00069
00070 typedef struct x_create_case2_commit_undo_args_s x_create_case2_commit_undo_args_t;
00071
00072 struct x_create_case2_commit_undo_args_s {
00073 int fd;
00074 txc_koa_t *koa;
00075 char temp_pathname[TXC_MAX_LEN_PATHNAME];
00076 char original_pathname[TXC_MAX_LEN_PATHNAME];
00077
00078 };
00079
00080
00081 static
00082 void
00083 x_create_case2_commit(void *args, int *result)
00084 {
00085 int local_result = 0;
00086 x_create_case2_commit_undo_args_t *myargs = (x_create_case2_commit_undo_args_t *) args;
00087
00088 if ((txc_libc_unlink(myargs->temp_pathname) < 0)) {
00089 local_result = errno;
00090 }
00091 if (result) {
00092 *result = local_result;
00093 }
00094 }
00095
00096
00097 static
00098 void
00099 x_create_case2_undo(void *args, int *result)
00100 {
00101 int ret1;
00102 int ret2;
00103 int local_result = 0;
00104 x_create_case2_commit_undo_args_t *myargs = (x_create_case2_commit_undo_args_t *) args;
00105 txc_koamgr_t *koamgr;
00106
00107 koamgr = txc_koa_get_koamgr(myargs->koa);
00108 txc_koa_lock_alias_cache(koamgr);
00109 if ((ret1 = txc_libc_unlink(myargs->original_pathname)) < 0) {
00110 local_result = errno;
00111 }
00112 if ((ret2 = txc_libc_rename(myargs->temp_pathname,
00113 myargs->original_pathname)) < 0)
00114 {
00115 if (ret1 == 0) {
00116 local_result = errno;
00117 }
00118 }
00119 txc_koa_detach_fd(myargs->koa, myargs->fd, 1);
00120 if (txc_libc_close(myargs->fd) < 0) {
00121 if (ret1 == 0 && ret2 == 0) {
00122 local_result = errno;
00123 }
00124 }
00125 txc_koa_unlock_alias_cache(koamgr);
00126 if (result) {
00127 *result = local_result;
00128 }
00129 }
00130
00131
00149 int
00150 XCALL_DEF(x_create)(const char *pathname, mode_t mode, int *result)
00151 {
00152 txc_tx_t *txd;
00153 txc_koamgr_t *koamgr = txc_g_koamgr;
00154 txc_koa_t *koa_new;
00155 txc_koa_t *koa_old;
00156 txc_sentinel_t *sentinel;
00157 txc_result_t xret;
00158 int fildes;
00159 int ret;
00160 int local_result = 0;
00161 ino_t inode;
00162 char temp_pathname[128];
00163 int creation_flags = O_CREAT| O_NOCTTY| O_TRUNC| O_RDWR;
00164
00165 txd = txc_tx_get_txd();
00166
00167 switch(txc_tx_get_xactstate(txd)) {
00168 case TXC_XACTSTATE_TRANSACTIONAL_RETRYABLE:
00169
00170 txc_koa_lock_alias_cache(koamgr);
00171 txc_koa_path2inode(pathname, &inode);
00172 TXC_DEBUG_PRINT(TXC_DEBUG_XCALL, "X_CREATE: path = %s, inode= %d\n",
00173 pathname, inode);
00174 if (inode == 0) {
00175 x_create_case1_commit_undo_args_t *args_commit_undo;
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 TXC_ASSERT(txc_koa_alias_cache_lookup_inode(koamgr, inode, &koa_old)
00186 == TXC_R_NOTEXISTS);
00187
00188 if ((ret = fildes = txc_libc_open(pathname,
00189 creation_flags,
00190 mode)) < 0)
00191 {
00192 txc_koa_unlock_alias_cache(koamgr);
00193 local_result = errno;
00194 goto done;
00195 }
00196 txc_koa_path2inode(pathname, &inode);
00197 txc_koa_create(koamgr, &koa_new, TXC_KOA_IS_FILE, (void *) inode);
00198 txc_koa_lock_fd(koamgr, fildes);
00199 txc_koa_attach_fd(koa_new, fildes, 0);
00200 sentinel = txc_koa_get_sentinel(koa_new);
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 xret = txc_sentinel_tryacquire(txd, sentinel, 0);
00217 if (xret != TXC_R_SUCCESS) {
00218 TXC_INTERNALERROR("Cannot acquire the sentinel of the KOA I've just created!\n");
00219 }
00220 args_commit_undo = (x_create_case1_commit_undo_args_t *)
00221 txc_buffer_linear_malloc(txd->buffer_linear,
00222 sizeof(x_create_case1_commit_undo_args_t));
00223 if (args_commit_undo == NULL) {
00224 TXC_INTERNALERROR("Allocation failed. Linear buffer out of space.\n");
00225 }
00226 strcpy(args_commit_undo->pathname, pathname);
00227 args_commit_undo->koa = koa_new;
00228 args_commit_undo->fd = fildes;
00229
00230 txc_tx_register_undo_action (txd, x_create_case1_undo,
00231 (void *) args_commit_undo, result,
00232 TXC_KOA_CREATE_UNDO_ACTION_ORDER);
00233
00234 txc_koa_unlock_fd(koamgr, fildes);
00235 txc_koa_unlock_alias_cache(koamgr);
00236 ret = fildes;
00237 } else {
00238
00239
00240
00241
00242 if (txc_koa_alias_cache_lookup_inode(koamgr, inode, &koa_old)
00243 == TXC_R_SUCCESS)
00244 {
00245 TXC_DEBUG_PRINT(TXC_DEBUG_XCALL, "X_CREATE: Case 2A\n");
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 txc_koa_lock_fds_refby_koa(koa_old);
00278 sentinel = txc_koa_get_sentinel(koa_old);
00279
00280 xret = txc_sentinel_tryacquire(txd, sentinel, 0);
00281 if (xret == TXC_R_BUSYSENTINEL) {
00282 txc_koa_unlock_fds_refby_koa(koa_old);
00283 txc_koa_unlock_alias_cache(koamgr);
00284 txc_tx_abort_transaction(txd, TXC_ABORTREASON_BUSYSENTINEL);
00285 TXC_INTERNALERROR("Never gets here. Transaction abort failed.\n");
00286 } else {
00287 txc_koa_unlock_fds_refby_koa(koa_old);
00288 }
00289
00290 } else {
00291 TXC_DEBUG_PRINT(TXC_DEBUG_XCALL, "X_CREATE: Case 2B\n");
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 }
00305 x_create_case2_commit_undo_args_t *args_commit_undo;
00306 strcpy(temp_pathname, "/tmp/libtxc.tmp.XXXXXX");
00307 mktemp(temp_pathname);
00308 txc_libc_rename(pathname, temp_pathname);
00309 if ((ret = fildes = txc_libc_open(pathname,
00310 creation_flags,
00311 mode)) < 0)
00312 {
00313 txc_libc_rename(temp_pathname, pathname);
00314 txc_koa_unlock_alias_cache(koamgr);
00315 local_result = errno;
00316 goto done;
00317 }
00318 txc_koa_path2inode(pathname, &inode);
00319 txc_koa_create(koamgr, &koa_new, TXC_KOA_IS_FILE, (void *) inode);
00320
00321 TXC_DEBUG_PRINT(TXC_DEBUG_XCALL,
00322 "X_CREATE: Case 2B: KOA = %x\n",
00323 koa_old);
00324 txc_koa_lock_fd(koamgr, fildes);
00325 txc_koa_attach_fd(koa_new, fildes, 0);
00326 TXC_ASSERT(TXC_R_SUCCESS == txc_koa_alias_cache_lookup_inode(koamgr, inode, &koa_old));
00327 sentinel = txc_koa_get_sentinel(koa_new);
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 xret = txc_sentinel_tryacquire(txd, sentinel, 0);
00344 if (xret != TXC_R_SUCCESS) {
00345 TXC_INTERNALERROR("Cannot acquire the sentinel of the KOA I've just created!\n");
00346 }
00347 args_commit_undo = (x_create_case2_commit_undo_args_t *)
00348 txc_buffer_linear_malloc(txd->buffer_linear,
00349 sizeof(x_create_case2_commit_undo_args_t));
00350 if (args_commit_undo == NULL) {
00351 TXC_INTERNALERROR("Allocation failed. Linear buffer out of space.\n");
00352 }
00353 strcpy(args_commit_undo->temp_pathname, temp_pathname);
00354 strcpy(args_commit_undo->original_pathname, pathname);
00355 args_commit_undo->koa = koa_new;
00356 args_commit_undo->fd = fildes;
00357
00358 txc_tx_register_commit_action(txd, x_create_case2_commit,
00359 (void *) args_commit_undo, result,
00360 TXC_KOA_CREATE_COMMIT_ACTION_ORDER);
00361 txc_tx_register_undo_action (txd, x_create_case2_undo,
00362 (void *) args_commit_undo, result,
00363 TXC_KOA_CREATE_UNDO_ACTION_ORDER);
00364
00365 txc_koa_unlock_fd(koamgr, fildes);
00366 txc_koa_unlock_alias_cache(koamgr);
00367 ret = fildes;
00368 }
00369 txc_stats_txstat_increment(txd, XCALL, x_create, 1);
00370 break;
00371 case TXC_XACTSTATE_TRANSACTIONAL_IRREVOCABLE:
00372 case TXC_XACTSTATE_NONTRANSACTIONAL:
00373
00374
00375
00376
00377
00378
00379
00380 txc_koa_lock_alias_cache(koamgr);
00381 if ((ret = fildes = txc_libc_open(pathname, creation_flags, mode)) < 0) {
00382 local_result = errno;
00383 goto done;
00384 }
00385 txc_koa_path2inode(pathname, &inode);
00386 txc_koa_create(koamgr, &koa_new, TXC_KOA_IS_FILE, (void *) inode);
00387 txc_koa_lock_fd(koamgr, fildes);
00388 txc_koa_attach_fd(koa_new, fildes, 0);
00389 sentinel = txc_koa_get_sentinel(koa_new);
00390 txc_koa_unlock_fd(koamgr, fildes);
00391 txc_koa_unlock_alias_cache(koamgr);
00392 ret = fildes;
00393 break;
00394 default:
00395 TXC_INTERNALERROR("Unknown transaction state\n");
00396 }
00397 done:
00398 if (result) {
00399 *result = local_result;
00400 }
00401 return ret;
00402 }