Exemple #1
0
void rozofs_ll_lookup_nb(fuse_req_t req, fuse_ino_t parent, const char *name) 
{
    ientry_t *ie = 0;
    ientry_t *nie = 0;
    epgw_lookup_arg_t arg;
    int    ret;        
    void *buffer_p = NULL;
    int trc_idx;
    mattr_obj_t mattr_obj;
    struct fuse_entry_param fep;
    struct stat stbuf;
    int allocated = 0;
    int len_name;
    fuse_ino_t child = 0;   
//    int  local_lookup_success = 0;
    uint32_t lookup_flags=0;
    int extra_length = 0;
    fuse_ino_t ino = 0;
    int trace_flag = 0;

    /*
    ** Update the IO statistics
    */
    rozofs_thr_cnt_update(rozofs_thr_counter[ROZOFSMOUNT_COUNTER_LOOKUP], 1);
    
    extra_length = rozofs_check_extra_inode_in_lookup((char*)name, &len_name);
    if (extra_length !=0)
    {
       uint8_t *pdata_p;
       uint32_t *lookup_flags_p = (uint32_t*)&name[len_name+1];
       lookup_flags =*lookup_flags_p;
       if (extra_length > 4)
       {
         pdata_p = (uint8_t*)&name[len_name+1];
	 pdata_p+=sizeof(uint32_t);
	 fuse_ino_t *inode_p = (fuse_ino_t*)pdata_p;
	 child = *inode_p;
	 ino = child;
       }
    }
    trace_flag = lookup_flags;
    if (ino != 0) {trace_flag |=(1<<31);}
    trc_idx = rozofs_trc_req_name_flags(srv_rozofs_ll_lookup,parent,(char*)name,(int)(trace_flag));
    /*
    ** allocate a context for saving the fuse parameters
    */
    buffer_p = rozofs_fuse_alloc_saved_context();
    if (buffer_p == NULL)
    {
      severe("out of fuse saved context");
      errno = ENOMEM;
      goto error;
    }
    SAVE_FUSE_PARAM(buffer_p,req);
    SAVE_FUSE_PARAM(buffer_p,parent);
    SAVE_FUSE_STRING(buffer_p,name);
    SAVE_FUSE_PARAM(buffer_p,trc_idx);
    SAVE_FUSE_PARAM(buffer_p,ino);
    SAVE_FUSE_PARAM(buffer_p,lookup_flags);
    

    DEBUG("lookup (%lu,%s)\n", (unsigned long int) parent, name);

    START_PROFILING_NB(buffer_p,rozofs_ll_lookup);
    len_name=strlen(name);
    if (len_name > ROZOFS_FILENAME_MAX) {
        errno = ENAMETOOLONG;
        goto error;
    }
    /*
    ** Check the case of NFS that attempt to revalidate an inode that has been flushed from the cache
    */
    if ((strcmp(name,"..")== 0) || (strcmp(name,".")==0))
    {
       fid_t lookup_fid;
       rozofs_inode_t *inode_p = (rozofs_inode_t*)lookup_fid;
       inode_p->fid[0]=0;
       inode_p->s.eid= exportclt.eid;
       inode_p->fid[1]=parent;
              
       arg.arg_gw.eid = exportclt.eid;
       memcpy(arg.arg_gw.parent,lookup_fid, sizeof (uuid_t));
       arg.arg_gw.name = (char*)name;    
       /*
       ** Queue the request and attempt to check if there is already the same
       ** request queued
       */
       if (rozofs_lookup_insert_queue(buffer_p,parent,name,req,trc_idx,lookup_flags)== 1)
       {
	 /*
	 ** There is already a pending request, so nothing to send to the export
	 */
	 gprofiler->rozofs_ll_lookup_agg[P_COUNT]++;
	 rozofs_fuse_release_saved_context(buffer_p);
	 return;
       }

       
       ret = rozofs_expgateway_send_routing_common(arg.arg_gw.eid,lookup_fid,EXPORT_PROGRAM, EXPORT_VERSION,
                        	 EP_LOOKUP,(xdrproc_t) xdr_epgw_lookup_arg_t,(void *)&arg,
                        	 rozofs_ll_lookup_cbk,buffer_p); 
       if (ret < 0) goto error;
       /*
       ** no error just waiting for the answer
       */
       return;    
    }
    if (!(ie = get_ientry_by_inode(parent))) {
        errno = ENOENT;
        goto error;
    }
    /*
    ** check for direct access
    */
    if (strncmp(name,"@rozofs@",8) == 0)
    {
      ret = rozofs_parse_object_name((char*)(name+8),&mattr_obj);
      if (ret == 0)
      {
	/*
	** successful parsing-> attempt to create a fake ientry
	*/
	//errno = ENOENT;
	goto lookup_objectmode;
      }     
    }    
    /*
    ** Queue the request and attempt to check if there is already the same
    ** request queued
    */
    if (rozofs_lookup_insert_queue(buffer_p,parent,name,req,trc_idx,lookup_flags)== 1)
    {
      /*
      ** There is already a pending request, so nothing to send to the export
      */
      gprofiler->rozofs_ll_lookup_agg[P_COUNT]++;
      rozofs_fuse_release_saved_context(buffer_p);
      return;
    }
    /*
    ** check if the lookup is a lookup revalidate. In such a case, the VFS provides*
    ** the inode. So if the i-node attributes are fine, we do not worry
    */
    if ((child != 0) && ((lookup_flags & 0x100) == 0))
    {
      uint64_t attr_us = rozofs_tmr_get_attr_us(rozofs_is_directory_inode(ino));    
      nie = get_ientry_by_inode(child);
      if (nie != NULL)
      {
	if (
           /* check regular file */
           ((((nie->timestamp+attr_us) > rozofs_get_ticker_us()) || (rozofs_mode == 1))&&(S_ISREG(nie->attrs.attrs.mode))) ||
	   /* check directory */
	   (((nie->pending_getattr_cnt>0)||((nie->timestamp+attr_us) > rozofs_get_ticker_us()))&&(S_ISDIR(nie->attrs.attrs.mode)))
	   ) 
        {
	  /*
	  ** check if parent and child are either deleted/deleted or active/active
	  */
	  int trash_state = 0;
	  if (rozofs_inode_is_del_pending(ie->attrs.attrs.fid)) trash_state = 1;
	  if (rozofs_inode_is_del_pending(nie->attrs.attrs.fid)) trash_state |= 1<<1;
	  switch (trash_state)
	  {
	     case 2:
	       if (rozofs_inode_is_trash(nie->attrs.attrs.fid) == 0)
	       {
		 errno = ENOENT;
		 goto error;
	       }	         
	       mattr_to_stat(&nie->attrs, &stbuf,exportclt.bsize);
	       stbuf.st_ino = child;
	       /*
	       ** set nlinks to reflect . & ..
	       */
	       stbuf.st_nlink =2;
	       goto success;
	       break;

	     case 0:
	     case 3:
	      mattr_to_stat(&nie->attrs, &stbuf,exportclt.bsize);
	      stbuf.st_ino = child;
	      goto success; 
	      break;
	     
	      
	    default: 
	     errno = ENOENT;
	     goto error;
	     break;  	  	  
	  }	    
	}                
      }
    }
    /*
    ** fill up the structure that will be used for creating the xdr message
    */    
    arg.arg_gw.eid = exportclt.eid;
    memcpy(arg.arg_gw.parent,ie->fid, sizeof (uuid_t));
    arg.arg_gw.name = (char*)name;    
    /*
    ** now initiates the transaction towards the remote end
    */
    
    
    /*
    ** In case the EXPORT LBG is down ans we know this ientry, let's respond to
    ** the requester with the current available information
    */
#if 1
    if ((common_config.client_fast_reconnect) && (child != 0)) {
      expgw_tx_routing_ctx_t routing_ctx; 
      
      if (expgw_get_export_routing_lbg_info(arg.arg_gw.eid,ie->fid,&routing_ctx) != 0) {
         goto error;
      }
      if (north_lbg_get_state(routing_ctx.lbg_id[0]) != NORTH_LBG_UP) {
	  if (!(nie = get_ientry_by_inode(child))) {
              errno = ENOENT;
              goto error;
	  }
	  mattr_to_stat(&nie->attrs, &stbuf,exportclt.bsize);
	  stbuf.st_ino = child;
	  goto success;        
      }      
    }  
#endif         
    
#if 1
    ret = rozofs_expgateway_send_routing_common(arg.arg_gw.eid,ie->fid,EXPORT_PROGRAM, EXPORT_VERSION,
                              EP_LOOKUP,(xdrproc_t) xdr_epgw_lookup_arg_t,(void *)&arg,
                              rozofs_ll_lookup_cbk,buffer_p); 
    
#else
    ret = rozofs_export_send_common(&exportclt,EXPORT_PROGRAM, EXPORT_VERSION,
                              EP_LOOKUP,(xdrproc_t) xdr_epgw_lookup_arg_t,(void *)&arg,
                              rozofs_ll_lookup_cbk,buffer_p); 
#endif
    if (ret < 0) {
      /*
      ** In case of fast reconnect mode let's respond with the previously knows 
      ** parameters instead of failing
      */
      if (common_config.client_fast_reconnect) {
        if (child != 0) {
	  if (!(nie = get_ientry_by_inode(child))) {
              errno = ENOENT;
              goto error;
	  }
	  mattr_to_stat(&nie->attrs, &stbuf,exportclt.bsize);
	  stbuf.st_ino = child;
	  goto success;
        }
      }
      goto error;
    }
    /*
    ** no error just waiting for the answer
    */

    return;

error:
    fuse_reply_err(req, errno);
    /*
    ** remove the context from the lookup queue
    */
    if (buffer_p != NULL) ruc_objRemove(buffer_p);
    /*
    ** release the buffer if has been allocated
    */
    rozofs_trc_rsp(srv_rozofs_ll_lookup,parent,NULL,1,trc_idx);
out:
    STOP_PROFILING_NB(buffer_p,rozofs_ll_lookup);
    if (buffer_p != NULL) rozofs_fuse_release_saved_context(buffer_p);

    return;
    /**
    * case of the object mode
    */
lookup_objectmode:
    if (!(nie = get_ientry_by_fid(mattr_obj.fid))) {
        nie = alloc_ientry(mattr_obj.fid);
	allocated=1;
    } 
    /**
    *  update the timestamp in the ientry context
    */
    nie->timestamp = rozofs_get_ticker_us();
    if (allocated)
    {
      /*
      ** update the attributes in the ientry
      */
      memcpy(nie->attrs.attrs.fid, mattr_obj.fid, sizeof(fid_t));
      nie->attrs.attrs.cid = mattr_obj.cid;
      memcpy(nie->attrs.attrs.sids, mattr_obj.sids, sizeof(sid_t)*ROZOFS_SAFE_MAX);
      nie->attrs.attrs.size = mattr_obj.size;
      nie->attrs.attrs.nlink = 1;
      nie->attrs.attrs.mode = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO ;
      nie->attrs.attrs.uid = 0;
      nie->attrs.attrs.gid = 0;
      nie->nlookup   = 0;
    }   
    mattr_to_stat(&nie->attrs, &stbuf,exportclt.bsize);
    stbuf.st_ino = nie->inode;

//    info("FDL %d mode %d  uid %d gid %d",allocated,nie->attrs.attrs.mode,nie->attrs.attrs.uid,nie->attrs.attrs.gid);
success:
    memset(&fep, 0, sizeof (fep));
    fep.ino =stbuf.st_ino;  
    fep.attr_timeout = rozofs_tmr_get_attr(rozofs_is_directory_inode(nie->inode));
    fep.entry_timeout = rozofs_tmr_get_entry(rozofs_is_directory_inode(nie->inode));
    memcpy(&fep.attr, &stbuf, sizeof (struct stat));
    nie->nlookup++;

    rozofs_inode_t * finode = (rozofs_inode_t *) nie->attrs.attrs.fid;
    fep.generation = finode->fid[0];    
    
    rz_fuse_reply_entry(req, &fep);

    rozofs_trc_rsp(srv_rozofs_ll_lookup,(nie==NULL)?0:nie->inode,(nie==NULL)?NULL:nie->attrs.attrs.fid,0,trc_idx);
    goto out;
}
Exemple #2
0
void rozofs_ll_open_nb(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) {
    ientry_t *ie = 0;
    int    ret;        
    void *buffer_p = NULL;
    epgw_mfile_arg_t arg;
    file_t *file = NULL;
    errno = 0;

    /*
    ** Update the IO statistics
    */
    rozofs_thr_cnt_update(rozofs_thr_counter[ROZOFSMOUNT_COUNTER_OTHER], 1);

    int trc_idx = rozofs_trc_req_flags(srv_rozofs_ll_open,ino,NULL,fi->flags);
    /*
    ** allocate a context for saving the fuse parameters
    */
    buffer_p = rozofs_fuse_alloc_saved_context();
    if (buffer_p == NULL)
    {
      severe("out of fuse saved context");
      errno = ENOMEM;
      goto error;
    }
    SAVE_FUSE_PARAM(buffer_p,req);
    SAVE_FUSE_PARAM(buffer_p,ino);
    SAVE_FUSE_PARAM(buffer_p,trc_idx);
    SAVE_FUSE_STRUCT(buffer_p,fi,sizeof( struct fuse_file_info));

    START_PROFILING_NB(buffer_p,rozofs_ll_open);

    DEBUG("open (%lu)\n", (unsigned long int) ino);

    if (!(ie = get_ientry_by_inode(ino))) {
        errno = ENOENT;
        goto error;
    }
    /*
    ** check if it is configured in block mode, in that case we avoid
    ** a transaction with the exportd
    */
    if ((rozofs_mode == 1) ||
       ((ie->timestamp+rozofs_tmr_get_attr_us(rozofs_is_directory_inode(ino))) > rozofs_get_ticker_us()))
    {
      /*
      ** allocate a context for the file descriptor
      */
      file = rozofs_file_working_var_init(ie,ie->fid);
      if (rozofs_cache_mode == 1)
         fi->direct_io = 1;
      else
      {
        if (rozofs_cache_mode == 2)
          fi->keep_cache = 1;
      }
      /*
      ** save the opening flags
      */
      file->open_flags = fi->flags;

      fi->fh = (unsigned long) file;
      /*
      ** update the statistics
      */
      rzkpi_file_stat_update(ie->pfid,(int)0,RZKPI_OPEN);
      /*
      ** Take care of the file caching cache for hybrid SSD/HDD configuration
      */
      rzcachetrack_file(ie->pfid,ie->attrs.attrs.size,ie->attrs.attrs.mtime);
      /*
      ** send back response to fuse
      */
      fuse_reply_open(req, fi);
      goto out; 
    }    
    /*
    ** get the attributes of the file
    */
    arg.arg_gw.eid = exportclt.eid;
    memcpy(arg.arg_gw.fid, ie->fid, sizeof (uuid_t));
    /*
    ** now initiates the transaction towards the remote end
    */

    /*
    ** In case the EXPORT LBG is down and we know this ientry, let's respond to
    ** the requester with the current available information
    */
    if (common_config.client_fast_reconnect) {
      expgw_tx_routing_ctx_t routing_ctx; 
      
      if (expgw_get_export_routing_lbg_info(arg.arg_gw.eid,ie->fid,&routing_ctx) != 0) {
         goto error;
      }
      if (north_lbg_get_state(routing_ctx.lbg_id[0]) != NORTH_LBG_UP) {
	goto short_cut;           
      }      
    } 

#if 1
    ret = rozofs_expgateway_send_routing_common(arg.arg_gw.eid,ie->fid,EXPORT_PROGRAM, EXPORT_VERSION,
                              EP_GETATTR,(xdrproc_t) xdr_epgw_mfile_arg_t,(void *)&arg,
                              rozofs_ll_open_cbk,buffer_p); 
#else
    ret = rozofs_export_send_common(&exportclt,EXPORT_PROGRAM, EXPORT_VERSION,
                              EP_GETATTR,(xdrproc_t) xdr_epgw_mfile_arg_t,(void *)&arg,
                              rozofs_ll_open_cbk,buffer_p); 

#endif
    if (ret < 0) {
      /*
      ** In case of fast reconnect mode let's respond with the previously knows 
      ** parameters instead of failing
      */
      if (common_config.client_fast_reconnect) {
short_cut:
	/*
	** allocate a context for the file descriptor
	*/
	file = rozofs_file_working_var_init(ie,ie->fid);
	if (rozofs_cache_mode == 1)
           fi->direct_io = 1;
	else
	{
          if (rozofs_cache_mode == 2)
            fi->keep_cache = 1;
	}
	/*
	** save the opening flags
	*/
	file->open_flags = fi->flags;
	fi->fh = (unsigned long) file;
	/*
	** update the statistics
	*/
	rzkpi_file_stat_update(ie->pfid,(int)0,RZKPI_OPEN);
	/*
	** Take care of the file caching cache for hybrid SSD/HDD configuration
	*/
	rzcachetrack_file(ie->pfid,ie->attrs.attrs.size,ie->attrs.attrs.mtime);
	/*
	** send back response to fuse
	*/
	fuse_reply_open(req, fi);
	goto out;         
      }
      goto error;  
    }    
    /*
    ** no error just waiting for the answer
    */
    return;
error:
    fuse_reply_err(req, errno);
    /*
    ** release the buffer if has been allocated
    */
out:
    rozofs_trc_rsp_attr(srv_rozofs_ll_open,(fuse_ino_t)file,(ie==NULL)?NULL:ie->attrs.attrs.fid,(errno==0)?0:1,(ie==NULL)?-1:ie->attrs.attrs.size,trc_idx);
    STOP_PROFILING_NB(buffer_p,rozofs_ll_open);
    if (buffer_p != NULL) rozofs_fuse_release_saved_context(buffer_p);

    return;
}