LCOV - code coverage report
Current view: top level - libubifs - dir.c (source / functions) Hit Total Coverage
Test: a simple test Lines: 132 162 81.5 %
Date: 2024-06-05 20:10:43 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : /* * This file is part of UBIFS.
       3             :  *
       4             :  * Copyright (C) 2006-2008 Nokia Corporation.
       5             :  * Copyright (C) 2006, 2007 University of Szeged, Hungary
       6             :  *
       7             :  * Authors: Artem Bityutskiy (Битюцкий Артём)
       8             :  *          Adrian Hunter
       9             :  *          Zoltan Sogor
      10             :  */
      11             : 
      12             : /*
      13             :  * This file implements directory operations.
      14             :  *
      15             :  * All FS operations in this file allocate budget before writing anything to the
      16             :  * media. If they fail to allocate it, the error is returned. The only
      17             :  * exceptions are 'ubifs_unlink()' and 'ubifs_rmdir()' which keep working even
      18             :  * if they unable to allocate the budget, because deletion %-ENOSPC failure is
      19             :  * not what users are usually ready to get. UBIFS budgeting subsystem has some
      20             :  * space reserved for these purposes.
      21             :  *
      22             :  * All operations in this file write all inodes which they change straight
      23             :  * away, instead of marking them dirty. For example, 'ubifs_link()' changes
      24             :  * @i_size of the parent inode and writes the parent inode together with the
      25             :  * target inode. This was done to simplify file-system recovery which would
      26             :  * otherwise be very difficult to do. The only exception is rename which marks
      27             :  * the re-named inode dirty (because its @i_ctime is updated) but does not
      28             :  * write it, but just marks it as dirty.
      29             :  */
      30             : 
      31             : #include <sys/stat.h>
      32             : 
      33             : #include "linux_err.h"
      34             : #include "bitops.h"
      35             : #include "kmem.h"
      36             : #include "ubifs.h"
      37             : #include "defs.h"
      38             : #include "debug.h"
      39             : #include "key.h"
      40             : #include "misc.h"
      41             : 
      42             : /**
      43             :  * inherit_flags - inherit flags of the parent inode.
      44             :  * @c: UBIFS file-system description object
      45             :  * @dir: parent inode
      46             :  * @mode: new inode mode flags
      47             :  *
      48             :  * This is a helper function for 'ubifs_new_inode()' which inherits flag of the
      49             :  * parent directory inode @dir. UBIFS inodes inherit the following flags:
      50             :  * o %UBIFS_COMPR_FL, which is useful to switch compression on/of on
      51             :  *   sub-directory basis;
      52             :  * o %UBIFS_SYNC_FL - useful for the same reasons;
      53             :  * o %UBIFS_DIRSYNC_FL - similar, but relevant only to directories.
      54             :  *
      55             :  * This function returns the inherited flags.
      56             :  */
      57          30 : static int inherit_flags(struct ubifs_info *c, const struct inode *dir,
      58             :                          unsigned int mode)
      59             : {
      60             :         int flags;
      61          30 :         const struct ubifs_inode *ui = ubifs_inode(dir);
      62             : 
      63          30 :         ubifs_assert(c, S_ISDIR(dir->mode));
      64             : 
      65          30 :         flags = ui->flags & (UBIFS_COMPR_FL | UBIFS_SYNC_FL | UBIFS_DIRSYNC_FL);
      66          30 :         if (!S_ISDIR(mode))
      67             :                 /* The "DIRSYNC" flag only applies to directories */
      68           0 :                 flags &= ~UBIFS_DIRSYNC_FL;
      69          30 :         return flags;
      70             : }
      71             : 
      72             : /**
      73             :  * ubifs_new_inode - allocate new UBIFS inode object.
      74             :  * @c: UBIFS file-system description object
      75             :  * @dir: parent inode
      76             :  * @mode: inode mode flags
      77             :  *
      78             :  * This function finds an unused inode number, allocates new ubifs inode and
      79             :  * initializes it. Returns new ubifs inode in case of success and an error code
      80             :  * in case of failure.
      81             :  */
      82          35 : static struct ubifs_inode *ubifs_new_inode(struct ubifs_info *c,
      83             :                                            const struct inode *dir,
      84             :                                            unsigned int mode)
      85             : {
      86             :         int err;
      87          35 :         time_t now = time(NULL);
      88             :         struct ubifs_inode *ui;
      89             :         struct inode *inode;
      90             : 
      91          35 :         ui = kzalloc(sizeof(struct ubifs_inode), GFP_KERNEL);
      92          35 :         if (!ui)
      93             :                 return ERR_PTR(-ENOMEM);
      94             : 
      95          35 :         inode = &ui->vfs_inode;
      96          35 :         inode->atime_sec = inode->ctime_sec = inode->mtime_sec = now;
      97          35 :         inode->nlink = 1;
      98          35 :         inode->mode = mode;
      99          35 :         if (dir) {
     100             :                 /* Create non root dir. */
     101          30 :                 inode->uid = dir->uid;
     102          30 :                 inode->gid = dir->gid;
     103          30 :                 if ((dir->mode & S_ISGID) && S_ISDIR(mode))
     104           0 :                         inode->mode |= S_ISGID;
     105          30 :                 ui->flags = inherit_flags(c, dir, mode);
     106             :         }
     107          35 :         if (S_ISDIR(mode))
     108          35 :                 ui->ui_size = UBIFS_INO_NODE_SZ;
     109          35 :         if (S_ISREG(mode))
     110           0 :                 ui->compr_type = c->default_compr;
     111             :         else
     112          35 :                 ui->compr_type = UBIFS_COMPR_NONE;
     113             : 
     114          35 :         if (dir) {
     115          30 :                 spin_lock(&c->cnt_lock);
     116             :                 /* Inode number overflow is currently not supported */
     117          30 :                 if (c->highest_inum >= INUM_WARN_WATERMARK) {
     118           0 :                         if (c->highest_inum >= INUM_WATERMARK) {
     119           0 :                                 spin_unlock(&c->cnt_lock);
     120           0 :                                 ubifs_err(c, "out of inode numbers");
     121           0 :                                 err = -EINVAL;
     122             :                                 goto out;
     123             :                         }
     124           0 :                         ubifs_warn(c, "running out of inode numbers (current %lu, max %u)",
     125             :                                    (unsigned long)c->highest_inum, INUM_WATERMARK);
     126             :                 }
     127          30 :                 inode->inum = ++c->highest_inum;
     128             :         } else {
     129             :                 /* Create root dir. */
     130           5 :                 inode->inum = UBIFS_ROOT_INO;
     131             :         }
     132             :         /*
     133             :          * The creation sequence number remains with this inode for its
     134             :          * lifetime. All nodes for this inode have a greater sequence number,
     135             :          * and so it is possible to distinguish obsolete nodes belonging to a
     136             :          * previous incarnation of the same inode number - for example, for the
     137             :          * purpose of rebuilding the index.
     138             :          */
     139          35 :         ui->creat_sqnum = ++c->max_sqnum;
     140          35 :         spin_unlock(&c->cnt_lock);
     141             : 
     142          35 :         return ui;
     143             : 
     144           0 : out:
     145           0 :         kfree(ui);
     146           0 :         return ERR_PTR(err);
     147             : }
     148             : 
     149             : /**
     150             :  * ubifs_lookup_by_inum - look up the UBIFS inode according to inode number.
     151             :  * @c: UBIFS file-system description object
     152             :  * @inum: inode number
     153             :  *
     154             :  * This function looks up the UBIFS inode according to a given inode number.
     155             :  * Returns zero in case of success and an error code in case of failure.
     156             :  */
     157        1977 : struct ubifs_inode *ubifs_lookup_by_inum(struct ubifs_info *c, ino_t inum)
     158             : {
     159             :         int err;
     160             :         union ubifs_key key;
     161             :         struct inode *inode;
     162             :         struct ubifs_inode *ui;
     163        1977 :         struct ubifs_ino_node *ino = NULL;
     164             : 
     165        1977 :         ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS);
     166        1977 :         if (!ino)
     167             :                 return ERR_PTR(-ENOMEM);
     168             : 
     169        1977 :         ui = kzalloc(sizeof(struct ubifs_inode), GFP_KERNEL);
     170        1977 :         if (!ui) {
     171             :                 err = -ENOMEM;
     172             :                 goto out;
     173             :         }
     174             : 
     175        1977 :         inode = &ui->vfs_inode;
     176        3954 :         ino_key_init(c, &key, inum);
     177        1977 :         err = ubifs_tnc_lookup(c, &key, ino);
     178        1977 :         if (err) {
     179           5 :                 kfree(ui);
     180           5 :                 ubifs_assert(c, !get_failure_reason_callback(c));
     181             :                 goto out;
     182             :         }
     183             : 
     184        1972 :         inode = &ui->vfs_inode;
     185        1972 :         inode->inum = inum;
     186        1972 :         inode->uid = le32_to_cpu(ino->uid);
     187        1972 :         inode->gid = le32_to_cpu(ino->gid);
     188        1972 :         inode->mode = le32_to_cpu(ino->mode);
     189        1972 :         inode->nlink = le32_to_cpu(ino->nlink);
     190        1972 :         inode->atime_sec = le64_to_cpu(ino->atime_sec);
     191        1972 :         inode->ctime_sec = le64_to_cpu(ino->ctime_sec);
     192        1972 :         inode->mtime_sec = le64_to_cpu(ino->mtime_sec);
     193        1972 :         inode->atime_nsec = le32_to_cpu(ino->atime_nsec);
     194        1972 :         inode->ctime_nsec = le32_to_cpu(ino->ctime_nsec);
     195        1972 :         inode->mtime_nsec = le32_to_cpu(ino->mtime_nsec);
     196        1972 :         ui->creat_sqnum = le64_to_cpu(ino->creat_sqnum);
     197        1972 :         ui->xattr_size = le32_to_cpu(ino->xattr_size);
     198        1972 :         ui->xattr_cnt = le32_to_cpu(ino->xattr_cnt);
     199        1972 :         ui->xattr_names = le32_to_cpu(ino->xattr_names);
     200        1972 :         ui->compr_type = le16_to_cpu(ino->compr_type);
     201        1972 :         ui->ui_size = le64_to_cpu(ino->size);
     202        1972 :         ui->flags = le32_to_cpu(ino->flags);
     203        1972 :         ui->data_len = le32_to_cpu(ino->data_len);
     204             : 
     205        1977 : out:
     206        1977 :         kfree(ino);
     207        1982 :         return err ? ERR_PTR(err) : ui;
     208             : }
     209             : 
     210         271 : struct ubifs_inode *ubifs_lookup(struct ubifs_info *c,
     211             :                                  struct ubifs_inode *dir_ui,
     212             :                                  const struct fscrypt_name *nm)
     213             : {
     214             :         int err;
     215             :         ino_t inum;
     216             :         union ubifs_key key;
     217             :         struct ubifs_dent_node *dent;
     218             : 
     219         271 :         if (fname_len(nm) > UBIFS_MAX_NLEN)
     220             :                 return ERR_PTR(-ENAMETOOLONG);
     221             : 
     222         271 :         dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
     223         271 :         if (!dent)
     224             :                 return ERR_PTR(-ENOMEM);
     225             : 
     226         271 :         dent_key_init(c, &key, dir_ui->vfs_inode.inum, nm);
     227         271 :         err = ubifs_tnc_lookup_nm(c, &key, dent, nm);
     228         271 :         if (err) {
     229         232 :                 kfree(dent);
     230         232 :                 ubifs_assert(c, !get_failure_reason_callback(c));
     231         464 :                 return ERR_PTR(err);
     232             :         }
     233          39 :         inum = le64_to_cpu(dent->inum);
     234          39 :         kfree(dent);
     235             : 
     236          39 :         return ubifs_lookup_by_inum(c, inum);
     237             : }
     238             : 
     239          30 : int ubifs_mkdir(struct ubifs_info *c, struct ubifs_inode *dir_ui,
     240             :                 const struct fscrypt_name *nm, unsigned int mode)
     241             : {
     242             :         struct ubifs_inode *ui;
     243          30 :         struct inode *inode, *dir = &dir_ui->vfs_inode;
     244             :         int err, sz_change;
     245          30 :         struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
     246             :                                         .dirtied_ino = 1};
     247             :         /*
     248             :          * Budget request settings: new inode, new direntry and changing parent
     249             :          * directory inode.
     250             :          */
     251          30 :         dbg_gen("dent '%s', mode %#hx in dir ino %lu",
     252             :                 fname_name(nm), mode, dir->inum);
     253             : 
     254             :         /* New dir is not allowed to be created under an encrypted directory. */
     255          30 :         ubifs_assert(c, !(dir_ui->flags & UBIFS_CRYPT_FL));
     256             : 
     257          30 :         err = ubifs_budget_space(c, &req);
     258          30 :         if (err)
     259             :                 return err;
     260             : 
     261          30 :         sz_change = CALC_DENT_SIZE(fname_len(nm));
     262             : 
     263          30 :         ui = ubifs_new_inode(c, dir, S_IFDIR | mode);
     264          30 :         if (IS_ERR(ui)) {
     265           0 :                 err = PTR_ERR(ui);
     266           0 :                 goto out_budg;
     267             :         }
     268             : 
     269          30 :         inode = &ui->vfs_inode;
     270          30 :         inode->nlink++;
     271          30 :         dir->nlink++;
     272          30 :         dir_ui->ui_size += sz_change;
     273          30 :         dir->ctime_sec = dir->mtime_sec = inode->ctime_sec;
     274          30 :         err = ubifs_jnl_update_file(c, dir_ui, nm, ui);
     275          30 :         if (err) {
     276           0 :                 ubifs_err(c, "cannot create directory, error %d", err);
     277             :                 goto out_cancel;
     278             :         }
     279             : 
     280          30 :         kfree(ui);
     281          30 :         ubifs_release_budget(c, &req);
     282          30 :         return 0;
     283             : 
     284           0 : out_cancel:
     285           0 :         dir_ui->ui_size -= sz_change;
     286           0 :         dir->nlink--;
     287             :         kfree(ui);
     288           0 : out_budg:
     289           0 :         ubifs_release_budget(c, &req);
     290           0 :         return err;
     291             : }
     292             : 
     293             : /**
     294             :  * ubifs_link_recovery - link a disconnected file into the target directory.
     295             :  * @c: UBIFS file-system description object
     296             :  * @dir_ui: target directory
     297             :  * @ui: the UBIFS inode of disconnected file
     298             :  * @nm: directory entry name
     299             :  *
     300             :  * This function links the inode of disconnected file to a directory entry name
     301             :  * under the target directory. Returns zero in case of success and an error code
     302             :  * in case of failure.
     303             :  */
     304         202 : int ubifs_link_recovery(struct ubifs_info *c, struct ubifs_inode *dir_ui,
     305             :                         struct ubifs_inode *ui, const struct fscrypt_name *nm)
     306             : {
     307         202 :         struct inode *inode = &ui->vfs_inode, *dir = &dir_ui->vfs_inode;
     308             :         int err, sz_change;
     309         404 :         struct ubifs_budget_req req = { .new_dent = 1, .dirtied_ino = 2,
     310         202 :                                 .dirtied_ino_d = ALIGN(ui->data_len, 8) };
     311         202 :         time_t now = time(NULL);
     312             : 
     313             :         /*
     314             :          * Budget request settings: new direntry, changing the target inode,
     315             :          * changing the parent inode.
     316             :          */
     317         202 :         dbg_gen("dent '%s' to ino %lu (nlink %d) in dir ino %lu",
     318             :                 fname_name(nm), inode->inum, inode->nlink, dir->inum);
     319             : 
     320             :         /* New dir is not allowed to be created under an encrypted directory. */
     321         202 :         ubifs_assert(c, !(dir_ui->flags & UBIFS_CRYPT_FL));
     322             : 
     323         202 :         sz_change = CALC_DENT_SIZE(fname_len(nm));
     324             : 
     325         202 :         err = ubifs_budget_space(c, &req);
     326         202 :         if (err)
     327             :                 return err;
     328             : 
     329         202 :         inode->ctime_sec = now;
     330         202 :         dir_ui->ui_size += sz_change;
     331         202 :         dir->ctime_sec = dir->mtime_sec = now;
     332         202 :         err = ubifs_jnl_update_file(c, dir_ui, nm, ui);
     333         202 :         if (err)
     334             :                 goto out_cancel;
     335             : 
     336         202 :         ubifs_release_budget(c, &req);
     337         202 :         return 0;
     338             : 
     339           0 : out_cancel:
     340           0 :         dir_ui->ui_size -= sz_change;
     341           0 :         ubifs_release_budget(c, &req);
     342           0 :         return err;
     343             : }
     344             : 
     345             : /**
     346             :  * ubifs_create_root - create the root inode.
     347             :  * @c: UBIFS file-system description object
     348             :  *
     349             :  * This function creates a new inode for the root directory. Returns zero in
     350             :  * case of success and an error code in case of failure.
     351             :  */
     352           5 : int ubifs_create_root(struct ubifs_info *c)
     353             : {
     354             :         int err;
     355             :         struct inode *inode;
     356           5 :         struct ubifs_budget_req req = { .new_ino = 1 };
     357             :         struct ubifs_inode *ui;
     358             : 
     359             :         /* Budget request settings: new inode. */
     360           5 :         dbg_gen("create root dir");
     361             : 
     362           5 :         err = ubifs_budget_space(c, &req);
     363           5 :         if (err)
     364             :                 return err;
     365             : 
     366           5 :         ui = ubifs_new_inode(c, NULL, S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO);
     367           5 :         if (IS_ERR(ui)) {
     368           0 :                 err = PTR_ERR(ui);
     369           0 :                 goto out_budg;
     370             :         }
     371             : 
     372           5 :         inode = &ui->vfs_inode;
     373           5 :         inode->nlink = 2;
     374           5 :         ui->ui_size = UBIFS_INO_NODE_SZ;
     375           5 :         ui->flags = UBIFS_COMPR_FL;
     376           5 :         err = ubifs_jnl_update_file(c, NULL, NULL, ui);
     377           5 :         if (err)
     378             :                 goto out_ui;
     379             : 
     380           5 :         kfree(ui);
     381           5 :         ubifs_release_budget(c, &req);
     382           5 :         return 0;
     383             : 
     384           0 : out_ui:
     385             :         kfree(ui);
     386           0 : out_budg:
     387           0 :         ubifs_release_budget(c, &req);
     388           0 :         ubifs_err(c, "cannot create root dir, error %d", err);
     389             :         return err;
     390             : }

Generated by: LCOV version 1.13