home *** CD-ROM | disk | FTP | other *** search
/ ftp.parl.clemson.edu / 2015-02-07.ftp.parl.clemson.edu.tar / ftp.parl.clemson.edu / pub / pvfs2 / orangefs-2.8.3-20110323.tar.gz / orangefs-2.8.3-20110323.tar / orangefs / src / io / buffer / ncac-job.c < prev    next >
C/C++ Source or Header  |  2006-12-05  |  10KB  |  328 lines

  1. /* This file defines the horseworkers for each particular type of jobs.  */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5.  
  6.  
  7. #include "internal.h"
  8. #include "state.h"
  9. #include "aiovec.h"
  10. #include "cache.h"
  11.  
  12. #include "ncac-trove.h"
  13. #include "ncac-job.h"
  14. #include "pvfs2-internal.h"
  15.  
  16. /* internal functions */
  17. static inline struct extent *find_extent(NCAC_req_t *ncac_req,
  18.                        unsigned long index);
  19. static inline struct extent *allocate_extent(NCAC_req_t *ncac_req, 
  20.                        int flag);
  21. static inline int free_extent(NCAC_req_t *ncac_req,
  22.                        struct extent *extent);
  23. static inline int init_extent_read(NCAC_req_t *ncac_req,
  24.                 struct extent *extent, PVFS_offset foffset, PVFS_size size);
  25. static inline void set_extent_read_pending(struct extent *extent);
  26. static inline int check_extent_read(NCAC_req_t *ncac_req, struct extent *extent);
  27. static inline void increase_read_reference(struct extent *extent);
  28. static inline int add_extent_to_cache(struct extent * extent,
  29.          unsigned long index, NCAC_req_t *ncac_req, int policy);
  30.  
  31. /* do a read job.
  32.  * return: < 0 error code
  33.  *         0: ok
  34.  * ncac_req->status shows the current status of the job
  35.  * ncac_req->error shows the current error of the job if any.
  36.  *
  37.  * Lock stuff: A design choice has been made to do locks as follows:
  38.  *     1) each inode has a lock;
  39.  *     2) each cache stack has a lock (many inodes may share a same 
  40.  *    cache stack).
  41.  * To avoid lock calls on each extent, we had a sort of "big" lock 
  42.  * across jobs on an inode. During a job processing, if the cache stack 
  43.  * is touched, the job should acquire the cache stack lock. So the lock 
  44.  * order is:
  45.  *    inode lock
  46.  *             ----> cache stack lock
  47.  *             ----> release cache stack lock
  48.  *  release inode lock
  49.  * 
  50.  *  So, we make a tradeoff between the number of lock calls and the 
  51.  *  granularity of lock.
  52.  */
  53.  
  54. int NCAC_do_a_read_job(struct NCAC_req *ncac_req)
  55. {
  56.     int ret;
  57.     struct extent **cbufhash;
  58.     PVFS_offset *foff;
  59.     int *cbufflag;
  60.     struct extent *new_extent;
  61.     struct extent *last_extent;
  62.  
  63.     unsigned long index;
  64.     int comcnt, readcnt;
  65.     int i;
  66.     
  67.  
  68.     /* even there are "comcnt" communication buffers, the
  69.      * number of extents needed may be less.
  70.      */
  71.     comcnt = ncac_req->cbufcnt;
  72.     fprintf(stderr, "NCAC_do_a_read_job: enter (comcnt=%d)\n", comcnt);
  73.  
  74.     cbufhash = ncac_req->cbufhash;
  75.     foff = ncac_req->foff;
  76.     cbufflag = ncac_req->cbufflag;
  77.  
  78.     inode_lock (&ncac_req->mapping->lock);
  79.  
  80.     last_extent = NULL;
  81.     for (i=0; i<comcnt; i++){
  82.         if ( NULL == cbufhash[i] ){
  83.             index = foff[i] >> NCAC_dev.extlog2;
  84.             new_extent = find_extent(ncac_req, index);
  85.             if ( NULL == new_extent ){ /* not cached */
  86.                 new_extent= allocate_extent(ncac_req,BLOCKING_EXTENT_ALLOC);
  87.                 if ( new_extent ){
  88.                     new_extent->index = index;
  89.                     new_extent->mapping = ncac_req->mapping;
  90.                     new_extent->ioreq = INVAL_IOREQ;
  91.  
  92.                     ret = init_extent_read(ncac_req, new_extent,
  93.                                          foff[i], NCAC_dev.extsize);
  94.                     if ( ret < 0 ) {
  95.                         NCAC_error("init_extent_read error ext:%p\n",
  96.                                  new_extent);
  97.  
  98.                         free_extent(ncac_req, new_extent);
  99.                         inode_unlock (&ncac_req->mapping->lock);
  100.                         return ret;
  101.                     }
  102.                     add_extent_to_cache(new_extent, index, ncac_req,
  103.                                         LRU_POLICY);
  104.                     set_extent_read_pending(new_extent);
  105.                     cbufhash[i] = new_extent;
  106.                 }
  107.             }else{ /* cached */
  108.                 cbufhash[i] = new_extent;
  109.                 hit_cache_item(new_extent, LRU_POLICY);
  110.             }
  111.  
  112.             /* only one reference for each request */
  113.             if ( cbufhash[i] && cbufhash[i] != last_extent )
  114.                 increase_read_reference(cbufhash[i]); 
  115.             last_extent = cbufhash[i];
  116.         }
  117.  
  118.         if ( cbufhash[i] ){
  119.             ret = 1;
  120.             if ( PageReadPending(cbufhash[i]) ){
  121.                 fprintf(stderr, "extent:%p ioreq:%lld\n", cbufhash[i], lld(cbufhash[i]->ioreq));
  122.                 ret = check_extent_read(ncac_req, cbufhash[i]);
  123.                 if (ret < 0){
  124.                     ncac_req->error = ret;    
  125.                     NCAC_error("check_read_pending extent=%p\n", cbufhash[i]);
  126.  
  127.                     inode_unlock (&ncac_req->mapping->lock);
  128.                     return ret;
  129.                 }
  130.             }
  131.             cbufflag[i] = ret;
  132.         }
  133.     }
  134.  
  135.     inode_unlock (&ncac_req->mapping->lock);
  136.  
  137.     readcnt = 0;
  138.     for (i=0; i<comcnt; i++){
  139.         if (ncac_req->cbufflag[i]) readcnt++;
  140.     }
  141.  
  142.     if (readcnt == ncac_req->cbufcnt) ncac_req->status = NCAC_BUFFER_COMPLETE;
  143.     else if (!readcnt) ncac_req->status = NCAC_REQ_SUBMITTED;
  144.     else ncac_req->status = NCAC_PARTIAL_PROCESS;
  145.  
  146.     fprintf(stderr, "NCAC_do_a_read_job: exit\n");
  147.     return 0;
  148. }
  149.  
  150. /* do a write job.
  151.  * return: <0 error code
  152.  *         0: ok
  153.  * ncac_req->status shows the current status of the job
  154.  * ncac_req->error shows the current error of the job if any.
  155.  */
  156.  
  157. int NCAC_do_a_write_job(struct NCAC_req *ncac_req)
  158. {
  159.     return 0;
  160.  
  161. } /* end of  do_a_write_job */
  162.  
  163.  
  164. int NCAC_do_a_query_job(struct NCAC_req *ncac_req)
  165. {
  166.     NCAC_error("NCAC_do_a_query_job: not implemented yet\n");
  167.     return 0;
  168. }
  169.  
  170. int NCAC_do_a_demote_job(struct NCAC_req *ncac_req)
  171. {
  172.     NCAC_error("NCAC_do_a_demote_job: not implemented yet\n");
  173.     return 0;
  174. }
  175.  
  176. int NCAC_do_a_sync_job(struct NCAC_req *ncac_req)
  177. {
  178.     NCAC_error("NCAC_do_a_sync_job: not implemented yet\n");
  179.     return 0;
  180. }
  181.  
  182.  
  183. /* 
  184.  * find_extent(): try to find an extent from the inode cache tree.
  185.  * This operation is protected by the inode lock. The caller should 
  186.  * acquire the inode lock.
  187.  */
  188. static inline struct extent *find_extent(NCAC_req_t *ncac_req, 
  189.                                         unsigned long index)
  190. {
  191.     struct extent *avail;
  192.  
  193.     avail = lookup_cache_item(ncac_req->mapping, index);
  194.     return avail;
  195. }
  196.  
  197.  
  198. /* 
  199.  * allocate_extent(): get a new extent. The caller should have 
  200.  * an inode lock. The flag is either BLOCKING_EXTENT_ALLOC or
  201.  * NONBLOCKING_EXTENT_ALLOC.
  202.  * If the "flag" is BLOCKING_EXTENT_ALLOC, if no extent is avaiable, 
  203.  * discard some if possible. Lock problem is a little more difficult 
  204.  * than others since this funtion may interact with the inode resource 
  205.  * and the cache resource.
  206.  * 
  207.  * This function is called by functions which holds its inode lock,
  208.  * only cache stack lock is needed.
  209.  */
  210.  
  211. static inline struct extent *allocate_extent(NCAC_req_t *ncac_req, int flag)
  212. {
  213.     struct extent *new = NULL;
  214.     struct cache_stack *cache;
  215.     unsigned int shrinked;
  216.  
  217.     char *buf;
  218.     int ret;
  219.  
  220.     cache = ncac_req->mapping->cache_stack;
  221.  
  222.     if ( !list_empty( &cache->free_extent_list ) ) {
  223.         cache_lock( &cache->lock);
  224.         new = get_free_extent_list_item( &(cache->free_extent_list) );
  225.         cache_unlock(&cache->lock);
  226.  
  227.         if ( new ) {
  228.             buf = new->addr;
  229.                memset(new, 0, sizeof(struct extent));
  230.             new->addr = buf;
  231.             SetPageBlank(new);
  232.             DPRINT("new extent:%p, flags:%lx\n", new, new->flags);
  233.             return new;
  234.         }
  235.     }
  236.  
  237.     /* No free extent so far */
  238.     if ( BLOCKING_EXTENT_ALLOC == flag ){
  239.  
  240.         cache_lock( &cache->lock);
  241.         ret = shrink_cache(cache, DELT_DISCARD_NUM, LRU_POLICY, &shrinked); 
  242.         if ( ret < 0 ) {
  243.             ncac_req->error = ret;
  244.             cache_unlock(&cache->lock);
  245.             return NULL;
  246.         }
  247.         new = get_free_extent_list_item( &(ncac_req->mapping->cache_stack->free_extent_list) );
  248.         cache_unlock(&cache->lock);
  249.  
  250.         if ( !new ) return NULL;
  251.         else {
  252.             buf = new->addr;
  253.                memset(new, 0, sizeof(struct extent));
  254.             new->addr = buf;
  255.             SetPageBlank(new);
  256.             DPRINT("new extent:%p, flags:%lx\n", new, new->flags);
  257.             return new;
  258.         }
  259.     }
  260.  
  261.     return NULL;
  262. }
  263.  
  264. /* add it later 
  265.  * free_extent: return an extent to a list
  266.  */
  267. static inline int free_extent(NCAC_req_t *ncac_req,struct extent *extent)
  268. {
  269.     return 0;
  270. }
  271.  
  272. /* 
  273.  * init_extent_read: initiate trove request to read an extent. The
  274.  * file offset is "foffset", and the size is "size".
  275.  */
  276. static inline int init_extent_read(NCAC_req_t *ncac_req, 
  277.                    struct extent *extent, PVFS_offset foffset, PVFS_size size)
  278. {
  279.     int ret;
  280.     PVFS_id_gen_t ioreq;
  281.  
  282.  
  283.     ret = init_io_read(ncac_req->coll_id, ncac_req->handle, 
  284.             ncac_req->context_id, foffset, size, extent->addr, &ioreq);
  285.     if ( ret < 0 ) {
  286.         NCAC_error("init_io_read error\n");
  287.         return ret;
  288.     }
  289.     extent->ioreq = ioreq;
  290.     fprintf(stderr, "init_extent_read: foff:%lld, size:%lld, extent:%p, opid:%lld\n", lld(foffset), lld(size), extent, lld(ioreq));
  291.     return 0;
  292. }
  293.  
  294. static inline void set_extent_read_pending(struct extent *extent)
  295. {
  296.     ClearPageBlank(extent);
  297.     SetPageReadPending(extent);
  298. }
  299.  
  300. static inline int check_extent_read(NCAC_req_t *ncac_req, struct extent *extent)
  301. {
  302.     int ret;
  303.  
  304.     ret = NCAC_check_ioreq(extent);
  305.     if ( ret > 0 ){
  306.          ClearPageReadPending(extent);
  307.         SetPageClean(extent);
  308.         return 1;
  309.     }
  310.     return 0;
  311. }
  312.  
  313. static inline void increase_read_reference(struct extent *extent)
  314. {
  315.     extent->reads ++;
  316.     return;
  317. }
  318.  
  319. static inline int add_extent_to_cache(struct extent * extent,
  320.             unsigned long index, NCAC_req_t *ncac_req, int policy)
  321. {
  322.     int ret;
  323.  
  324.     ret = add_cache_item(extent, ncac_req->mapping, index, policy);
  325.  
  326.     return ret;
  327. }
  328.