LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/libdm/ioctl - libdm-iface.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 13 710 1.8 %
Date: 2010-04-13 Functions: 2 54 3.7 %
Branches: 2 631 0.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 the device-mapper userspace tools.
       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 "dmlib.h"
      17                 :            : #include "libdm-targets.h"
      18                 :            : #include "libdm-common.h"
      19                 :            : 
      20                 :            : #ifdef DM_COMPAT
      21                 :            : #  include "libdm-compat.h"
      22                 :            : #endif
      23                 :            : 
      24                 :            : #include <fcntl.h>
      25                 :            : #include <dirent.h>
      26                 :            : #include <sys/ioctl.h>
      27                 :            : #include <sys/utsname.h>
      28                 :            : #include <limits.h>
      29                 :            : 
      30                 :            : #ifdef linux
      31                 :            : #  include "kdev_t.h"
      32                 :            : #  include <linux/limits.h>
      33                 :            : #else
      34                 :            : #  define MAJOR(x) major((x))
      35                 :            : #  define MINOR(x) minor((x))
      36                 :            : #  define MKDEV(x,y) makedev((x),(y))
      37                 :            : #endif
      38                 :            : 
      39                 :            : #include "dm-ioctl.h"
      40                 :            : 
      41                 :            : /*
      42                 :            :  * Ensure build compatibility.  
      43                 :            :  * The hard-coded versions here are the highest present 
      44                 :            :  * in the _cmd_data arrays.
      45                 :            :  */
      46                 :            : 
      47                 :            : #if !((DM_VERSION_MAJOR == 1 && DM_VERSION_MINOR >= 0) || \
      48                 :            :       (DM_VERSION_MAJOR == 4 && DM_VERSION_MINOR >= 0))
      49                 :            : #error The version of dm-ioctl.h included is incompatible.
      50                 :            : #endif
      51                 :            : 
      52                 :            : /* FIXME This should be exported in device-mapper.h */
      53                 :            : #define DM_NAME "device-mapper"
      54                 :            : 
      55                 :            : #define PROC_MISC "/proc/misc"
      56                 :            : #define PROC_DEVICES "/proc/devices"
      57                 :            : #define MISC_NAME "misc"
      58                 :            : 
      59                 :            : #define NUMBER_OF_MAJORS 4096
      60                 :            : 
      61                 :            : /* dm major version no for running kernel */
      62                 :            : static unsigned _dm_version = DM_VERSION_MAJOR;
      63                 :            : static unsigned _dm_version_minor = 0;
      64                 :            : static unsigned _dm_version_patchlevel = 0;
      65                 :            : static int _log_suppress = 0;
      66                 :            : 
      67                 :            : /*
      68                 :            :  * If the kernel dm driver only supports one major number
      69                 :            :  * we store it in _dm_device_major.  Otherwise we indicate
      70                 :            :  * which major numbers have been claimed by device-mapper
      71                 :            :  * in _dm_bitset.
      72                 :            :  */
      73                 :            : static unsigned _dm_multiple_major_support = 1;
      74                 :            : static dm_bitset_t _dm_bitset = NULL;
      75                 :            : static uint32_t _dm_device_major = 0;
      76                 :            : 
      77                 :            : static int _control_fd = -1;
      78                 :            : static int _version_checked = 0;
      79                 :            : static int _version_ok = 1;
      80                 :            : static unsigned _ioctl_buffer_double_factor = 0;
      81                 :            : 
      82                 :            : 
      83                 :            : /*
      84                 :            :  * Support both old and new major numbers to ease the transition.
      85                 :            :  * Clumsy, but only temporary.
      86                 :            :  */
      87                 :            : #if DM_VERSION_MAJOR == 4 && defined(DM_COMPAT)
      88                 :            : const int _dm_compat = 1;
      89                 :            : #else
      90                 :            : const int _dm_compat = 0;
      91                 :            : #endif
      92                 :            : 
      93                 :            : 
      94                 :            : /* *INDENT-OFF* */
      95                 :            : static struct cmd_data _cmd_data_v4[] = {
      96                 :            :         {"create",    DM_DEV_CREATE,          {4, 0, 0}},
      97                 :            :         {"reload",    DM_TABLE_LOAD,          {4, 0, 0}},
      98                 :            :         {"remove",    DM_DEV_REMOVE,          {4, 0, 0}},
      99                 :            :         {"remove_all",        DM_REMOVE_ALL,          {4, 0, 0}},
     100                 :            :         {"suspend",   DM_DEV_SUSPEND,         {4, 0, 0}},
     101                 :            :         {"resume",    DM_DEV_SUSPEND,         {4, 0, 0}},
     102                 :            :         {"info",      DM_DEV_STATUS,          {4, 0, 0}},
     103                 :            :         {"deps",      DM_TABLE_DEPS,          {4, 0, 0}},
     104                 :            :         {"rename",    DM_DEV_RENAME,          {4, 0, 0}},
     105                 :            :         {"version",   DM_VERSION,             {4, 0, 0}},
     106                 :            :         {"status",    DM_TABLE_STATUS,        {4, 0, 0}},
     107                 :            :         {"table",     DM_TABLE_STATUS,        {4, 0, 0}},
     108                 :            :         {"waitevent", DM_DEV_WAIT,            {4, 0, 0}},
     109                 :            :         {"names",     DM_LIST_DEVICES,        {4, 0, 0}},
     110                 :            :         {"clear",     DM_TABLE_CLEAR,         {4, 0, 0}},
     111                 :            :         {"mknodes",   DM_DEV_STATUS,          {4, 0, 0}},
     112                 :            : #ifdef DM_LIST_VERSIONS
     113                 :            :         {"versions",  DM_LIST_VERSIONS,       {4, 1, 0}},
     114                 :            : #endif
     115                 :            : #ifdef DM_TARGET_MSG
     116                 :            :         {"message",   DM_TARGET_MSG,          {4, 2, 0}},
     117                 :            : #endif
     118                 :            : #ifdef DM_DEV_SET_GEOMETRY
     119                 :            :         {"setgeometry",       DM_DEV_SET_GEOMETRY,    {4, 6, 0}},
     120                 :            : #endif
     121                 :            : };
     122                 :            : /* *INDENT-ON* */
     123                 :            : 
     124                 :            : #define ALIGNMENT_V1 sizeof(int)
     125                 :            : #define ALIGNMENT 8
     126                 :            : 
     127                 :            : /* FIXME Rejig library to record & use errno instead */
     128                 :            : #ifndef DM_EXISTS_FLAG
     129                 :            : #  define DM_EXISTS_FLAG 0x00000004
     130                 :            : #endif
     131                 :            : 
     132                 :          0 : static void *_align(void *ptr, unsigned int a)
     133                 :            : {
     134                 :          0 :         register unsigned long agn = --a;
     135                 :            : 
     136                 :          0 :         return (void *) (((unsigned long) ptr + agn) & ~agn);
     137                 :            : }
     138                 :            : 
     139                 :            : #ifdef DM_IOCTLS
     140                 :            : /*
     141                 :            :  * Set number to NULL to populate _dm_bitset - otherwise first
     142                 :            :  * match is returned.
     143                 :            :  */
     144                 :          0 : static int _get_proc_number(const char *file, const char *name,
     145                 :            :                             uint32_t *number)
     146                 :            : {
     147                 :            :         FILE *fl;
     148                 :            :         char nm[256];
     149                 :            :         int c;
     150                 :            :         uint32_t num;
     151                 :            : 
     152         [ #  # ]:          0 :         if (!(fl = fopen(file, "r"))) {
     153         [ #  # ]:          0 :                 log_sys_error("fopen", file);
     154                 :          0 :                 return 0;
     155                 :            :         }
     156                 :            : 
     157         [ #  # ]:          0 :         while (!feof(fl)) {
     158         [ #  # ]:          0 :                 if (fscanf(fl, "%d %255s\n", &num, &nm[0]) == 2) {
     159         [ #  # ]:          0 :                         if (!strcmp(name, nm)) {
     160         [ #  # ]:          0 :                                 if (number) {
     161                 :          0 :                                         *number = num;
     162         [ #  # ]:          0 :                                         if (fclose(fl))
     163         [ #  # ]:          0 :                                                 log_sys_error("fclose", file);
     164                 :          0 :                                         return 1;
     165                 :            :                                 }
     166                 :          0 :                                 dm_bit_set(_dm_bitset, num);
     167                 :            :                         }
     168                 :            :                 } else do {
     169                 :          0 :                         c = fgetc(fl);
     170   [ #  #  #  # ]:          0 :                 } while (c != EOF && c != '\n');
     171                 :            :         }
     172         [ #  # ]:          0 :         if (fclose(fl))
     173         [ #  # ]:          0 :                 log_sys_error("fclose", file);
     174                 :            : 
     175         [ #  # ]:          0 :         if (number) {
     176         [ #  # ]:          0 :                 log_error("%s: No entry for %s found", file, name);
     177                 :          0 :                 return 0;
     178                 :            :         }
     179                 :            : 
     180                 :          0 :         return 1;
     181                 :            : }
     182                 :            : 
     183                 :          0 : static int _control_device_number(uint32_t *major, uint32_t *minor)
     184                 :            : {
     185   [ #  #  #  # ]:          0 :         if (!_get_proc_number(PROC_DEVICES, MISC_NAME, major) ||
     186                 :          0 :             !_get_proc_number(PROC_MISC, DM_NAME, minor)) {
     187                 :          0 :                 *major = 0;
     188                 :          0 :                 return 0;
     189                 :            :         }
     190                 :            : 
     191                 :          0 :         return 1;
     192                 :            : }
     193                 :            : 
     194                 :            : /*
     195                 :            :  * Returns 1 if exists; 0 if it doesn't; -1 if it's wrong
     196                 :            :  */
     197                 :          0 : static int _control_exists(const char *control, uint32_t major, uint32_t minor)
     198                 :            : {
     199                 :            :         struct stat buf;
     200                 :            : 
     201         [ #  # ]:          0 :         if (stat(control, &buf) < 0) {
     202         [ #  # ]:          0 :                 if (errno != ENOENT)
     203         [ #  # ]:          0 :                         log_sys_error("stat", control);
     204                 :          0 :                 return 0;
     205                 :            :         }
     206                 :            : 
     207         [ #  # ]:          0 :         if (!S_ISCHR(buf.st_mode)) {
     208         [ #  # ]:          0 :                 log_verbose("%s: Wrong inode type", control);
     209         [ #  # ]:          0 :                 if (!unlink(control))
     210                 :          0 :                         return 0;
     211         [ #  # ]:          0 :                 log_sys_error("unlink", control);
     212                 :          0 :                 return -1;
     213                 :            :         }
     214                 :            : 
     215 [ #  # ][ #  # ]:          0 :         if (major && buf.st_rdev != MKDEV(major, minor)) {
     216         [ #  # ]:          0 :                 log_verbose("%s: Wrong device number: (%u, %u) instead of "
     217                 :            :                             "(%u, %u)", control,
     218                 :            :                             MAJOR(buf.st_mode), MINOR(buf.st_mode),
     219                 :            :                             major, minor);
     220         [ #  # ]:          0 :                 if (!unlink(control))
     221                 :          0 :                         return 0;
     222         [ #  # ]:          0 :                 log_sys_error("unlink", control);
     223                 :          0 :                 return -1;
     224                 :            :         }
     225                 :            : 
     226                 :          0 :         return 1;
     227                 :            : }
     228                 :            : 
     229                 :          0 : static int _create_control(const char *control, uint32_t major, uint32_t minor)
     230                 :            : {
     231                 :            :         int ret;
     232                 :            :         mode_t old_umask;
     233                 :            : 
     234         [ #  # ]:          0 :         if (!major)
     235                 :          0 :                 return 0;
     236                 :            : 
     237                 :          0 :         old_umask = umask(DM_DEV_DIR_UMASK);
     238                 :          0 :         ret = dm_create_dir(dm_dir());
     239                 :          0 :         umask(old_umask);
     240                 :            : 
     241         [ #  # ]:          0 :         if (!ret)
     242                 :          0 :                 return 0;
     243                 :            : 
     244         [ #  # ]:          0 :         log_verbose("Creating device %s (%u, %u)", control, major, minor);
     245                 :            : 
     246         [ #  # ]:          0 :         if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR,
     247                 :          0 :                   MKDEV(major, minor)) < 0)  {
     248         [ #  # ]:          0 :                 log_sys_error("mknod", control);
     249                 :          0 :                 return 0;
     250                 :            :         }
     251                 :            : 
     252                 :            : #ifdef HAVE_SELINUX
     253                 :            :         if (!dm_set_selinux_context(control, S_IFCHR)) {
     254                 :            :                 stack;
     255                 :            :                 return 0;
     256                 :            :         }
     257                 :            : #endif
     258                 :            : 
     259                 :          0 :         return 1;
     260                 :            : }
     261                 :            : #endif
     262                 :            : 
     263                 :            : /*
     264                 :            :  * FIXME Update bitset in long-running process if dm claims new major numbers.
     265                 :            :  */
     266                 :          0 : static int _create_dm_bitset(void)
     267                 :            : {
     268                 :            : #ifdef DM_IOCTLS
     269                 :            :         struct utsname uts;
     270                 :            : 
     271 [ #  # ][ #  # ]:          0 :         if (_dm_bitset || _dm_device_major)
     272                 :          0 :                 return 1;
     273                 :            : 
     274         [ #  # ]:          0 :         if (uname(&uts))
     275                 :          0 :                 return 0;
     276                 :            : 
     277                 :            :         /*
     278                 :            :          * 2.6 kernels are limited to one major number.
     279                 :            :          * Assume 2.4 kernels are patched not to.
     280                 :            :          * FIXME Check _dm_version and _dm_version_minor if 2.6 changes this.
     281                 :            :          */
     282         [ #  # ]:          0 :         if (!strncmp(uts.release, "2.6.", 4))
     283                 :          0 :                 _dm_multiple_major_support = 0;
     284                 :            : 
     285         [ #  # ]:          0 :         if (!_dm_multiple_major_support) {
     286         [ #  # ]:          0 :                 if (!_get_proc_number(PROC_DEVICES, DM_NAME, &_dm_device_major))
     287                 :          0 :                         return 0;
     288                 :          0 :                 return 1;
     289                 :            :         }
     290                 :            : 
     291                 :            :         /* Multiple major numbers supported */
     292         [ #  # ]:          0 :         if (!(_dm_bitset = dm_bitset_create(NULL, NUMBER_OF_MAJORS)))
     293                 :          0 :                 return 0;
     294                 :            : 
     295         [ #  # ]:          0 :         if (!_get_proc_number(PROC_DEVICES, DM_NAME, NULL)) {
     296                 :          0 :                 dm_bitset_destroy(_dm_bitset);
     297                 :          0 :                 _dm_bitset = NULL;
     298                 :          0 :                 return 0;
     299                 :            :         }
     300                 :            : 
     301                 :          0 :         return 1;
     302                 :            : #else
     303                 :            :         return 0;
     304                 :            : #endif
     305                 :            : }
     306                 :            : 
     307                 :          0 : int dm_is_dm_major(uint32_t major)
     308                 :            : {
     309         [ #  # ]:          0 :         if (!_create_dm_bitset())
     310                 :          0 :                 return 0;
     311                 :            : 
     312         [ #  # ]:          0 :         if (_dm_multiple_major_support)
     313                 :          0 :                 return dm_bit(_dm_bitset, major) ? 1 : 0;
     314                 :            :         else
     315                 :          0 :                 return (major == _dm_device_major) ? 1 : 0;
     316                 :            : }
     317                 :            : 
     318                 :          0 : static int _open_control(void)
     319                 :            : {
     320                 :            : #ifdef DM_IOCTLS
     321                 :            :         char control[PATH_MAX];
     322                 :          0 :         uint32_t major = 0, minor;
     323                 :            : 
     324         [ #  # ]:          0 :         if (_control_fd != -1)
     325                 :          0 :                 return 1;
     326                 :            : 
     327                 :          0 :         snprintf(control, sizeof(control), "%s/control", dm_dir());
     328                 :            : 
     329         [ #  # ]:          0 :         if (!_control_device_number(&major, &minor))
     330         [ #  # ]:          0 :                 log_error("Is device-mapper driver missing from kernel?");
     331                 :            : 
     332   [ #  #  #  # ]:          0 :         if (!_control_exists(control, major, minor) &&
     333                 :          0 :             !_create_control(control, major, minor))
     334                 :          0 :                 goto error;
     335                 :            : 
     336         [ #  # ]:          0 :         if ((_control_fd = open(control, O_RDWR)) < 0) {
     337         [ #  # ]:          0 :                 log_sys_error("open", control);
     338                 :          0 :                 goto error;
     339                 :            :         }
     340                 :            : 
     341         [ #  # ]:          0 :         if (!_create_dm_bitset()) {
     342         [ #  # ]:          0 :                 log_error("Failed to set up list of device-mapper major numbers");
     343                 :          0 :                 return 0;
     344                 :            :         }
     345                 :            : 
     346                 :          0 :         return 1;
     347                 :            : 
     348                 :            : error:
     349         [ #  # ]:          0 :         log_error("Failure to communicate with kernel device-mapper driver.");
     350                 :          0 :         return 0;
     351                 :            : #else
     352                 :            :         return 1;
     353                 :            : #endif
     354                 :            : }
     355                 :            : 
     356                 :          0 : static void _dm_zfree_string(char *string)
     357                 :            : {
     358         [ #  # ]:          0 :         if (string) {
     359                 :          0 :                 memset(string, 0, strlen(string));
     360                 :          0 :                 dm_free(string);
     361                 :            :         }
     362                 :          0 : }
     363                 :            : 
     364                 :          0 : static void _dm_zfree_dmi(struct dm_ioctl *dmi)
     365                 :            : {
     366         [ #  # ]:          0 :         if (dmi) {
     367                 :          0 :                 memset(dmi, 0, dmi->data_size);
     368                 :          0 :                 dm_free(dmi);
     369                 :            :         }
     370                 :          0 : }
     371                 :            : 
     372                 :          0 : void dm_task_destroy(struct dm_task *dmt)
     373                 :            : {
     374                 :            :         struct target *t, *n;
     375                 :            : 
     376         [ #  # ]:          0 :         for (t = dmt->head; t; t = n) {
     377                 :          0 :                 n = t->next;
     378                 :          0 :                 _dm_zfree_string(t->params);
     379                 :          0 :                 dm_free(t->type);
     380                 :          0 :                 dm_free(t);
     381                 :            :         }
     382                 :            : 
     383         [ #  # ]:          0 :         if (dmt->dev_name)
     384                 :          0 :                 dm_free(dmt->dev_name);
     385                 :            : 
     386         [ #  # ]:          0 :         if (dmt->newname)
     387                 :          0 :                 dm_free(dmt->newname);
     388                 :            : 
     389         [ #  # ]:          0 :         if (dmt->message)
     390                 :          0 :                 dm_free(dmt->message);
     391                 :            : 
     392                 :          0 :         _dm_zfree_dmi(dmt->dmi.v4);
     393                 :            : 
     394         [ #  # ]:          0 :         if (dmt->uuid)
     395                 :          0 :                 dm_free(dmt->uuid);
     396                 :            : 
     397                 :          0 :         dm_free(dmt);
     398                 :          0 : }
     399                 :            : 
     400                 :            : /*
     401                 :            :  * Protocol Version 1 compatibility functions.
     402                 :            :  */
     403                 :            : 
     404                 :            : #ifdef DM_COMPAT
     405                 :            : 
     406                 :            : static void _dm_zfree_dmi_v1(struct dm_ioctl_v1 *dmi)
     407                 :            : {
     408                 :            :         if (dmi) {
     409                 :            :                 memset(dmi, 0, dmi->data_size);
     410                 :            :                 dm_free(dmi);
     411                 :            :         }
     412                 :            : }
     413                 :            : 
     414                 :            : static int _dm_task_get_driver_version_v1(struct dm_task *dmt, char *version,
     415                 :            :                                           size_t size)
     416                 :            : {
     417                 :            :         unsigned int *v;
     418                 :            : 
     419                 :            :         if (!dmt->dmi.v1) {
     420                 :            :                 version[0] = '\0';
     421                 :            :                 return 0;
     422                 :            :         }
     423                 :            : 
     424                 :            :         v = dmt->dmi.v1->version;
     425                 :            :         snprintf(version, size, "%u.%u.%u", v[0], v[1], v[2]);
     426                 :            :         return 1;
     427                 :            : }
     428                 :            : 
     429                 :            : /* Unmarshall the target info returned from a status call */
     430                 :            : static int _unmarshal_status_v1(struct dm_task *dmt, struct dm_ioctl_v1 *dmi)
     431                 :            : {
     432                 :            :         char *outbuf = (char *) dmi + dmi->data_start;
     433                 :            :         char *outptr = outbuf;
     434                 :            :         int32_t i;
     435                 :            :         struct dm_target_spec_v1 *spec;
     436                 :            : 
     437                 :            :         for (i = 0; i < dmi->target_count; i++) {
     438                 :            :                 spec = (struct dm_target_spec_v1 *) outptr;
     439                 :            : 
     440                 :            :                 if (!dm_task_add_target(dmt, spec->sector_start,
     441                 :            :                                         (uint64_t) spec->length,
     442                 :            :                                         spec->target_type,
     443                 :            :                                         outptr + sizeof(*spec))) {
     444                 :            :                         return 0;
     445                 :            :                 }
     446                 :            : 
     447                 :            :                 outptr = outbuf + spec->next;
     448                 :            :         }
     449                 :            : 
     450                 :            :         return 1;
     451                 :            : }
     452                 :            : 
     453                 :            : static int _dm_format_dev_v1(char *buf, int bufsize, uint32_t dev_major,
     454                 :            :                              uint32_t dev_minor)
     455                 :            : {
     456                 :            :         int r;
     457                 :            : 
     458                 :            :         if (bufsize < 8)
     459                 :            :                 return 0;
     460                 :            : 
     461                 :            :         r = snprintf(buf, bufsize, "%03x:%03x", dev_major, dev_minor);
     462                 :            :         if (r < 0 || r > bufsize - 1)
     463                 :            :                 return 0;
     464                 :            : 
     465                 :            :         return 1;
     466                 :            : }
     467                 :            : 
     468                 :            : static int _dm_task_get_info_v1(struct dm_task *dmt, struct dm_info *info)
     469                 :            : {
     470                 :            :         if (!dmt->dmi.v1)
     471                 :            :                 return 0;
     472                 :            : 
     473                 :            :         memset(info, 0, sizeof(*info));
     474                 :            : 
     475                 :            :         info->exists = dmt->dmi.v1->flags & DM_EXISTS_FLAG ? 1 : 0;
     476                 :            :         if (!info->exists)
     477                 :            :                 return 1;
     478                 :            : 
     479                 :            :         info->suspended = dmt->dmi.v1->flags & DM_SUSPEND_FLAG ? 1 : 0;
     480                 :            :         info->read_only = dmt->dmi.v1->flags & DM_READONLY_FLAG ? 1 : 0;
     481                 :            :         info->target_count = dmt->dmi.v1->target_count;
     482                 :            :         info->open_count = dmt->dmi.v1->open_count;
     483                 :            :         info->event_nr = 0;
     484                 :            :         info->major = MAJOR(dmt->dmi.v1->dev);
     485                 :            :         info->minor = MINOR(dmt->dmi.v1->dev);
     486                 :            :         info->live_table = 1;
     487                 :            :         info->inactive_table = 0;
     488                 :            : 
     489                 :            :         return 1;
     490                 :            : }
     491                 :            : 
     492                 :            : static const char *_dm_task_get_name_v1(const struct dm_task *dmt)
     493                 :            : {
     494                 :            :         return (dmt->dmi.v1->name);
     495                 :            : }
     496                 :            : 
     497                 :            : static const char *_dm_task_get_uuid_v1(const struct dm_task *dmt)
     498                 :            : {
     499                 :            :         return (dmt->dmi.v1->uuid);
     500                 :            : }
     501                 :            : 
     502                 :            : static struct dm_deps *_dm_task_get_deps_v1(struct dm_task *dmt)
     503                 :            : {
     504                 :            :         log_error("deps version 1 no longer supported by libdevmapper");
     505                 :            :         return NULL;
     506                 :            : }
     507                 :            : 
     508                 :            : static struct dm_names *_dm_task_get_names_v1(struct dm_task *dmt)
     509                 :            : {
     510                 :            :         return (struct dm_names *) (((void *) dmt->dmi.v1) +
     511                 :            :                                     dmt->dmi.v1->data_start);
     512                 :            : }
     513                 :            : 
     514                 :            : static void *_add_target_v1(struct target *t, void *out, void *end)
     515                 :            : {
     516                 :            :         void *out_sp = out;
     517                 :            :         struct dm_target_spec_v1 sp;
     518                 :            :         size_t sp_size = sizeof(struct dm_target_spec_v1);
     519                 :            :         int len;
     520                 :            : 
     521                 :            :         out += sp_size;
     522                 :            :         if (out >= end)
     523                 :            :                 return_NULL;
     524                 :            : 
     525                 :            :         sp.status = 0;
     526                 :            :         sp.sector_start = t->start;
     527                 :            :         sp.length = t->length;
     528                 :            :         strncpy(sp.target_type, t->type, sizeof(sp.target_type));
     529                 :            : 
     530                 :            :         len = strlen(t->params);
     531                 :            : 
     532                 :            :         if ((out + len + 1) >= end)
     533                 :            :                 return_NULL;
     534                 :            : 
     535                 :            :         strcpy((char *) out, t->params);
     536                 :            :         out += len + 1;
     537                 :            : 
     538                 :            :         /* align next block */
     539                 :            :         out = _align(out, ALIGNMENT_V1);
     540                 :            : 
     541                 :            :         sp.next = out - out_sp;
     542                 :            : 
     543                 :            :         memcpy(out_sp, &sp, sp_size);
     544                 :            : 
     545                 :            :         return out;
     546                 :            : }
     547                 :            : 
     548                 :            : static struct dm_ioctl_v1 *_flatten_v1(struct dm_task *dmt)
     549                 :            : {
     550                 :            :         const size_t min_size = 16 * 1024;
     551                 :            :         const int (*version)[3];
     552                 :            : 
     553                 :            :         struct dm_ioctl_v1 *dmi;
     554                 :            :         struct target *t;
     555                 :            :         size_t len = sizeof(struct dm_ioctl_v1);
     556                 :            :         void *b, *e;
     557                 :            :         int count = 0;
     558                 :            : 
     559                 :            :         for (t = dmt->head; t; t = t->next) {
     560                 :            :                 len += sizeof(struct dm_target_spec_v1);
     561                 :            :                 len += strlen(t->params) + 1 + ALIGNMENT_V1;
     562                 :            :                 count++;
     563                 :            :         }
     564                 :            : 
     565                 :            :         if (count && dmt->newname) {
     566                 :            :                 log_error("targets and newname are incompatible");
     567                 :            :                 return NULL;
     568                 :            :         }
     569                 :            : 
     570                 :            :         if (dmt->newname)
     571                 :            :                 len += strlen(dmt->newname) + 1;
     572                 :            : 
     573                 :            :         /*
     574                 :            :          * Give len a minimum size so that we have space to store
     575                 :            :          * dependencies or status information.
     576                 :            :          */
     577                 :            :         if (len < min_size)
     578                 :            :                 len = min_size;
     579                 :            : 
     580                 :            :         if (!(dmi = dm_malloc(len)))
     581                 :            :                 return NULL;
     582                 :            : 
     583                 :            :         memset(dmi, 0, len);
     584                 :            : 
     585                 :            :         version = &_cmd_data_v1[dmt->type].version;
     586                 :            : 
     587                 :            :         dmi->version[0] = (*version)[0];
     588                 :            :         dmi->version[1] = (*version)[1];
     589                 :            :         dmi->version[2] = (*version)[2];
     590                 :            : 
     591                 :            :         dmi->data_size = len;
     592                 :            :         dmi->data_start = sizeof(struct dm_ioctl_v1);
     593                 :            : 
     594                 :            :         if (dmt->dev_name)
     595                 :            :                 strncpy(dmi->name, dmt->dev_name, sizeof(dmi->name));
     596                 :            : 
     597                 :            :         if (dmt->type == DM_DEVICE_SUSPEND)
     598                 :            :                 dmi->flags |= DM_SUSPEND_FLAG;
     599                 :            :         if (dmt->read_only)
     600                 :            :                 dmi->flags |= DM_READONLY_FLAG;
     601                 :            : 
     602                 :            :         if (dmt->minor >= 0) {
     603                 :            :                 if (dmt->major <= 0) {
     604                 :            :                         log_error("Missing major number for persistent device");
     605                 :            :                         return NULL;
     606                 :            :                 }
     607                 :            :                 dmi->flags |= DM_PERSISTENT_DEV_FLAG;
     608                 :            :                 dmi->dev = MKDEV(dmt->major, dmt->minor);
     609                 :            :         }
     610                 :            : 
     611                 :            :         if (dmt->uuid)
     612                 :            :                 strncpy(dmi->uuid, dmt->uuid, sizeof(dmi->uuid));
     613                 :            : 
     614                 :            :         dmi->target_count = count;
     615                 :            : 
     616                 :            :         b = (void *) (dmi + 1);
     617                 :            :         e = (void *) ((char *) dmi + len);
     618                 :            : 
     619                 :            :         for (t = dmt->head; t; t = t->next)
     620                 :            :                 if (!(b = _add_target_v1(t, b, e))) {
     621                 :            :                         log_error("Ran out of memory building ioctl parameter");
     622                 :            :                         goto bad;
     623                 :            :                 }
     624                 :            : 
     625                 :            :         if (dmt->newname)
     626                 :            :                 strcpy(b, dmt->newname);
     627                 :            : 
     628                 :            :         return dmi;
     629                 :            : 
     630                 :            :       bad:
     631                 :            :         _dm_zfree_dmi_v1(dmi);
     632                 :            :         return NULL;
     633                 :            : }
     634                 :            : 
     635                 :            : static int _dm_names_v1(struct dm_ioctl_v1 *dmi)
     636                 :            : {
     637                 :            :         const char *dev_dir = dm_dir();
     638                 :            :         int r = 1, len;
     639                 :            :         const char *name;
     640                 :            :         struct dirent *dirent;
     641                 :            :         DIR *d;
     642                 :            :         struct dm_names *names, *old_names = NULL;
     643                 :            :         void *end = (void *) dmi + dmi->data_size;
     644                 :            :         struct stat buf;
     645                 :            :         char path[PATH_MAX];
     646                 :            : 
     647                 :            :         log_warn("WARNING: Device list may be incomplete with interface "
     648                 :            :                   "version 1.");
     649                 :            :         log_warn("Please upgrade your kernel device-mapper driver.");
     650                 :            : 
     651                 :            :         if (!(d = opendir(dev_dir))) {
     652                 :            :                 log_sys_error("opendir", dev_dir);
     653                 :            :                 return 0;
     654                 :            :         }
     655                 :            : 
     656                 :            :         names = (struct dm_names *) ((void *) dmi + dmi->data_start);
     657                 :            : 
     658                 :            :         names->dev = 0;              /* Flags no data */
     659                 :            : 
     660                 :            :         while ((dirent = readdir(d))) {
     661                 :            :                 name = dirent->d_name;
     662                 :            : 
     663                 :            :                 if (name[0] == '.' || !strcmp(name, "control"))
     664                 :            :                         continue;
     665                 :            : 
     666                 :            :                 if (old_names)
     667                 :            :                         old_names->next = (uint32_t) ((void *) names -
     668                 :            :                                                       (void *) old_names);
     669                 :            :                 snprintf(path, sizeof(path), "%s/%s", dev_dir, name);
     670                 :            :                 if (stat(path, &buf)) {
     671                 :            :                         log_sys_error("stat", path);
     672                 :            :                         continue;
     673                 :            :                 }
     674                 :            :                 if (!S_ISBLK(buf.st_mode))
     675                 :            :                         continue;
     676                 :            :                 names->dev = (uint64_t) buf.st_rdev;
     677                 :            :                 names->next = 0;
     678                 :            :                 len = strlen(name);
     679                 :            :                 if (((void *) (names + 1) + len + 1) >= end) {
     680                 :            :                         log_error("Insufficient buffer space for device list");
     681                 :            :                         r = 0;
     682                 :            :                         break;
     683                 :            :                 }
     684                 :            : 
     685                 :            :                 strcpy(names->name, name);
     686                 :            : 
     687                 :            :                 old_names = names;
     688                 :            :                 names = _align((void *) ++names + len + 1, ALIGNMENT);
     689                 :            :         }
     690                 :            : 
     691                 :            :         if (closedir(d))
     692                 :            :                 log_sys_error("closedir", dev_dir);
     693                 :            : 
     694                 :            :         return r;
     695                 :            : }
     696                 :            : 
     697                 :            : static int _dm_task_run_v1(struct dm_task *dmt)
     698                 :            : {
     699                 :            :         struct dm_ioctl_v1 *dmi;
     700                 :            :         unsigned int command;
     701                 :            : 
     702                 :            :         dmi = _flatten_v1(dmt);
     703                 :            :         if (!dmi) {
     704                 :            :                 log_error("Couldn't create ioctl argument.");
     705                 :            :                 return 0;
     706                 :            :         }
     707                 :            : 
     708                 :            :         if (!_open_control())
     709                 :            :                 return 0;
     710                 :            : 
     711                 :            :         if ((unsigned) dmt->type >=
     712                 :            :             (sizeof(_cmd_data_v1) / sizeof(*_cmd_data_v1))) {
     713                 :            :                 log_error(INTERNAL ERROR "unknown device-mapper task %d",
     714                 :            :                           dmt->type);
     715                 :            :                 goto bad;
     716                 :            :         }
     717                 :            : 
     718                 :            :         command = _cmd_data_v1[dmt->type].cmd;
     719                 :            : 
     720                 :            :         if (dmt->type == DM_DEVICE_TABLE)
     721                 :            :                 dmi->flags |= DM_STATUS_TABLE_FLAG;
     722                 :            : 
     723                 :            :         log_debug("dm %s %s %s%s%s [%u]", _cmd_data_v1[dmt->type].name,
     724                 :            :                   dmi->name, dmi->uuid, dmt->newname ? " " : "",
     725                 :            :                   dmt->newname ? dmt->newname : "",
     726                 :            :                   dmi->data_size);
     727                 :            :         if (dmt->type == DM_DEVICE_LIST) {
     728                 :            :                 if (!_dm_names_v1(dmi))
     729                 :            :                         goto bad;
     730                 :            :         } 
     731                 :            : #ifdef DM_IOCTLS
     732                 :            :         else if (ioctl(_control_fd, command, dmi) < 0) {
     733                 :            :                 if (_log_suppress)
     734                 :            :                         log_verbose("device-mapper: %s ioctl failed: %s", 
     735                 :            :                                     _cmd_data_v1[dmt->type].name,
     736                 :            :                                     strerror(errno));
     737                 :            :                 else
     738                 :            :                         log_error("device-mapper: %s ioctl failed: %s",
     739                 :            :                                   _cmd_data_v1[dmt->type].name,
     740                 :            :                                   strerror(errno));
     741                 :            :                 goto bad;
     742                 :            :         }
     743                 :            : #else /* Userspace alternative for testing */
     744                 :            : #endif
     745                 :            : 
     746                 :            :         if (dmi->flags & DM_BUFFER_FULL_FLAG)
     747                 :            :                 /* FIXME Increase buffer size and retry operation (if query) */
     748                 :            :                 log_error("WARNING: libdevmapper buffer too small for data");
     749                 :            : 
     750                 :            :         switch (dmt->type) {
     751                 :            :         case DM_DEVICE_CREATE:
     752                 :            :                 add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev),
     753                 :            :                              dmt->uid, dmt->gid, dmt->mode, 0);
     754                 :            :                 break;
     755                 :            : 
     756                 :            :         case DM_DEVICE_REMOVE:
     757                 :            :                 rm_dev_node(dmt->dev_name, 0);
     758                 :            :                 break;
     759                 :            : 
     760                 :            :         case DM_DEVICE_RENAME:
     761                 :            :                 rename_dev_node(dmt->dev_name, dmt->newname, 0);
     762                 :            :                 break;
     763                 :            : 
     764                 :            :         case DM_DEVICE_MKNODES:
     765                 :            :                 if (dmi->flags & DM_EXISTS_FLAG)
     766                 :            :                         add_dev_node(dmt->dev_name, MAJOR(dmi->dev),
     767                 :            :                                      MINOR(dmi->dev), dmt->uid,
     768                 :            :                                      dmt->gid, dmt->mode, 0);
     769                 :            :                 else
     770                 :            :                         rm_dev_node(dmt->dev_name, 0);
     771                 :            :                 break;
     772                 :            : 
     773                 :            :         case DM_DEVICE_STATUS:
     774                 :            :         case DM_DEVICE_TABLE:
     775                 :            :                 if (!_unmarshal_status_v1(dmt, dmi))
     776                 :            :                         goto bad;
     777                 :            :                 break;
     778                 :            : 
     779                 :            :         case DM_DEVICE_SUSPEND:
     780                 :            :         case DM_DEVICE_RESUME:
     781                 :            :                 dmt->type = DM_DEVICE_INFO;
     782                 :            :                 if (!dm_task_run(dmt))
     783                 :            :                         goto bad;
     784                 :            :                 _dm_zfree_dmi_v1(dmi);  /* We'll use what info returned */
     785                 :            :                 return 1;
     786                 :            :         }
     787                 :            : 
     788                 :            :         dmt->dmi.v1 = dmi;
     789                 :            :         return 1;
     790                 :            : 
     791                 :            :       bad:
     792                 :            :         _dm_zfree_dmi_v1(dmi);
     793                 :            :         return 0;
     794                 :            : }
     795                 :            : 
     796                 :            : #endif
     797                 :            : 
     798                 :            : /*
     799                 :            :  * Protocol Version 4 functions.
     800                 :            :  */
     801                 :            : 
     802                 :          0 : int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size)
     803                 :            : {
     804                 :            :         unsigned *v;
     805                 :            : 
     806                 :            : #ifdef DM_COMPAT
     807                 :            :         if (_dm_version == 1)
     808                 :            :                 return _dm_task_get_driver_version_v1(dmt, version, size);
     809                 :            : #endif
     810                 :            : 
     811         [ #  # ]:          0 :         if (!dmt->dmi.v4) {
     812                 :          0 :                 version[0] = '\0';
     813                 :          0 :                 return 0;
     814                 :            :         }
     815                 :            : 
     816                 :          0 :         v = dmt->dmi.v4->version;
     817                 :          0 :         snprintf(version, size, "%u.%u.%u", v[0], v[1], v[2]);
     818                 :          0 :         _dm_version_minor = v[1];
     819                 :          0 :         _dm_version_patchlevel = v[2];
     820                 :            : 
     821                 :          0 :         return 1;
     822                 :            : }
     823                 :            : 
     824                 :          0 : static int _check_version(char *version, size_t size, int log_suppress)
     825                 :            : {
     826                 :            :         struct dm_task *task;
     827                 :            :         int r;
     828                 :            : 
     829         [ #  # ]:          0 :         if (!(task = dm_task_create(DM_DEVICE_VERSION))) {
     830         [ #  # ]:          0 :                 log_error("Failed to get device-mapper version");
     831                 :          0 :                 version[0] = '\0';
     832                 :          0 :                 return 0;
     833                 :            :         }
     834                 :            : 
     835         [ #  # ]:          0 :         if (log_suppress)
     836                 :          0 :                 _log_suppress = 1;
     837                 :            : 
     838                 :          0 :         r = dm_task_run(task);
     839                 :          0 :         dm_task_get_driver_version(task, version, size);
     840                 :          0 :         dm_task_destroy(task);
     841                 :          0 :         _log_suppress = 0;
     842                 :            : 
     843                 :          0 :         return r;
     844                 :            : }
     845                 :            : 
     846                 :            : /*
     847                 :            :  * Find out device-mapper's major version number the first time 
     848                 :            :  * this is called and whether or not we support it.
     849                 :            :  */
     850                 :          0 : int dm_check_version(void)
     851                 :            : {
     852                 :            :         char libversion[64], dmversion[64];
     853                 :          0 :         const char *compat = "";
     854                 :            : 
     855         [ #  # ]:          0 :         if (_version_checked)
     856                 :          0 :                 return _version_ok;
     857                 :            : 
     858                 :          0 :         _version_checked = 1;
     859                 :            : 
     860         [ #  # ]:          0 :         if (_check_version(dmversion, sizeof(dmversion), _dm_compat))
     861                 :          0 :                 return 1;
     862                 :            : 
     863         [ #  # ]:          0 :         if (!_dm_compat)
     864                 :          0 :                 goto bad;
     865                 :            : 
     866         [ #  # ]:          0 :         log_verbose("device-mapper ioctl protocol version %u failed. "
     867                 :            :                     "Trying protocol version 1.", _dm_version);
     868                 :          0 :         _dm_version = 1;
     869         [ #  # ]:          0 :         if (_check_version(dmversion, sizeof(dmversion), 0)) {
     870         [ #  # ]:          0 :                 log_verbose("Using device-mapper ioctl protocol version 1");
     871                 :          0 :                 return 1;
     872                 :            :         }
     873                 :            : 
     874                 :          0 :         compat = "(compat)";
     875                 :            : 
     876                 :          0 :         dm_get_library_version(libversion, sizeof(libversion));
     877                 :            : 
     878         [ #  # ]:          0 :         log_error("Incompatible libdevmapper %s%s and kernel driver %s",
     879                 :            :                   libversion, compat, dmversion);
     880                 :            : 
     881                 :            :       bad:
     882                 :          0 :         _version_ok = 0;
     883                 :          0 :         return 0;
     884                 :            : }
     885                 :            : 
     886                 :          0 : int dm_cookie_supported(void)
     887                 :            : {
     888 [ #  # ][ #  # ]:          0 :         return (dm_check_version() &&
                 [ #  # ]
     889                 :          0 :                 _dm_version >= 4 &&
     890                 :          0 :                 _dm_version_minor >= 15);
     891                 :            : }
     892                 :            : 
     893                 :          0 : void *dm_get_next_target(struct dm_task *dmt, void *next,
     894                 :            :                          uint64_t *start, uint64_t *length,
     895                 :            :                          char **target_type, char **params)
     896                 :            : {
     897                 :          0 :         struct target *t = (struct target *) next;
     898                 :            : 
     899         [ #  # ]:          0 :         if (!t)
     900                 :          0 :                 t = dmt->head;
     901                 :            : 
     902         [ #  # ]:          0 :         if (!t)
     903                 :          0 :                 return NULL;
     904                 :            : 
     905                 :          0 :         *start = t->start;
     906                 :          0 :         *length = t->length;
     907                 :          0 :         *target_type = t->type;
     908                 :          0 :         *params = t->params;
     909                 :            : 
     910                 :          0 :         return t->next;
     911                 :            : }
     912                 :            : 
     913                 :            : /* Unmarshall the target info returned from a status call */
     914                 :          0 : static int _unmarshal_status(struct dm_task *dmt, struct dm_ioctl *dmi)
     915                 :            : {
     916                 :          0 :         char *outbuf = (char *) dmi + dmi->data_start;
     917                 :          0 :         char *outptr = outbuf;
     918                 :            :         uint32_t i;
     919                 :            :         struct dm_target_spec *spec;
     920                 :            : 
     921         [ #  # ]:          0 :         for (i = 0; i < dmi->target_count; i++) {
     922                 :          0 :                 spec = (struct dm_target_spec *) outptr;
     923         [ #  # ]:          0 :                 if (!dm_task_add_target(dmt, spec->sector_start,
     924                 :            :                                         spec->length,
     925                 :            :                                         spec->target_type,
     926                 :            :                                         outptr + sizeof(*spec))) {
     927                 :          0 :                         return 0;
     928                 :            :                 }
     929                 :            : 
     930                 :          0 :                 outptr = outbuf + spec->next;
     931                 :            :         }
     932                 :            : 
     933                 :          0 :         return 1;
     934                 :            : }
     935                 :            : 
     936                 :          0 : int dm_format_dev(char *buf, int bufsize, uint32_t dev_major,
     937                 :            :                   uint32_t dev_minor)
     938                 :            : {
     939                 :            :         int r;
     940                 :            : 
     941                 :            : #ifdef DM_COMPAT
     942                 :            :         if (_dm_version == 1)
     943                 :            :                 return _dm_format_dev_v1(buf, bufsize, dev_major, dev_minor);
     944                 :            : #endif
     945                 :            : 
     946         [ #  # ]:          0 :         if (bufsize < 8)
     947                 :          0 :                 return 0;
     948                 :            : 
     949                 :          0 :         r = snprintf(buf, (size_t) bufsize, "%u:%u", dev_major, dev_minor);
     950 [ #  # ][ #  # ]:          0 :         if (r < 0 || r > bufsize - 1)
     951                 :          0 :                 return 0;
     952                 :            : 
     953                 :          0 :         return 1;
     954                 :            : }
     955                 :            : 
     956                 :          0 : int dm_task_get_info(struct dm_task *dmt, struct dm_info *info)
     957                 :            : {
     958                 :            : #ifdef DM_COMPAT
     959                 :            :         if (_dm_version == 1)
     960                 :            :                 return _dm_task_get_info_v1(dmt, info);
     961                 :            : #endif
     962                 :            : 
     963         [ #  # ]:          0 :         if (!dmt->dmi.v4)
     964                 :          0 :                 return 0;
     965                 :            : 
     966                 :          0 :         memset(info, 0, sizeof(*info));
     967                 :            : 
     968                 :          0 :         info->exists = dmt->dmi.v4->flags & DM_EXISTS_FLAG ? 1 : 0;
     969         [ #  # ]:          0 :         if (!info->exists)
     970                 :          0 :                 return 1;
     971                 :            : 
     972                 :          0 :         info->suspended = dmt->dmi.v4->flags & DM_SUSPEND_FLAG ? 1 : 0;
     973                 :          0 :         info->read_only = dmt->dmi.v4->flags & DM_READONLY_FLAG ? 1 : 0;
     974                 :          0 :         info->live_table = dmt->dmi.v4->flags & DM_ACTIVE_PRESENT_FLAG ? 1 : 0;
     975                 :          0 :         info->inactive_table = dmt->dmi.v4->flags & DM_INACTIVE_PRESENT_FLAG ?
     976                 :            :             1 : 0;
     977                 :          0 :         info->target_count = dmt->dmi.v4->target_count;
     978                 :          0 :         info->open_count = dmt->dmi.v4->open_count;
     979                 :          0 :         info->event_nr = dmt->dmi.v4->event_nr;
     980                 :          0 :         info->major = MAJOR(dmt->dmi.v4->dev);
     981                 :          0 :         info->minor = MINOR(dmt->dmi.v4->dev);
     982                 :            : 
     983                 :          0 :         return 1;
     984                 :            : }
     985                 :            : 
     986                 :          0 : uint32_t dm_task_get_read_ahead(const struct dm_task *dmt, uint32_t *read_ahead)
     987                 :            : {              
     988                 :            :         const char *dev_name;
     989                 :            : 
     990                 :          0 :         *read_ahead = 0;
     991                 :            : 
     992                 :            : #ifdef DM_COMPAT
     993                 :            :         /* Not supporting this */
     994                 :            :         if (_dm_version == 1)
     995                 :            :                 return 1;
     996                 :            : #endif  
     997                 :            : 
     998 [ #  # ][ #  # ]:          0 :         if (!dmt->dmi.v4 || !(dmt->dmi.v4->flags & DM_EXISTS_FLAG))
     999                 :          0 :                 return 0;
    1000                 :            : 
    1001         [ #  # ]:          0 :         if (*dmt->dmi.v4->name)
    1002                 :          0 :                 dev_name = dmt->dmi.v4->name;
    1003         [ #  # ]:          0 :         else if (dmt->dev_name)
    1004                 :          0 :                 dev_name = dmt->dev_name;
    1005                 :            :         else {
    1006         [ #  # ]:          0 :                 log_error("Get read ahead request failed: device name unrecorded.");
    1007                 :          0 :                 return 0;
    1008                 :            :         }
    1009                 :            : 
    1010                 :          0 :         return get_dev_node_read_ahead(dev_name, read_ahead);
    1011                 :            : }
    1012                 :            : 
    1013                 :          0 : const char *dm_task_get_name(const struct dm_task *dmt)
    1014                 :            : {
    1015                 :            : #ifdef DM_COMPAT
    1016                 :            :         if (_dm_version == 1)
    1017                 :            :                 return _dm_task_get_name_v1(dmt);
    1018                 :            : #endif
    1019                 :            : 
    1020                 :          0 :         return (dmt->dmi.v4->name);
    1021                 :            : }
    1022                 :            : 
    1023                 :          0 : const char *dm_task_get_uuid(const struct dm_task *dmt)
    1024                 :            : {
    1025                 :            : #ifdef DM_COMPAT
    1026                 :            :         if (_dm_version == 1)
    1027                 :            :                 return _dm_task_get_uuid_v1(dmt);
    1028                 :            : #endif
    1029                 :            : 
    1030                 :          0 :         return (dmt->dmi.v4->uuid);
    1031                 :            : }
    1032                 :            : 
    1033                 :          0 : struct dm_deps *dm_task_get_deps(struct dm_task *dmt)
    1034                 :            : {
    1035                 :            : #ifdef DM_COMPAT
    1036                 :            :         if (_dm_version == 1)
    1037                 :            :                 return _dm_task_get_deps_v1(dmt);
    1038                 :            : #endif
    1039                 :            : 
    1040                 :          0 :         return (struct dm_deps *) (((void *) dmt->dmi.v4) +
    1041                 :          0 :                                    dmt->dmi.v4->data_start);
    1042                 :            : }
    1043                 :            : 
    1044                 :          0 : struct dm_names *dm_task_get_names(struct dm_task *dmt)
    1045                 :            : {
    1046                 :            : #ifdef DM_COMPAT
    1047                 :            :         if (_dm_version == 1)
    1048                 :            :                 return _dm_task_get_names_v1(dmt);
    1049                 :            : #endif
    1050                 :            : 
    1051                 :          0 :         return (struct dm_names *) (((void *) dmt->dmi.v4) +
    1052                 :          0 :                                     dmt->dmi.v4->data_start);
    1053                 :            : }
    1054                 :            : 
    1055                 :          0 : struct dm_versions *dm_task_get_versions(struct dm_task *dmt)
    1056                 :            : {
    1057                 :          0 :         return (struct dm_versions *) (((void *) dmt->dmi.v4) +
    1058                 :          0 :                                        dmt->dmi.v4->data_start);
    1059                 :            : }
    1060                 :            : 
    1061                 :          0 : int dm_task_set_ro(struct dm_task *dmt)
    1062                 :            : {
    1063                 :          0 :         dmt->read_only = 1;
    1064                 :          0 :         return 1;
    1065                 :            : }
    1066                 :            : 
    1067                 :          0 : int dm_task_set_read_ahead(struct dm_task *dmt, uint32_t read_ahead,
    1068                 :            :                            uint32_t read_ahead_flags)
    1069                 :            : {
    1070                 :          0 :         dmt->read_ahead = read_ahead;
    1071                 :          0 :         dmt->read_ahead_flags = read_ahead_flags;
    1072                 :            : 
    1073                 :          0 :         return 1;
    1074                 :            : }
    1075                 :            : 
    1076                 :          0 : int dm_task_suppress_identical_reload(struct dm_task *dmt)
    1077                 :            : {
    1078                 :          0 :         dmt->suppress_identical_reload = 1;
    1079                 :          0 :         return 1;
    1080                 :            : }
    1081                 :            : 
    1082                 :          0 : int dm_task_set_newname(struct dm_task *dmt, const char *newname)
    1083                 :            : {
    1084         [ #  # ]:          0 :         if (strchr(newname, '/')) {
    1085         [ #  # ]:          0 :                 log_error("Name \"%s\" invalid. It contains \"/\".", newname);
    1086                 :          0 :                 return 0;
    1087                 :            :         }
    1088                 :            : 
    1089         [ #  # ]:          0 :         if (strlen(newname) >= DM_NAME_LEN) {
    1090         [ #  # ]:          0 :                 log_error("Name \"%s\" too long", newname);
    1091                 :          0 :                 return 0;
    1092                 :            :         }
    1093                 :            : 
    1094         [ #  # ]:          0 :         if (!(dmt->newname = dm_strdup(newname))) {
    1095         [ #  # ]:          0 :                 log_error("dm_task_set_newname: strdup(%s) failed", newname);
    1096                 :          0 :                 return 0;
    1097                 :            :         }
    1098                 :            : 
    1099                 :          0 :         return 1;
    1100                 :            : }
    1101                 :            : 
    1102                 :          0 : int dm_task_set_message(struct dm_task *dmt, const char *message)
    1103                 :            : {
    1104         [ #  # ]:          0 :         if (!(dmt->message = dm_strdup(message))) {
    1105         [ #  # ]:          0 :                 log_error("dm_task_set_message: strdup(%s) failed", message);
    1106                 :          0 :                 return 0;
    1107                 :            :         }
    1108                 :            : 
    1109                 :          0 :         return 1;
    1110                 :            : }
    1111                 :            : 
    1112                 :          0 : int dm_task_set_sector(struct dm_task *dmt, uint64_t sector)
    1113                 :            : {
    1114                 :          0 :         dmt->sector = sector;
    1115                 :            : 
    1116                 :          0 :         return 1;
    1117                 :            : }
    1118                 :            : 
    1119                 :          0 : int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders, const char *heads, const char *sectors, const char *start)
    1120                 :            : {
    1121                 :          0 :         size_t len = strlen(cylinders) + 1 + strlen(heads) + 1 + strlen(sectors) + 1 + strlen(start) + 1;
    1122                 :            : 
    1123         [ #  # ]:          0 :         if (!(dmt->geometry = dm_malloc(len))) {
    1124         [ #  # ]:          0 :                 log_error("dm_task_set_geometry: dm_malloc failed");
    1125                 :          0 :                 return 0;
    1126                 :            :         }
    1127                 :            : 
    1128         [ #  # ]:          0 :         if (sprintf(dmt->geometry, "%s %s %s %s", cylinders, heads, sectors, start) < 0) {
    1129         [ #  # ]:          0 :                 log_error("dm_task_set_geometry: sprintf failed");
    1130                 :          0 :                 return 0;
    1131                 :            :         }
    1132                 :            : 
    1133                 :          0 :         return 1;
    1134                 :            : }
    1135                 :            : 
    1136                 :          0 : int dm_task_no_flush(struct dm_task *dmt)
    1137                 :            : {
    1138                 :          0 :         dmt->no_flush = 1;
    1139                 :            : 
    1140                 :          0 :         return 1;
    1141                 :            : }
    1142                 :            : 
    1143                 :          0 : int dm_task_no_open_count(struct dm_task *dmt)
    1144                 :            : {
    1145                 :          0 :         dmt->no_open_count = 1;
    1146                 :            : 
    1147                 :          0 :         return 1;
    1148                 :            : }
    1149                 :            : 
    1150                 :          0 : int dm_task_skip_lockfs(struct dm_task *dmt)
    1151                 :            : {
    1152                 :          0 :         dmt->skip_lockfs = 1;
    1153                 :            : 
    1154                 :          0 :         return 1;
    1155                 :            : }
    1156                 :            : 
    1157                 :          0 : int dm_task_query_inactive_table(struct dm_task *dmt)
    1158                 :            : {
    1159                 :          0 :         dmt->query_inactive_table = 1;
    1160                 :            : 
    1161                 :          0 :         return 1;
    1162                 :            : }
    1163                 :            : 
    1164                 :          0 : int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr)
    1165                 :            : {
    1166                 :          0 :         dmt->event_nr = event_nr;
    1167                 :            : 
    1168                 :          0 :         return 1;
    1169                 :            : }
    1170                 :            : 
    1171                 :          0 : struct target *create_target(uint64_t start, uint64_t len, const char *type,
    1172                 :            :                              const char *params)
    1173                 :            : {
    1174                 :          0 :         struct target *t = dm_malloc(sizeof(*t));
    1175                 :            : 
    1176         [ #  # ]:          0 :         if (!t) {
    1177         [ #  # ]:          0 :                 log_error("create_target: malloc(%" PRIsize_t ") failed",
    1178                 :            :                           sizeof(*t));
    1179                 :          0 :                 return NULL;
    1180                 :            :         }
    1181                 :            : 
    1182                 :          0 :         memset(t, 0, sizeof(*t));
    1183                 :            : 
    1184         [ #  # ]:          0 :         if (!(t->params = dm_strdup(params))) {
    1185         [ #  # ]:          0 :                 log_error("create_target: strdup(params) failed");
    1186                 :          0 :                 goto bad;
    1187                 :            :         }
    1188                 :            : 
    1189         [ #  # ]:          0 :         if (!(t->type = dm_strdup(type))) {
    1190         [ #  # ]:          0 :                 log_error("create_target: strdup(type) failed");
    1191                 :          0 :                 goto bad;
    1192                 :            :         }
    1193                 :            : 
    1194                 :          0 :         t->start = start;
    1195                 :          0 :         t->length = len;
    1196                 :          0 :         return t;
    1197                 :            : 
    1198                 :            :       bad:
    1199                 :          0 :         _dm_zfree_string(t->params);
    1200                 :          0 :         dm_free(t->type);
    1201                 :          0 :         dm_free(t);
    1202                 :          0 :         return NULL;
    1203                 :            : }
    1204                 :            : 
    1205                 :          0 : static void *_add_target(struct target *t, void *out, void *end)
    1206                 :            : {
    1207                 :          0 :         void *out_sp = out;
    1208                 :            :         struct dm_target_spec sp;
    1209                 :          0 :         size_t sp_size = sizeof(struct dm_target_spec);
    1210                 :            :         int len;
    1211                 :            : 
    1212                 :          0 :         out += sp_size;
    1213         [ #  # ]:          0 :         if (out >= end)
    1214         [ #  # ]:          0 :                 return_NULL;
    1215                 :            : 
    1216                 :          0 :         sp.status = 0;
    1217                 :          0 :         sp.sector_start = t->start;
    1218                 :          0 :         sp.length = t->length;
    1219                 :          0 :         strncpy(sp.target_type, t->type, sizeof(sp.target_type));
    1220                 :            : 
    1221                 :          0 :         len = strlen(t->params);
    1222                 :            : 
    1223         [ #  # ]:          0 :         if ((out + len + 1) >= end)
    1224         [ #  # ]:          0 :                 return_NULL;
    1225                 :            : 
    1226                 :          0 :         strcpy((char *) out, t->params);
    1227                 :          0 :         out += len + 1;
    1228                 :            : 
    1229                 :            :         /* align next block */
    1230                 :          0 :         out = _align(out, ALIGNMENT);
    1231                 :            : 
    1232                 :          0 :         sp.next = out - out_sp;
    1233                 :          0 :         memcpy(out_sp, &sp, sp_size);
    1234                 :            : 
    1235                 :          0 :         return out;
    1236                 :            : }
    1237                 :            : 
    1238                 :          0 : static int _lookup_dev_name(uint64_t dev, char *buf, size_t len)
    1239                 :            : {
    1240                 :            :         struct dm_names *names;
    1241                 :          0 :         unsigned next = 0;
    1242                 :            :         struct dm_task *dmt;
    1243                 :          0 :         int r = 0;
    1244                 :            :  
    1245         [ #  # ]:          0 :         if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
    1246                 :          0 :                 return 0;
    1247                 :            :  
    1248         [ #  # ]:          0 :         if (!dm_task_run(dmt))
    1249                 :          0 :                 goto out;
    1250                 :            : 
    1251         [ #  # ]:          0 :         if (!(names = dm_task_get_names(dmt)))
    1252                 :          0 :                 goto out;
    1253                 :            :  
    1254         [ #  # ]:          0 :         if (!names->dev)
    1255                 :          0 :                 goto out;
    1256                 :            :  
    1257                 :            :         do {
    1258                 :          0 :                 names = (void *) names + next;
    1259         [ #  # ]:          0 :                 if (names->dev == dev) {
    1260                 :          0 :                         strncpy(buf, names->name, len);
    1261                 :          0 :                         r = 1;
    1262                 :          0 :                         break;
    1263                 :            :                 }
    1264                 :          0 :                 next = names->next;
    1265         [ #  # ]:          0 :         } while (next);
    1266                 :            : 
    1267                 :            :       out:
    1268                 :          0 :         dm_task_destroy(dmt);
    1269                 :          0 :         return r;
    1270                 :            : }
    1271                 :            : 
    1272                 :          0 : static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
    1273                 :            : {
    1274                 :          0 :         const size_t min_size = 16 * 1024;
    1275                 :            :         const int (*version)[3];
    1276                 :            : 
    1277                 :            :         struct dm_ioctl *dmi;
    1278                 :            :         struct target *t;
    1279                 :            :         struct dm_target_msg *tmsg;
    1280                 :          0 :         size_t len = sizeof(struct dm_ioctl);
    1281                 :            :         void *b, *e;
    1282                 :          0 :         int count = 0;
    1283                 :            : 
    1284         [ #  # ]:          0 :         for (t = dmt->head; t; t = t->next) {
    1285                 :          0 :                 len += sizeof(struct dm_target_spec);
    1286                 :          0 :                 len += strlen(t->params) + 1 + ALIGNMENT;
    1287                 :          0 :                 count++;
    1288                 :            :         }
    1289                 :            : 
    1290 [ #  # ][ #  # ]:          0 :         if (count && (dmt->sector || dmt->message)) {
                 [ #  # ]
    1291         [ #  # ]:          0 :                 log_error("targets and message are incompatible");
    1292                 :          0 :                 return NULL;
    1293                 :            :         }
    1294                 :            : 
    1295 [ #  # ][ #  # ]:          0 :         if (count && dmt->newname) {
    1296         [ #  # ]:          0 :                 log_error("targets and newname are incompatible");
    1297                 :          0 :                 return NULL;
    1298                 :            :         }
    1299                 :            : 
    1300 [ #  # ][ #  # ]:          0 :         if (count && dmt->geometry) {
    1301         [ #  # ]:          0 :                 log_error("targets and geometry are incompatible");
    1302                 :          0 :                 return NULL;
    1303                 :            :         }
    1304                 :            : 
    1305 [ #  # ][ #  # ]:          0 :         if (dmt->newname && (dmt->sector || dmt->message)) {
                 [ #  # ]
    1306         [ #  # ]:          0 :                 log_error("message and newname are incompatible");
    1307                 :          0 :                 return NULL;
    1308                 :            :         }
    1309                 :            : 
    1310 [ #  # ][ #  # ]:          0 :         if (dmt->newname && dmt->geometry) {
    1311         [ #  # ]:          0 :                 log_error("geometry and newname are incompatible");
    1312                 :          0 :                 return NULL;
    1313                 :            :         }
    1314                 :            : 
    1315 [ #  # ][ #  # ]:          0 :         if (dmt->geometry && (dmt->sector || dmt->message)) {
                 [ #  # ]
    1316         [ #  # ]:          0 :                 log_error("geometry and message are incompatible");
    1317                 :          0 :                 return NULL;
    1318                 :            :         }
    1319                 :            : 
    1320 [ #  # ][ #  # ]:          0 :         if (dmt->sector && !dmt->message) {
    1321         [ #  # ]:          0 :                 log_error("message is required with sector");
    1322                 :          0 :                 return NULL;
    1323                 :            :         }
    1324                 :            : 
    1325         [ #  # ]:          0 :         if (dmt->newname)
    1326                 :          0 :                 len += strlen(dmt->newname) + 1;
    1327                 :            : 
    1328         [ #  # ]:          0 :         if (dmt->message)
    1329                 :          0 :                 len += sizeof(struct dm_target_msg) + strlen(dmt->message) + 1;
    1330                 :            : 
    1331         [ #  # ]:          0 :         if (dmt->geometry)
    1332                 :          0 :                 len += strlen(dmt->geometry) + 1;
    1333                 :            : 
    1334                 :            :         /*
    1335                 :            :          * Give len a minimum size so that we have space to store
    1336                 :            :          * dependencies or status information.
    1337                 :            :          */
    1338         [ #  # ]:          0 :         if (len < min_size)
    1339                 :          0 :                 len = min_size;
    1340                 :            : 
    1341                 :            :         /* Increase buffer size if repeating because buffer was too small */
    1342         [ #  # ]:          0 :         while (repeat_count--)
    1343                 :          0 :                 len *= 2;
    1344                 :            : 
    1345         [ #  # ]:          0 :         if (!(dmi = dm_malloc(len)))
    1346                 :          0 :                 return NULL;
    1347                 :            : 
    1348                 :          0 :         memset(dmi, 0, len);
    1349                 :            : 
    1350                 :          0 :         version = &_cmd_data_v4[dmt->type].version;
    1351                 :            : 
    1352                 :          0 :         dmi->version[0] = (*version)[0];
    1353                 :          0 :         dmi->version[1] = (*version)[1];
    1354                 :          0 :         dmi->version[2] = (*version)[2];
    1355                 :            : 
    1356                 :          0 :         dmi->data_size = len;
    1357                 :          0 :         dmi->data_start = sizeof(struct dm_ioctl);
    1358                 :            : 
    1359         [ #  # ]:          0 :         if (dmt->minor >= 0) {
    1360         [ #  # ]:          0 :                 if (dmt->major <= 0) {
    1361         [ #  # ]:          0 :                         log_error("Missing major number for persistent device.");
    1362                 :          0 :                         goto bad;
    1363                 :            :                 }
    1364                 :            : 
    1365 [ #  # ][ #  # ]:          0 :                 if (!_dm_multiple_major_support && dmt->allow_default_major_fallback &&
                 [ #  # ]
    1366                 :          0 :                     dmt->major != _dm_device_major) {
    1367         [ #  # ]:          0 :                         log_verbose("Overriding major number of %" PRIu32 
    1368                 :            :                                     " with %" PRIu32 " for persistent device.",
    1369                 :            :                                     dmt->major, _dm_device_major);
    1370                 :          0 :                         dmt->major = _dm_device_major;
    1371                 :            :                 }
    1372                 :            : 
    1373                 :          0 :                 dmi->flags |= DM_PERSISTENT_DEV_FLAG;
    1374                 :          0 :                 dmi->dev = MKDEV(dmt->major, dmt->minor);
    1375                 :            :         }
    1376                 :            : 
    1377                 :            :         /* Does driver support device number referencing? */
    1378 [ #  # ][ #  # ]:          0 :         if (_dm_version_minor < 3 && !dmt->dev_name && !dmt->uuid && dmi->dev) {
         [ #  # ][ #  # ]
    1379         [ #  # ]:          0 :                 if (!_lookup_dev_name(dmi->dev, dmi->name, sizeof(dmi->name))) {
    1380         [ #  # ]:          0 :                         log_error("Unable to find name for device (%" PRIu32
    1381                 :            :                                   ":%" PRIu32 ")", dmt->major, dmt->minor);
    1382                 :          0 :                         goto bad;
    1383                 :            :                 }
    1384         [ #  # ]:          0 :                 log_verbose("device (%" PRIu32 ":%" PRIu32 ") is %s "
    1385                 :            :                             "for compatibility with old kernel",
    1386                 :            :                             dmt->major, dmt->minor, dmi->name);
    1387                 :            :         }
    1388                 :            : 
    1389                 :            :         /* FIXME Until resume ioctl supplies name, use dev_name for readahead */
    1390 [ #  # ][ #  # ]:          0 :         if (dmt->dev_name && (dmt->type != DM_DEVICE_RESUME || dmt->minor < 0 ||
         [ #  # ][ #  # ]
    1391                 :          0 :                               dmt->major < 0))
    1392                 :          0 :                 strncpy(dmi->name, dmt->dev_name, sizeof(dmi->name));
    1393                 :            : 
    1394         [ #  # ]:          0 :         if (dmt->uuid)
    1395                 :          0 :                 strncpy(dmi->uuid, dmt->uuid, sizeof(dmi->uuid));
    1396                 :            : 
    1397         [ #  # ]:          0 :         if (dmt->type == DM_DEVICE_SUSPEND)
    1398                 :          0 :                 dmi->flags |= DM_SUSPEND_FLAG;
    1399         [ #  # ]:          0 :         if (dmt->no_flush)
    1400                 :          0 :                 dmi->flags |= DM_NOFLUSH_FLAG;
    1401         [ #  # ]:          0 :         if (dmt->read_only)
    1402                 :          0 :                 dmi->flags |= DM_READONLY_FLAG;
    1403         [ #  # ]:          0 :         if (dmt->skip_lockfs)
    1404                 :          0 :                 dmi->flags |= DM_SKIP_LOCKFS_FLAG;
    1405         [ #  # ]:          0 :         if (dmt->query_inactive_table) {
    1406         [ #  # ]:          0 :                 if (_dm_version_minor < 16)
    1407         [ #  # ]:          0 :                         log_warn("WARNING: Inactive table query unsupported "
    1408                 :            :                                  "by kernel.  It will use live table.");
    1409                 :          0 :                 dmi->flags |= DM_QUERY_INACTIVE_TABLE_FLAG;
    1410                 :            :         }
    1411                 :            : 
    1412                 :          0 :         dmi->target_count = count;
    1413                 :          0 :         dmi->event_nr = dmt->event_nr;
    1414                 :            : 
    1415                 :          0 :         b = (void *) (dmi + 1);
    1416                 :          0 :         e = (void *) ((char *) dmi + len);
    1417                 :            : 
    1418         [ #  # ]:          0 :         for (t = dmt->head; t; t = t->next)
    1419         [ #  # ]:          0 :                 if (!(b = _add_target(t, b, e))) {
    1420         [ #  # ]:          0 :                         log_error("Ran out of memory building ioctl parameter");
    1421                 :          0 :                         goto bad;
    1422                 :            :                 }
    1423                 :            : 
    1424         [ #  # ]:          0 :         if (dmt->newname)
    1425                 :          0 :                 strcpy(b, dmt->newname);
    1426                 :            : 
    1427         [ #  # ]:          0 :         if (dmt->message) {
    1428                 :          0 :                 tmsg = (struct dm_target_msg *) b;
    1429                 :          0 :                 tmsg->sector = dmt->sector;
    1430                 :          0 :                 strcpy(tmsg->message, dmt->message);
    1431                 :            :         }
    1432                 :            : 
    1433         [ #  # ]:          0 :         if (dmt->geometry)
    1434                 :          0 :                 strcpy(b, dmt->geometry);
    1435                 :            : 
    1436                 :          0 :         return dmi;
    1437                 :            : 
    1438                 :            :       bad:
    1439                 :          0 :         _dm_zfree_dmi(dmi);
    1440                 :          0 :         return NULL;
    1441                 :            : }
    1442                 :            : 
    1443                 :          0 : static int _process_mapper_dir(struct dm_task *dmt)
    1444                 :            : {
    1445                 :            :         struct dirent *dirent;
    1446                 :            :         DIR *d;
    1447                 :            :         const char *dir;
    1448                 :          0 :         int r = 1;
    1449                 :            : 
    1450                 :          0 :         dir = dm_dir();
    1451         [ #  # ]:          0 :         if (!(d = opendir(dir))) {
    1452         [ #  # ]:          0 :                 log_sys_error("opendir", dir);
    1453                 :          0 :                 return 0;
    1454                 :            :         }
    1455                 :            : 
    1456         [ #  # ]:          0 :         while ((dirent = readdir(d))) {
    1457 [ #  # ][ #  # ]:          0 :                 if (!strcmp(dirent->d_name, ".") ||
                 [ #  # ]
    1458                 :          0 :                     !strcmp(dirent->d_name, "..") ||
    1459                 :          0 :                     !strcmp(dirent->d_name, "control"))
    1460                 :          0 :                         continue;
    1461                 :          0 :                 dm_task_set_name(dmt, dirent->d_name);
    1462                 :          0 :                 dm_task_run(dmt);
    1463                 :            :         }
    1464                 :            : 
    1465         [ #  # ]:          0 :         if (closedir(d))
    1466         [ #  # ]:          0 :                 log_sys_error("closedir", dir);
    1467                 :            : 
    1468                 :          0 :         return r;
    1469                 :            : }
    1470                 :            : 
    1471                 :          0 : static int _process_all_v4(struct dm_task *dmt)
    1472                 :            : {
    1473                 :            :         struct dm_task *task;
    1474                 :            :         struct dm_names *names;
    1475                 :          0 :         unsigned next = 0;
    1476                 :          0 :         int r = 1;
    1477                 :            : 
    1478         [ #  # ]:          0 :         if (!(task = dm_task_create(DM_DEVICE_LIST)))
    1479                 :          0 :                 return 0;
    1480                 :            : 
    1481         [ #  # ]:          0 :         if (!dm_task_run(task)) {
    1482                 :          0 :                 r = 0;
    1483                 :          0 :                 goto out;
    1484                 :            :         }
    1485                 :            : 
    1486         [ #  # ]:          0 :         if (!(names = dm_task_get_names(task))) {
    1487                 :          0 :                 r = 0;
    1488                 :          0 :                 goto out;
    1489                 :            :         }
    1490                 :            : 
    1491         [ #  # ]:          0 :         if (!names->dev)
    1492                 :          0 :                 goto out;
    1493                 :            : 
    1494                 :            :         do {
    1495                 :          0 :                 names = (void *) names + next;
    1496         [ #  # ]:          0 :                 if (!dm_task_set_name(dmt, names->name)) {
    1497                 :          0 :                         r = 0;
    1498                 :          0 :                         goto out;
    1499                 :            :                 }
    1500         [ #  # ]:          0 :                 if (!dm_task_run(dmt))
    1501                 :          0 :                         r = 0;
    1502                 :          0 :                 next = names->next;
    1503         [ #  # ]:          0 :         } while (next);
    1504                 :            : 
    1505                 :            :       out:
    1506                 :          0 :         dm_task_destroy(task);
    1507                 :          0 :         return r;
    1508                 :            : }
    1509                 :            : 
    1510                 :          0 : static int _mknodes_v4(struct dm_task *dmt)
    1511                 :            : {
    1512                 :          0 :         (void) _process_mapper_dir(dmt);
    1513                 :            : 
    1514                 :          0 :         return _process_all_v4(dmt);
    1515                 :            : }
    1516                 :            : 
    1517                 :            : /*
    1518                 :            :  * If an operation that uses a cookie fails, decrement the
    1519                 :            :  * semaphore instead of udev.
    1520                 :            :  */
    1521                 :          0 : static int _udev_complete(struct dm_task *dmt)
    1522                 :            : {
    1523                 :            :         uint16_t base;
    1524                 :            : 
    1525 [ #  # ][ #  # ]:          0 :         if (dmt->cookie_set &&
    1526                 :          0 :             (base = dmt->event_nr & ~DM_UDEV_FLAGS_MASK))
    1527                 :            :                 /* strip flags from the cookie and use cookie magic instead */
    1528                 :          0 :                 return dm_udev_complete(base | (DM_COOKIE_MAGIC <<
    1529                 :            :                                                 DM_UDEV_FLAGS_SHIFT));
    1530                 :            : 
    1531                 :          0 :         return 1;
    1532                 :            : }
    1533                 :            : 
    1534                 :          0 : static int _check_uevent_generated(struct dm_ioctl *dmi)
    1535                 :            : {
    1536 [ #  # ][ #  # ]:          0 :         if (!dm_check_version() ||
                 [ #  # ]
    1537                 :          0 :             _dm_version < 4 ||
    1538                 :          0 :             _dm_version_minor < 17)
    1539                 :            :                 /* can't check, assume uevent is generated */
    1540                 :          0 :                 return 1;
    1541                 :            : 
    1542                 :          0 :         return dmi->flags & DM_UEVENT_GENERATED_FLAG;
    1543                 :            : }
    1544                 :            : 
    1545                 :          0 : static int _create_and_load_v4(struct dm_task *dmt)
    1546                 :            : {
    1547                 :            :         struct dm_task *task;
    1548                 :            :         int r;
    1549                 :            : 
    1550                 :            :         /* Use new task struct to create the device */
    1551         [ #  # ]:          0 :         if (!(task = dm_task_create(DM_DEVICE_CREATE))) {
    1552         [ #  # ]:          0 :                 log_error("Failed to create device-mapper task struct");
    1553                 :          0 :                 _udev_complete(dmt);
    1554                 :          0 :                 return 0;
    1555                 :            :         }
    1556                 :            : 
    1557                 :            :         /* Copy across relevant fields */
    1558 [ #  # ][ #  # ]:          0 :         if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) {
    1559                 :          0 :                 dm_task_destroy(task);
    1560                 :          0 :                 _udev_complete(dmt);
    1561                 :          0 :                 return 0;
    1562                 :            :         }
    1563                 :            : 
    1564 [ #  # ][ #  # ]:          0 :         if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) {
    1565                 :          0 :                 dm_task_destroy(task);
    1566                 :          0 :                 _udev_complete(dmt);
    1567                 :          0 :                 return 0;
    1568                 :            :         }
    1569                 :            : 
    1570                 :          0 :         task->major = dmt->major;
    1571                 :          0 :         task->minor = dmt->minor;
    1572                 :          0 :         task->uid = dmt->uid;
    1573                 :          0 :         task->gid = dmt->gid;
    1574                 :          0 :         task->mode = dmt->mode;
    1575                 :            :         /* FIXME: Just for udev_check in dm_task_run. Can we avoid this? */
    1576                 :          0 :         task->event_nr = dmt->event_nr & DM_UDEV_FLAGS_MASK;
    1577                 :          0 :         task->cookie_set = dmt->cookie_set;
    1578                 :            : 
    1579                 :          0 :         r = dm_task_run(task);
    1580                 :          0 :         dm_task_destroy(task);
    1581         [ #  # ]:          0 :         if (!r) {
    1582                 :          0 :                 _udev_complete(dmt);
    1583                 :          0 :                 return 0;
    1584                 :            :         }
    1585                 :            : 
    1586                 :            :         /* Next load the table */
    1587         [ #  # ]:          0 :         if (!(task = dm_task_create(DM_DEVICE_RELOAD))) {
    1588         [ #  # ]:          0 :                 log_error("Failed to create device-mapper task struct");
    1589                 :          0 :                 _udev_complete(dmt);
    1590                 :          0 :                 return 0;
    1591                 :            :         }
    1592                 :            : 
    1593                 :            :         /* Copy across relevant fields */
    1594 [ #  # ][ #  # ]:          0 :         if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) {
    1595                 :          0 :                 dm_task_destroy(task);
    1596                 :          0 :                 _udev_complete(dmt);
    1597                 :          0 :                 return 0;
    1598                 :            :         }
    1599                 :            : 
    1600                 :          0 :         task->read_only = dmt->read_only;
    1601                 :          0 :         task->head = dmt->head;
    1602                 :          0 :         task->tail = dmt->tail;
    1603                 :            : 
    1604                 :          0 :         r = dm_task_run(task);
    1605                 :            : 
    1606                 :          0 :         task->head = NULL;
    1607                 :          0 :         task->tail = NULL;
    1608                 :          0 :         dm_task_destroy(task);
    1609         [ #  # ]:          0 :         if (!r) {
    1610                 :          0 :                 _udev_complete(dmt);
    1611                 :          0 :                 goto revert;
    1612                 :            :         }
    1613                 :            : 
    1614                 :            :         /* Use the original structure last so the info will be correct */
    1615                 :          0 :         dmt->type = DM_DEVICE_RESUME;
    1616                 :          0 :         dm_free(dmt->uuid);
    1617                 :          0 :         dmt->uuid = NULL;
    1618                 :            : 
    1619                 :          0 :         r = dm_task_run(dmt);
    1620                 :            : 
    1621         [ #  # ]:          0 :         if (r)
    1622                 :          0 :                 return r;
    1623                 :            : 
    1624                 :            :       revert:
    1625                 :          0 :         dmt->type = DM_DEVICE_REMOVE;
    1626                 :          0 :         dm_free(dmt->uuid);
    1627                 :          0 :         dmt->uuid = NULL;
    1628                 :          0 :         dmt->cookie_set = 0;
    1629                 :            : 
    1630         [ #  # ]:          0 :         if (!dm_task_run(dmt))
    1631         [ #  # ]:          0 :                 log_error("Failed to revert device creation.");
    1632                 :            : 
    1633                 :          0 :         return r;
    1634                 :            : }
    1635                 :            : 
    1636                 :          0 : uint64_t dm_task_get_existing_table_size(struct dm_task *dmt)
    1637                 :            : {
    1638                 :          0 :         return dmt->existing_table_size;
    1639                 :            : }
    1640                 :            : 
    1641                 :          0 : static int _reload_with_suppression_v4(struct dm_task *dmt)
    1642                 :            : {
    1643                 :            :         struct dm_task *task;
    1644                 :            :         struct target *t1, *t2;
    1645                 :            :         int r;
    1646                 :            : 
    1647                 :            :         /* New task to get existing table information */
    1648         [ #  # ]:          0 :         if (!(task = dm_task_create(DM_DEVICE_TABLE))) {
    1649         [ #  # ]:          0 :                 log_error("Failed to create device-mapper task struct");
    1650                 :          0 :                 return 0;
    1651                 :            :         }
    1652                 :            : 
    1653                 :            :         /* Copy across relevant fields */
    1654 [ #  # ][ #  # ]:          0 :         if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) {
    1655                 :          0 :                 dm_task_destroy(task);
    1656                 :          0 :                 return 0;
    1657                 :            :         }
    1658                 :            : 
    1659 [ #  # ][ #  # ]:          0 :         if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) {
    1660                 :          0 :                 dm_task_destroy(task);
    1661                 :          0 :                 return 0;
    1662                 :            :         }
    1663                 :            : 
    1664                 :          0 :         task->major = dmt->major;
    1665                 :          0 :         task->minor = dmt->minor;
    1666                 :            : 
    1667                 :          0 :         r = dm_task_run(task);
    1668                 :            : 
    1669         [ #  # ]:          0 :         if (!r) {
    1670                 :          0 :                 dm_task_destroy(task);
    1671                 :          0 :                 return r;
    1672                 :            :         }
    1673                 :            : 
    1674                 :            :         /* Store existing table size */
    1675                 :          0 :         t2 = task->head;
    1676 [ #  # ][ #  # ]:          0 :         while (t2 && t2->next)
    1677                 :          0 :                 t2 = t2->next;
    1678         [ #  # ]:          0 :         dmt->existing_table_size = t2 ? t2->start + t2->length : 0;
    1679                 :            : 
    1680 [ #  # ][ #  # ]:          0 :         if ((task->dmi.v4->flags & DM_READONLY_FLAG) ? 1 : 0 != dmt->read_only)
    1681                 :          0 :                 goto no_match;
    1682                 :            : 
    1683                 :          0 :         t1 = dmt->head;
    1684                 :          0 :         t2 = task->head;
    1685                 :            : 
    1686 [ #  # ][ #  # ]:          0 :         while (t1 && t2) {
    1687         [ #  # ]:          0 :                 while (t2->params[strlen(t2->params) - 1] == ' ')
    1688                 :          0 :                         t2->params[strlen(t2->params) - 1] = '\0';
    1689 [ #  # ][ #  # ]:          0 :                 if ((t1->start != t2->start) ||
         [ #  # ][ #  # ]
    1690                 :          0 :                     (t1->length != t2->length) ||
    1691                 :          0 :                     (strcmp(t1->type, t2->type)) ||
    1692                 :          0 :                     (strcmp(t1->params, t2->params)))
    1693                 :            :                         goto no_match;
    1694                 :          0 :                 t1 = t1->next;
    1695                 :          0 :                 t2 = t2->next;
    1696                 :            :         }
    1697                 :            :         
    1698 [ #  # ][ #  # ]:          0 :         if (!t1 && !t2) {
    1699                 :          0 :                 dmt->dmi.v4 = task->dmi.v4;
    1700                 :          0 :                 task->dmi.v4 = NULL;
    1701                 :          0 :                 dm_task_destroy(task);
    1702                 :          0 :                 return 1;
    1703                 :            :         }
    1704                 :            : 
    1705                 :            : no_match:
    1706                 :          0 :         dm_task_destroy(task);
    1707                 :            : 
    1708                 :            :         /* Now do the original reload */
    1709                 :          0 :         dmt->suppress_identical_reload = 0;
    1710                 :          0 :         r = dm_task_run(dmt);
    1711                 :            : 
    1712                 :          0 :         return r;
    1713                 :            : }
    1714                 :            : 
    1715                 :          0 : static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
    1716                 :            :                                      unsigned repeat_count)
    1717                 :            : {
    1718                 :            :         struct dm_ioctl *dmi;
    1719                 :            :         int ioctl_with_uevent;
    1720                 :            : 
    1721                 :          0 :         dmi = _flatten(dmt, repeat_count);
    1722         [ #  # ]:          0 :         if (!dmi) {
    1723         [ #  # ]:          0 :                 log_error("Couldn't create ioctl argument.");
    1724                 :          0 :                 return NULL;
    1725                 :            :         }
    1726                 :            : 
    1727         [ #  # ]:          0 :         if (dmt->type == DM_DEVICE_TABLE)
    1728                 :          0 :                 dmi->flags |= DM_STATUS_TABLE_FLAG;
    1729                 :            : 
    1730                 :          0 :         dmi->flags |= DM_EXISTS_FLAG;        /* FIXME */
    1731                 :            : 
    1732         [ #  # ]:          0 :         if (dmt->no_open_count)
    1733                 :          0 :                 dmi->flags |= DM_SKIP_BDGET_FLAG;
    1734                 :            : 
    1735 [ #  # ][ #  # ]:          0 :         ioctl_with_uevent = dmt->type == DM_DEVICE_RESUME ||
                 [ #  # ]
    1736                 :          0 :                             dmt->type == DM_DEVICE_REMOVE ||
    1737                 :          0 :                             dmt->type == DM_DEVICE_RENAME;
    1738                 :            : 
    1739                 :            :         /*
    1740                 :            :          * Prevent udev vs. libdevmapper race when processing nodes and
    1741                 :            :          * symlinks. This can happen when the udev rules are installed and
    1742                 :            :          * udev synchronisation code is enabled in libdevmapper but the
    1743                 :            :          * software using libdevmapper does not make use of it (by not calling
    1744                 :            :          * dm_task_set_cookie before). We need to instruct the udev rules not
    1745                 :            :          * to be applied at all in this situation so we can gracefully fallback
    1746                 :            :          * to libdevmapper's node and symlink creation code.
    1747                 :            :          */
    1748 [ #  # ][ #  # ]:          0 :         if (dm_udev_get_sync_support() && !dmt->cookie_set && ioctl_with_uevent) {
                 [ #  # ]
    1749         [ #  # ]:          0 :                 log_debug("Cookie value is not set while trying to call "
    1750                 :            :                           "DM_DEVICE_RESUME, DM_DEVICE_REMOVE or DM_DEVICE_RENAME "
    1751                 :            :                           "ioctl. Please, consider using libdevmapper's udev "
    1752                 :            :                           "synchronisation interface or disable it explicitly "
    1753                 :            :                           "by calling dm_udev_set_sync_support(0).");
    1754         [ #  # ]:          0 :                 log_debug("Switching off device-mapper and all subsystem related "
    1755                 :            :                           "udev rules. Falling back to libdevmapper node creation.");
    1756                 :            :                 /*
    1757                 :            :                  * Disable general dm and subsystem rules but keep dm disk rules
    1758                 :            :                  * if not flagged out explicitly before. We need /dev/disk content
    1759                 :            :                  * for the software that expects it.
    1760                 :            :                 */
    1761                 :          0 :                 dmi->event_nr |= (DM_UDEV_DISABLE_DM_RULES_FLAG |
    1762                 :            :                                   DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG) <<
    1763                 :            :                                  DM_UDEV_FLAGS_SHIFT;
    1764                 :            :         }
    1765                 :            : 
    1766 [ #  # ][ #  # ]:          0 :         log_debug("dm %s %s %s%s%s %s%.0d%s%.0d%s"
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1767                 :            :                   "%s%c%c%s%s %.0" PRIu64 " %s [%u]",
    1768                 :            :                   _cmd_data_v4[dmt->type].name,
    1769                 :            :                   dmi->name, dmi->uuid, dmt->newname ? " " : "",
    1770                 :            :                   dmt->newname ? dmt->newname : "",
    1771                 :            :                   dmt->major > 0 ? "(" : "",
    1772                 :            :                   dmt->major > 0 ? dmt->major : 0,
    1773                 :            :                   dmt->major > 0 ? ":" : "",
    1774                 :            :                   dmt->minor > 0 ? dmt->minor : 0,
    1775                 :            :                   dmt->major > 0 && dmt->minor == 0 ? "0" : "",
    1776                 :            :                   dmt->major > 0 ? ") " : "",
    1777                 :            :                   dmt->no_open_count ? 'N' : 'O',
    1778                 :            :                   dmt->no_flush ? 'N' : 'F',
    1779                 :            :                   dmt->skip_lockfs ? "S " : "",
    1780                 :            :                   dmt->query_inactive_table ? "I " : "",
    1781                 :            :                   dmt->sector, dmt->message ? dmt->message : "",
    1782                 :            :                   dmi->data_size);
    1783                 :            : #ifdef DM_IOCTLS
    1784         [ #  # ]:          0 :         if (ioctl(_control_fd, command, dmi) < 0) {
    1785 [ #  # ][ #  # ]:          0 :                 if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) ||
         [ #  # ][ #  # ]
    1786                 :          0 :                                        (dmt->type == DM_DEVICE_MKNODES) ||
    1787                 :          0 :                                        (dmt->type == DM_DEVICE_STATUS)))
    1788                 :          0 :                         dmi->flags &= ~DM_EXISTS_FLAG;   /* FIXME */
    1789                 :            :                 else {
    1790         [ #  # ]:          0 :                         if (_log_suppress)
    1791         [ #  # ]:          0 :                                 log_verbose("device-mapper: %s ioctl "
    1792                 :            :                                             "failed: %s",
    1793                 :            :                                             _cmd_data_v4[dmt->type].name,
    1794                 :            :                                             strerror(errno));
    1795                 :            :                         else
    1796         [ #  # ]:          0 :                                 log_error("device-mapper: %s ioctl "
    1797                 :            :                                           "failed: %s",
    1798                 :            :                                            _cmd_data_v4[dmt->type].name,
    1799                 :            :                                           strerror(errno));
    1800                 :          0 :                         _dm_zfree_dmi(dmi);
    1801                 :          0 :                         return NULL;
    1802                 :            :                 }
    1803                 :            :         }
    1804                 :            : 
    1805 [ #  # ][ #  # ]:          0 :         if (ioctl_with_uevent && !_check_uevent_generated(dmi))
    1806                 :          0 :                 _udev_complete(dmt);
    1807                 :            : 
    1808                 :            : #else /* Userspace alternative for testing */
    1809                 :            : #endif
    1810                 :          0 :         return dmi;
    1811                 :            : }
    1812                 :            : 
    1813                 :          0 : void dm_task_update_nodes(void)
    1814                 :            : {
    1815                 :          0 :         update_devs();
    1816                 :          0 : }
    1817                 :            : 
    1818                 :          0 : int dm_task_run(struct dm_task *dmt)
    1819                 :            : {
    1820                 :            :         struct dm_ioctl *dmi;
    1821                 :            :         unsigned command;
    1822                 :            :         int check_udev;
    1823                 :            :         int udev_only;
    1824                 :            : 
    1825                 :            : #ifdef DM_COMPAT
    1826                 :            :         if (_dm_version == 1)
    1827                 :            :                 return _dm_task_run_v1(dmt);
    1828                 :            : #endif
    1829                 :            : 
    1830         [ #  # ]:          0 :         if ((unsigned) dmt->type >=
    1831                 :            :             (sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) {
    1832         [ #  # ]:          0 :                 log_error(INTERNAL_ERROR "unknown device-mapper task %d",
    1833                 :            :                           dmt->type);
    1834                 :          0 :                 return 0;
    1835                 :            :         }
    1836                 :            : 
    1837                 :          0 :         command = _cmd_data_v4[dmt->type].cmd;
    1838                 :            : 
    1839                 :            :         /* Old-style creation had a table supplied */
    1840 [ #  # ][ #  # ]:          0 :         if (dmt->type == DM_DEVICE_CREATE && dmt->head)
    1841                 :          0 :                 return _create_and_load_v4(dmt);
    1842                 :            : 
    1843 [ #  # ][ #  # ]:          0 :         if (dmt->type == DM_DEVICE_MKNODES && !dmt->dev_name &&
         [ #  # ][ #  # ]
    1844                 :          0 :             !dmt->uuid && dmt->major <= 0)
    1845                 :          0 :                 return _mknodes_v4(dmt);
    1846                 :            : 
    1847 [ #  # ][ #  # ]:          0 :         if ((dmt->type == DM_DEVICE_RELOAD) && dmt->suppress_identical_reload)
    1848                 :          0 :                 return _reload_with_suppression_v4(dmt);
    1849                 :            : 
    1850         [ #  # ]:          0 :         if (!_open_control()) {
    1851                 :          0 :                 _udev_complete(dmt);
    1852                 :          0 :                 return 0;
    1853                 :            :         }
    1854                 :            : 
    1855                 :            :         /* FIXME Detect and warn if cookie set but should not be. */
    1856                 :            : repeat_ioctl:
    1857         [ #  # ]:          0 :         if (!(dmi = _do_dm_ioctl(dmt, command, _ioctl_buffer_double_factor))) {
    1858                 :          0 :                 _udev_complete(dmt);
    1859                 :          0 :                 return 0;
    1860                 :            :         }
    1861                 :            : 
    1862         [ #  # ]:          0 :         if (dmi->flags & DM_BUFFER_FULL_FLAG) {
    1863         [ #  # ]:          0 :                 switch (dmt->type) {
    1864                 :            :                 case DM_DEVICE_LIST_VERSIONS:
    1865                 :            :                 case DM_DEVICE_LIST:
    1866                 :            :                 case DM_DEVICE_DEPS:
    1867                 :            :                 case DM_DEVICE_STATUS:
    1868                 :            :                 case DM_DEVICE_TABLE:
    1869                 :            :                 case DM_DEVICE_WAITEVENT:
    1870                 :          0 :                         _ioctl_buffer_double_factor++;
    1871                 :          0 :                         _dm_zfree_dmi(dmi);
    1872                 :          0 :                         goto repeat_ioctl;
    1873                 :            :                 default:
    1874         [ #  # ]:          0 :                         log_error("WARNING: libdevmapper buffer too small for data");
    1875                 :            :                 }
    1876                 :            :         }
    1877                 :            : 
    1878 [ #  # ][ #  # ]:          0 :         check_udev = dmt->cookie_set &&
    1879                 :          0 :                      !(dmt->event_nr >> DM_UDEV_FLAGS_SHIFT &
    1880                 :            :                        DM_UDEV_DISABLE_DM_RULES_FLAG);
    1881                 :            : 
    1882         [ #  # ]:          0 :         udev_only = dmt->cookie_set ? (dmt->event_nr >> DM_UDEV_FLAGS_SHIFT &
    1883                 :            :                                         DM_UDEV_DISABLE_LIBRARY_FALLBACK) : 0;
    1884                 :            : 
    1885 [ #  #  #  #  # :          0 :         switch (dmt->type) {
                   #  # ]
    1886                 :            :         case DM_DEVICE_CREATE:
    1887 [ #  # ][ #  # ]:          0 :                 if (dmt->dev_name && *dmt->dev_name && !udev_only)
                 [ #  # ]
    1888                 :          0 :                         add_dev_node(dmt->dev_name, MAJOR(dmi->dev),
    1889                 :          0 :                                      MINOR(dmi->dev), dmt->uid, dmt->gid,
    1890                 :            :                                      dmt->mode, check_udev);
    1891                 :          0 :                 break;
    1892                 :            :         case DM_DEVICE_REMOVE:
    1893                 :            :                 /* FIXME Kernel needs to fill in dmi->name */
    1894 [ #  # ][ #  # ]:          0 :                 if (dmt->dev_name && !udev_only)
    1895                 :          0 :                         rm_dev_node(dmt->dev_name, check_udev);
    1896                 :          0 :                 break;
    1897                 :            : 
    1898                 :            :         case DM_DEVICE_RENAME:
    1899                 :            :                 /* FIXME Kernel needs to fill in dmi->name */
    1900 [ #  # ][ #  # ]:          0 :                 if (dmt->dev_name && !udev_only)
    1901                 :          0 :                         rename_dev_node(dmt->dev_name, dmt->newname,
    1902                 :            :                                         check_udev);
    1903                 :          0 :                 break;
    1904                 :            : 
    1905                 :            :         case DM_DEVICE_RESUME:
    1906                 :            :                 /* FIXME Kernel needs to fill in dmi->name */
    1907                 :          0 :                 set_dev_node_read_ahead(dmt->dev_name, dmt->read_ahead,
    1908                 :            :                                         dmt->read_ahead_flags);
    1909                 :          0 :                 break;
    1910                 :            :         
    1911                 :            :         case DM_DEVICE_MKNODES:
    1912         [ #  # ]:          0 :                 if (dmi->flags & DM_EXISTS_FLAG)
    1913                 :          0 :                         add_dev_node(dmi->name, MAJOR(dmi->dev),
    1914                 :          0 :                                      MINOR(dmi->dev), dmt->uid,
    1915                 :            :                                      dmt->gid, dmt->mode, 0);
    1916         [ #  # ]:          0 :                 else if (dmt->dev_name)
    1917                 :          0 :                         rm_dev_node(dmt->dev_name, 0);
    1918                 :          0 :                 break;
    1919                 :            : 
    1920                 :            :         case DM_DEVICE_STATUS:
    1921                 :            :         case DM_DEVICE_TABLE:
    1922                 :            :         case DM_DEVICE_WAITEVENT:
    1923         [ #  # ]:          0 :                 if (!_unmarshal_status(dmt, dmi))
    1924                 :          0 :                         goto bad;
    1925                 :            :                 break;
    1926                 :            :         }
    1927                 :            : 
    1928                 :            :         /* Was structure reused? */
    1929                 :          0 :         _dm_zfree_dmi(dmt->dmi.v4);
    1930                 :          0 :         dmt->dmi.v4 = dmi;
    1931                 :          0 :         return 1;
    1932                 :            : 
    1933                 :            :       bad:
    1934                 :          0 :         _dm_zfree_dmi(dmi);
    1935                 :          0 :         return 0;
    1936                 :            : }
    1937                 :            : 
    1938                 :          3 : void dm_lib_release(void)
    1939                 :            : {
    1940         [ -  + ]:          3 :         if (_control_fd != -1) {
    1941                 :          0 :                 close(_control_fd);
    1942                 :          0 :                 _control_fd = -1;
    1943                 :            :         }
    1944                 :          3 :         update_devs();
    1945                 :          3 : }
    1946                 :            : 
    1947                 :            : void dm_pools_check_leaks(void);
    1948                 :            : 
    1949                 :          1 : void dm_lib_exit(void)
    1950                 :            : {
    1951                 :          1 :         dm_lib_release();
    1952         [ -  + ]:          1 :         if (_dm_bitset)
    1953                 :          0 :                 dm_bitset_destroy(_dm_bitset);
    1954                 :          1 :         _dm_bitset = NULL;
    1955                 :          1 :         dm_pools_check_leaks();
    1956                 :          1 :         dm_dump_memory();
    1957                 :          1 :         _version_ok = 1;
    1958                 :          1 :         _version_checked = 0;
    1959                 :          1 : }

Generated by: LCOV version 1.8