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_unlink_commit_args_s x_unlink_commit_args_t;
00025
00026 struct x_unlink_commit_args_s {
00027 int fd;
00028 txc_koa_t *koa;
00029 char pathname[TXC_MAX_LEN_PATHNAME];
00030 };
00031
00032
00033 static
00034 void
00035 x_unlink_commit(void *args, int *result)
00036 {
00037 int local_errno = 0;
00038 x_unlink_commit_args_t *myargs = (x_unlink_commit_args_t *) args;
00039 txc_koamgr_t *koamgr;
00040 txc_result_t xret;
00041
00042 koamgr = txc_koa_get_koamgr(myargs->koa);
00043 txc_koa_lock_alias_cache(koamgr);
00044 txc_koa_lock_fds_refby_koa(myargs->koa);
00045 xret = txc_koa_detach(myargs->koa);
00046 if (xret == TXC_R_SUCCESS) {
00047 if (txc_libc_unlink(myargs->pathname) < 0) {
00048 local_errno = errno;
00049 }
00050 } else {
00051 local_errno = EBADF;
00052
00053 }
00054 txc_koa_unlock_fds_refby_koa(myargs->koa);
00055 txc_koa_unlock_alias_cache(koamgr);
00056 if (result) {
00057 *result = local_errno;
00058 }
00059 }
00060
00061
00075 int
00076 XCALL_DEF(x_unlink)(const char *pathname, int *result)
00077 {
00078 txc_tx_t *txd;
00079 txc_koamgr_t *koamgr = txc_g_koamgr;
00080 txc_koa_t *koa;
00081 txc_sentinel_t *sentinel;
00082 txc_result_t xret;
00083 int ret;
00084 ino_t inode;
00085 x_unlink_commit_args_t *args_commit;
00086 int local_result = 0;
00087
00088 txd = txc_tx_get_txd();
00089
00090 switch(txc_tx_get_xactstate(txd)) {
00091 case TXC_XACTSTATE_TRANSACTIONAL_RETRYABLE:
00092 txc_koa_lock_alias_cache(koamgr);
00093 txc_koa_path2inode(pathname, &inode);
00094 if (inode == 0) {
00095
00096 txc_koa_unlock_alias_cache(koamgr);
00097 local_result = EACCES;
00098 ret = -1;
00099 goto done;
00100 } else {
00101 if (txc_koa_alias_cache_lookup_inode(koamgr, inode, &koa)
00102 == TXC_R_SUCCESS)
00103 {
00104
00105
00106
00107
00108
00109 txc_koa_lock_fds_refby_koa(koa);
00110 txc_koa_attach(koa);
00111 sentinel = txc_koa_get_sentinel(koa);
00112 xret = txc_sentinel_tryacquire(txd, sentinel,
00113 TXC_SENTINEL_ACQUIREONRETRY);
00114 if (xret == TXC_R_BUSYSENTINEL) {
00115 txc_koa_detach(koa);
00116 txc_koa_unlock_fds_refby_koa(koa);
00117 txc_koa_unlock_alias_cache(koamgr);
00118 txc_tx_abort_transaction(txd, TXC_ABORTREASON_BUSYSENTINEL);
00119 TXC_INTERNALERROR("Never gets here. Transaction abort failed.\n");
00120 }
00121 txc_koa_unlock_fds_refby_koa(koa);
00122 } else {
00123
00124
00125
00126
00127
00128
00129 txc_koa_create(koamgr, &koa, TXC_KOA_IS_FILE, (void *) inode);
00130 txc_koa_attach(koa);
00131 sentinel = txc_koa_get_sentinel(koa);
00132 xret = txc_sentinel_tryacquire(txd, sentinel, 0);
00133 if (xret != TXC_R_SUCCESS) {
00134 TXC_INTERNALERROR("Cannot acquire the sentinel of the KOA I've just created!\n");
00135 }
00136 }
00137 args_commit = (x_unlink_commit_args_t *)
00138 txc_buffer_linear_malloc(txd->buffer_linear,
00139 sizeof(x_unlink_commit_args_t));
00140 if (args_commit == NULL) {
00141 TXC_INTERNALERROR("Allocation failed. Linear buffer out of space.\n");
00142 }
00143
00144 args_commit->koa = koa;
00145 strcpy(args_commit->pathname, pathname);
00146
00147 txc_tx_register_commit_action(txd, x_unlink_commit,
00148 (void *) args_commit, result,
00149 TXC_KOA_DESTROY_COMMIT_ACTION_ORDER);
00150
00151 txc_koa_unlock_alias_cache(koamgr);
00152 ret = 0;
00153 }
00154 txc_stats_txstat_increment(txd, XCALL, x_unlink, 1);
00155 break;
00156
00157 case TXC_XACTSTATE_TRANSACTIONAL_IRREVOCABLE:
00158 case TXC_XACTSTATE_NONTRANSACTIONAL:
00159 if ((ret = txc_libc_unlink(pathname)) < 0) {
00160 local_result = errno;
00161 }
00162 ret = 0;
00163 }
00164 done:
00165 if (result) {
00166 *result = local_result;
00167 }
00168 return ret;
00169 }