⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 afr_self_heal.c

📁 分布式文件系统
💻 C
字号:
/*   Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com>   This file is part of GlusterFS.   GlusterFS is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published   by the Free Software Foundation; either version 3 of the License,   or (at your option) any later version.   GlusterFS is distributed in the hope that it will be useful, but   WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program.  If not, see   <http://www.gnu.org/licenses/>.*/#include <libgen.h>#include <unistd.h>#include <fnmatch.h>#include <sys/time.h>#include <stdlib.h>#include "compat.h"#include "glusterfs.h"#include "afr.h"#include "dict.h"#include "xlator.h"#include "hashfn.h"#include "logging.h"#include "stack.h"#include "list.h"#include "call-stub.h"#include "defaults.h"#include "common-utils.h"enum {  AFR_LABEL_1,  AFR_LABEL_2,  AFR_LABEL_3,  AFR_LABEL_4,  AFR_LABEL_5,  AFR_LABEL_6,  AFR_LABEL_7,  AFR_LABEL_8,  AFR_LABEL_9,};#define AFR_DEBUG_FMT(xl, format, args...) if(((afr_private_t*)(xl)->private)->debug) gf_log ((xl)->name, GF_LOG_DEBUG, "AFRDEBUG:" format, ##args);#define AFR_DEBUG(xl) if(((afr_private_t*)xl->private)->debug) gf_log (xl->name, GF_LOG_DEBUG, "AFRDEBUG:");extern int32_tafr_lookup_unlock_cbk (call_frame_t *frame,		       void *cookie,		       xlator_t *this,		       int32_t op_ret,		       int32_t op_errno);void afr_lookup_directory_selfheal (call_frame_t*);voiddummy_inode_destroy (inode_t * inode){  dict_destroy (inode->ctx);  LOCK_DESTROY (&inode->lock);  freee (inode);}static inode_t *dummy_inode (inode_table_t *table){  inode_t *dummy;  dummy = calloc (1, sizeof (*dummy));  dummy->table = table;  INIT_LIST_HEAD (&dummy->list);  INIT_LIST_HEAD (&dummy->inode_hash);  INIT_LIST_HEAD (&dummy->fds);  INIT_LIST_HEAD (&dummy->dentry.name_hash);  INIT_LIST_HEAD (&dummy->dentry.inode_list);  dummy->ref = 1;  dummy->ctx = get_new_dict ();  LOCK_INIT (&dummy->lock);  return dummy;}int32_tafr_lds_closedir_cbk (call_frame_t *frame,		      void *cookie,		      xlator_t *this,		      int32_t op_ret,		      int32_t op_errno){  int32_t callcnt;  afr_local_t *local = frame->local;  afr_selfheal_private_t *asp = local->asp;  if (op_ret == -1) {    asp->error = 1;    GF_ERROR (this, "op_ret=-1 op_errno=%d", op_errno);  }  LOCK(&frame->lock);  callcnt = --local->call_count;  UNLOCK(&frame->lock);  if (callcnt == 0)    afr_lookup_directory_selfheal (frame);  return 0;}int32_tafr_lds_setxattr_cbk (call_frame_t *frame,		      void *cookie,		      xlator_t *this,		      int32_t op_ret,		      int32_t op_errno){  int32_t callcnt;  afr_local_t *local = frame->local;  afr_selfheal_private_t *asp = local->asp;  if (op_ret == -1) {    asp->error = 1;    GF_ERROR (this, "op_ret=-1 op_errno=%d", op_errno);  }  LOCK(&frame->lock);  callcnt = --local->call_count;  UNLOCK(&frame->lock);  if (callcnt == 0)    afr_lookup_directory_selfheal (frame);  return 0;}int32_tafr_lds_setdents_cbk (call_frame_t *frame,		      void *cookie,		      xlator_t *this,		      int32_t op_ret,		      int32_t op_errno){  int32_t callcnt;  afr_local_t *local = frame->local;  afr_selfheal_private_t *asp = local->asp;  if (op_ret == -1) {    asp->error = 1;    GF_ERROR (this, "op_ret=-1 op_errno=%d", op_errno);  }  LOCK(&frame->lock);  callcnt = --local->call_count;  UNLOCK(&frame->lock);  if (callcnt == 0)    afr_lookup_directory_selfheal (frame);  return 0;}int32_tafr_lds_rmelem_cbk (call_frame_t *frame,		    void *cookie,		    xlator_t *this,		    int32_t op_ret,		    int32_t op_errno){  int32_t callcnt;  afr_local_t *local = frame->local;  afr_selfheal_private_t *asp = local->asp;  if (op_ret == -1) {    asp->error = 1;    GF_ERROR (this, "op_ret=-1 op_errno=%d", op_errno);  }  LOCK(&frame->lock);  callcnt = --local->call_count;  UNLOCK(&frame->lock);  if (callcnt == 0) {    dir_entry_t *entry;    for (entry = asp->entries; entry;) {      dir_entry_t *temp;      temp = entry;      entry = temp->next;      if (temp->name)	freee (temp->name);      freee (temp);    }    afr_lookup_directory_selfheal (frame);  }  return 0;}int32_tafr_lds_lookup_cbk (call_frame_t *frame,		    void *cookie,		    xlator_t *this,		    int32_t op_ret,		    int32_t op_errno,		    inode_t *inode,		    struct stat *buf,		    dict_t *xattr){  int32_t callcnt;  afr_local_t *local = frame->local;  afr_selfheal_private_t *asp = local->asp;  dir_entry_t *entry = asp->entries;  if (inode != NULL)    inode_destroy (inode);  else    GF_ERROR (this, "inode is NULL");  if (op_ret == -1 && op_errno != ENOENT) {    asp->error = 1;    GF_ERROR (this, "op_ret=-1 op_errno=%d", op_errno);  }  LOCK(&frame->lock);  if (op_ret == 0) {    if (entry == cookie) {      freee (entry->name);      entry->name = NULL;    } else {      while (entry) {	if (entry->next == cookie) {	  freee (entry->next->name);	  entry->next->name = NULL;	  break;	}	entry = entry->next;      }    }  }  callcnt = --local->call_count;  UNLOCK(&frame->lock);  if (callcnt == 0)    afr_lookup_directory_selfheal (frame);  return 0;}int32_tafr_lds_getdents_cbk (call_frame_t *frame,		      void *cookie,		      xlator_t *this,		      int32_t op_ret,		      int32_t op_errno,		      dir_entry_t *entry,		      int32_t count){  afr_local_t *local = frame->local;  afr_selfheal_private_t *asp = local->asp;  if (op_ret == -1) {    asp->error = 1;    GF_ERROR (this, "op_ret=-1 op_errno=%d", op_errno);  } else    asp->dents_count = count;  if (count > 0) {    asp->entries = entry->next;    entry->next = NULL;  }  afr_lookup_directory_selfheal(frame);  return 0;}int32_tafr_lds_opendir_cbk (call_frame_t *frame,		     void *cookie,		     xlator_t *this,		     int32_t op_ret,		     int32_t op_errno,		     fd_t *fd){  int32_t callcnt;  afr_local_t *local = frame->local;  afr_selfheal_private_t *asp = local->asp;  LOCK (&frame->lock);  callcnt = --local->call_count;  UNLOCK (&frame->lock);  if (op_ret == -1) {    asp->error = 1;    GF_ERROR (this, "op_ret=-1 op_errno=%d", op_errno);  }  if (callcnt == 0) {    afr_lookup_directory_selfheal (frame);  }  return 0;}void afr_lookup_directory_selfheal(call_frame_t *frame){  afr_private_t *pvt = frame->this->private;  afr_local_t *local = frame->local;  afr_selfheal_private_t *asp = local->asp;  int32_t child_count = pvt->child_count, i;  afr_selfheal_t *ashptr = local->ashptr;  xlator_t **children = pvt->children;  dir_entry_t *entry;  int32_t latest = local->latest;  int32_t cnt;  local = frame->local;  asp = local->asp;  if (asp == NULL)    goto AFR_LABEL_1_GOTO;  i = asp->i;  switch (asp->label) {  case AFR_LABEL_2:    goto AFR_LABEL_2_GOTO;  case AFR_LABEL_3:    goto AFR_LABEL_3_GOTO;  case AFR_LABEL_4:    goto AFR_LABEL_4_GOTO;  case AFR_LABEL_5:    goto AFR_LABEL_5_GOTO;  case AFR_LABEL_6:    goto AFR_LABEL_6_GOTO;  case AFR_LABEL_7:    goto AFR_LABEL_7_GOTO;  case AFR_LABEL_8:    goto AFR_LABEL_8_GOTO;  case AFR_LABEL_9:    goto AFR_LABEL_9_GOTO;  default:    goto AFR_ERROR;  } AFR_LABEL_1_GOTO:  /* FIXME: free asp */  asp = calloc (1, sizeof(*asp));  asp->loc = calloc (1, sizeof (loc_t));  local->asp = asp;  for (i = 0; i < child_count; i++) {    if (i == local->latest || ashptr[i].repair)      local->call_count++;  }  asp->label = AFR_LABEL_2;  for (i = 0; i < child_count; i++) {    if (i == local->latest || ashptr[i].repair) {      STACK_WIND (frame,		  afr_lds_opendir_cbk,		  children[i],		  children[i]->fops->opendir,		  local->loc,		  local->fd);    }  }  return; AFR_LABEL_2_GOTO:  if (asp->error)    goto AFR_ERROR;  for (i = 0; i < child_count; i++) {    local->offset = 0;    if (ashptr[i].repair) {      while (1) {	asp->i = i;	asp->label = AFR_LABEL_3;	STACK_WIND (frame,		    afr_lds_getdents_cbk,		    children[i],		    children[i]->fops->getdents,		    local->fd,		    100,		    0,		    0);	return; AFR_LABEL_3_GOTO:	if (asp->error)	  goto AFR_ERROR;	/* all the contents read */	if (asp->dents_count == 0) {	  break;	}	asp->label = AFR_LABEL_4;	for (entry = asp->entries; entry; entry = entry->next) {	  local->call_count++;	}	cnt = local->call_count;	for (entry = asp->entries; entry; entry = entry->next) {	  char path[PATH_MAX];	  strcpy (path, local->loc->path);	  strcat (path, "/");	  strcat (path, entry->name);	  asp->loc->path = path;	  asp->loc->inode = dummy_inode (local->loc->inode->table);	  /* inode structure will be freed in the call back */	  STACK_WIND_COOKIE (frame,			     afr_lds_lookup_cbk,			     entry,			     children[local->latest],			     children[local->latest]->fops->lookup,			     asp->loc,			     0);	  if (--cnt == 0)	    break;	}	return; AFR_LABEL_4_GOTO:	if (asp->error)	  goto AFR_ERROR;	asp->label = AFR_LABEL_5;	for (entry = asp->entries; entry; entry = entry->next) {	  if (entry->name == NULL)	    continue;	  local->call_count++;	}	if (local->call_count == 0)	  continue;	cnt = local->call_count;	for (entry = asp->entries; entry; entry = entry->next) {	  char path[PATH_MAX];	  if (entry->name == NULL)	    continue;	  strcpy (path, local->loc->path);	  strcat (path, "/");	  strcat (path, entry->name);	  STACK_WIND (frame,		      afr_lds_rmelem_cbk,		      children[i],		      children[i]->fops->rmelem,		      path);	  if (--cnt == 0)	    break;	}	return; AFR_LABEL_5_GOTO:	if (asp->error)	  goto AFR_ERROR;      }    }  }  while (1) {    asp->label = AFR_LABEL_6;    STACK_WIND (frame,		afr_lds_getdents_cbk,		children[local->latest],		children[local->latest]->fops->getdents,		local->fd,		100,		0,		0);    return; AFR_LABEL_6_GOTO:    if (asp->error)      goto  AFR_ERROR;    if (asp->dents_count == 0)      break;    asp->label = AFR_LABEL_7;    for (i = 0; i < child_count; i++) {      if (ashptr[i].repair)	local->call_count++;    }    int32_t count = 0, cnt;    for (entry = asp->entries; entry; entry = entry->next)      count++;    cnt = local->call_count;    dir_entry_t *tmpdir = calloc (1, sizeof (*tmpdir));    tmpdir->next = asp->entries;    asp->entries = tmpdir;    for (i = 0; i < child_count; i++) {      if (ashptr[i].repair) {	STACK_WIND (frame,		    afr_lds_setdents_cbk,		    children[i],		    children[i]->fops->setdents,		    local->fd,		    GF_SET_IF_NOT_PRESENT | GF_SET_EPOCH_TIME,		    asp->entries,		    count);	if (--cnt == 0)	  break;      }    }    for (entry = tmpdir->next; entry;) {      dir_entry_t *temp;      temp = entry;      entry = temp->next;      freee (temp->name);      freee (temp);    }    freee (tmpdir);    return; AFR_LABEL_7_GOTO:    if (asp->error)      goto AFR_ERROR;  }  {    dict_t *latest_xattr;    char *version_str, *ctime_str;    latest_xattr = get_new_dict();    asprintf (&version_str, "%u", ashptr[latest].version);    asprintf (&ctime_str, "%u", ashptr[latest].ctime);    dict_set (latest_xattr, GLUSTERFS_VERSION, data_from_dynptr (version_str, strlen(version_str)));    dict_set (latest_xattr, GLUSTERFS_CREATETIME, data_from_dynptr (ctime_str, strlen(ctime_str)));    for (i = 0; i < child_count; i++) {      if (ashptr[i].repair)	local->call_count++;    }    cnt = local->call_count;    asp->label = AFR_LABEL_8;    for (i = 0; i < child_count; i++) {      if (ashptr[i].repair) {	STACK_WIND (frame,		    afr_lds_setxattr_cbk,		    children[i],		    children[i]->fops->setxattr,		    local->loc,		    latest_xattr,		    0);	if (--cnt == 0)	  break;      }    }    dict_destroy (latest_xattr);    return;  } AFR_LABEL_8_GOTO:  if (asp->error)    goto AFR_ERROR;  for (i = 0; i < child_count; i++) {    if (ashptr[i].repair || i == latest)      local->call_count++;  }  asp->label = AFR_LABEL_9;  cnt = local->call_count;  for (i = 0; i < child_count; i++) {    if (ashptr[i].repair || i == latest) {      STACK_WIND (frame,		  afr_lds_closedir_cbk,		  children[i],		  children[i]->fops->closedir,		  local->fd);      if (--cnt == 0)	break;    }  }  return; AFR_LABEL_9_GOTO:  if (asp->error)    goto AFR_ERROR;  goto AFR_SUCCESS; AFR_ERROR:  local->rmelem_status = 1; AFR_SUCCESS:  if (asp) {    freee (asp->loc);    freee (asp);  }  char *lock_path;  asprintf (&lock_path, "/%s%s", local->lock_node->name, local->loc->path);  STACK_WIND (frame,	      afr_lookup_unlock_cbk,	      local->lock_node,	      local->lock_node->mops->unlock,	      lock_path);  return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -