Пример #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;
}
Пример #2
0
int export_unlink_multiple(export_t * e, fid_t parent, char *name, fid_t fid,mattr_t * pattrs,lv2_entry_t *plv2) {
    int status = -1;
    lv2_entry_t *lv2=NULL;
    fid_t child_fid;
    uint32_t child_type;
    uint16_t nlink = 0;
    int fdp = -1;
    int ret;
    rozofs_inode_t *fake_inode_p;
    rmfentry_disk_t trash_entry;
    int root_dirent_mask = 0;
    int unknown_fid = 0;
    int deleted_fid_count = 0;
    char filename[1024];
    char *basename;
    int filecount;
    char *filename_p;
    int k;    

    /*
    ** search for rozofs key in the filename
    */
    if (strncmp(name,".@rozofs-mf@",12) == 0)
    {
      ret = rozofs_parse_object_name((char*)(name+12),&basename,&filecount);
      if (ret < 0)
      {
	errno = ENOTSUP;
	goto error;
      }
    }
    /*
    ** load the root_idx bitmap of the old parent
    */
    export_dir_load_root_idx_bitmap(e,parent,plv2);
    /*
    ** set global variables associated with the export
    */
    fdp = export_open_parent_directory(e,parent);
    if (get_mdirentry(plv2->dirent_root_idx_p,fdp, parent, name, child_fid, &child_type,&root_dirent_mask) != 0)
        goto out;

    if (S_ISDIR(child_type)) {
        errno = EISDIR;
        goto out;
    }
    /*
    ** do a loop on the file count
    */
    for (k = 0; k < filecount ; k++)
    {
      sprintf(filename,"%s.%d",basename,k);
      filename_p = filename;
      // Delete the mdirentry if exist
      ret =del_mdirentry(plv2->dirent_root_idx_p,fdp, parent, name, child_fid, &child_type,root_dirent_mask);
      if (ret != 0)
      {
	  if (errno != ENOENT) goto out;
	  /*
	  ** check the next entry
	  */
	  continue;
      }
      // Get mattrs of child to delete
      if (!(lv2 = export_lookup_fid(e->trk_tb_p,e->lv2_cache, child_fid)))
      {
	    unknown_fid++;
	    /*
	    ** check the next entry
	    */
	    continue;
      }
      deleted_fid_count++;    

      // Compute hash value for this fid
      uint32_t hash = 0;
      uint8_t *c = 0;
      for (c = lv2->attributes.s.attrs.fid; c != lv2->attributes.s.attrs.fid + 16; c++)
	  hash = *c + (hash << 6) + (hash << 16) - hash;
      hash %= RM_MAX_BUCKETS;	    
      /*
      ** prepare the trash entry
      */
      trash_entry.size = lv2->attributes.s.attrs.size;
      memcpy(trash_entry.fid, lv2->attributes.s.attrs.fid, sizeof (fid_t));
      trash_entry.cid = lv2->attributes.s.attrs.cid;
      memcpy(trash_entry.initial_dist_set, lv2->attributes.s.attrs.sids,
              sizeof (sid_t) * ROZOFS_SAFE_MAX);
      memcpy(trash_entry.current_dist_set, lv2->attributes.s.attrs.sids,
              sizeof (sid_t) * ROZOFS_SAFE_MAX);
      fake_inode_p =  (rozofs_inode_t *)parent;   
      ret = exp_trash_entry_create(e->trk_tb_p,fake_inode_p->s.usr_id,&trash_entry); 
      if (ret < 0)
      {
	 /*
	 ** error while inserting entry in trash file
	 */
	 severe("error on trash insertion name %s error %s",name,strerror(errno)); 
      }
      /*
      ** delete the metadata associated with the file
      */
      ret = exp_delete_file(e,lv2);
      /*
      * In case of geo replication, insert a delete request from the 2 sites 
      */
      if (e->volume->georep) 
      {
	/*
	** update the geo replication: set start=end=0 to indicate a deletion 
	*/
	geo_rep_insert_fid(e->geo_replication_tb[0],
                	   lv2->attributes.s.attrs.fid,
			   0/*start*/,0/*end*/,
			   e->layout,
			   lv2->attributes.s.attrs.cid,
			   lv2->attributes.s.attrs.sids);
	/*
	** update the geo replication: set start=end=0 to indicate a deletion 
	*/
	geo_rep_insert_fid(e->geo_replication_tb[1],
                	   lv2->attributes.s.attrs.fid,
			   0/*start*/,0/*end*/,
			   e->layout,
			   lv2->attributes.s.attrs.cid,
			   lv2->attributes.s.attrs.sids);
      }	
      /*
      ** Preparation of the rmfentry
      */
      rmfentry_t *rmfe = xmalloc(sizeof (rmfentry_t));
      export_rm_bins_pending_count++;
      memcpy(rmfe->fid, trash_entry.fid, sizeof (fid_t));
      rmfe->cid = trash_entry.cid;
      memcpy(rmfe->initial_dist_set, trash_entry.initial_dist_set,
              sizeof (sid_t) * ROZOFS_SAFE_MAX);
      memcpy(rmfe->current_dist_set, trash_entry.current_dist_set,
              sizeof (sid_t) * ROZOFS_SAFE_MAX);
      memcpy(rmfe->trash_inode,trash_entry.trash_inode,sizeof(fid_t));
      list_init(&rmfe->list);
      /* Acquire lock on bucket trash list
      */
      if ((errno = pthread_rwlock_wrlock
              (&e->trash_buckets[hash].rm_lock)) != 0) {
	  severe("pthread_rwlock_wrlock failed: %s", strerror(errno));
	  // Best effort
      }
      /*
      ** Check size of file 
      */
      if (lv2->attributes.s.attrs.size >= RM_FILE_SIZE_TRESHOLD) {
	  // Add to front of list
	  list_push_front(&e->trash_buckets[hash].rmfiles, &rmfe->list);
      } else {
	  // Add to back of list
	  list_push_back(&e->trash_buckets[hash].rmfiles, &rmfe->list);
      }

      if ((errno = pthread_rwlock_unlock
              (&e->trash_buckets[hash].rm_lock)) != 0) {
	  severe("pthread_rwlock_unlock failed: %s", strerror(errno));
	  // Best effort
      }
      // Update the nb. of blocks
      if (export_update_blocks(e,
              -(((int64_t) lv2->attributes.s.attrs.size + ROZOFS_BSIZE_BYTES(e->bsize) - 1)
              / ROZOFS_BSIZE_BYTES(e->bsize))) != 0) {
	  severe("export_update_blocks failed: %s", strerror(errno));
	  // Best effort
      }
      // Remove from the cache (will be closed and freed)
      lv2_cache_del(e->lv2_cache, child_fid);
    }  
    /*
    ** al the subfile have been deleted so  Update export files
    */
    if (export_update_files(e, 0-deleted_fid_count) != 0)
      goto out;

    // Update parent
    plv2->attributes.s.attrs.mtime = plv2->attributes.s.attrs.ctime = time(NULL);
    plv2->attributes.s.attrs.children--;

    // Write attributes of parents
    if (export_lv2_write_attributes(e->trk_tb_p,plv2) != 0)
        goto out;
    /*
    ** return the parent attributes
    */
    memcpy(pattrs, &plv2->attributes.s.attrs, sizeof (mattr_t));
    status = 0;

out:
    /*
    ** check if parent root idx bitmap must be updated
    */
    if (plv2 != NULL) export_dir_flush_root_idx_bitmap(e,parent,plv2->dirent_root_idx_p);
    
    if(fdp != -1) close(fdp);
    return status;
}