dir.c revision 182854b46f9feb6f1b03abe747bb2beeebf2adb0
11e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy/* * This file is part of UBIFS. 21e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 31e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Copyright (C) 2006-2008 Nokia Corporation. 41e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Copyright (C) 2006, 2007 University of Szeged, Hungary 51e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 61e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * This program is free software; you can redistribute it and/or modify it 71e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * under the terms of the GNU General Public License version 2 as published by 81e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * the Free Software Foundation. 91e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 101e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * This program is distributed in the hope that it will be useful, but WITHOUT 111e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 121e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 131e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * more details. 141e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 151e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * You should have received a copy of the GNU General Public License along with 161e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * this program; if not, write to the Free Software Foundation, Inc., 51 171e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 181e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 191e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Authors: Artem Bityutskiy (Битюцкий Артём) 201e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Adrian Hunter 211e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Zoltan Sogor 221e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 231e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 241e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy/* 251e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * This file implements directory operations. 261e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 271e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * All FS operations in this file allocate budget before writing anything to the 281e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * media. If they fail to allocate it, the error is returned. The only 291e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * exceptions are 'ubifs_unlink()' and 'ubifs_rmdir()' which keep working even 301e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * if they unable to allocate the budget, because deletion %-ENOSPC failure is 311e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * not what users are usually ready to get. UBIFS budgeting subsystem has some 321e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * space reserved for these purposes. 331e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 341e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * All operations in this file write all inodes which they change straight 351e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * away, instead of marking them dirty. For example, 'ubifs_link()' changes 361e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @i_size of the parent inode and writes the parent inode together with the 371e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * target inode. This was done to simplify file-system recovery which would 381e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * otherwise be very difficult to do. The only exception is rename which marks 391e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * the re-named inode dirty (because its @i_ctime is updated) but does not 401e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * write it, but just marks it as dirty. 411e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 421e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 431e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy#include "ubifs.h" 441e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 451e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy/** 461e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * inherit_flags - inherit flags of the parent inode. 471e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @dir: parent inode 481e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @mode: new inode mode flags 491e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 501e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * This is a helper function for 'ubifs_new_inode()' which inherits flag of the 511e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * parent directory inode @dir. UBIFS inodes inherit the following flags: 521e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * o %UBIFS_COMPR_FL, which is useful to switch compression on/of on 531e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * sub-directory basis; 541e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * o %UBIFS_SYNC_FL - useful for the same reasons; 551e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * o %UBIFS_DIRSYNC_FL - similar, but relevant only to directories. 561e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 571e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * This function returns the inherited flags. 581e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 591e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic int inherit_flags(const struct inode *dir, int mode) 601e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 611e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int flags; 621e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy const struct ubifs_inode *ui = ubifs_inode(dir); 631e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 641e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (!S_ISDIR(dir->i_mode)) 651e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 661e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * The parent is not a directory, which means that an extended 671e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * attribute inode is being created. No flags. 681e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 691e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 701e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 711e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy flags = ui->flags & (UBIFS_COMPR_FL | UBIFS_SYNC_FL | UBIFS_DIRSYNC_FL); 721e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (!S_ISDIR(mode)) 731e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* The "DIRSYNC" flag only applies to directories */ 741e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy flags &= ~UBIFS_DIRSYNC_FL; 751e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return flags; 761e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 771e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 781e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy/** 791e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * ubifs_new_inode - allocate new UBIFS inode object. 801e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @c: UBIFS file-system description object 811e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @dir: parent directory inode 821e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @mode: inode mode flags 831e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 841e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * This function finds an unused inode number, allocates new inode and 851e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * initializes it. Returns new inode in case of success and an error code in 861e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * case of failure. 871e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 881e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystruct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir, 891e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int mode) 901e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 911e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *inode; 921e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_inode *ui; 931e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 941e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode = new_inode(c->vfs_sb); 951e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ui = ubifs_inode(inode); 961e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (!inode) 971e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return ERR_PTR(-ENOMEM); 981e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 991e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 1001e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Set 'S_NOCMTIME' to prevent VFS form updating [mc]time of inodes and 1011e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * marking them dirty in file write path (see 'file_update_time()'). 1021e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * UBIFS has to fully control "clean <-> dirty" transitions of inodes 1031e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * to make budgeting work. 1041e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 1051e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_flags |= (S_NOCMTIME); 1061e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 1071e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_uid = current->fsuid; 1081e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (dir->i_mode & S_ISGID) { 1091e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_gid = dir->i_gid; 1101e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (S_ISDIR(mode)) 1111e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mode |= S_ISGID; 1121e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } else 1131e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_gid = current->fsgid; 1141e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_mode = mode; 1151e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_mtime = inode->i_atime = inode->i_ctime = 1161e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_current_time(inode); 1171e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_mapping->nrpages = 0; 1181e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* Disable readahead */ 1191e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_mapping->backing_dev_info = &c->bdi; 1201e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 1211e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy switch (mode & S_IFMT) { 1221e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy case S_IFREG: 1231e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_mapping->a_ops = &ubifs_file_address_operations; 1241e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_op = &ubifs_file_inode_operations; 1251e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_fop = &ubifs_file_operations; 1261e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy break; 1271e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy case S_IFDIR: 1281e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_op = &ubifs_dir_inode_operations; 1291e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_fop = &ubifs_dir_operations; 1301e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_size = ui->ui_size = UBIFS_INO_NODE_SZ; 1311e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy break; 1321e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy case S_IFLNK: 1331e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_op = &ubifs_symlink_inode_operations; 1341e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy break; 1351e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy case S_IFSOCK: 1361e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy case S_IFIFO: 1371e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy case S_IFBLK: 1381e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy case S_IFCHR: 1391e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_op = &ubifs_file_inode_operations; 1401e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy break; 1411e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy default: 1421e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy BUG(); 1431e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 1441e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 1451e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ui->flags = inherit_flags(dir, mode); 1461e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_set_inode_flags(inode); 1471e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (S_ISREG(mode)) 1481e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ui->compr_type = c->default_compr; 1491e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy else 1501e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ui->compr_type = UBIFS_COMPR_NONE; 1511e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ui->synced_i_size = 0; 1521e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 1531e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy spin_lock(&c->cnt_lock); 1541e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* Inode number overflow is currently not supported */ 1551e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (c->highest_inum >= INUM_WARN_WATERMARK) { 1561e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (c->highest_inum >= INUM_WATERMARK) { 1571e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy spin_unlock(&c->cnt_lock); 1581e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_err("out of inode numbers"); 1591e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy make_bad_inode(inode); 1601e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy iput(inode); 1611e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return ERR_PTR(-EINVAL); 1621e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 1631e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_warn("running out of inode numbers (current %lu, max %d)", 1641e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy c->highest_inum, INUM_WATERMARK); 1651e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 1661e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 1671e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_ino = ++c->highest_inum; 1681e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_generation = ++c->vfs_gen; 1691e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 1701e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * The creation sequence number remains with this inode for its 1711e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * lifetime. All nodes for this inode have a greater sequence number, 1721e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * and so it is possible to distinguish obsolete nodes belonging to a 1731e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * previous incarnation of the same inode number - for example, for the 1741e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * purpose of rebuilding the index. 1751e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 1761e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ui->creat_sqnum = ++c->max_sqnum; 1771e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy spin_unlock(&c->cnt_lock); 1781e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return inode; 1791e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 1801e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 1811e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy#ifdef CONFIG_UBIFS_FS_DEBUG 1821e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 1831e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic int dbg_check_name(struct ubifs_dent_node *dent, struct qstr *nm) 1841e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 1851e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) 1861e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 1871e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (le16_to_cpu(dent->nlen) != nm->len) 1881e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return -EINVAL; 1891e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (memcmp(dent->name, nm->name, nm->len)) 1901e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return -EINVAL; 1911e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 1921e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 1931e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 1941e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy#else 1951e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 1961e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy#define dbg_check_name(dent, nm) 0 1971e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 1981e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy#endif 1991e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2001e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, 2011e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct nameidata *nd) 2021e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 2031e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int err; 2041e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy union ubifs_key key; 2051e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *inode = NULL; 2061e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_dent_node *dent; 2071e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_info *c = dir->i_sb->s_fs_info; 2081e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2091e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dbg_gen("'%.*s' in dir ino %lu", 2101e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dentry->d_name.len, dentry->d_name.name, dir->i_ino); 2111e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2121e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (dentry->d_name.len > UBIFS_MAX_NLEN) 2131e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return ERR_PTR(-ENAMETOOLONG); 2141e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2151e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dent = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS); 2161e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (!dent) 2171e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return ERR_PTR(-ENOMEM); 2181e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2191e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dent_key_init(c, &key, dir->i_ino, &dentry->d_name); 2201e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2211e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_tnc_lookup_nm(c, &key, dent, &dentry->d_name); 2221e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) { 2231e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 2241e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Do not hash the direntry if parent 'i_nlink' is zero, because 2251e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * this has side-effects - '->delete_inode()' call will not be 2261e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * called for the parent orphan inode, because 'd_count' of its 2271e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * direntry will stay 1 (it'll be negative direntry I guess) 2281e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * and prevent 'iput_final()' until the dentry is destroyed due 2291e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * to unmount or memory pressure. 2301e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 2311e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err == -ENOENT && dir->i_nlink != 0) { 2321e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dbg_gen("not found"); 2331e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto done; 2341e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 2351e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out; 2361e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 2371e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2381e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (dbg_check_name(dent, &dentry->d_name)) { 2391e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = -EINVAL; 2401e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out; 2411e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 2421e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2431e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode = ubifs_iget(dir->i_sb, le64_to_cpu(dent->inum)); 2441e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (IS_ERR(inode)) { 2451e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 2461e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * This should not happen. Probably the file-system needs 2471e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * checking. 2481e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 2491e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = PTR_ERR(inode); 2501e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_err("dead directory entry '%.*s', error %d", 2511e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dentry->d_name.len, dentry->d_name.name, err); 2521e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_ro_mode(c, err); 2531e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out; 2541e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 2551e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2561e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiydone: 2571e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy kfree(dent); 2581e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 2591e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Note, d_splice_alias() would be required instead if we supported 2601e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * NFS. 2611e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 2621e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy d_add(dentry, inode); 2631e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return NULL; 2641e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2651e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout: 2661e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy kfree(dent); 2671e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return ERR_PTR(err); 2681e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 2691e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2701e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic int ubifs_create(struct inode *dir, struct dentry *dentry, int mode, 2711e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct nameidata *nd) 2721e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 2731e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *inode; 2741e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_info *c = dir->i_sb->s_fs_info; 2751e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len); 2761e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, 2771e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .dirtied_ino = 1 }; 2781e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_inode *dir_ui = ubifs_inode(dir); 2791e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2801e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 2811e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Budget request settings: new inode, new direntry, changing the 2821e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * parent directory inode. 2831e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 2841e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2851e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dbg_gen("dent '%.*s', mode %#x in dir ino %lu", 2861e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino); 2871e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2881e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_budget_space(c, &req); 2891e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 2901e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 2911e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2921e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode = ubifs_new_inode(c, dir, mode); 2931e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (IS_ERR(inode)) { 2941e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = PTR_ERR(inode); 2951e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out_budg; 2961e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 2971e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 2981e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_lock(&dir_ui->ui_mutex); 2991e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_size += sz_change; 3001e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir_ui->ui_size = dir->i_size; 3011e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_mtime = dir->i_ctime = inode->i_ctime; 3021e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0); 3031e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 3041e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out_cancel; 3051e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&dir_ui->ui_mutex); 3061e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 3071e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 3081e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy insert_inode_hash(inode); 3091e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy d_instantiate(dentry, inode); 3101e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 3111e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 3121e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout_cancel: 3131e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_size -= sz_change; 3141e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir_ui->ui_size = dir->i_size; 3151e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&dir_ui->ui_mutex); 3161e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy make_bad_inode(inode); 3171e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy iput(inode); 3181e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout_budg: 3191e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 3201e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_err("cannot create regular file, error %d", err); 3211e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 3221e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 3231e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 3241e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy/** 3251e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * vfs_dent_type - get VFS directory entry type. 3261e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @type: UBIFS directory entry type 3271e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 3281e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * This function converts UBIFS directory entry type into VFS directory entry 3291e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * type. 3301e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 3311e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic unsigned int vfs_dent_type(uint8_t type) 3321e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 3331e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy switch (type) { 3341e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy case UBIFS_ITYPE_REG: 3351e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return DT_REG; 3361e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy case UBIFS_ITYPE_DIR: 3371e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return DT_DIR; 3381e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy case UBIFS_ITYPE_LNK: 3391e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return DT_LNK; 3401e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy case UBIFS_ITYPE_BLK: 3411e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return DT_BLK; 3421e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy case UBIFS_ITYPE_CHR: 3431e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return DT_CHR; 3441e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy case UBIFS_ITYPE_FIFO: 3451e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return DT_FIFO; 3461e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy case UBIFS_ITYPE_SOCK: 3471e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return DT_SOCK; 3481e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy default: 3491e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy BUG(); 3501e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 3511e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 3521e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 3531e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 3541e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy/* 3551e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * The classical Unix view for directory is that it is a linear array of 3561e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * (name, inode number) entries. Linux/VFS assumes this model as well. 3571e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Particularly, 'readdir()' call wants us to return a directory entry offset 3581e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * which later may be used to continue 'readdir()'ing the directory or to 3591e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 'seek()' to that specific direntry. Obviously UBIFS does not really fit this 3601e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * model because directory entries are identified by keys, which may collide. 3611e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 3621e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * UBIFS uses directory entry hash value for directory offsets, so 3631e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 'seekdir()'/'telldir()' may not always work because of possible key 3641e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * collisions. But UBIFS guarantees that consecutive 'readdir()' calls work 3651e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * properly by means of saving full directory entry name in the private field 3661e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * of the file description object. 3671e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 3681e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * This means that UBIFS cannot support NFS which requires full 3691e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 'seekdir()'/'telldir()' support. 3701e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 3711e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) 3721e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 3731e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int err, over = 0; 3741e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct qstr nm; 3751e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy union ubifs_key key; 3761e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_dent_node *dent; 3771e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *dir = file->f_path.dentry->d_inode; 3781e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_info *c = dir->i_sb->s_fs_info; 3791e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 3801e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos); 3811e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 3821e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2) 3831e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 3841e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * The directory was seek'ed to a senseless position or there 3851e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * are no more entries. 3861e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 3871e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 3881e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 3891e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* File positions 0 and 1 correspond to "." and ".." */ 3901e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (file->f_pos == 0) { 3911e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_assert(!file->private_data); 3921e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR); 3931e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (over) 3941e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 3951e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy file->f_pos = 1; 3961e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 3971e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 3981e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (file->f_pos == 1) { 3991e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_assert(!file->private_data); 4001e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy over = filldir(dirent, "..", 2, 1, 4011e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy parent_ino(file->f_path.dentry), DT_DIR); 4021e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (over) 4031e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 4041e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 4051e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* Find the first entry in TNC and save it */ 4061e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy lowest_dent_key(c, &key, dir->i_ino); 4071e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy nm.name = NULL; 4081e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dent = ubifs_tnc_next_ent(c, &key, &nm); 4091e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (IS_ERR(dent)) { 4101e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = PTR_ERR(dent); 4111e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out; 4121e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 4131e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 4141e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy file->f_pos = key_hash_flash(c, &dent->key); 4151e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy file->private_data = dent; 4161e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 4171e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 4181e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dent = file->private_data; 4191e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (!dent) { 4201e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 4211e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * The directory was seek'ed to and is now readdir'ed. 4221e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Find the entry corresponding to @file->f_pos or the 4231e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * closest one. 4241e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 4251e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dent_key_init_hash(c, &key, dir->i_ino, file->f_pos); 4261e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy nm.name = NULL; 4271e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dent = ubifs_tnc_next_ent(c, &key, &nm); 4281e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (IS_ERR(dent)) { 4291e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = PTR_ERR(dent); 4301e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out; 4311e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 4321e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy file->f_pos = key_hash_flash(c, &dent->key); 4331e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy file->private_data = dent; 4341e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 4351e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 4361e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy while (1) { 4371e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dbg_gen("feed '%s', ino %llu, new f_pos %#x", 4381e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dent->name, le64_to_cpu(dent->inum), 4391e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy key_hash_flash(c, &dent->key)); 4401e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_assert(dent->ch.sqnum > ubifs_inode(dir)->creat_sqnum); 4411e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 4421e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy nm.len = le16_to_cpu(dent->nlen); 4431e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy over = filldir(dirent, dent->name, nm.len, file->f_pos, 4441e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy le64_to_cpu(dent->inum), 4451e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy vfs_dent_type(dent->type)); 4461e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (over) 4471e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 4481e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 4491e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* Switch to the next entry */ 4501e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy key_read(c, &dent->key, &key); 4511e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy nm.name = dent->name; 4521e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dent = ubifs_tnc_next_ent(c, &key, &nm); 4531e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (IS_ERR(dent)) { 4541e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = PTR_ERR(dent); 4551e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out; 4561e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 4571e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 4581e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy kfree(file->private_data); 4591e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy file->f_pos = key_hash_flash(c, &dent->key); 4601e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy file->private_data = dent; 4611e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy cond_resched(); 4621e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 4631e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 4641e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout: 4651e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err != -ENOENT) { 4661e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_err("cannot find next direntry, error %d", err); 4671e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 4681e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 4691e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 4701e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy kfree(file->private_data); 4711e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy file->private_data = NULL; 4721e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy file->f_pos = 2; 4731e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 4741e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 4751e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 4761e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy/* If a directory is seeked, we have to free saved readdir() state */ 4771e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int origin) 4781e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 4791e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy kfree(file->private_data); 4801e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy file->private_data = NULL; 4811e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return generic_file_llseek(file, offset, origin); 4821e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 4831e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 4841e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy/* Free saved readdir() state when the directory is closed */ 4851e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic int ubifs_dir_release(struct inode *dir, struct file *file) 4861e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 4871e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy kfree(file->private_data); 4881e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy file->private_data = NULL; 4891e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 4901e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 4911e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 4921e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy/** 4931e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * lock_2_inodes - lock two UBIFS inodes. 4941e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @inode1: first inode 4951e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @inode2: second inode 4961e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 4971e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic void lock_2_inodes(struct inode *inode1, struct inode *inode2) 4981e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 4991e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (inode1->i_ino < inode2->i_ino) { 5001e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_2); 5011e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_3); 5021e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } else { 5031e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2); 5041e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_3); 5051e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 5061e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 5071e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 5081e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy/** 5091e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * unlock_2_inodes - unlock two UBIFS inodes inodes. 5101e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @inode1: first inode 5111e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @inode2: second inode 5121e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 5131e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic void unlock_2_inodes(struct inode *inode1, struct inode *inode2) 5141e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 5151e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&ubifs_inode(inode1)->ui_mutex); 5161e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&ubifs_inode(inode2)->ui_mutex); 5171e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 5181e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 5191e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic int ubifs_link(struct dentry *old_dentry, struct inode *dir, 5201e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct dentry *dentry) 5211e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 5221e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_info *c = dir->i_sb->s_fs_info; 5231e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *inode = old_dentry->d_inode; 5241e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_inode *ui = ubifs_inode(inode); 5251e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_inode *dir_ui = ubifs_inode(dir); 5261e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len); 5271e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_budget_req req = { .new_dent = 1, .dirtied_ino = 2, 5281e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .dirtied_ino_d = ui->data_len }; 5291e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 5301e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 5311e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Budget request settings: new direntry, changing the target inode, 5321e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * changing the parent inode. 5331e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 5341e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 5351e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dbg_gen("dent '%.*s' to ino %lu (nlink %d) in dir ino %lu", 5361e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dentry->d_name.len, dentry->d_name.name, inode->i_ino, 5371e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_nlink, dir->i_ino); 5381e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = dbg_check_synced_i_size(inode); 5391e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 5401e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 5411e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 5421e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_budget_space(c, &req); 5431e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 5441e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 5451e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 5461e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy lock_2_inodes(dir, inode); 5471e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inc_nlink(inode); 5481e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy atomic_inc(&inode->i_count); 5491e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_ctime = ubifs_current_time(inode); 5501e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_size += sz_change; 5511e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir_ui->ui_size = dir->i_size; 5521e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_mtime = dir->i_ctime = inode->i_ctime; 5531e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0); 5541e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 5551e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out_cancel; 5561e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy unlock_2_inodes(dir, inode); 5571e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 5581e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 5591e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy d_instantiate(dentry, inode); 5601e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 5611e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 5621e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout_cancel: 5631e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_size -= sz_change; 5641e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir_ui->ui_size = dir->i_size; 5651e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy drop_nlink(inode); 5661e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy unlock_2_inodes(dir, inode); 5671e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 5681e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy iput(inode); 5691e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 5701e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 5711e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 5721e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic int ubifs_unlink(struct inode *dir, struct dentry *dentry) 5731e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 5741e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_info *c = dir->i_sb->s_fs_info; 5751e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *inode = dentry->d_inode; 5761e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_inode *dir_ui = ubifs_inode(dir); 5771e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int sz_change = CALC_DENT_SIZE(dentry->d_name.len); 5781e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int err, budgeted = 1; 5791e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 }; 5801e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 5811e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 5821e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Budget request settings: deletion direntry, deletion inode (+1 for 5831e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @dirtied_ino), changing the parent directory inode. If budgeting 5841e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * fails, go ahead anyway because we have extra space reserved for 5851e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * deletions. 5861e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 5871e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 5881e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dbg_gen("dent '%.*s' from ino %lu (nlink %d) in dir ino %lu", 5891e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dentry->d_name.len, dentry->d_name.name, inode->i_ino, 5901e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_nlink, dir->i_ino); 5911e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = dbg_check_synced_i_size(inode); 5921e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 5931e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 5941e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 5951e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_budget_space(c, &req); 5961e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) { 5971e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err != -ENOSPC) 5981e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 5991e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = 0; 6001e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy budgeted = 0; 6011e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 6021e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 6031e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy lock_2_inodes(dir, inode); 6041e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_ctime = ubifs_current_time(dir); 6051e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy drop_nlink(inode); 6061e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_size -= sz_change; 6071e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir_ui->ui_size = dir->i_size; 6081e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_mtime = dir->i_ctime = inode->i_ctime; 6091e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1, 0); 6101e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 6111e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out_cancel; 6121e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy unlock_2_inodes(dir, inode); 6131e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 6141e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (budgeted) 6151e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 6161e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy else { 6171e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* We've deleted something - clean the "no space" flags */ 6181e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy c->nospace = c->nospace_rp = 0; 6191e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy smp_wmb(); 6201e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 6211e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 6221e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 6231e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout_cancel: 6241e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_size += sz_change; 6251e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir_ui->ui_size = dir->i_size; 6261e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inc_nlink(inode); 6271e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy unlock_2_inodes(dir, inode); 6281e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (budgeted) 6291e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 6301e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 6311e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 6321e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 6331e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy/** 6341e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * check_dir_empty - check if a directory is empty or not. 6351e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @c: UBIFS file-system description object 6361e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @dir: VFS inode object of the directory to check 6371e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 6381e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * This function checks if directory @dir is empty. Returns zero if the 6391e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * directory is empty, %-ENOTEMPTY if it is not, and other negative error codes 6401e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * in case of of errors. 6411e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 6421e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic int check_dir_empty(struct ubifs_info *c, struct inode *dir) 6431e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 6441e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct qstr nm = { .name = NULL }; 6451e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_dent_node *dent; 6461e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy union ubifs_key key; 6471e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int err; 6481e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 6491e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy lowest_dent_key(c, &key, dir->i_ino); 6501e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dent = ubifs_tnc_next_ent(c, &key, &nm); 6511e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (IS_ERR(dent)) { 6521e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = PTR_ERR(dent); 6531e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err == -ENOENT) 6541e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = 0; 6551e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } else { 6561e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy kfree(dent); 6571e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = -ENOTEMPTY; 6581e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 6591e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 6601e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 6611e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 6621e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic int ubifs_rmdir(struct inode *dir, struct dentry *dentry) 6631e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 6641e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_info *c = dir->i_sb->s_fs_info; 6651e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *inode = dentry->d_inode; 6661e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int sz_change = CALC_DENT_SIZE(dentry->d_name.len); 6671e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int err, budgeted = 1; 6681e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_inode *dir_ui = ubifs_inode(dir); 6691e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 }; 6701e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 6711e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 6721e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Budget request settings: deletion direntry, deletion inode and 6731e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * changing the parent inode. If budgeting fails, go ahead anyway 6741e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * because we have extra space reserved for deletions. 6751e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 6761e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 6771e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dbg_gen("directory '%.*s', ino %lu in dir ino %lu", dentry->d_name.len, 6781e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dentry->d_name.name, inode->i_ino, dir->i_ino); 6791e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 6801e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = check_dir_empty(c, dentry->d_inode); 6811e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 6821e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 6831e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 6841e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_budget_space(c, &req); 6851e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) { 6861e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err != -ENOSPC) 6871e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 6881e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy budgeted = 0; 6891e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 6901e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 6911e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy lock_2_inodes(dir, inode); 6921e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_ctime = ubifs_current_time(dir); 6931e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy clear_nlink(inode); 6941e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy drop_nlink(dir); 6951e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_size -= sz_change; 6961e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir_ui->ui_size = dir->i_size; 6971e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_mtime = dir->i_ctime = inode->i_ctime; 6981e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1, 0); 6991e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 7001e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out_cancel; 7011e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy unlock_2_inodes(dir, inode); 7021e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 7031e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (budgeted) 7041e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 7051e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy else { 7061e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* We've deleted something - clean the "no space" flags */ 7071e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy c->nospace = c->nospace_rp = 0; 7081e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy smp_wmb(); 7091e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 7101e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 7111e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 7121e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout_cancel: 7131e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_size += sz_change; 7141e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir_ui->ui_size = dir->i_size; 7151e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inc_nlink(dir); 7161e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inc_nlink(inode); 7171e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inc_nlink(inode); 7181e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy unlock_2_inodes(dir, inode); 7191e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (budgeted) 7201e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 7211e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 7221e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 7231e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 7241e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic int ubifs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 7251e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 7261e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *inode; 7271e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_inode *dir_ui = ubifs_inode(dir); 7281e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_info *c = dir->i_sb->s_fs_info; 7291e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len); 730182854b46f9feb6f1b03abe747bb2beeebf2adb0Artem Bityutskiy struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 }; 7311e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 7321e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 7331e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Budget request settings: new inode, new direntry and changing parent 7341e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * directory inode. 7351e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 7361e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 7371e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dbg_gen("dent '%.*s', mode %#x in dir ino %lu", 7381e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino); 7391e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 7401e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_budget_space(c, &req); 7411e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 7421e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 7431e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 7441e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode = ubifs_new_inode(c, dir, S_IFDIR | mode); 7451e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (IS_ERR(inode)) { 7461e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = PTR_ERR(inode); 7471e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out_budg; 7481e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 7491e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 7501e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_lock(&dir_ui->ui_mutex); 7511e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy insert_inode_hash(inode); 7521e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inc_nlink(inode); 7531e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inc_nlink(dir); 7541e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_size += sz_change; 7551e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir_ui->ui_size = dir->i_size; 7561e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_mtime = dir->i_ctime = inode->i_ctime; 7571e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0); 7581e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) { 7591e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_err("cannot create directory, error %d", err); 7601e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out_cancel; 7611e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 7621e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&dir_ui->ui_mutex); 7631e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 7641e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 7651e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy d_instantiate(dentry, inode); 7661e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 7671e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 7681e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout_cancel: 7691e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_size -= sz_change; 7701e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir_ui->ui_size = dir->i_size; 7711e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy drop_nlink(dir); 7721e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&dir_ui->ui_mutex); 7731e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy make_bad_inode(inode); 7741e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy iput(inode); 7751e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout_budg: 7761e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 7771e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 7781e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 7791e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 7801e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic int ubifs_mknod(struct inode *dir, struct dentry *dentry, 7811e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int mode, dev_t rdev) 7821e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 7831e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *inode; 7841e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_inode *ui; 7851e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_inode *dir_ui = ubifs_inode(dir); 7861e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_info *c = dir->i_sb->s_fs_info; 7871e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy union ubifs_dev_desc *dev = NULL; 7881e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int sz_change = CALC_DENT_SIZE(dentry->d_name.len); 7891e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int err, devlen = 0; 7901e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, 7911e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .new_ino_d = devlen, .dirtied_ino = 1 }; 7921e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 7931e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 7941e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Budget request settings: new inode, new direntry and changing parent 7951e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * directory inode. 7961e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 7971e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 7981e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dbg_gen("dent '%.*s' in dir ino %lu", 7991e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dentry->d_name.len, dentry->d_name.name, dir->i_ino); 8001e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8011e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (!new_valid_dev(rdev)) 8021e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return -EINVAL; 8031e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8041e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (S_ISBLK(mode) || S_ISCHR(mode)) { 8051e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS); 8061e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (!dev) 8071e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return -ENOMEM; 8081e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy devlen = ubifs_encode_dev(dev, rdev); 8091e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 8101e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8111e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_budget_space(c, &req); 8121e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) { 8131e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy kfree(dev); 8141e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 8151e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 8161e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8171e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode = ubifs_new_inode(c, dir, mode); 8181e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (IS_ERR(inode)) { 8191e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy kfree(dev); 8201e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = PTR_ERR(inode); 8211e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out_budg; 8221e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 8231e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8241e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy init_special_inode(inode, inode->i_mode, rdev); 8251e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_size = ubifs_inode(inode)->ui_size = devlen; 8261e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ui = ubifs_inode(inode); 8271e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ui->data = dev; 8281e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ui->data_len = devlen; 8291e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8301e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_lock(&dir_ui->ui_mutex); 8311e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_size += sz_change; 8321e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir_ui->ui_size = dir->i_size; 8331e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_mtime = dir->i_ctime = inode->i_ctime; 8341e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0); 8351e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 8361e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out_cancel; 8371e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&dir_ui->ui_mutex); 8381e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8391e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 8401e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy insert_inode_hash(inode); 8411e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy d_instantiate(dentry, inode); 8421e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 8431e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8441e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout_cancel: 8451e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_size -= sz_change; 8461e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir_ui->ui_size = dir->i_size; 8471e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&dir_ui->ui_mutex); 8481e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy make_bad_inode(inode); 8491e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy iput(inode); 8501e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout_budg: 8511e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 8521e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 8531e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 8541e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8551e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic int ubifs_symlink(struct inode *dir, struct dentry *dentry, 8561e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy const char *symname) 8571e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 8581e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *inode; 8591e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_inode *ui; 8601e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_inode *dir_ui = ubifs_inode(dir); 8611e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_info *c = dir->i_sb->s_fs_info; 8621e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int err, len = strlen(symname); 8631e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int sz_change = CALC_DENT_SIZE(dentry->d_name.len); 8641e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, 8651e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .new_ino_d = len, .dirtied_ino = 1 }; 8661e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8671e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 8681e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Budget request settings: new inode, new direntry and changing parent 8691e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * directory inode. 8701e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 8711e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8721e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dbg_gen("dent '%.*s', target '%s' in dir ino %lu", dentry->d_name.len, 8731e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dentry->d_name.name, symname, dir->i_ino); 8741e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8751e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (len > UBIFS_MAX_INO_DATA) 8761e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return -ENAMETOOLONG; 8771e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8781e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_budget_space(c, &req); 8791e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 8801e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 8811e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8821e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode = ubifs_new_inode(c, dir, S_IFLNK | S_IRWXUGO); 8831e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (IS_ERR(inode)) { 8841e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = PTR_ERR(inode); 8851e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out_budg; 8861e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 8871e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8881e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ui = ubifs_inode(inode); 8891e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ui->data = kmalloc(len + 1, GFP_NOFS); 8901e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (!ui->data) { 8911e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = -ENOMEM; 8921e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out_inode; 8931e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 8941e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 8951e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy memcpy(ui->data, symname, len); 8961e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ((char *)ui->data)[len] = '\0'; 8971e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 8981e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * The terminating zero byte is not written to the flash media and it 8991e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * is put just to make later in-memory string processing simpler. Thus, 9001e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * data length is @len, not @len + %1. 9011e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 9021e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ui->data_len = len; 9031e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inode->i_size = ubifs_inode(inode)->ui_size = len; 9041e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 9051e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_lock(&dir_ui->ui_mutex); 9061e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_size += sz_change; 9071e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir_ui->ui_size = dir->i_size; 9081e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_mtime = dir->i_ctime = inode->i_ctime; 9091e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0); 9101e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 9111e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out_cancel; 9121e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&dir_ui->ui_mutex); 9131e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 9141e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 9151e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy insert_inode_hash(inode); 9161e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy d_instantiate(dentry, inode); 9171e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 9181e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 9191e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout_cancel: 9201e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir->i_size -= sz_change; 9211e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dir_ui->ui_size = dir->i_size; 9221e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&dir_ui->ui_mutex); 9231e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout_inode: 9241e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy make_bad_inode(inode); 9251e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy iput(inode); 9261e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout_budg: 9271e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 9281e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 9291e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 9301e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 9311e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy/** 9321e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * lock_3_inodes - lock three UBIFS inodes for rename. 9331e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @inode1: first inode 9341e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @inode2: second inode 9351e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @inode3: third inode 9361e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 9371e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * For 'ubifs_rename()', @inode1 may be the same as @inode2 whereas @inode3 may 9381e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * be null. 9391e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 9401e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic void lock_3_inodes(struct inode *inode1, struct inode *inode2, 9411e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *inode3) 9421e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 9431e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *i1, *i2, *i3; 9441e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 9451e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (!inode3) { 9461e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (inode1 != inode2) { 9471e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy lock_2_inodes(inode1, inode2); 9481e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return; 9491e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 9501e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1); 9511e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return; 9521e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 9531e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 9541e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (inode1 == inode2) { 9551e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy lock_2_inodes(inode1, inode3); 9561e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return; 9571e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 9581e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 9591e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 3 different inodes */ 9601e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (inode1 < inode2) { 9611e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy i3 = inode2; 9621e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (inode1 < inode3) { 9631e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy i1 = inode1; 9641e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy i2 = inode3; 9651e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } else { 9661e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy i1 = inode3; 9671e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy i2 = inode1; 9681e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 9691e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } else { 9701e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy i3 = inode1; 9711e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (inode2 < inode3) { 9721e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy i1 = inode2; 9731e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy i2 = inode3; 9741e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } else { 9751e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy i1 = inode3; 9761e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy i2 = inode2; 9771e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 9781e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 9791e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_lock_nested(&ubifs_inode(i1)->ui_mutex, WB_MUTEX_1); 9801e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy lock_2_inodes(i2, i3); 9811e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 9821e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 9831e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy/** 9841e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * unlock_3_inodes - unlock three UBIFS inodes for rename. 9851e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @inode1: first inode 9861e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @inode2: second inode 9871e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @inode3: third inode 9881e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 9891e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic void unlock_3_inodes(struct inode *inode1, struct inode *inode2, 9901e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *inode3) 9911e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 9921e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&ubifs_inode(inode1)->ui_mutex); 9931e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (inode1 != inode2) 9941e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&ubifs_inode(inode2)->ui_mutex); 9951e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (inode3) 9961e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&ubifs_inode(inode3)->ui_mutex); 9971e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 9981e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 9991e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystatic int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, 10001e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *new_dir, struct dentry *new_dentry) 10011e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 10021e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_info *c = old_dir->i_sb->s_fs_info; 10031e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *old_inode = old_dentry->d_inode; 10041e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *new_inode = new_dentry->d_inode; 10051e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_inode *old_inode_ui = ubifs_inode(old_inode); 10061e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int err, release, sync = 0, move = (new_dir != old_dir); 10071e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int is_dir = S_ISDIR(old_inode->i_mode); 10081e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int unlink = !!new_inode; 10091e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int new_sz = CALC_DENT_SIZE(new_dentry->d_name.len); 10101e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy int old_sz = CALC_DENT_SIZE(old_dentry->d_name.len); 10111e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_budget_req req = { .new_dent = 1, .mod_dent = 1, 10121e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .dirtied_ino = 3 }; 10131e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_budget_req ino_req = { .dirtied_ino = 1, 10141e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .dirtied_ino_d = old_inode_ui->data_len }; 10151e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct timespec time; 10161e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 10171e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 10181e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Budget request settings: deletion direntry, new direntry, removing 10191e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * the old inode, and changing old and new parent directory inodes. 10201e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 10211e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * However, this operation also marks the target inode as dirty and 10221e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * does not write it, so we allocate budget for the target inode 10231e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * separately. 10241e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 10251e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 10261e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy dbg_gen("dent '%.*s' ino %lu in dir ino %lu to dent '%.*s' in " 10271e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy "dir ino %lu", old_dentry->d_name.len, old_dentry->d_name.name, 10281e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy old_inode->i_ino, old_dir->i_ino, new_dentry->d_name.len, 10291e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy new_dentry->d_name.name, new_dir->i_ino); 10301e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 10311e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (unlink && is_dir) { 10321e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = check_dir_empty(c, new_inode); 10331e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 10341e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 10351e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 10361e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 10371e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_budget_space(c, &req); 10381e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 10391e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 10401e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_budget_space(c, &ino_req); 10411e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) { 10421e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 10431e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 10441e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 10451e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 10461e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy lock_3_inodes(old_dir, new_dir, new_inode); 10471e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 10481e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 10491e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Like most other Unix systems, set the @i_ctime for inodes on a 10501e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * rename. 10511e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 10521e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy time = ubifs_current_time(old_dir); 10531e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy old_inode->i_ctime = time; 10541e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 10551e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* We must adjust parent link count when renaming directories */ 10561e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (is_dir) { 10571e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (move) { 10581e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 10591e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @old_dir loses a link because we are moving 10601e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @old_inode to a different directory. 10611e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 10621e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy drop_nlink(old_dir); 10631e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 10641e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @new_dir only gains a link if we are not also 10651e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * overwriting an existing directory. 10661e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 10671e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (!unlink) 10681e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inc_nlink(new_dir); 10691e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } else { 10701e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 10711e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * @old_inode is not moving to a different directory, 10721e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * but @old_dir still loses a link if we are 10731e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * overwriting an existing directory. 10741e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 10751e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (unlink) 10761e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy drop_nlink(old_dir); 10771e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 10781e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 10791e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 10801e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy old_dir->i_size -= old_sz; 10811e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_inode(old_dir)->ui_size = old_dir->i_size; 10821e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy old_dir->i_mtime = old_dir->i_ctime = time; 10831e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy new_dir->i_mtime = new_dir->i_ctime = time; 10841e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 10851e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 10861e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * And finally, if we unlinked a direntry which happened to have the 10871e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * same name as the moved direntry, we have to decrement @i_nlink of 10881e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * the unlinked inode and change its ctime. 10891e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 10901e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (unlink) { 10911e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 10921e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Directories cannot have hard-links, so if this is a 10931e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * directory, decrement its @i_nlink twice because an empty 10941e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * directory has @i_nlink 2. 10951e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 10961e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (is_dir) 10971e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy drop_nlink(new_inode); 10981e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy new_inode->i_ctime = time; 10991e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy drop_nlink(new_inode); 11001e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } else { 11011e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy new_dir->i_size += new_sz; 11021e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_inode(new_dir)->ui_size = new_dir->i_size; 11031e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 11041e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 11051e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 11061e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Do not ask 'ubifs_jnl_rename()' to flush write-buffer if @old_inode 11071e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * is dirty, because this will be done later on at the end of 11081e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * 'ubifs_rename()'. 11091e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 11101e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (IS_SYNC(old_inode)) { 11111e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy sync = IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir); 11121e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (unlink && IS_SYNC(new_inode)) 11131e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy sync = 1; 11141e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 11151e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry, 11161e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy sync); 11171e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (err) 11181e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy goto out_cancel; 11191e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 11201e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy unlock_3_inodes(old_dir, new_dir, new_inode); 11211e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 11221e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 11231e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_lock(&old_inode_ui->ui_mutex); 11241e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy release = old_inode_ui->dirty; 11251e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mark_inode_dirty_sync(old_inode); 11261e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&old_inode_ui->ui_mutex); 11271e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 11281e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (release) 11291e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &ino_req); 11301e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (IS_SYNC(old_inode)) 11311e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy err = old_inode->i_sb->s_op->write_inode(old_inode, 1); 11321e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 11331e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 11341e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyout_cancel: 11351e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (unlink) { 11361e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (is_dir) 11371e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inc_nlink(new_inode); 11381e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inc_nlink(new_inode); 11391e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } else { 11401e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy new_dir->i_size -= new_sz; 11411e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_inode(new_dir)->ui_size = new_dir->i_size; 11421e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 11431e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy old_dir->i_size += old_sz; 11441e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_inode(old_dir)->ui_size = old_dir->i_size; 11451e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (is_dir) { 11461e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (move) { 11471e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inc_nlink(old_dir); 11481e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (!unlink) 11491e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy drop_nlink(new_dir); 11501e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } else { 11511e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (unlink) 11521e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy inc_nlink(old_dir); 11531e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 11541e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } 11551e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy unlock_3_inodes(old_dir, new_dir, new_inode); 11561e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &ino_req); 11571e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy ubifs_release_budget(c, &req); 11581e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return err; 11591e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 11601e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 11611e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiyint ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry, 11621e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct kstat *stat) 11631e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy{ 11641e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy loff_t size; 11651e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct inode *inode = dentry->d_inode; 11661e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy struct ubifs_inode *ui = ubifs_inode(inode); 11671e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 11681e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_lock(&ui->ui_mutex); 11691e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy stat->dev = inode->i_sb->s_dev; 11701e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy stat->ino = inode->i_ino; 11711e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy stat->mode = inode->i_mode; 11721e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy stat->nlink = inode->i_nlink; 11731e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy stat->uid = inode->i_uid; 11741e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy stat->gid = inode->i_gid; 11751e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy stat->rdev = inode->i_rdev; 11761e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy stat->atime = inode->i_atime; 11771e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy stat->mtime = inode->i_mtime; 11781e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy stat->ctime = inode->i_ctime; 11791e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy stat->blksize = UBIFS_BLOCK_SIZE; 11801e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy stat->size = ui->ui_size; 11811e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 11821e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 11831e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Unfortunately, the 'stat()' system call was designed for block 11841e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * device based file systems, and it is not appropriate for UBIFS, 11851e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * because UBIFS does not have notion of "block". For example, it is 11861e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * difficult to tell how many block a directory takes - it actually 11871e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * takes less than 300 bytes, but we have to round it to block size, 11881e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * which introduces large mistake. This makes utilities like 'du' to 11891e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * report completely senseless numbers. This is the reason why UBIFS 11901e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * goes the same way as JFFS2 - it reports zero blocks for everything 11911e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * but regular files, which makes more sense than reporting completely 11921e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * wrong sizes. 11931e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 11941e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy if (S_ISREG(inode->i_mode)) { 11951e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy size = ui->xattr_size; 11961e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy size += stat->size; 11971e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy size = ALIGN(size, UBIFS_BLOCK_SIZE); 11981e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy /* 11991e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * Note, user-space expects 512-byte blocks count irrespectively 12001e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy * of what was reported in @stat->size. 12011e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy */ 12021e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy stat->blocks = size >> 9; 12031e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy } else 12041e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy stat->blocks = 0; 12051e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy mutex_unlock(&ui->ui_mutex); 12061e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy return 0; 12071e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy} 12081e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 12091e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystruct inode_operations ubifs_dir_inode_operations = { 12101e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .lookup = ubifs_lookup, 12111e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .create = ubifs_create, 12121e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .link = ubifs_link, 12131e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .symlink = ubifs_symlink, 12141e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .unlink = ubifs_unlink, 12151e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .mkdir = ubifs_mkdir, 12161e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .rmdir = ubifs_rmdir, 12171e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .mknod = ubifs_mknod, 12181e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .rename = ubifs_rename, 12191e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .setattr = ubifs_setattr, 12201e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .getattr = ubifs_getattr, 12211e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy#ifdef CONFIG_UBIFS_FS_XATTR 12221e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .setxattr = ubifs_setxattr, 12231e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .getxattr = ubifs_getxattr, 12241e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .listxattr = ubifs_listxattr, 12251e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .removexattr = ubifs_removexattr, 12261e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy#endif 12271e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy}; 12281e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy 12291e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiystruct file_operations ubifs_dir_operations = { 12301e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .llseek = ubifs_dir_llseek, 12311e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .release = ubifs_dir_release, 12321e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .read = generic_read_dir, 12331e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .readdir = ubifs_readdir, 12341e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .fsync = ubifs_fsync, 12351e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .unlocked_ioctl = ubifs_ioctl, 12361e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy#ifdef CONFIG_COMPAT 12371e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy .compat_ioctl = ubifs_compat_ioctl, 12381e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy#endif 12391e51764a3c2ac05a23a22b2a95ddee4d9bffb16dArtem Bityutskiy}; 1240