Beispiel #1
0
void rozofs_ll_create_nb(fuse_req_t req, fuse_ino_t parent, const char *name,
        mode_t mode, struct fuse_file_info *fi) 
{
    ientry_t *ie = 0;
    const struct fuse_ctx *ctx;
    ctx = fuse_req_ctx(req);
    epgw_mknod_arg_t arg;

    int    ret;
    void *buffer_p = NULL;
    int trc_idx = rozofs_trc_req_name(srv_rozofs_ll_create,parent,(char*)name);
    /*
    ** 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,mode);
    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_create);
    
    DEBUG("create (%lu,%s,%04o)\n", (unsigned long int) parent, name,
            (unsigned int) mode);

    if (strlen(name) > ROZOFS_FILENAME_MAX) {
        errno = ENAMETOOLONG;
        goto error;
    }
    if (!(ie = get_ientry_by_inode(parent))) {
        errno = ENOENT;
        goto error;
    }
    /*
    ** 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;    
    arg.arg_gw.uid  = ctx->uid;
    arg.arg_gw.gid  = ctx->gid;
    arg.arg_gw.mode = mode;
    /*
    ** now initiates the transaction towards the remote end
    */
#if 1
    ret = rozofs_expgateway_send_routing_common(arg.arg_gw.eid,ie->fid,EXPORT_PROGRAM, EXPORT_VERSION,
                              EP_MKNOD,(xdrproc_t) xdr_epgw_mknod_arg_t,(void *)&arg,
                              rozofs_ll_create_cbk,buffer_p); 
#else
    ret = rozofs_export_send_common(&exportclt,EXPORT_PROGRAM, EXPORT_VERSION,
                              EP_MKNOD,(xdrproc_t) xdr_epgw_mknod_arg_t,(void *)&arg,
                              rozofs_ll_create_cbk,buffer_p); 
#endif
    if (ret < 0) goto error;
    
    /*
    ** no error just waiting for the answer
    */
    return;
error:
    fuse_reply_err(req, errno);
    rozofs_trc_rsp(srv_rozofs_ll_create,parent,NULL,1,trc_idx);
    STOP_PROFILING_NB(buffer_p,rozofs_ll_create);
    if (buffer_p != NULL) rozofs_fuse_release_saved_context(buffer_p);
    return;
}
Beispiel #2
0
 void rozofs_ll_getattr_nb(fuse_req_t req, fuse_ino_t ino,
        struct fuse_file_info *fi) 
{
    (void) fi;
    ientry_t *ie = 0;
    epgw_mfile_arg_t arg;
    int ret;
    struct stat stbuf;
    int trc_idx;
    errno = 0;


    trc_idx = rozofs_trc_req(srv_rozofs_ll_getattr,ino,NULL);
    DEBUG("getattr for inode: %lu\n", (unsigned long int) ino);
    void *buffer_p = NULL;
    /*
    ** 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_getattr);

    if (!(ie = get_ientry_by_inode(ino))) {
        errno = ENOENT;
        goto error;
    }
    /*
    ** In block mode the attributes of regular files are directly retrieved 
    ** from the ie entry. For directories and links one ask to the exportd
    ** 
    */

//    severe("FDL ie %llu cur_time %llu %s %u",ie->timestamp+rozofs_tmr_get(TMR_FUSE_ATTR_CACHE)*1000000,rozofs_get_ticker_us(),
//     ((ie->timestamp+rozofs_tmr_get(TMR_FUSE_ATTR_CACHE)*1000000) > rozofs_get_ticker_us())?"Match":"no Match",
//     rozofs_tmr_get(TMR_FUSE_ATTR_CACHE)*1000000);
    if (((rozofs_mode == 1) || ((ie->timestamp+rozofs_tmr_get(TMR_FUSE_ATTR_CACHE)*1000000) > rozofs_get_ticker_us()))
         &&(S_ISREG(ie->attrs.mode))) 
    {
      mattr_to_stat(&ie->attrs, &stbuf);
      stbuf.st_ino = ino; 
      fuse_reply_attr(req, &stbuf, rozofs_tmr_get(TMR_FUSE_ATTR_CACHE));
      goto out;   
    }
    /*
    ** fill up the structure that will be used for creating the xdr message
    */    
    arg.arg_gw.eid = exportclt.eid;
    memcpy(arg.arg_gw.fid, ie->fid, sizeof (uuid_t));
    /*
    ** now initiates the transaction towards the remote end
    */
#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_getattr_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_getattr_cbk,buffer_p); 
#endif
    if (ret < 0) 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(srv_rozofs_ll_getattr,0/*ino*/,(ie==NULL)?NULL:ie->attrs.fid,(errno==0)?0:1,trc_idx);
    STOP_PROFILING_NB(buffer_p,rozofs_ll_getattr);
    if (buffer_p != NULL) rozofs_fuse_release_saved_context(buffer_p);

    return;
}
Beispiel #3
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;
}
Beispiel #4
0
void rozofs_ll_setxattr_nb(fuse_req_t req, fuse_ino_t ino, const char *name, const char *value, size_t size, int flags) 
{
    ientry_t         *ie = 0;
    int               ret;        
    void             *buffer_p = NULL;
    epgw_setxattr_arg_t arg;


    DEBUG("setxattr (inode: %lu, name: %s, value: %s, size: %llu)\n",
            (unsigned long int) ino, name, value,
            (unsigned long long int) size);
	    
    /*
    ** allocate a context for saving the fuse parameters
    */
    int trc_idx = rozofs_trc_req_name(srv_rozofs_ll_setxattr,ino,(char*)name);
    buffer_p = rozofs_fuse_alloc_saved_context();
    if (buffer_p == NULL)
    {
      severe("out of fuse saved context");
      errno = ENOMEM;
      goto error;
    }
    START_PROFILING_NB(buffer_p,rozofs_ll_setxattr);

    if (!(ie = get_ientry_by_inode(ino))) {
        errno = ENOENT;
        goto error;
    }

    
    SAVE_FUSE_PARAM(buffer_p,req);
    SAVE_FUSE_PARAM(buffer_p,ino);
    SAVE_FUSE_PARAM(buffer_p,trc_idx);


    // Invalidate ientry
    if ((strcmp(name,ROZOFS_XATTR)==0)||(strcmp(name,ROZOFS_USER_XATTR)==0)||(strcmp(name,ROZOFS_ROOT_XATTR)==0)) {
        ie->timestamp=0;
    }
    /*
    ** update the mode at the ientry level when it extended attribute is ACL
    */
    rozofs_acl_access_check(name,value,size,(mode_t*)&ie->attrs.mode);
    /*
    ** Set xattr indicator in ientry
    */
    rozofs_set_xattr_flag(&ie->attrs.mode);
    
    /*
    ** fill up the structure that will be used for creating the xdr message
    */    
    arg.arg_gw.eid = exportclt.eid;
    memcpy(arg.arg_gw.fid,  ie->fid, sizeof (uuid_t));
    arg.arg_gw.name = (char *)name;
    arg.arg_gw.value.value_len = size;
    arg.arg_gw.value.value_val = (char *)value;
    arg.arg_gw.flags = flags;    
    
    /*
    ** now initiates the transaction towards the remote end
    */
#if 1
    ret = rozofs_expgateway_send_routing_common(arg.arg_gw.eid,(unsigned char*)arg.arg_gw.fid,EXPORT_PROGRAM, EXPORT_VERSION,
                              EP_SETXATTR,(xdrproc_t) xdr_epgw_setxattr_arg_t,(void *)&arg,
                              rozofs_ll_setxattr_cbk,buffer_p); 
#else
    ret = rozofs_export_send_common(&exportclt,ROZOFS_TMR_GET(TMR_EXPORT_PROGRAM),EXPORT_PROGRAM, EXPORT_VERSION,
                              EP_SETXATTR,(xdrproc_t) xdr_epgw_setxattr_arg_t,(void *)&arg,
                              rozofs_ll_setxattr_cbk,buffer_p); 
#endif
    if (ret < 0) goto error;
    
    /*
    ** no error just waiting for the answer
    */
    return;

error:
    fuse_reply_err(req, errno);
    /*
    ** release the buffer if has been allocated
    */
    rozofs_trc_rsp(srv_rozofs_ll_setxattr,ino,NULL,1,trc_idx);
    STOP_PROFILING_NB(buffer_p,rozofs_ll_setxattr);
    if (buffer_p != NULL) rozofs_fuse_release_saved_context(buffer_p);
    return;
}