LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/lib/format_text - archiver.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 32 200 16.0 %
Date: 2010-04-13 Functions: 6 21 28.6 %
Branches: 10 120 8.3 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
       3                 :            :  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
       4                 :            :  *
       5                 :            :  * This file is part of LVM2.
       6                 :            :  *
       7                 :            :  * This copyrighted material is made available to anyone wishing to use,
       8                 :            :  * modify, copy, or redistribute it subject to the terms and conditions
       9                 :            :  * of the GNU Lesser General Public License v.2.1.
      10                 :            :  *
      11                 :            :  * You should have received a copy of the GNU Lesser General Public License
      12                 :            :  * along with this program; if not, write to the Free Software Foundation,
      13                 :            :  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "lib.h"
      17                 :            : #include "archiver.h"
      18                 :            : #include "format-text.h"
      19                 :            : #include "lvm-file.h"
      20                 :            : #include "lvm-string.h"
      21                 :            : #include "lvmcache.h"
      22                 :            : #include "toolcontext.h"
      23                 :            : #include "locking.h"
      24                 :            : 
      25                 :            : #include <unistd.h>
      26                 :            : 
      27                 :            : struct archive_params {
      28                 :            :         int enabled;
      29                 :            :         char *dir;
      30                 :            :         unsigned int keep_days;
      31                 :            :         unsigned int keep_number;
      32                 :            : };
      33                 :            : 
      34                 :            : struct backup_params {
      35                 :            :         int enabled;
      36                 :            :         char *dir;
      37                 :            : };
      38                 :            : 
      39                 :          1 : int archive_init(struct cmd_context *cmd, const char *dir,
      40                 :            :                  unsigned int keep_days, unsigned int keep_min,
      41                 :            :                  int enabled)
      42                 :            : {
      43         [ -  + ]:          1 :         if (!(cmd->archive_params = dm_pool_zalloc(cmd->libmem,
      44                 :            :                                                 sizeof(*cmd->archive_params)))) {
      45                 :          0 :                 log_error("archive_params alloc failed");
      46                 :          0 :                 return 0;
      47                 :            :         }
      48                 :            : 
      49                 :          1 :         cmd->archive_params->dir = NULL;
      50                 :            : 
      51         [ -  + ]:          1 :         if (!*dir)
      52                 :          0 :                 return 1;
      53                 :            : 
      54         [ -  + ]:          1 :         if (!(cmd->archive_params->dir = dm_strdup(dir))) {
      55                 :          0 :                 log_error("Couldn't copy archive directory name.");
      56                 :          0 :                 return 0;
      57                 :            :         }
      58                 :            : 
      59                 :          1 :         cmd->archive_params->keep_days = keep_days;
      60                 :          1 :         cmd->archive_params->keep_number = keep_min;
      61                 :          1 :         archive_enable(cmd, enabled);
      62                 :            : 
      63                 :          1 :         return 1;
      64                 :            : }
      65                 :            : 
      66                 :          1 : void archive_exit(struct cmd_context *cmd)
      67                 :            : {
      68         [ -  + ]:          1 :         if (!cmd->archive_params)
      69                 :          0 :                 return;
      70         [ +  - ]:          1 :         if (cmd->archive_params->dir)
      71                 :          1 :                 dm_free(cmd->archive_params->dir);
      72                 :          1 :         memset(cmd->archive_params, 0, sizeof(*cmd->archive_params));
      73                 :            : }
      74                 :            : 
      75                 :          3 : void archive_enable(struct cmd_context *cmd, int flag)
      76                 :            : {
      77                 :          3 :         cmd->archive_params->enabled = flag;
      78                 :          3 : }
      79                 :            : 
      80                 :          0 : static char *_build_desc(struct dm_pool *mem, const char *line, int before)
      81                 :            : {
      82                 :          0 :         size_t len = strlen(line) + 32;
      83                 :            :         char *buffer;
      84                 :            : 
      85         [ #  # ]:          0 :         if (!(buffer = dm_pool_zalloc(mem, strlen(line) + 32)))
      86                 :          0 :                 return_NULL;
      87                 :            : 
      88 [ #  # ][ #  # ]:          0 :         if (snprintf(buffer, len,
      89                 :            :                      "Created %s executing '%s'",
      90                 :            :                      before ? "*before*" : "*after*", line) < 0)
      91                 :          0 :                 return_NULL;
      92                 :            : 
      93                 :          0 :         return buffer;
      94                 :            : }
      95                 :            : 
      96                 :          0 : static int __archive(struct volume_group *vg)
      97                 :            : {
      98                 :            :         char *desc;
      99                 :            : 
     100         [ #  # ]:          0 :         if (!(desc = _build_desc(vg->cmd->mem, vg->cmd->cmd_line, 1)))
     101                 :          0 :                 return_0;
     102                 :            : 
     103                 :          0 :         return archive_vg(vg, vg->cmd->archive_params->dir, desc,
     104                 :          0 :                           vg->cmd->archive_params->keep_days,
     105                 :          0 :                           vg->cmd->archive_params->keep_number);
     106                 :            : }
     107                 :            : 
     108                 :          0 : int archive(struct volume_group *vg)
     109                 :            : {
     110 [ #  # ][ #  # ]:          0 :         if (!vg->cmd->archive_params->enabled || !vg->cmd->archive_params->dir)
     111                 :          0 :                 return 1;
     112                 :            : 
     113         [ #  # ]:          0 :         if (test_mode()) {
     114                 :          0 :                 log_verbose("Test mode: Skipping archiving of volume group.");
     115                 :          0 :                 return 1;
     116                 :            :         }
     117                 :            : 
     118         [ #  # ]:          0 :         if (!dm_create_dir(vg->cmd->archive_params->dir))
     119                 :          0 :                 return 0;
     120                 :            : 
     121                 :            :         /* Trap a read-only file system */
     122   [ #  #  #  # ]:          0 :         if ((access(vg->cmd->archive_params->dir, R_OK | W_OK | X_OK) == -1) &&
     123                 :          0 :              (errno == EROFS))
     124                 :          0 :                 return 0;
     125                 :            : 
     126                 :          0 :         log_verbose("Archiving volume group \"%s\" metadata (seqno %u).", vg->name,
     127                 :            :                     vg->seqno);
     128         [ #  # ]:          0 :         if (!__archive(vg)) {
     129                 :          0 :                 log_error("Volume group \"%s\" metadata archive failed.",
     130                 :            :                           vg->name);
     131                 :          0 :                 return 0;
     132                 :            :         }
     133                 :            : 
     134                 :          0 :         return 1;
     135                 :            : }
     136                 :            : 
     137                 :          0 : int archive_display(struct cmd_context *cmd, const char *vg_name)
     138                 :            : {
     139                 :            :         int r1, r2;
     140                 :            : 
     141                 :          0 :         r1 = archive_list(cmd, cmd->archive_params->dir, vg_name);
     142                 :          0 :         r2 = backup_list(cmd, cmd->backup_params->dir, vg_name);
     143                 :            : 
     144   [ #  #  #  # ]:          0 :         return r1 && r2;
     145                 :            : }
     146                 :            : 
     147                 :          0 : int archive_display_file(struct cmd_context *cmd, const char *file)
     148                 :            : {
     149                 :            :         int r;
     150                 :            : 
     151                 :          0 :         r = archive_list_file(cmd, file);
     152                 :            : 
     153                 :          0 :         return r;
     154                 :            : }
     155                 :            : 
     156                 :          1 : int backup_init(struct cmd_context *cmd, const char *dir,
     157                 :            :                 int enabled)
     158                 :            : {
     159         [ -  + ]:          1 :         if (!(cmd->backup_params = dm_pool_zalloc(cmd->libmem,
     160                 :            :                                                sizeof(*cmd->backup_params)))) {
     161                 :          0 :                 log_error("backup_params alloc failed");
     162                 :          0 :                 return 0;
     163                 :            :         }
     164                 :            : 
     165                 :          1 :         cmd->backup_params->dir = NULL;
     166         [ -  + ]:          1 :         if (!*dir)
     167                 :          0 :                 return 1;
     168                 :            : 
     169         [ -  + ]:          1 :         if (!(cmd->backup_params->dir = dm_strdup(dir))) {
     170                 :          0 :                 log_error("Couldn't copy backup directory name.");
     171                 :          0 :                 return 0;
     172                 :            :         }
     173                 :          1 :         backup_enable(cmd, enabled);
     174                 :            : 
     175                 :          1 :         return 1;
     176                 :            : }
     177                 :            : 
     178                 :          1 : void backup_exit(struct cmd_context *cmd)
     179                 :            : {
     180         [ -  + ]:          1 :         if (!cmd->backup_params)
     181                 :          0 :                 return;
     182         [ +  - ]:          1 :         if (cmd->backup_params->dir)
     183                 :          1 :                 dm_free(cmd->backup_params->dir);
     184                 :          1 :         memset(cmd->backup_params, 0, sizeof(*cmd->backup_params));
     185                 :            : }
     186                 :            : 
     187                 :          3 : void backup_enable(struct cmd_context *cmd, int flag)
     188                 :            : {
     189                 :          3 :         cmd->backup_params->enabled = flag;
     190                 :          3 : }
     191                 :            : 
     192                 :          0 : static int __backup(struct volume_group *vg)
     193                 :            : {
     194                 :            :         char name[PATH_MAX];
     195                 :            :         char *desc;
     196                 :            : 
     197         [ #  # ]:          0 :         if (!(desc = _build_desc(vg->cmd->mem, vg->cmd->cmd_line, 0)))
     198                 :          0 :                 return_0;
     199                 :            : 
     200         [ #  # ]:          0 :         if (dm_snprintf(name, sizeof(name), "%s/%s",
     201                 :          0 :                          vg->cmd->backup_params->dir, vg->name) < 0) {
     202                 :          0 :                 log_error("Failed to generate volume group metadata backup "
     203                 :            :                           "filename.");
     204                 :          0 :                 return 0;
     205                 :            :         }
     206                 :            : 
     207                 :          0 :         return backup_to_file(name, desc, vg);
     208                 :            : }
     209                 :            : 
     210                 :          0 : int backup_locally(struct volume_group *vg)
     211                 :            : {
     212 [ #  # ][ #  # ]:          0 :         if (!vg->cmd->backup_params->enabled || !vg->cmd->backup_params->dir) {
     213                 :          0 :                 log_warn("WARNING: This metadata update is NOT backed up");
     214                 :          0 :                 return 1;
     215                 :            :         }
     216                 :            : 
     217         [ #  # ]:          0 :         if (test_mode()) {
     218                 :          0 :                 log_verbose("Test mode: Skipping volume group backup.");
     219                 :          0 :                 return 1;
     220                 :            :         }
     221                 :            : 
     222         [ #  # ]:          0 :         if (!dm_create_dir(vg->cmd->backup_params->dir))
     223                 :          0 :                 return 0;
     224                 :            : 
     225                 :            :         /* Trap a read-only file system */
     226   [ #  #  #  # ]:          0 :         if ((access(vg->cmd->backup_params->dir, R_OK | W_OK | X_OK) == -1) &&
     227                 :          0 :             (errno == EROFS))
     228                 :          0 :                 return 0;
     229                 :            : 
     230         [ #  # ]:          0 :         if (!__backup(vg)) {
     231                 :          0 :                 log_error("Backup of volume group %s metadata failed.",
     232                 :            :                           vg->name);
     233                 :          0 :                 return 0;
     234                 :            :         }
     235                 :            : 
     236                 :          0 :         return 1;
     237                 :            : }
     238                 :            : 
     239                 :          0 : int backup(struct volume_group *vg)
     240                 :            : {
     241         [ #  # ]:          0 :         if (vg_is_clustered(vg))
     242                 :          0 :                 remote_backup_metadata(vg);
     243                 :            : 
     244                 :          0 :         return backup_locally(vg);
     245                 :            : }
     246                 :            : 
     247                 :          0 : int backup_remove(struct cmd_context *cmd, const char *vg_name)
     248                 :            : {
     249                 :            :         char path[PATH_MAX];
     250                 :            : 
     251         [ #  # ]:          0 :         if (dm_snprintf(path, sizeof(path), "%s/%s",
     252                 :          0 :                          cmd->backup_params->dir, vg_name) < 0) {
     253                 :          0 :                 log_error("Failed to generate backup filename (for removal).");
     254                 :          0 :                 return 0;
     255                 :            :         }
     256                 :            : 
     257                 :            :         /*
     258                 :            :          * Let this fail silently.
     259                 :            :          */
     260                 :          0 :         unlink(path);
     261                 :          0 :         return 1;
     262                 :            : }
     263                 :            : 
     264                 :          0 : struct volume_group *backup_read_vg(struct cmd_context *cmd,
     265                 :            :                                     const char *vg_name, const char *file)
     266                 :            : {
     267                 :          0 :         struct volume_group *vg = NULL;
     268                 :            :         struct format_instance *tf;
     269                 :            :         struct metadata_area *mda;
     270                 :            :         void *context;
     271                 :            : 
     272   [ #  #  #  # ]:          0 :         if (!(context = create_text_context(cmd, file,
     273                 :            :                                             cmd->cmd_line)) ||
     274                 :          0 :             !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
     275                 :            :                                                          NULL, context))) {
     276                 :          0 :                 log_error("Couldn't create text format object.");
     277                 :          0 :                 return NULL;
     278                 :            :         }
     279                 :            : 
     280         [ #  # ]:          0 :         dm_list_iterate_items(mda, &tf->metadata_areas) {
     281         [ #  # ]:          0 :                 if (!(vg = mda->ops->vg_read(tf, vg_name, mda)))
     282                 :          0 :                         stack;
     283                 :          0 :                 break;
     284                 :            :         }
     285                 :            : 
     286                 :          0 :         tf->fmt->ops->destroy_instance(tf);
     287                 :          0 :         return vg;
     288                 :            : }
     289                 :            : 
     290                 :            : /* ORPHAN and VG locks held before calling this */
     291                 :          0 : int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
     292                 :            : {
     293                 :            :         struct pv_list *pvl;
     294                 :            :         struct physical_volume *pv;
     295                 :            :         struct lvmcache_info *info;
     296                 :            : 
     297                 :            :         /*
     298                 :            :          * FIXME: Check that the PVs referenced in the backup are
     299                 :            :          * not members of other existing VGs.
     300                 :            :          */
     301                 :            : 
     302                 :            :         /* Attempt to write out using currently active format */
     303         [ #  # ]:          0 :         if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg->name,
     304                 :            :                                                        NULL, NULL))) {
     305                 :          0 :                 log_error("Failed to allocate format instance");
     306                 :          0 :                 return 0;
     307                 :            :         }
     308                 :            : 
     309                 :            :         /* Add any metadata areas on the PVs */
     310         [ #  # ]:          0 :         dm_list_iterate_items(pvl, &vg->pvs) {
     311                 :          0 :                 pv = pvl->pv;
     312         [ #  # ]:          0 :                 if (!(info = info_from_pvid(pv->dev->pvid, 0))) {
     313                 :          0 :                         log_error("PV %s missing from cache",
     314                 :            :                                   pv_dev_name(pv));
     315                 :          0 :                         return 0;
     316                 :            :                 }
     317         [ #  # ]:          0 :                 if (cmd->fmt != info->fmt) {
     318                 :          0 :                         log_error("PV %s is a different format (seqno %s)",
     319                 :            :                                   pv_dev_name(pv), info->fmt->name);
     320                 :          0 :                         return 0;
     321                 :            :                 }
     322         [ #  # ]:          0 :                 if (!vg->fid->fmt->ops->
     323                 :          0 :                     pv_setup(vg->fid->fmt, UINT64_C(0), 0, 0, 0, 0, 0UL,
     324                 :          0 :                              UINT64_C(0), &vg->fid->metadata_areas, pv, vg)) {
     325                 :          0 :                         log_error("Format-specific setup for %s failed",
     326                 :            :                                   pv_dev_name(pv));
     327                 :          0 :                         return 0;
     328                 :            :                 }
     329                 :            :         }
     330                 :            : 
     331 [ #  # ][ #  # ]:          0 :         if (!vg_write(vg) || !vg_commit(vg))
     332                 :          0 :                 return_0;
     333                 :            : 
     334                 :          0 :         return 1;
     335                 :            : }
     336                 :            : 
     337                 :            : /* ORPHAN and VG locks held before calling this */
     338                 :          0 : int backup_restore_from_file(struct cmd_context *cmd, const char *vg_name,
     339                 :            :                              const char *file)
     340                 :            : {
     341                 :            :         struct volume_group *vg;
     342                 :          0 :         int missing_pvs, r = 0;
     343                 :            : 
     344                 :            :         /*
     345                 :            :          * Read in the volume group from the text file.
     346                 :            :          */
     347         [ #  # ]:          0 :         if (!(vg = backup_read_vg(cmd, vg_name, file)))
     348                 :          0 :                 return_0;
     349                 :            : 
     350                 :          0 :         missing_pvs = vg_missing_pv_count(vg);
     351         [ #  # ]:          0 :         if (missing_pvs == 0)
     352                 :          0 :                 r = backup_restore_vg(cmd, vg);
     353                 :            :         else
     354                 :          0 :                 log_error("Cannot restore Volume Group %s with %i PVs "
     355                 :            :                           "marked as missing.", vg->name, missing_pvs);
     356                 :            : 
     357                 :          0 :         vg_release(vg);
     358                 :          0 :         return r;
     359                 :            : }
     360                 :            : 
     361                 :          0 : int backup_restore(struct cmd_context *cmd, const char *vg_name)
     362                 :            : {
     363                 :            :         char path[PATH_MAX];
     364                 :            : 
     365         [ #  # ]:          0 :         if (dm_snprintf(path, sizeof(path), "%s/%s",
     366                 :          0 :                          cmd->backup_params->dir, vg_name) < 0) {
     367                 :          0 :                 log_error("Failed to generate backup filename (for restore).");
     368                 :          0 :                 return 0;
     369                 :            :         }
     370                 :            : 
     371                 :          0 :         return backup_restore_from_file(cmd, vg_name, path);
     372                 :            : }
     373                 :            : 
     374                 :          0 : int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
     375                 :            : {
     376                 :          0 :         int r = 0;
     377                 :            :         struct format_instance *tf;
     378                 :            :         struct metadata_area *mda;
     379                 :            :         void *context;
     380                 :            :         struct cmd_context *cmd;
     381                 :            : 
     382                 :          0 :         cmd = vg->cmd;
     383                 :            : 
     384                 :          0 :         log_verbose("Creating volume group backup \"%s\" (seqno %u).", file, vg->seqno);
     385                 :            : 
     386   [ #  #  #  # ]:          0 :         if (!(context = create_text_context(cmd, file, desc)) ||
     387                 :          0 :             !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
     388                 :            :                                                          NULL, context))) {
     389                 :          0 :                 log_error("Couldn't create backup object.");
     390                 :          0 :                 return 0;
     391                 :            :         }
     392                 :            : 
     393                 :            :         /* Write and commit the metadata area */
     394         [ #  # ]:          0 :         dm_list_iterate_items(mda, &tf->metadata_areas) {
     395         [ #  # ]:          0 :                 if (!(r = mda->ops->vg_write(tf, vg, mda))) {
     396                 :          0 :                         stack;
     397                 :          0 :                         continue;
     398                 :            :                 }
     399   [ #  #  #  # ]:          0 :                 if (mda->ops->vg_commit &&
     400                 :          0 :                     !(r = mda->ops->vg_commit(tf, vg, mda))) {
     401                 :          0 :                         stack;
     402                 :            :                 }
     403                 :            :         }
     404                 :            : 
     405                 :          0 :         tf->fmt->ops->destroy_instance(tf);
     406                 :          0 :         return r;
     407                 :            : }
     408                 :            : 
     409                 :            : /*
     410                 :            :  * Update backup (and archive) if they're out-of-date or don't exist.
     411                 :            :  */
     412                 :          0 : void check_current_backup(struct volume_group *vg)
     413                 :            : {
     414                 :            :         char path[PATH_MAX];
     415                 :            :         struct volume_group *vg_backup;
     416                 :            :         int old_suppress;
     417                 :            : 
     418         [ #  # ]:          0 :         if (vg_is_exported(vg))
     419                 :          0 :                 return;
     420                 :            : 
     421         [ #  # ]:          0 :         if (dm_snprintf(path, sizeof(path), "%s/%s",
     422                 :          0 :                          vg->cmd->backup_params->dir, vg->name) < 0) {
     423                 :          0 :                 log_debug("Failed to generate backup filename.");
     424                 :          0 :                 return;
     425                 :            :         }
     426                 :            : 
     427                 :          0 :         old_suppress = log_suppress(1);
     428                 :            :         /* Up-to-date backup exists? */
     429 [ #  #  #  #  # :          0 :         if ((vg_backup = backup_read_vg(vg->cmd, vg->name, path)) &&
                      # ]
     430                 :          0 :             (vg->seqno == vg_backup->seqno) &&
     431                 :          0 :             (id_equal(&vg->id, &vg_backup->id))) {
     432                 :          0 :                 log_suppress(old_suppress);
     433                 :          0 :                 vg_release(vg_backup);
     434                 :          0 :                 return;
     435                 :            :         }
     436                 :          0 :         log_suppress(old_suppress);
     437                 :            : 
     438         [ #  # ]:          0 :         if (vg_backup) {
     439                 :          0 :                 archive(vg_backup);
     440                 :          0 :                 vg_release(vg_backup);
     441                 :            :         }
     442                 :          0 :         archive(vg);
     443                 :          0 :         backup_locally(vg);
     444                 :            : }

Generated by: LCOV version 1.8