src/xcalls/x_open.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/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                         /* Serialize open/create/close file operations to detect aliasing */
00088                         txc_koa_lock_alias_cache(koamgr);
00089                         txc_koa_path2inode(pathname, &inode);
00090                         if (inode == 0) {
00091                                 /* File does not exist. */
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                                          * CASE 1:
00107                                          *  - KOA exists in the alias cache so other in-flight 
00108                                          *    transaction may operate on the file.
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                                                  * Explicitly release the lock on fildes because we 
00120                                                  * have detached it from the KOA.
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                                          * Don't need to explicitly release the lock on fildes 
00144                                          * because it is attached to KOA koa, so it will be  
00145                                          * released by the following operation:
00146                                          *   txc_koa_unlock_fds_refby_koa(koa);
00147                                          */
00148                                         txc_koa_unlock_fds_refby_koa(koa);
00149                                         txc_koa_unlock_alias_cache(koamgr);
00150                                         ret = fildes;
00151                                 } else {
00152                                         /* 
00153                                          * CASE 2:
00154                                          * - KOA does not exist in the alias cache so there is no
00155                                          *   way for some other in-flight transaction to have a reference 
00156                                          *   to the file to operate on it.
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                          * Even if xCalls don't provide transactional properties when called
00190                          * outside of a transaction, we still need to create a KOA and assign
00191                          * a sentinel to be used later by any transactional xCalls. Thus we
00192                          * still need to properly synchronize accesses to internal data
00193                          * structures.
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 }

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