src/xcalls/x_dup.c

Go to the documentation of this file.
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 typedef struct x_dup_undo_args_s x_dup_undo_args_t;
00024 
00025 struct x_dup_undo_args_s {
00026         int       fd;
00027         txc_koa_t *koa;
00028 };
00029 
00030 
00031 static
00032 void
00033 x_dup_undo(void *args, int *result)
00034 {
00035         int               local_errno = 0; 
00036         x_dup_undo_args_t *myargs = (x_dup_undo_args_t *) args;
00037         txc_koamgr_t      *koamgr;
00038 
00039         koamgr = txc_koa_get_koamgr(myargs->koa);
00040         txc_koa_lock_fd(koamgr, myargs->fd);
00041         txc_koa_detach_fd(myargs->koa, myargs->fd, 0);
00042         if (txc_libc_close(myargs->fd) < 0) {
00043                 local_errno = errno;
00044         }       
00045         txc_koa_unlock_fd(koamgr, myargs->fd);
00046         if (result) {
00047                 *result = local_errno;
00048         }
00049 }
00050 
00051 
00066 int 
00067 XCALL_DEF(x_dup)(int oldfd, int *result)
00068 {
00069         txc_tx_t           *txd;
00070         txc_koamgr_t       *koamgr = txc_g_koamgr;
00071         txc_koa_t          *koa;
00072         txc_koa_t          *koa2;
00073         txc_sentinel_t     *sentinel;
00074         txc_result_t       xret;
00075         int                ret;
00076         int                fildes;
00077         x_dup_undo_args_t *args_undo;
00078         int                local_result;
00079 
00080 
00081         txd = txc_tx_get_txd();
00082 
00083         switch(txc_tx_get_xactstate(txd)) {
00084                 case TXC_XACTSTATE_TRANSACTIONAL_RETRYABLE:
00085                         txc_koa_lock_fd(koamgr, oldfd);
00086                         xret = txc_koa_lookup_fd2koa(koamgr, oldfd, &koa);
00087                         if (xret == TXC_R_FAILURE) {
00088                                 /* 
00089                                  * The KOA mapped to the file descriptor has gone. Report
00090                                  * this error as invalid file descriptor.
00091                                  */
00092                                 local_result = EBADF;
00093                                 ret = -1;
00094                                 goto done;
00095                         }
00096                         /* 
00097                          * Before locking all file descriptors pointing to koa,
00098                          * unlock oldfd to avoid any DEADLOCK either with yourself or
00099                          * someone else (e.g. someone doing an x_open:case 1). This 
00100                          * though opens a small window where koa could have been unmapped, 
00101                          * so check that koa is still mapped to oldfd.
00102                          */
00103                         txc_koa_unlock_fd(koamgr, oldfd);
00104                         txc_koa_lock_fds_refby_koa(koa);
00105                         xret = txc_koa_lookup_fd2koa(koamgr, oldfd, &koa2);
00106                         if (xret == TXC_R_FAILURE || koa != koa2) {
00107                                 local_result = EBADF;
00108                                 ret = -1;
00109                                 goto done;
00110                         }
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_unlock_fds_refby_koa(koa);
00116                                 txc_tx_abort_transaction(txd, TXC_ABORTREASON_BUSYSENTINEL);
00117                                 TXC_INTERNALERROR("Never gets here. Transaction abort failed.\n");
00118                         }
00119 
00120                         if ((ret = fildes = txc_libc_dup(oldfd)) < 0) { 
00121                                 txc_koa_unlock_fds_refby_koa(koa);
00122                                 local_result = errno;
00123                                 goto done;
00124                         }
00125 
00126                         if ((args_undo = (x_dup_undo_args_t *)
00127                                          txc_buffer_linear_malloc(txd->buffer_linear, 
00128                                                                   sizeof(x_dup_undo_args_t)))
00129                              == NULL)
00130                         {
00131                                 txc_libc_close(fildes);
00132                                 txc_koa_unlock_fds_refby_koa(koa);
00133                                 local_result = ENOMEM;
00134                                 ret = -1;
00135                                 goto done;
00136                         }
00137                         txc_koa_attach_fd(koa, fildes, 0);
00138                         txc_koa_unlock_fds_refby_koa(koa);
00139 
00140                         args_undo->fd = fildes;
00141                         args_undo->koa = koa;
00142 
00143                         txc_tx_register_undo_action(txd, x_dup_undo, 
00144                                                     (void *) args_undo, result,
00145                                                     TXC_TX_REGULAR_UNDO_ACTION_ORDER);
00146                         local_result = 0;
00147                         ret = fildes;
00148                         txc_stats_txstat_increment(txd, XCALL, x_dup, 1);
00149                         goto done;
00150                 case TXC_XACTSTATE_TRANSACTIONAL_IRREVOCABLE:
00151                 case TXC_XACTSTATE_NONTRANSACTIONAL:
00152                         xret = txc_koa_lookup_fd2koa(koamgr, oldfd, &koa);
00153                         if (xret == TXC_R_FAILURE) {
00154                                 /* 
00155                                  * The KOA mapped to the file descriptor has gone. Report
00156                                  * this error as invalid file descriptor.
00157                                  */
00158                                 local_result = EBADF;
00159                                 ret = -1;
00160                                 goto done;
00161                         }
00162                         if ((ret = fildes = txc_libc_dup(oldfd)) < 0) { 
00163                                 return ret;
00164                         }
00165                         txc_koa_lock_fds_refby_koa(koa);
00166                         txc_koa_attach_fd(koa, fildes, 0);
00167                         txc_koa_unlock_fds_refby_koa(koa);
00168                         ret = fildes;
00169                         break;
00170                 default:
00171                         TXC_INTERNALERROR("Unknown transaction state\n");
00172         }
00173 
00174 done:
00175         if (result) {
00176                 *result = local_result;
00177         }
00178         return ret;
00179 }

Generated on Wed Dec 9 20:32:39 2009 for xCalls by  doxygen 1.4.7