LCOV - code coverage report
Current view: directory - libdm/ioctl - libdm-iface.c (source / functions) Found Hit Coverage
Test: unnamed Lines: 710 296 41.7 %
Date: 2010-04-13 Functions: 54 28 51.9 %

       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             602 : static void *_align(void *ptr, unsigned int a)
     133                 : {
     134             602 :         register unsigned long agn = --a;
     135                 : 
     136             602 :         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            1809 : 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            1809 :         if (!(fl = fopen(file, "r"))) {
     153               0 :                 log_sys_error("fopen", file);
     154               0 :                 return 0;
     155                 :         }
     156                 : 
     157           36783 :         while (!feof(fl)) {
     158           34974 :                 if (fscanf(fl, "%d %255s\n", &num, &nm[0]) == 2) {
     159           33165 :                         if (!strcmp(name, nm)) {
     160            1809 :                                 if (number) {
     161            1809 :                                         *number = num;
     162            1809 :                                         if (fclose(fl))
     163               0 :                                                 log_sys_error("fclose", file);
     164            1809 :                                         return 1;
     165                 :                                 }
     166               0 :                                 dm_bit_set(_dm_bitset, num);
     167                 :                         }
     168                 :                 } else do {
     169           31959 :                         c = fgetc(fl);
     170           31959 :                 } 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             603 : static int _control_device_number(uint32_t *major, uint32_t *minor)
     184                 : {
     185            1206 :         if (!_get_proc_number(PROC_DEVICES, MISC_NAME, major) ||
     186             603 :             !_get_proc_number(PROC_MISC, DM_NAME, minor)) {
     187               0 :                 *major = 0;
     188               0 :                 return 0;
     189                 :         }
     190                 : 
     191             603 :         return 1;
     192                 : }
     193                 : 
     194                 : /*
     195                 :  * Returns 1 if exists; 0 if it doesn't; -1 if it's wrong
     196                 :  */
     197             603 : static int _control_exists(const char *control, uint32_t major, uint32_t minor)
     198                 : {
     199                 :         struct stat buf;
     200                 : 
     201             603 :         if (stat(control, &buf) < 0) {
     202               0 :                 if (errno != ENOENT)
     203               0 :                         log_sys_error("stat", control);
     204               0 :                 return 0;
     205                 :         }
     206                 : 
     207             603 :         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             603 :         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             603 :         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             603 : static int _create_dm_bitset(void)
     267                 : {
     268                 : #ifdef DM_IOCTLS
     269                 :         struct utsname uts;
     270                 : 
     271             603 :         if (_dm_bitset || _dm_device_major)
     272               0 :                 return 1;
     273                 : 
     274             603 :         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             603 :         if (!strncmp(uts.release, "2.6.", 4))
     283             603 :                 _dm_multiple_major_support = 0;
     284                 : 
     285             603 :         if (!_dm_multiple_major_support) {
     286             603 :                 if (!_get_proc_number(PROC_DEVICES, DM_NAME, &_dm_device_major))
     287               0 :                         return 0;
     288             603 :                 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            2110 : static int _open_control(void)
     319                 : {
     320                 : #ifdef DM_IOCTLS
     321                 :         char control[PATH_MAX];
     322            2110 :         uint32_t major = 0, minor;
     323                 : 
     324            2110 :         if (_control_fd != -1)
     325            1507 :                 return 1;
     326                 : 
     327             603 :         snprintf(control, sizeof(control), "%s/control", dm_dir());
     328                 : 
     329             603 :         if (!_control_device_number(&major, &minor))
     330               0 :                 log_error("Is device-mapper driver missing from kernel?");
     331                 : 
     332             603 :         if (!_control_exists(control, major, minor) &&
     333               0 :             !_create_control(control, major, minor))
     334               0 :                 goto error;
     335                 : 
     336             603 :         if ((_control_fd = open(control, O_RDWR)) < 0) {
     337               0 :                 log_sys_error("open", control);
     338               0 :                 goto error;
     339                 :         }
     340                 : 
     341             603 :         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             603 :         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             301 : static void _dm_zfree_string(char *string)
     357                 : {
     358             301 :         if (string) {
     359             301 :                 memset(string, 0, strlen(string));
     360             301 :                 dm_free(string);
     361                 :         }
     362             301 : }
     363                 : 
     364            3920 : static void _dm_zfree_dmi(struct dm_ioctl *dmi)
     365                 : {
     366            3920 :         if (dmi) {
     367            2110 :                 memset(dmi, 0, dmi->data_size);
     368            2110 :                 dm_free(dmi);
     369                 :         }
     370            3920 : }
     371                 : 
     372            1810 : void dm_task_destroy(struct dm_task *dmt)
     373                 : {
     374                 :         struct target *t, *n;
     375                 : 
     376            2111 :         for (t = dmt->head; t; t = n) {
     377             301 :                 n = t->next;
     378             301 :                 _dm_zfree_string(t->params);
     379             301 :                 dm_free(t->type);
     380             301 :                 dm_free(t);
     381                 :         }
     382                 : 
     383            1810 :         if (dmt->dev_name)
     384            1206 :                 dm_free(dmt->dev_name);
     385                 : 
     386            1810 :         if (dmt->newname)
     387               0 :                 dm_free(dmt->newname);
     388                 : 
     389            1810 :         if (dmt->message)
     390               0 :                 dm_free(dmt->message);
     391                 : 
     392            1810 :         _dm_zfree_dmi(dmt->dmi.v4);
     393                 : 
     394            1810 :         if (dmt->uuid)
     395               0 :                 dm_free(dmt->uuid);
     396                 : 
     397            1810 :         dm_free(dmt);
     398            1810 : }
     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             603 : 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             603 :         if (!dmt->dmi.v4) {
     812               0 :                 version[0] = '\0';
     813               0 :                 return 0;
     814                 :         }
     815                 : 
     816             603 :         v = dmt->dmi.v4->version;
     817             603 :         snprintf(version, size, "%u.%u.%u", v[0], v[1], v[2]);
     818             603 :         _dm_version_minor = v[1];
     819             603 :         _dm_version_patchlevel = v[2];
     820                 : 
     821             603 :         return 1;
     822                 : }
     823                 : 
     824             603 : static int _check_version(char *version, size_t size, int log_suppress)
     825                 : {
     826                 :         struct dm_task *task;
     827                 :         int r;
     828                 : 
     829             603 :         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             603 :         if (log_suppress)
     836               0 :                 _log_suppress = 1;
     837                 : 
     838             603 :         r = dm_task_run(task);
     839             603 :         dm_task_get_driver_version(task, version, size);
     840             603 :         dm_task_destroy(task);
     841             603 :         _log_suppress = 0;
     842                 : 
     843             603 :         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            5726 : int dm_check_version(void)
     851                 : {
     852                 :         char libversion[64], dmversion[64];
     853            5726 :         const char *compat = "";
     854                 : 
     855            5726 :         if (_version_checked)
     856            5123 :                 return _version_ok;
     857                 : 
     858             603 :         _version_checked = 1;
     859                 : 
     860             603 :         if (_check_version(dmversion, sizeof(dmversion), _dm_compat))
     861             603 :                 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            3314 : int dm_cookie_supported(void)
     887                 : {
     888            9942 :         return (dm_check_version() &&
     889            3314 :                 _dm_version >= 4 &&
     890            3314 :                 _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               1 : 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               2 :         return (struct dm_names *) (((void *) dmt->dmi.v4) +
    1052               1 :                                     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               1 : int dm_task_no_open_count(struct dm_task *dmt)
    1144                 : {
    1145               1 :         dmt->no_open_count = 1;
    1146                 : 
    1147               1 :         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             301 : struct target *create_target(uint64_t start, uint64_t len, const char *type,
    1172                 :                              const char *params)
    1173                 : {
    1174             301 :         struct target *t = dm_malloc(sizeof(*t));
    1175                 : 
    1176             301 :         if (!t) {
    1177               0 :                 log_error("create_target: malloc(%" PRIsize_t ") failed",
    1178                 :                           sizeof(*t));
    1179               0 :                 return NULL;
    1180                 :         }
    1181                 : 
    1182             301 :         memset(t, 0, sizeof(*t));
    1183                 : 
    1184             301 :         if (!(t->params = dm_strdup(params))) {
    1185               0 :                 log_error("create_target: strdup(params) failed");
    1186               0 :                 goto bad;
    1187                 :         }
    1188                 : 
    1189             301 :         if (!(t->type = dm_strdup(type))) {
    1190               0 :                 log_error("create_target: strdup(type) failed");
    1191               0 :                 goto bad;
    1192                 :         }
    1193                 : 
    1194             301 :         t->start = start;
    1195             301 :         t->length = len;
    1196             301 :         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             602 : static void *_add_target(struct target *t, void *out, void *end)
    1206                 : {
    1207             602 :         void *out_sp = out;
    1208                 :         struct dm_target_spec sp;
    1209             602 :         size_t sp_size = sizeof(struct dm_target_spec);
    1210                 :         int len;
    1211                 : 
    1212             602 :         out += sp_size;
    1213             602 :         if (out >= end)
    1214               0 :                 return_NULL;
    1215                 : 
    1216             602 :         sp.status = 0;
    1217             602 :         sp.sector_start = t->start;
    1218             602 :         sp.length = t->length;
    1219             602 :         strncpy(sp.target_type, t->type, sizeof(sp.target_type));
    1220                 : 
    1221             602 :         len = strlen(t->params);
    1222                 : 
    1223             602 :         if ((out + len + 1) >= end)
    1224               0 :                 return_NULL;
    1225                 : 
    1226             602 :         strcpy((char *) out, t->params);
    1227             602 :         out += len + 1;
    1228                 : 
    1229                 :         /* align next block */
    1230             602 :         out = _align(out, ALIGNMENT);
    1231                 : 
    1232             602 :         sp.next = out - out_sp;
    1233             602 :         memcpy(out_sp, &sp, sp_size);
    1234                 : 
    1235             602 :         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            2110 : static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
    1273                 : {
    1274            2110 :         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            2110 :         size_t len = sizeof(struct dm_ioctl);
    1281                 :         void *b, *e;
    1282            2110 :         int count = 0;
    1283                 : 
    1284            2712 :         for (t = dmt->head; t; t = t->next) {
    1285             602 :                 len += sizeof(struct dm_target_spec);
    1286             602 :                 len += strlen(t->params) + 1 + ALIGNMENT;
    1287             602 :                 count++;
    1288                 :         }
    1289                 : 
    1290            2110 :         if (count && (dmt->sector || dmt->message)) {
    1291               0 :                 log_error("targets and message are incompatible");
    1292               0 :                 return NULL;
    1293                 :         }
    1294                 : 
    1295            2110 :         if (count && dmt->newname) {
    1296               0 :                 log_error("targets and newname are incompatible");
    1297               0 :                 return NULL;
    1298                 :         }
    1299                 : 
    1300            2110 :         if (count && dmt->geometry) {
    1301               0 :                 log_error("targets and geometry are incompatible");
    1302               0 :                 return NULL;
    1303                 :         }
    1304                 : 
    1305            2110 :         if (dmt->newname && (dmt->sector || dmt->message)) {
    1306               0 :                 log_error("message and newname are incompatible");
    1307               0 :                 return NULL;
    1308                 :         }
    1309                 : 
    1310            2110 :         if (dmt->newname && dmt->geometry) {
    1311               0 :                 log_error("geometry and newname are incompatible");
    1312               0 :                 return NULL;
    1313                 :         }
    1314                 : 
    1315            2110 :         if (dmt->geometry && (dmt->sector || dmt->message)) {
    1316               0 :                 log_error("geometry and message are incompatible");
    1317               0 :                 return NULL;
    1318                 :         }
    1319                 : 
    1320            2110 :         if (dmt->sector && !dmt->message) {
    1321               0 :                 log_error("message is required with sector");
    1322               0 :                 return NULL;
    1323                 :         }
    1324                 : 
    1325            2110 :         if (dmt->newname)
    1326               0 :                 len += strlen(dmt->newname) + 1;
    1327                 : 
    1328            2110 :         if (dmt->message)
    1329               0 :                 len += sizeof(struct dm_target_msg) + strlen(dmt->message) + 1;
    1330                 : 
    1331            2110 :         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            2110 :         if (len < min_size)
    1339            2110 :                 len = min_size;
    1340                 : 
    1341                 :         /* Increase buffer size if repeating because buffer was too small */
    1342            4220 :         while (repeat_count--)
    1343               0 :                 len *= 2;
    1344                 : 
    1345            2110 :         if (!(dmi = dm_malloc(len)))
    1346               0 :                 return NULL;
    1347                 : 
    1348            2110 :         memset(dmi, 0, len);
    1349                 : 
    1350            2110 :         version = &_cmd_data_v4[dmt->type].version;
    1351                 : 
    1352            2110 :         dmi->version[0] = (*version)[0];
    1353            2110 :         dmi->version[1] = (*version)[1];
    1354            2110 :         dmi->version[2] = (*version)[2];
    1355                 : 
    1356            2110 :         dmi->data_size = len;
    1357            2110 :         dmi->data_start = sizeof(struct dm_ioctl);
    1358                 : 
    1359            2110 :         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            2110 :         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            2110 :         if (dmt->dev_name && (dmt->type != DM_DEVICE_RESUME || dmt->minor < 0 ||
    1391               0 :                               dmt->major < 0))
    1392            1506 :                 strncpy(dmi->name, dmt->dev_name, sizeof(dmi->name));
    1393                 : 
    1394            2110 :         if (dmt->uuid)
    1395               0 :                 strncpy(dmi->uuid, dmt->uuid, sizeof(dmi->uuid));
    1396                 : 
    1397            2110 :         if (dmt->type == DM_DEVICE_SUSPEND)
    1398               0 :                 dmi->flags |= DM_SUSPEND_FLAG;
    1399            2110 :         if (dmt->no_flush)
    1400               0 :                 dmi->flags |= DM_NOFLUSH_FLAG;
    1401            2110 :         if (dmt->read_only)
    1402               0 :                 dmi->flags |= DM_READONLY_FLAG;
    1403            2110 :         if (dmt->skip_lockfs)
    1404               0 :                 dmi->flags |= DM_SKIP_LOCKFS_FLAG;
    1405            2110 :         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            2110 :         dmi->target_count = count;
    1413            2110 :         dmi->event_nr = dmt->event_nr;
    1414                 : 
    1415            2110 :         b = (void *) (dmi + 1);
    1416            2110 :         e = (void *) ((char *) dmi + len);
    1417                 : 
    1418            2712 :         for (t = dmt->head; t; t = t->next)
    1419             602 :                 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            2110 :         if (dmt->newname)
    1425               0 :                 strcpy(b, dmt->newname);
    1426                 : 
    1427            2110 :         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            2110 :         if (dmt->geometry)
    1434               0 :                 strcpy(b, dmt->geometry);
    1435                 : 
    1436            2110 :         return dmi;
    1437                 : 
    1438                 :       bad:
    1439               0 :         _dm_zfree_dmi(dmi);
    1440               0 :         return NULL;
    1441                 : }
    1442                 : 
    1443               1 : static int _process_mapper_dir(struct dm_task *dmt)
    1444                 : {
    1445                 :         struct dirent *dirent;
    1446                 :         DIR *d;
    1447                 :         const char *dir;
    1448               1 :         int r = 1;
    1449                 : 
    1450               1 :         dir = dm_dir();
    1451               1 :         if (!(d = opendir(dir))) {
    1452               0 :                 log_sys_error("opendir", dir);
    1453               0 :                 return 0;
    1454                 :         }
    1455                 : 
    1456             306 :         while ((dirent = readdir(d))) {
    1457             909 :                 if (!strcmp(dirent->d_name, ".") ||
    1458             303 :                     !strcmp(dirent->d_name, "..") ||
    1459             302 :                     !strcmp(dirent->d_name, "control"))
    1460               3 :                         continue;
    1461             301 :                 dm_task_set_name(dmt, dirent->d_name);
    1462             301 :                 dm_task_run(dmt);
    1463                 :         }
    1464                 : 
    1465               1 :         if (closedir(d))
    1466               0 :                 log_sys_error("closedir", dir);
    1467                 : 
    1468               1 :         return r;
    1469                 : }
    1470                 : 
    1471               1 : static int _process_all_v4(struct dm_task *dmt)
    1472                 : {
    1473                 :         struct dm_task *task;
    1474                 :         struct dm_names *names;
    1475               1 :         unsigned next = 0;
    1476               1 :         int r = 1;
    1477                 : 
    1478               1 :         if (!(task = dm_task_create(DM_DEVICE_LIST)))
    1479               0 :                 return 0;
    1480                 : 
    1481               1 :         if (!dm_task_run(task)) {
    1482               0 :                 r = 0;
    1483               0 :                 goto out;
    1484                 :         }
    1485                 : 
    1486               1 :         if (!(names = dm_task_get_names(task))) {
    1487               0 :                 r = 0;
    1488               0 :                 goto out;
    1489                 :         }
    1490                 : 
    1491               1 :         if (!names->dev)
    1492               1 :                 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               1 :         dm_task_destroy(task);
    1507               1 :         return r;
    1508                 : }
    1509                 : 
    1510               1 : static int _mknodes_v4(struct dm_task *dmt)
    1511                 : {
    1512               1 :         (void) _process_mapper_dir(dmt);
    1513                 : 
    1514               1 :         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             602 : static int _udev_complete(struct dm_task *dmt)
    1522                 : {
    1523                 :         uint16_t base;
    1524                 : 
    1525             602 :         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             602 :         return 1;
    1532                 : }
    1533                 : 
    1534             602 : static int _check_uevent_generated(struct dm_ioctl *dmi)
    1535                 : {
    1536            1806 :         if (!dm_check_version() ||
    1537             602 :             _dm_version < 4 ||
    1538             602 :             _dm_version_minor < 17)
    1539                 :                 /* can't check, assume uevent is generated */
    1540               0 :                 return 1;
    1541                 : 
    1542             602 :         return dmi->flags & DM_UEVENT_GENERATED_FLAG;
    1543                 : }
    1544                 : 
    1545             301 : 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             301 :         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             301 :         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             301 :         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             301 :         task->major = dmt->major;
    1571             301 :         task->minor = dmt->minor;
    1572             301 :         task->uid = dmt->uid;
    1573             301 :         task->gid = dmt->gid;
    1574             301 :         task->mode = dmt->mode;
    1575                 :         /* FIXME: Just for udev_check in dm_task_run. Can we avoid this? */
    1576             301 :         task->event_nr = dmt->event_nr & DM_UDEV_FLAGS_MASK;
    1577             301 :         task->cookie_set = dmt->cookie_set;
    1578                 : 
    1579             301 :         r = dm_task_run(task);
    1580             301 :         dm_task_destroy(task);
    1581             301 :         if (!r) {
    1582               0 :                 _udev_complete(dmt);
    1583               0 :                 return 0;
    1584                 :         }
    1585                 : 
    1586                 :         /* Next load the table */
    1587             301 :         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             301 :         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             301 :         task->read_only = dmt->read_only;
    1601             301 :         task->head = dmt->head;
    1602             301 :         task->tail = dmt->tail;
    1603                 : 
    1604             301 :         r = dm_task_run(task);
    1605                 : 
    1606             301 :         task->head = NULL;
    1607             301 :         task->tail = NULL;
    1608             301 :         dm_task_destroy(task);
    1609             301 :         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             301 :         dmt->type = DM_DEVICE_RESUME;
    1616             301 :         dm_free(dmt->uuid);
    1617             301 :         dmt->uuid = NULL;
    1618                 : 
    1619             301 :         r = dm_task_run(dmt);
    1620                 : 
    1621             301 :         if (r)
    1622             301 :                 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            2110 : 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            2110 :         dmi = _flatten(dmt, repeat_count);
    1722            2110 :         if (!dmi) {
    1723               0 :                 log_error("Couldn't create ioctl argument.");
    1724               0 :                 return NULL;
    1725                 :         }
    1726                 : 
    1727            2110 :         if (dmt->type == DM_DEVICE_TABLE)
    1728               0 :                 dmi->flags |= DM_STATUS_TABLE_FLAG;
    1729                 : 
    1730            2110 :         dmi->flags |= DM_EXISTS_FLAG;        /* FIXME */
    1731                 : 
    1732            2110 :         if (dmt->no_open_count)
    1733             301 :                 dmi->flags |= DM_SKIP_BDGET_FLAG;
    1734                 : 
    1735            5126 :         ioctl_with_uevent = dmt->type == DM_DEVICE_RESUME ||
    1736            1508 :                             dmt->type == DM_DEVICE_REMOVE ||
    1737            1508 :                             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            2110 :         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            2110 :         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            2110 :         if (ioctl(_control_fd, command, dmi) < 0) {
    1785             903 :                 if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) ||
    1786             301 :                                        (dmt->type == DM_DEVICE_MKNODES) ||
    1787               0 :                                        (dmt->type == DM_DEVICE_STATUS)))
    1788             301 :                         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            2110 :         if (ioctl_with_uevent && !_check_uevent_generated(dmi))
    1806             602 :                 _udev_complete(dmt);
    1807                 : 
    1808                 : #else /* Userspace alternative for testing */
    1809                 : #endif
    1810            2110 :         return dmi;
    1811                 : }
    1812                 : 
    1813               0 : void dm_task_update_nodes(void)
    1814                 : {
    1815               0 :         update_devs();
    1816               0 : }
    1817                 : 
    1818            2412 : 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            2412 :         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            2412 :         command = _cmd_data_v4[dmt->type].cmd;
    1838                 : 
    1839                 :         /* Old-style creation had a table supplied */
    1840            2412 :         if (dmt->type == DM_DEVICE_CREATE && dmt->head)
    1841             301 :                 return _create_and_load_v4(dmt);
    1842                 : 
    1843            2113 :         if (dmt->type == DM_DEVICE_MKNODES && !dmt->dev_name &&
    1844               2 :             !dmt->uuid && dmt->major <= 0)
    1845               1 :                 return _mknodes_v4(dmt);
    1846                 : 
    1847            2110 :         if ((dmt->type == DM_DEVICE_RELOAD) && dmt->suppress_identical_reload)
    1848               0 :                 return _reload_with_suppression_v4(dmt);
    1849                 : 
    1850            2110 :         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            2110 :         if (!(dmi = _do_dm_ioctl(dmt, command, _ioctl_buffer_double_factor))) {
    1858               0 :                 _udev_complete(dmt);
    1859               0 :                 return 0;
    1860                 :         }
    1861                 : 
    1862            2110 :         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            2110 :         check_udev = dmt->cookie_set &&
    1879               0 :                      !(dmt->event_nr >> DM_UDEV_FLAGS_SHIFT &
    1880                 :                        DM_UDEV_DISABLE_DM_RULES_FLAG);
    1881                 : 
    1882            2110 :         udev_only = dmt->cookie_set ? (dmt->event_nr >> DM_UDEV_FLAGS_SHIFT &
    1883                 :                                         DM_UDEV_DISABLE_LIBRARY_FALLBACK) : 0;
    1884                 : 
    1885            2110 :         switch (dmt->type) {
    1886                 :         case DM_DEVICE_CREATE:
    1887             301 :                 if (dmt->dev_name && *dmt->dev_name && !udev_only)
    1888             602 :                         add_dev_node(dmt->dev_name, MAJOR(dmi->dev),
    1889             301 :                                      MINOR(dmi->dev), dmt->uid, dmt->gid,
    1890                 :                                      dmt->mode, check_udev);
    1891             301 :                 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             602 :                 set_dev_node_read_ahead(dmt->dev_name, dmt->read_ahead,
    1908                 :                                         dmt->read_ahead_flags);
    1909             602 :                 break;
    1910                 :         
    1911                 :         case DM_DEVICE_MKNODES:
    1912             301 :                 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             301 :                 else if (dmt->dev_name)
    1917             301 :                         rm_dev_node(dmt->dev_name, 0);
    1918             301 :                 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            2110 :         _dm_zfree_dmi(dmt->dmi.v4);
    1930            2110 :         dmt->dmi.v4 = dmi;
    1931            2110 :         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.7