LCOV - code coverage report
Current view: top level - plugins/fs - nilfs.c (source / functions) Coverage Total Hit
Test: libblockdev Coverage Report Lines: 71.0 % 138 98
Test Date: 2026-01-26 13:19:28 Functions: 81.8 % 11 9
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              :  * Copyright (C) 2020  Red Hat, Inc.
       3              :  *
       4              :  * This library is free software; you can redistribute it and/or
       5              :  * modify it under the terms of the GNU Lesser General Public
       6              :  * License as published by the Free Software Foundation; either
       7              :  * version 2.1 of the License, or (at your option) any later version.
       8              :  *
       9              :  * This library is distributed in the hope that it will be useful,
      10              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12              :  * Lesser General Public License for more details.
      13              :  *
      14              :  * You should have received a copy of the GNU Lesser General Public
      15              :  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      16              :  *
      17              :  * Author: Vojtech Trefny <vtrefny@redhat.com>
      18              :  */
      19              : 
      20              : #include <blockdev/utils.h>
      21              : #include <check_deps.h>
      22              : #include <uuid.h>
      23              : 
      24              : #include "nilfs.h"
      25              : #include "fs.h"
      26              : #include "common.h"
      27              : 
      28              : static volatile guint avail_deps = 0;
      29              : static GMutex deps_check_lock;
      30              : 
      31              : #define DEPS_MKFSNILFS2 0
      32              : #define DEPS_MKFSNILFS2_MASK (1 << DEPS_MKFSNILFS2)
      33              : #define DEPS_NILFSTUNE 1
      34              : #define DEPS_NILFSTUNE_MASK (1 <<  DEPS_NILFSTUNE)
      35              : #define DEPS_NILFSRESIZE 2
      36              : #define DEPS_NILFSRESIZE_MASK (1 << DEPS_NILFSRESIZE)
      37              : 
      38              : #define DEPS_LAST 3
      39              : 
      40              : static const UtilDep deps[DEPS_LAST] = {
      41              :     {"mkfs.nilfs2", NULL, NULL, NULL},
      42              :     {"nilfs-tune", NULL, NULL, NULL},
      43              :     {"nilfs-resize", NULL, NULL, NULL},
      44              : };
      45              : 
      46              : static guint32 fs_mode_util[BD_FS_MODE_LAST+1] = {
      47              :     DEPS_MKFSNILFS2_MASK,       /* mkfs */
      48              :     0,                          /* wipe */
      49              :     0,                          /* check */
      50              :     0,                          /* repair */
      51              :     DEPS_NILFSTUNE_MASK,        /* set-label */
      52              :     DEPS_NILFSTUNE_MASK,        /* query */
      53              :     DEPS_NILFSRESIZE_MASK,      /* resize */
      54              :     DEPS_NILFSTUNE_MASK,        /* set-uuid */
      55              : };
      56              : 
      57              : 
      58              : #ifdef __clang__
      59              : #define ZERO_INIT {}
      60              : #else
      61              : #define ZERO_INIT {0}
      62              : #endif
      63              : 
      64              : /**
      65              :  * bd_fs_nilfs2_is_tech_avail:
      66              :  * @tech: the queried tech
      67              :  * @mode: a bit mask of queried modes of operation (#BDFSTechMode) for @tech
      68              :  * @error: (out) (optional): place to store error (details about why the @tech-@mode combination is not available)
      69              :  *
      70              :  * Returns: whether the @tech-@mode combination is available -- supported by the
      71              :  *          plugin implementation and having all the runtime dependencies available
      72              :  */
      73              : G_GNUC_INTERNAL gboolean
      74           99 : bd_fs_nilfs2_is_tech_avail (BDFSTech tech G_GNUC_UNUSED, guint64 mode, GError **error) {
      75           99 :     guint32 required = 0;
      76           99 :     guint i = 0;
      77              : 
      78           99 :     if (mode & BD_FS_TECH_MODE_CHECK) {
      79            1 :         g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_TECH_UNAVAIL,
      80              :                      "NILFS2 doesn't support filesystem check.");
      81            1 :         return FALSE;
      82              :     }
      83              : 
      84           98 :     if (mode & BD_FS_TECH_MODE_REPAIR) {
      85            1 :         g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_TECH_UNAVAIL,
      86              :                      "NILFS2 doesn't support filesystem repair.");
      87            1 :         return FALSE;
      88              :     }
      89              : 
      90          873 :     for (i = 0; i <= BD_FS_MODE_LAST; i++)
      91          776 :         if (mode & (1 << i))
      92          285 :             required |= fs_mode_util[i];
      93              : 
      94           97 :     return check_deps (&avail_deps, required, deps, DEPS_LAST, &deps_check_lock, error);
      95              : }
      96              : 
      97              : /**
      98              :  * bd_fs_nilfs2_info_copy: (skip)
      99              :  *
     100              :  * Creates a new copy of @data.
     101              :  */
     102            0 : BDFSNILFS2Info* bd_fs_nilfs2_info_copy (BDFSNILFS2Info *data) {
     103            0 :     if (data == NULL)
     104            0 :         return NULL;
     105              : 
     106            0 :     BDFSNILFS2Info *ret = g_new0 (BDFSNILFS2Info, 1);
     107              : 
     108            0 :     ret->label = g_strdup (data->label);
     109            0 :     ret->uuid = g_strdup (data->uuid);
     110            0 :     ret->size = data->size;
     111            0 :     ret->block_size = data->block_size;
     112            0 :     ret->free_blocks = data->free_blocks;
     113              : 
     114            0 :     return ret;
     115              : }
     116              : 
     117              : /**
     118              :  * bd_fs_nilfs2_info_free: (skip)
     119              :  *
     120              :  * Frees @data.
     121              :  */
     122            0 : void bd_fs_nilfs2_info_free (BDFSNILFS2Info *data) {
     123            0 :     if (data == NULL)
     124            0 :         return;
     125              : 
     126            0 :     g_free (data->label);
     127            0 :     g_free (data->uuid);
     128            0 :     g_free (data);
     129              : }
     130              : 
     131              : G_GNUC_INTERNAL BDExtraArg **
     132            8 : bd_fs_nilfs2_mkfs_options (BDFSMkfsOptions *options, const BDExtraArg **extra) {
     133            8 :     GPtrArray *options_array = g_ptr_array_new ();
     134            8 :     const BDExtraArg **extra_p = NULL;
     135              : 
     136            8 :     if (options->label && g_strcmp0 (options->label, "") != 0)
     137            1 :         g_ptr_array_add (options_array, bd_extra_arg_new ("-L", options->label));
     138              : 
     139            8 :     if (options->dry_run)
     140            2 :         g_ptr_array_add (options_array, bd_extra_arg_new ("-n", ""));
     141              : 
     142            8 :     if (options->no_discard)
     143            0 :         g_ptr_array_add (options_array, bd_extra_arg_new ("-K", ""));
     144              : 
     145            8 :     if (options->force)
     146            2 :         g_ptr_array_add (options_array, bd_extra_arg_new ("-f", ""));
     147              : 
     148            8 :     if (extra) {
     149            0 :         for (extra_p = extra; *extra_p; extra_p++)
     150            0 :             g_ptr_array_add (options_array, bd_extra_arg_copy ((BDExtraArg *) *extra_p));
     151              :     }
     152              : 
     153            8 :     g_ptr_array_add (options_array, NULL);
     154              : 
     155            8 :     return (BDExtraArg **) g_ptr_array_free (options_array, FALSE);
     156              : }
     157              : 
     158              : /**
     159              :  * bd_fs_nilfs2_mkfs:
     160              :  * @device: the device to create a new nilfs fs on
     161              :  * @extra: (nullable) (array zero-terminated=1): extra options for the creation (right now
     162              :  *                                                 passed to the 'mkfs.nilfs2' utility)
     163              :  * @error: (out) (optional): place to store error (if any)
     164              :  *
     165              :  * Returns: whether a new nilfs fs was successfully created on @device or not
     166              :  *
     167              :  * Tech category: %BD_FS_TECH_NILFS2-%BD_FS_TECH_MODE_MKFS
     168              :  */
     169           22 : gboolean bd_fs_nilfs2_mkfs (const gchar *device, const BDExtraArg **extra, GError **error) {
     170           22 :     const gchar *args[4] = {"mkfs.nilfs2", "-q", device, NULL};
     171              : 
     172           22 :     if (!check_deps (&avail_deps, DEPS_MKFSNILFS2_MASK, deps, DEPS_LAST, &deps_check_lock, error))
     173            0 :         return FALSE;
     174              : 
     175           22 :     return bd_utils_exec_and_report_error (args, extra, error);
     176              : }
     177              : 
     178              : /**
     179              :  * bd_fs_nilfs2_set_label:
     180              :  * @device: the device containing the file system to set label for
     181              :  * @label: label to set
     182              :  * @error: (out) (optional): place to store error (if any)
     183              :  *
     184              :  * Returns: whether the label of nilfs file system on the @device was
     185              :  *          successfully set or not
     186              :  *
     187              :  * Tech category: %BD_FS_TECH_NILFS2-%BD_FS_TECH_MODE_SET_LABEL
     188              :  */
     189            5 : gboolean bd_fs_nilfs2_set_label (const gchar *device, const gchar *label, GError **error) {
     190            5 :     const gchar *args[5] = {"nilfs-tune", "-L", label, device, NULL};
     191              : 
     192            5 :     if (!check_deps (&avail_deps, DEPS_NILFSTUNE_MASK, deps, DEPS_LAST, &deps_check_lock, error))
     193            0 :         return FALSE;
     194              : 
     195            5 :     return bd_utils_exec_and_report_error (args, NULL, error);
     196              : }
     197              : 
     198              : /**
     199              :  * bd_fs_nilfs2_check_label:
     200              :  * @label: label to check
     201              :  * @error: (out) (optional): place to store error
     202              :  *
     203              :  * Returns: whether @label is a valid label for the nilfs2 file system or not
     204              :  *          (reason is provided in @error)
     205              :  *
     206              :  * Tech category: always available
     207              :  */
     208            4 : gboolean bd_fs_nilfs2_check_label (const gchar *label, GError **error) {
     209            4 :     if (strlen (label) > 80) {
     210            2 :         g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_LABEL_INVALID,
     211              :                      "Label for nilfs2 filesystem must be at most 80 characters long.");
     212            2 :         return FALSE;
     213              :     }
     214              : 
     215            2 :     return TRUE;
     216              : }
     217              : 
     218              : /**
     219              :  * bd_fs_nilfs2_set_uuid:
     220              :  * @device: the device containing the file system to set UUID for
     221              :  * @uuid: (nullable): UUID to set or %NULL to generate a new one
     222              :  * @error: (out) (optional): place to store error (if any)
     223              :  *
     224              :  * Returns: whether the uuid of nilfs file system on the @device was
     225              :  *          successfully set or not
     226              :  *
     227              :  * Tech category: %BD_FS_TECH_NILFS2-%BD_FS_TECH_MODE_SET_UUID
     228              :  */
     229            4 : gboolean bd_fs_nilfs2_set_uuid (const gchar *device, const gchar *uuid, GError **error) {
     230            4 :     const gchar *args[5] = {"nilfs-tune", "-U", uuid, device, NULL};
     231              :     uuid_t uu;
     232            4 :     gchar uuidbuf[37] = {0};
     233              : 
     234            4 :     if (!uuid) {
     235            2 :         uuid_generate (uu);
     236            2 :         uuid_unparse (uu, uuidbuf);
     237            2 :         args[2] = uuidbuf;
     238              :     }
     239              : 
     240            4 :     if (!check_deps (&avail_deps, DEPS_NILFSTUNE_MASK, deps, DEPS_LAST, &deps_check_lock, error))
     241            0 :         return FALSE;
     242              : 
     243            4 :     return bd_utils_exec_and_report_error (args, NULL, error);
     244              : }
     245              : 
     246              : /**
     247              :  * bd_fs_nilfs2_check_uuid:
     248              :  * @uuid: UUID to check
     249              :  * @error: (out) (optional): place to store error
     250              :  *
     251              :  * Returns: whether @uuid is a valid UUID for the nilfs file system or not
     252              :  *          (reason is provided in @error)
     253              :  *
     254              :  * Tech category: always available
     255              :  */
     256            3 : gboolean bd_fs_nilfs2_check_uuid (const gchar *uuid, GError **error) {
     257            3 :     return check_uuid (uuid, error);
     258              : }
     259              : 
     260              : /**
     261              :  * bd_fs_nilfs2_get_info:
     262              :  * @device: the device containing the file system to get info for
     263              :  * @error: (out) (optional): place to store error (if any)
     264              :  *
     265              :  * Returns: (transfer full): information about the file system on @device or
     266              :  *                           %NULL in case of error
     267              :  *
     268              :  * Tech category: %BD_FS_TECH_NILFS2-%BD_FS_TECH_MODE_QUERY
     269              :  */
     270           17 : BDFSNILFS2Info* bd_fs_nilfs2_get_info (const gchar *device, GError **error) {
     271           17 :     const gchar *args[4] = {"nilfs-tune", "-l", device, NULL};
     272           17 :     gboolean success = FALSE;
     273           17 :     gchar *output = NULL;
     274           17 :     BDFSNILFS2Info *ret = NULL;
     275           17 :     gchar **lines = NULL;
     276           17 :     gchar **line_p = NULL;
     277           17 :     gchar *val_start = NULL;
     278              : 
     279           17 :     if (!check_deps (&avail_deps, DEPS_NILFSTUNE_MASK, deps, DEPS_LAST, &deps_check_lock, error))
     280            0 :         return NULL;
     281              : 
     282           17 :     ret = g_new0 (BDFSNILFS2Info, 1);
     283              : 
     284           17 :     success = get_uuid_label (device, &(ret->uuid), &(ret->label), error);
     285           17 :     if (!success) {
     286              :         /* error is already populated */
     287            0 :         bd_fs_nilfs2_info_free (ret);
     288            0 :         return NULL;
     289              :     }
     290              : 
     291           17 :     success = bd_utils_exec_and_capture_output (args, NULL, &output, error);
     292           17 :     if (!success) {
     293              :         /* error is already populated */
     294            0 :         bd_fs_nilfs2_info_free (ret);
     295            0 :         return NULL;
     296              :     }
     297              : 
     298           17 :     lines = g_strsplit (output, "\n", 0);
     299           17 :     g_free (output);
     300           17 :     line_p = lines;
     301              : 
     302          136 :     while (line_p && *line_p && !g_str_has_prefix (*line_p, "Block size:"))
     303          119 :         line_p++;
     304           17 :     if (!line_p || !(*line_p)) {
     305            0 :         g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse NILFS2 file system information");
     306            0 :         g_strfreev (lines);
     307            0 :         bd_fs_nilfs2_info_free (ret);
     308            0 :         return NULL;
     309              :     }
     310              : 
     311              :     /* * extract data from something like this: "Block size: 4096" */
     312           17 :     val_start = strchr (*line_p, ':');
     313           17 :     val_start++;
     314           17 :     ret->block_size = g_ascii_strtoull (val_start, NULL, 0);
     315              : 
     316           17 :     line_p = lines;
     317          374 :     while (line_p && *line_p && !g_str_has_prefix (*line_p, "Device size"))
     318          357 :         line_p++;
     319           17 :     if (!line_p || !(*line_p)) {
     320            0 :         g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse NILFS2 file system information");
     321            0 :         g_strfreev (lines);
     322            0 :         bd_fs_nilfs2_info_free (ret);
     323            0 :         return NULL;
     324              :     }
     325              : 
     326              :     /* extract data from something like this: "Device size: 167772160" */
     327           17 :     val_start = strchr (*line_p, ':');
     328           17 :     val_start++;
     329           17 :     ret->size = g_ascii_strtoull (val_start, NULL, 0);
     330              : 
     331           17 :     line_p = lines;
     332          493 :     while (line_p && *line_p && !g_str_has_prefix (*line_p, "Free blocks count"))
     333          476 :         line_p++;
     334           17 :     if (!line_p || !(*line_p)) {
     335            0 :         g_set_error (error, BD_FS_ERROR, BD_FS_ERROR_PARSE, "Failed to parse NILFS2 file system information");
     336            0 :         g_strfreev (lines);
     337            0 :         bd_fs_nilfs2_info_free (ret);
     338            0 :         return NULL;
     339              :     }
     340              : 
     341              :     /* extract data from something like this: "Free blocks count: 389120" */
     342           17 :     val_start = strchr (*line_p, ':');
     343           17 :     val_start++;
     344           17 :     ret->free_blocks = g_ascii_strtoull (val_start, NULL, 0);
     345              : 
     346           17 :     g_strfreev (lines);
     347              : 
     348           17 :     return ret;
     349              : }
     350              : 
     351              : /**
     352              :  * bd_fs_nilfs2_resize:
     353              :  * @device: the device the file system of which to resize
     354              :  * @new_size: new requested size for the file system (if 0, the file system is
     355              :  *            adapted to the underlying block device)
     356              :  * @error: (out) (optional): place to store error (if any)
     357              :  *
     358              :  * Returns: whether the file system on @device was successfully resized or not
     359              :  *
     360              :  * Note: Filesystem must be mounted for the resize operation.
     361              :  *
     362              :  * Tech category: %BD_FS_TECH_NILFS2-%BD_FS_TECH_MODE_RESIZE
     363              :  */
     364            7 : gboolean bd_fs_nilfs2_resize (const gchar *device, guint64 new_size, GError **error) {
     365            7 :     const gchar *args[5] = {"nilfs-resize", "-y", device, NULL, NULL};
     366            7 :     gboolean ret = FALSE;
     367              : 
     368            7 :     if (!check_deps (&avail_deps, DEPS_NILFSRESIZE_MASK, deps, DEPS_LAST, &deps_check_lock, error))
     369            0 :         return FALSE;
     370              : 
     371            7 :     if (new_size != 0)
     372            5 :         args[3] = g_strdup_printf ("%"G_GUINT64_FORMAT, new_size);
     373              : 
     374            7 :     ret = bd_utils_exec_and_report_error (args, NULL, error);
     375              : 
     376            7 :     g_free ((gchar *) args[3]);
     377            7 :     return ret;
     378              : }
        

Generated by: LCOV version 2.0-1