10b61f8a4SDave Chinner // SPDX-License-Identifier: GPL-2.0 230f712c9SDave Chinner /* 330f712c9SDave Chinner * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. 430f712c9SDave Chinner * All Rights Reserved. 530f712c9SDave Chinner */ 630f712c9SDave Chinner #include "xfs.h" 730f712c9SDave Chinner #include "xfs_fs.h" 85467b34bSDarrick J. Wong #include "xfs_shared.h" 930f712c9SDave Chinner #include "xfs_format.h" 1030f712c9SDave Chinner #include "xfs_log_format.h" 1130f712c9SDave Chinner #include "xfs_trans_resv.h" 1230f712c9SDave Chinner #include "xfs_mount.h" 1330f712c9SDave Chinner #include "xfs_inode.h" 1430f712c9SDave Chinner #include "xfs_trans.h" 1530f712c9SDave Chinner #include "xfs_bmap.h" 1630f712c9SDave Chinner #include "xfs_dir2.h" 1730f712c9SDave Chinner #include "xfs_dir2_priv.h" 18e9e899a2SDarrick J. Wong #include "xfs_errortag.h" 1930f712c9SDave Chinner #include "xfs_error.h" 2030f712c9SDave Chinner #include "xfs_trace.h" 21ca14c096SDarrick J. Wong #include "xfs_health.h" 2230f712c9SDave Chinner 23744e6c8aSDarrick J. Wong const struct xfs_name xfs_name_dotdot = { 24744e6c8aSDarrick J. Wong .name = (const unsigned char *)"..", 25744e6c8aSDarrick J. Wong .len = 2, 26744e6c8aSDarrick J. Wong .type = XFS_DIR3_FT_DIR, 27744e6c8aSDarrick J. Wong }; 2830f712c9SDave Chinner 29e99bfc9eSDarrick J. Wong const struct xfs_name xfs_name_dot = { 30e99bfc9eSDarrick J. Wong .name = (const unsigned char *)".", 31e99bfc9eSDarrick J. Wong .len = 1, 32e99bfc9eSDarrick J. Wong .type = XFS_DIR3_FT_DIR, 33e99bfc9eSDarrick J. Wong }; 34e99bfc9eSDarrick J. Wong 351b767ee3SDave Chinner /* 361fc4d33fSAmir Goldstein * Convert inode mode to directory entry filetype 371b767ee3SDave Chinner */ 38a5c46e5eSDarrick J. Wong unsigned char 39a5c46e5eSDarrick J. Wong xfs_mode_to_ftype( 40a5c46e5eSDarrick J. Wong int mode) 411fc4d33fSAmir Goldstein { 421fc4d33fSAmir Goldstein switch (mode & S_IFMT) { 431fc4d33fSAmir Goldstein case S_IFREG: 441fc4d33fSAmir Goldstein return XFS_DIR3_FT_REG_FILE; 451fc4d33fSAmir Goldstein case S_IFDIR: 461fc4d33fSAmir Goldstein return XFS_DIR3_FT_DIR; 471fc4d33fSAmir Goldstein case S_IFCHR: 481fc4d33fSAmir Goldstein return XFS_DIR3_FT_CHRDEV; 491fc4d33fSAmir Goldstein case S_IFBLK: 501fc4d33fSAmir Goldstein return XFS_DIR3_FT_BLKDEV; 511fc4d33fSAmir Goldstein case S_IFIFO: 521fc4d33fSAmir Goldstein return XFS_DIR3_FT_FIFO; 531fc4d33fSAmir Goldstein case S_IFSOCK: 541fc4d33fSAmir Goldstein return XFS_DIR3_FT_SOCK; 551fc4d33fSAmir Goldstein case S_IFLNK: 561fc4d33fSAmir Goldstein return XFS_DIR3_FT_SYMLINK; 571fc4d33fSAmir Goldstein default: 581fc4d33fSAmir Goldstein return XFS_DIR3_FT_UNKNOWN; 591fc4d33fSAmir Goldstein } 601fc4d33fSAmir Goldstein } 6130f712c9SDave Chinner 6230f712c9SDave Chinner /* 6330f712c9SDave Chinner * ASCII case-insensitive (ie. A-Z) support for directories that was 6430f712c9SDave Chinner * used in IRIX. 6530f712c9SDave Chinner */ 66d8d11fc7SChristoph Hellwig xfs_dahash_t 6730f712c9SDave Chinner xfs_ascii_ci_hashname( 68996b2329SDarrick J. Wong const struct xfs_name *name) 6930f712c9SDave Chinner { 7030f712c9SDave Chinner xfs_dahash_t hash; 7130f712c9SDave Chinner int i; 7230f712c9SDave Chinner 7330f712c9SDave Chinner for (i = 0, hash = 0; i < name->len; i++) 74a9248538SDarrick J. Wong hash = xfs_ascii_ci_xfrm(name->name[i]) ^ rol32(hash, 7); 7530f712c9SDave Chinner 7630f712c9SDave Chinner return hash; 7730f712c9SDave Chinner } 7830f712c9SDave Chinner 79d8d11fc7SChristoph Hellwig enum xfs_dacmp 8030f712c9SDave Chinner xfs_ascii_ci_compname( 8130f712c9SDave Chinner struct xfs_da_args *args, 8230f712c9SDave Chinner const unsigned char *name, 8330f712c9SDave Chinner int len) 8430f712c9SDave Chinner { 8530f712c9SDave Chinner enum xfs_dacmp result; 8630f712c9SDave Chinner int i; 8730f712c9SDave Chinner 8830f712c9SDave Chinner if (args->namelen != len) 8930f712c9SDave Chinner return XFS_CMP_DIFFERENT; 9030f712c9SDave Chinner 9130f712c9SDave Chinner result = XFS_CMP_EXACT; 9230f712c9SDave Chinner for (i = 0; i < len; i++) { 9330f712c9SDave Chinner if (args->name[i] == name[i]) 9430f712c9SDave Chinner continue; 95a9248538SDarrick J. Wong if (xfs_ascii_ci_xfrm(args->name[i]) != 96a9248538SDarrick J. Wong xfs_ascii_ci_xfrm(name[i])) 9730f712c9SDave Chinner return XFS_CMP_DIFFERENT; 9830f712c9SDave Chinner result = XFS_CMP_CASE; 9930f712c9SDave Chinner } 10030f712c9SDave Chinner 10130f712c9SDave Chinner return result; 10230f712c9SDave Chinner } 10330f712c9SDave Chinner 10430f712c9SDave Chinner int 10530f712c9SDave Chinner xfs_da_mount( 10630f712c9SDave Chinner struct xfs_mount *mp) 10730f712c9SDave Chinner { 10830f712c9SDave Chinner struct xfs_da_geometry *dageo; 10930f712c9SDave Chinner 11030f712c9SDave Chinner 11130f712c9SDave Chinner ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT); 112ac503a4cSDarrick J. Wong ASSERT(xfs_dir2_dirblock_bytes(&mp->m_sb) <= XFS_MAX_BLOCKSIZE); 11330f712c9SDave Chinner 11410634530SDave Chinner mp->m_dir_geo = kzalloc(sizeof(struct xfs_da_geometry), 11510634530SDave Chinner GFP_KERNEL | __GFP_RETRY_MAYFAIL); 11610634530SDave Chinner mp->m_attr_geo = kzalloc(sizeof(struct xfs_da_geometry), 11710634530SDave Chinner GFP_KERNEL | __GFP_RETRY_MAYFAIL); 11830f712c9SDave Chinner if (!mp->m_dir_geo || !mp->m_attr_geo) { 119d4c75a1bSDave Chinner kfree(mp->m_dir_geo); 120d4c75a1bSDave Chinner kfree(mp->m_attr_geo); 1212451337dSDave Chinner return -ENOMEM; 12230f712c9SDave Chinner } 12330f712c9SDave Chinner 12430f712c9SDave Chinner /* set up directory geometry */ 12530f712c9SDave Chinner dageo = mp->m_dir_geo; 12630f712c9SDave Chinner dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog; 12730f712c9SDave Chinner dageo->fsblog = mp->m_sb.sb_blocklog; 128ac503a4cSDarrick J. Wong dageo->blksize = xfs_dir2_dirblock_bytes(&mp->m_sb); 12930f712c9SDave Chinner dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog; 130ebd9027dSDave Chinner if (xfs_has_crc(mp)) { 1313b344413SChristoph Hellwig dageo->node_hdr_size = sizeof(struct xfs_da3_node_hdr); 132545910bcSChristoph Hellwig dageo->leaf_hdr_size = sizeof(struct xfs_dir3_leaf_hdr); 133ed1d612fSChristoph Hellwig dageo->free_hdr_size = sizeof(struct xfs_dir3_free_hdr); 134d73e1ceeSChristoph Hellwig dageo->data_entry_offset = 135d73e1ceeSChristoph Hellwig sizeof(struct xfs_dir3_data_hdr); 136545910bcSChristoph Hellwig } else { 1373b344413SChristoph Hellwig dageo->node_hdr_size = sizeof(struct xfs_da_node_hdr); 138545910bcSChristoph Hellwig dageo->leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr); 139ed1d612fSChristoph Hellwig dageo->free_hdr_size = sizeof(struct xfs_dir2_free_hdr); 140d73e1ceeSChristoph Hellwig dageo->data_entry_offset = 141d73e1ceeSChristoph Hellwig sizeof(struct xfs_dir2_data_hdr); 142545910bcSChristoph Hellwig } 143478c7835SChristoph Hellwig dageo->leaf_max_ents = (dageo->blksize - dageo->leaf_hdr_size) / 144478c7835SChristoph Hellwig sizeof(struct xfs_dir2_leaf_entry); 1455893e4feSChristoph Hellwig dageo->free_max_bests = (dageo->blksize - dageo->free_hdr_size) / 1465893e4feSChristoph Hellwig sizeof(xfs_dir2_data_off_t); 14730f712c9SDave Chinner 148d73e1ceeSChristoph Hellwig dageo->data_first_offset = dageo->data_entry_offset + 149d73e1ceeSChristoph Hellwig xfs_dir2_data_entsize(mp, 1) + 150d73e1ceeSChristoph Hellwig xfs_dir2_data_entsize(mp, 2); 151d73e1ceeSChristoph Hellwig 15230f712c9SDave Chinner /* 15330f712c9SDave Chinner * Now we've set up the block conversion variables, we can calculate the 15430f712c9SDave Chinner * segment block constants using the geometry structure. 15530f712c9SDave Chinner */ 15630f712c9SDave Chinner dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET); 15730f712c9SDave Chinner dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET); 15830f712c9SDave Chinner dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET); 1593b344413SChristoph Hellwig dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) / 16030f712c9SDave Chinner (uint)sizeof(xfs_da_node_entry_t); 16183a21c18SChandan Babu R dageo->max_extents = (XFS_DIR2_MAX_SPACES * XFS_DIR2_SPACE_SIZE) >> 16283a21c18SChandan Babu R mp->m_sb.sb_blocklog; 16330f712c9SDave Chinner dageo->magicpct = (dageo->blksize * 37) / 100; 16430f712c9SDave Chinner 16530f712c9SDave Chinner /* set up attribute geometry - single fsb only */ 16630f712c9SDave Chinner dageo = mp->m_attr_geo; 16730f712c9SDave Chinner dageo->blklog = mp->m_sb.sb_blocklog; 16830f712c9SDave Chinner dageo->fsblog = mp->m_sb.sb_blocklog; 16930f712c9SDave Chinner dageo->blksize = 1 << dageo->blklog; 17030f712c9SDave Chinner dageo->fsbcount = 1; 1713b344413SChristoph Hellwig dageo->node_hdr_size = mp->m_dir_geo->node_hdr_size; 1723b344413SChristoph Hellwig dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) / 17330f712c9SDave Chinner (uint)sizeof(xfs_da_node_entry_t); 17483a21c18SChandan Babu R 17583a21c18SChandan Babu R if (xfs_has_large_extent_counts(mp)) 17683a21c18SChandan Babu R dageo->max_extents = XFS_MAX_EXTCNT_ATTR_FORK_LARGE; 17783a21c18SChandan Babu R else 17883a21c18SChandan Babu R dageo->max_extents = XFS_MAX_EXTCNT_ATTR_FORK_SMALL; 17983a21c18SChandan Babu R 18030f712c9SDave Chinner dageo->magicpct = (dageo->blksize * 37) / 100; 18130f712c9SDave Chinner return 0; 18230f712c9SDave Chinner } 18330f712c9SDave Chinner 18430f712c9SDave Chinner void 18530f712c9SDave Chinner xfs_da_unmount( 18630f712c9SDave Chinner struct xfs_mount *mp) 18730f712c9SDave Chinner { 188d4c75a1bSDave Chinner kfree(mp->m_dir_geo); 189d4c75a1bSDave Chinner kfree(mp->m_attr_geo); 19030f712c9SDave Chinner } 19130f712c9SDave Chinner 19230f712c9SDave Chinner /* 19330f712c9SDave Chinner * Return 1 if directory contains only "." and "..". 19430f712c9SDave Chinner */ 19530f712c9SDave Chinner int 19630f712c9SDave Chinner xfs_dir_isempty( 19730f712c9SDave Chinner xfs_inode_t *dp) 19830f712c9SDave Chinner { 19930f712c9SDave Chinner xfs_dir2_sf_hdr_t *sfp; 20030f712c9SDave Chinner 201c19b3b05SDave Chinner ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 20213d2c10bSChristoph Hellwig if (dp->i_disk_size == 0) /* might happen during shutdown. */ 20330f712c9SDave Chinner return 1; 204c01147d9SDarrick J. Wong if (dp->i_disk_size > xfs_inode_data_fork_size(dp)) 20530f712c9SDave Chinner return 0; 2066e145f94SChristoph Hellwig sfp = dp->i_df.if_data; 20730f712c9SDave Chinner return !sfp->count; 20830f712c9SDave Chinner } 20930f712c9SDave Chinner 21030f712c9SDave Chinner /* 21130f712c9SDave Chinner * Validate a given inode number. 21230f712c9SDave Chinner */ 21330f712c9SDave Chinner int 21430f712c9SDave Chinner xfs_dir_ino_validate( 21530f712c9SDave Chinner xfs_mount_t *mp, 21630f712c9SDave Chinner xfs_ino_t ino) 21730f712c9SDave Chinner { 21891fb9afcSDarrick J. Wong bool ino_ok = xfs_verify_dir_ino(mp, ino); 21930f712c9SDave Chinner 220a71895c5SDarrick J. Wong if (XFS_IS_CORRUPT(mp, !ino_ok) || 221a71895c5SDarrick J. Wong XFS_TEST_ERROR(false, mp, XFS_ERRTAG_DIR_INO_VALIDATE)) { 22230f712c9SDave Chinner xfs_warn(mp, "Invalid inode number 0x%Lx", 22330f712c9SDave Chinner (unsigned long long) ino); 2242451337dSDave Chinner return -EFSCORRUPTED; 22530f712c9SDave Chinner } 22630f712c9SDave Chinner return 0; 22730f712c9SDave Chinner } 22830f712c9SDave Chinner 22930f712c9SDave Chinner /* 23030f712c9SDave Chinner * Initialize a directory with its "." and ".." entries. 23130f712c9SDave Chinner */ 23230f712c9SDave Chinner int 23330f712c9SDave Chinner xfs_dir_init( 23430f712c9SDave Chinner xfs_trans_t *tp, 23530f712c9SDave Chinner xfs_inode_t *dp, 23630f712c9SDave Chinner xfs_inode_t *pdp) 23730f712c9SDave Chinner { 23830f712c9SDave Chinner struct xfs_da_args *args; 23930f712c9SDave Chinner int error; 24030f712c9SDave Chinner 241c19b3b05SDave Chinner ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 24230f712c9SDave Chinner error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino); 24330f712c9SDave Chinner if (error) 24430f712c9SDave Chinner return error; 24530f712c9SDave Chinner 2460b3a76e9SDave Chinner args = kzalloc(sizeof(*args), GFP_KERNEL | __GFP_NOFAIL); 24730f712c9SDave Chinner if (!args) 2482451337dSDave Chinner return -ENOMEM; 24930f712c9SDave Chinner 25030f712c9SDave Chinner args->geo = dp->i_mount->m_dir_geo; 25130f712c9SDave Chinner args->dp = dp; 25230f712c9SDave Chinner args->trans = tp; 2539eef772fSDarrick J. Wong args->owner = dp->i_ino; 25430f712c9SDave Chinner error = xfs_dir2_sf_create(args, pdp->i_ino); 255d4c75a1bSDave Chinner kfree(args); 25630f712c9SDave Chinner return error; 25730f712c9SDave Chinner } 25830f712c9SDave Chinner 259*e58ac177SChristoph Hellwig enum xfs_dir2_fmt 260*e58ac177SChristoph Hellwig xfs_dir2_format( 261*e58ac177SChristoph Hellwig struct xfs_da_args *args, 262*e58ac177SChristoph Hellwig int *error) 263*e58ac177SChristoph Hellwig { 264*e58ac177SChristoph Hellwig struct xfs_inode *dp = args->dp; 265*e58ac177SChristoph Hellwig struct xfs_mount *mp = dp->i_mount; 266*e58ac177SChristoph Hellwig struct xfs_da_geometry *geo = mp->m_dir_geo; 267*e58ac177SChristoph Hellwig xfs_fileoff_t eof; 268*e58ac177SChristoph Hellwig 269*e58ac177SChristoph Hellwig xfs_assert_ilocked(dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL); 270*e58ac177SChristoph Hellwig 271*e58ac177SChristoph Hellwig *error = 0; 272*e58ac177SChristoph Hellwig if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) 273*e58ac177SChristoph Hellwig return XFS_DIR2_FMT_SF; 274*e58ac177SChristoph Hellwig 275*e58ac177SChristoph Hellwig *error = xfs_bmap_last_offset(dp, &eof, XFS_DATA_FORK); 276*e58ac177SChristoph Hellwig if (*error) 277*e58ac177SChristoph Hellwig return XFS_DIR2_FMT_ERROR; 278*e58ac177SChristoph Hellwig 279*e58ac177SChristoph Hellwig if (eof == XFS_B_TO_FSB(mp, geo->blksize)) { 280*e58ac177SChristoph Hellwig if (XFS_IS_CORRUPT(mp, dp->i_disk_size != geo->blksize)) { 281*e58ac177SChristoph Hellwig xfs_da_mark_sick(args); 282*e58ac177SChristoph Hellwig *error = -EFSCORRUPTED; 283*e58ac177SChristoph Hellwig return XFS_DIR2_FMT_ERROR; 284*e58ac177SChristoph Hellwig } 285*e58ac177SChristoph Hellwig return XFS_DIR2_FMT_BLOCK; 286*e58ac177SChristoph Hellwig } 287*e58ac177SChristoph Hellwig if (eof == geo->leafblk + geo->fsbcount) 288*e58ac177SChristoph Hellwig return XFS_DIR2_FMT_LEAF; 289*e58ac177SChristoph Hellwig return XFS_DIR2_FMT_NODE; 290*e58ac177SChristoph Hellwig } 291*e58ac177SChristoph Hellwig 2924d893a40SChristoph Hellwig int 2934d893a40SChristoph Hellwig xfs_dir_createname_args( 2944d893a40SChristoph Hellwig struct xfs_da_args *args) 2954d893a40SChristoph Hellwig { 2964d893a40SChristoph Hellwig int error; 2974d893a40SChristoph Hellwig 2984d893a40SChristoph Hellwig if (!args->inumber) 2994d893a40SChristoph Hellwig args->op_flags |= XFS_DA_OP_JUSTCHECK; 3004d893a40SChristoph Hellwig 301*e58ac177SChristoph Hellwig switch (xfs_dir2_format(args, &error)) { 302*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_SF: 3034d893a40SChristoph Hellwig return xfs_dir2_sf_addname(args); 304*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_BLOCK: 3054d893a40SChristoph Hellwig return xfs_dir2_block_addname(args); 306*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_LEAF: 3074d893a40SChristoph Hellwig return xfs_dir2_leaf_addname(args); 308*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_NODE: 3094d893a40SChristoph Hellwig return xfs_dir2_node_addname(args); 310*e58ac177SChristoph Hellwig default: 311*e58ac177SChristoph Hellwig return error; 312*e58ac177SChristoph Hellwig } 3134d893a40SChristoph Hellwig } 3144d893a40SChristoph Hellwig 31530f712c9SDave Chinner /* 316b16ed7c1SEric Sandeen * Enter a name in a directory, or check for available space. 317b16ed7c1SEric Sandeen * If inum is 0, only the available space test is performed. 31830f712c9SDave Chinner */ 31930f712c9SDave Chinner int 32030f712c9SDave Chinner xfs_dir_createname( 32132a9b7c6SBrian Foster struct xfs_trans *tp, 32232a9b7c6SBrian Foster struct xfs_inode *dp, 323996b2329SDarrick J. Wong const struct xfs_name *name, 32430f712c9SDave Chinner xfs_ino_t inum, /* new entry inode number */ 32530f712c9SDave Chinner xfs_extlen_t total) /* bmap's total block count */ 32630f712c9SDave Chinner { 32730f712c9SDave Chinner struct xfs_da_args *args; 32830f712c9SDave Chinner int rval; 32930f712c9SDave Chinner 330c19b3b05SDave Chinner ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 331c9cfdb38SBrian Foster 332b16ed7c1SEric Sandeen if (inum) { 33330f712c9SDave Chinner rval = xfs_dir_ino_validate(tp->t_mountp, inum); 33430f712c9SDave Chinner if (rval) 33530f712c9SDave Chinner return rval; 336ff6d6af2SBill O'Donnell XFS_STATS_INC(dp->i_mount, xs_dir_create); 337b16ed7c1SEric Sandeen } 33830f712c9SDave Chinner 3390b3a76e9SDave Chinner args = kzalloc(sizeof(*args), GFP_KERNEL | __GFP_NOFAIL); 34030f712c9SDave Chinner if (!args) 3412451337dSDave Chinner return -ENOMEM; 34230f712c9SDave Chinner 34330f712c9SDave Chinner args->geo = dp->i_mount->m_dir_geo; 34430f712c9SDave Chinner args->name = name->name; 34530f712c9SDave Chinner args->namelen = name->len; 34630f712c9SDave Chinner args->filetype = name->type; 347d8d11fc7SChristoph Hellwig args->hashval = xfs_dir2_hashname(dp->i_mount, name); 34830f712c9SDave Chinner args->inumber = inum; 34930f712c9SDave Chinner args->dp = dp; 35030f712c9SDave Chinner args->total = total; 35130f712c9SDave Chinner args->whichfork = XFS_DATA_FORK; 35230f712c9SDave Chinner args->trans = tp; 35330f712c9SDave Chinner args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; 3549eef772fSDarrick J. Wong args->owner = dp->i_ino; 35530f712c9SDave Chinner 3564d893a40SChristoph Hellwig rval = xfs_dir_createname_args(args); 357d4c75a1bSDave Chinner kfree(args); 35830f712c9SDave Chinner return rval; 35930f712c9SDave Chinner } 36030f712c9SDave Chinner 36130f712c9SDave Chinner /* 36230f712c9SDave Chinner * If doing a CI lookup and case-insensitive match, dup actual name into 36330f712c9SDave Chinner * args.value. Return EEXIST for success (ie. name found) or an error. 36430f712c9SDave Chinner */ 36530f712c9SDave Chinner int 36630f712c9SDave Chinner xfs_dir_cilookup_result( 36730f712c9SDave Chinner struct xfs_da_args *args, 36830f712c9SDave Chinner const unsigned char *name, 36930f712c9SDave Chinner int len) 37030f712c9SDave Chinner { 37130f712c9SDave Chinner if (args->cmpresult == XFS_CMP_DIFFERENT) 3722451337dSDave Chinner return -ENOENT; 37330f712c9SDave Chinner if (args->cmpresult != XFS_CMP_CASE || 37430f712c9SDave Chinner !(args->op_flags & XFS_DA_OP_CILOOKUP)) 3752451337dSDave Chinner return -EEXIST; 37630f712c9SDave Chinner 37794a69db2SDave Chinner args->value = kmalloc(len, 37894a69db2SDave Chinner GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_RETRY_MAYFAIL); 37930f712c9SDave Chinner if (!args->value) 3802451337dSDave Chinner return -ENOMEM; 38130f712c9SDave Chinner 38230f712c9SDave Chinner memcpy(args->value, name, len); 38330f712c9SDave Chinner args->valuelen = len; 3842451337dSDave Chinner return -EEXIST; 38530f712c9SDave Chinner } 38630f712c9SDave Chinner 38714ee22feSChristoph Hellwig int 38814ee22feSChristoph Hellwig xfs_dir_lookup_args( 38914ee22feSChristoph Hellwig struct xfs_da_args *args) 39014ee22feSChristoph Hellwig { 39114ee22feSChristoph Hellwig int error; 39214ee22feSChristoph Hellwig 393*e58ac177SChristoph Hellwig switch (xfs_dir2_format(args, &error)) { 394*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_SF: 39514ee22feSChristoph Hellwig error = xfs_dir2_sf_lookup(args); 396*e58ac177SChristoph Hellwig break; 397*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_BLOCK: 39814ee22feSChristoph Hellwig error = xfs_dir2_block_lookup(args); 399*e58ac177SChristoph Hellwig break; 400*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_LEAF: 401*e58ac177SChristoph Hellwig error = xfs_dir2_leaf_lookup(args); 402*e58ac177SChristoph Hellwig break; 403*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_NODE: 404*e58ac177SChristoph Hellwig error = xfs_dir2_node_lookup(args); 405*e58ac177SChristoph Hellwig break; 406*e58ac177SChristoph Hellwig default: 407*e58ac177SChristoph Hellwig break; 40814ee22feSChristoph Hellwig } 40914ee22feSChristoph Hellwig 41014ee22feSChristoph Hellwig if (error != -EEXIST) 41114ee22feSChristoph Hellwig return error; 41214ee22feSChristoph Hellwig return 0; 41314ee22feSChristoph Hellwig } 41414ee22feSChristoph Hellwig 41530f712c9SDave Chinner /* 41630f712c9SDave Chinner * Lookup a name in a directory, give back the inode number. 41730f712c9SDave Chinner * If ci_name is not NULL, returns the actual name in ci_name if it differs 41830f712c9SDave Chinner * to name, or ci_name->name is set to NULL for an exact match. 41930f712c9SDave Chinner */ 42030f712c9SDave Chinner 42130f712c9SDave Chinner int 42230f712c9SDave Chinner xfs_dir_lookup( 423996b2329SDarrick J. Wong struct xfs_trans *tp, 424996b2329SDarrick J. Wong struct xfs_inode *dp, 425996b2329SDarrick J. Wong const struct xfs_name *name, 42630f712c9SDave Chinner xfs_ino_t *inum, /* out: inode number */ 42730f712c9SDave Chinner struct xfs_name *ci_name) /* out: actual name if CI match */ 42830f712c9SDave Chinner { 42930f712c9SDave Chinner struct xfs_da_args *args; 43030f712c9SDave Chinner int rval; 431dbad7c99SDave Chinner int lock_mode; 43230f712c9SDave Chinner 433c19b3b05SDave Chinner ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 434ff6d6af2SBill O'Donnell XFS_STATS_INC(dp->i_mount, xs_dir_lookup); 43530f712c9SDave Chinner 43694a69db2SDave Chinner args = kzalloc(sizeof(*args), 43794a69db2SDave Chinner GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL); 43830f712c9SDave Chinner args->geo = dp->i_mount->m_dir_geo; 43930f712c9SDave Chinner args->name = name->name; 44030f712c9SDave Chinner args->namelen = name->len; 44130f712c9SDave Chinner args->filetype = name->type; 442d8d11fc7SChristoph Hellwig args->hashval = xfs_dir2_hashname(dp->i_mount, name); 44330f712c9SDave Chinner args->dp = dp; 44430f712c9SDave Chinner args->whichfork = XFS_DATA_FORK; 44530f712c9SDave Chinner args->trans = tp; 44630f712c9SDave Chinner args->op_flags = XFS_DA_OP_OKNOENT; 4479eef772fSDarrick J. Wong args->owner = dp->i_ino; 44830f712c9SDave Chinner if (ci_name) 44930f712c9SDave Chinner args->op_flags |= XFS_DA_OP_CILOOKUP; 45030f712c9SDave Chinner 451dbad7c99SDave Chinner lock_mode = xfs_ilock_data_map_shared(dp); 45214ee22feSChristoph Hellwig rval = xfs_dir_lookup_args(args); 45330f712c9SDave Chinner if (!rval) { 45430f712c9SDave Chinner *inum = args->inumber; 45530f712c9SDave Chinner if (ci_name) { 45630f712c9SDave Chinner ci_name->name = args->value; 45730f712c9SDave Chinner ci_name->len = args->valuelen; 45830f712c9SDave Chinner } 45930f712c9SDave Chinner } 460dbad7c99SDave Chinner xfs_iunlock(dp, lock_mode); 461d4c75a1bSDave Chinner kfree(args); 46230f712c9SDave Chinner return rval; 46330f712c9SDave Chinner } 46430f712c9SDave Chinner 4653866e6e6SChristoph Hellwig int 4663866e6e6SChristoph Hellwig xfs_dir_removename_args( 4673866e6e6SChristoph Hellwig struct xfs_da_args *args) 4683866e6e6SChristoph Hellwig { 4693866e6e6SChristoph Hellwig int error; 4703866e6e6SChristoph Hellwig 471*e58ac177SChristoph Hellwig switch (xfs_dir2_format(args, &error)) { 472*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_SF: 4733866e6e6SChristoph Hellwig return xfs_dir2_sf_removename(args); 474*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_BLOCK: 4753866e6e6SChristoph Hellwig return xfs_dir2_block_removename(args); 476*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_LEAF: 4773866e6e6SChristoph Hellwig return xfs_dir2_leaf_removename(args); 478*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_NODE: 4793866e6e6SChristoph Hellwig return xfs_dir2_node_removename(args); 480*e58ac177SChristoph Hellwig default: 481*e58ac177SChristoph Hellwig return error; 482*e58ac177SChristoph Hellwig } 4833866e6e6SChristoph Hellwig } 4843866e6e6SChristoph Hellwig 48530f712c9SDave Chinner /* 48630f712c9SDave Chinner * Remove an entry from a directory. 48730f712c9SDave Chinner */ 48830f712c9SDave Chinner int 48930f712c9SDave Chinner xfs_dir_removename( 49032a9b7c6SBrian Foster struct xfs_trans *tp, 49132a9b7c6SBrian Foster struct xfs_inode *dp, 4925769aa41SDarrick J. Wong const struct xfs_name *name, 49330f712c9SDave Chinner xfs_ino_t ino, 49430f712c9SDave Chinner xfs_extlen_t total) /* bmap's total block count */ 49530f712c9SDave Chinner { 49630f712c9SDave Chinner struct xfs_da_args *args; 49730f712c9SDave Chinner int rval; 49830f712c9SDave Chinner 499c19b3b05SDave Chinner ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 500ff6d6af2SBill O'Donnell XFS_STATS_INC(dp->i_mount, xs_dir_remove); 50130f712c9SDave Chinner 5020b3a76e9SDave Chinner args = kzalloc(sizeof(*args), GFP_KERNEL | __GFP_NOFAIL); 50330f712c9SDave Chinner if (!args) 5042451337dSDave Chinner return -ENOMEM; 50530f712c9SDave Chinner 50630f712c9SDave Chinner args->geo = dp->i_mount->m_dir_geo; 50730f712c9SDave Chinner args->name = name->name; 50830f712c9SDave Chinner args->namelen = name->len; 50930f712c9SDave Chinner args->filetype = name->type; 510d8d11fc7SChristoph Hellwig args->hashval = xfs_dir2_hashname(dp->i_mount, name); 51130f712c9SDave Chinner args->inumber = ino; 51230f712c9SDave Chinner args->dp = dp; 51330f712c9SDave Chinner args->total = total; 51430f712c9SDave Chinner args->whichfork = XFS_DATA_FORK; 51530f712c9SDave Chinner args->trans = tp; 5169eef772fSDarrick J. Wong args->owner = dp->i_ino; 5173866e6e6SChristoph Hellwig rval = xfs_dir_removename_args(args); 518d4c75a1bSDave Chinner kfree(args); 51930f712c9SDave Chinner return rval; 52030f712c9SDave Chinner } 52130f712c9SDave Chinner 522dfe5febeSChristoph Hellwig int 523dfe5febeSChristoph Hellwig xfs_dir_replace_args( 524dfe5febeSChristoph Hellwig struct xfs_da_args *args) 525dfe5febeSChristoph Hellwig { 526dfe5febeSChristoph Hellwig int error; 527dfe5febeSChristoph Hellwig 528*e58ac177SChristoph Hellwig switch (xfs_dir2_format(args, &error)) { 529*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_SF: 530dfe5febeSChristoph Hellwig return xfs_dir2_sf_replace(args); 531*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_BLOCK: 532dfe5febeSChristoph Hellwig return xfs_dir2_block_replace(args); 533*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_LEAF: 534dfe5febeSChristoph Hellwig return xfs_dir2_leaf_replace(args); 535*e58ac177SChristoph Hellwig case XFS_DIR2_FMT_NODE: 536dfe5febeSChristoph Hellwig return xfs_dir2_node_replace(args); 537*e58ac177SChristoph Hellwig default: 538*e58ac177SChristoph Hellwig return error; 539*e58ac177SChristoph Hellwig } 540dfe5febeSChristoph Hellwig } 541dfe5febeSChristoph Hellwig 54230f712c9SDave Chinner /* 54330f712c9SDave Chinner * Replace the inode number of a directory entry. 54430f712c9SDave Chinner */ 54530f712c9SDave Chinner int 54630f712c9SDave Chinner xfs_dir_replace( 54732a9b7c6SBrian Foster struct xfs_trans *tp, 54832a9b7c6SBrian Foster struct xfs_inode *dp, 549996b2329SDarrick J. Wong const struct xfs_name *name, /* name of entry to replace */ 55030f712c9SDave Chinner xfs_ino_t inum, /* new inode number */ 55130f712c9SDave Chinner xfs_extlen_t total) /* bmap's total block count */ 55230f712c9SDave Chinner { 55330f712c9SDave Chinner struct xfs_da_args *args; 55430f712c9SDave Chinner int rval; 55530f712c9SDave Chinner 556c19b3b05SDave Chinner ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); 55730f712c9SDave Chinner 55830f712c9SDave Chinner rval = xfs_dir_ino_validate(tp->t_mountp, inum); 55930f712c9SDave Chinner if (rval) 56030f712c9SDave Chinner return rval; 56130f712c9SDave Chinner 5620b3a76e9SDave Chinner args = kzalloc(sizeof(*args), GFP_KERNEL | __GFP_NOFAIL); 56330f712c9SDave Chinner if (!args) 5642451337dSDave Chinner return -ENOMEM; 56530f712c9SDave Chinner 56630f712c9SDave Chinner args->geo = dp->i_mount->m_dir_geo; 56730f712c9SDave Chinner args->name = name->name; 56830f712c9SDave Chinner args->namelen = name->len; 56930f712c9SDave Chinner args->filetype = name->type; 570d8d11fc7SChristoph Hellwig args->hashval = xfs_dir2_hashname(dp->i_mount, name); 57130f712c9SDave Chinner args->inumber = inum; 57230f712c9SDave Chinner args->dp = dp; 57330f712c9SDave Chinner args->total = total; 57430f712c9SDave Chinner args->whichfork = XFS_DATA_FORK; 57530f712c9SDave Chinner args->trans = tp; 5769eef772fSDarrick J. Wong args->owner = dp->i_ino; 577dfe5febeSChristoph Hellwig rval = xfs_dir_replace_args(args); 578d4c75a1bSDave Chinner kfree(args); 57930f712c9SDave Chinner return rval; 58030f712c9SDave Chinner } 58130f712c9SDave Chinner 58230f712c9SDave Chinner /* 58330f712c9SDave Chinner * See if this entry can be added to the directory without allocating space. 58430f712c9SDave Chinner */ 58530f712c9SDave Chinner int 58630f712c9SDave Chinner xfs_dir_canenter( 58730f712c9SDave Chinner xfs_trans_t *tp, 58830f712c9SDave Chinner xfs_inode_t *dp, 58994f3cad5SEric Sandeen struct xfs_name *name) /* name of entry to add */ 59030f712c9SDave Chinner { 591381eee69SBrian Foster return xfs_dir_createname(tp, dp, name, 0, 0); 59230f712c9SDave Chinner } 59330f712c9SDave Chinner 59430f712c9SDave Chinner /* 59530f712c9SDave Chinner * Utility routines. 59630f712c9SDave Chinner */ 59730f712c9SDave Chinner 59830f712c9SDave Chinner /* 59930f712c9SDave Chinner * Add a block to the directory. 60030f712c9SDave Chinner * 60130f712c9SDave Chinner * This routine is for data and free blocks, not leaf/node blocks which are 60230f712c9SDave Chinner * handled by xfs_da_grow_inode. 60330f712c9SDave Chinner */ 60430f712c9SDave Chinner int 60530f712c9SDave Chinner xfs_dir2_grow_inode( 60630f712c9SDave Chinner struct xfs_da_args *args, 60730f712c9SDave Chinner int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ 60830f712c9SDave Chinner xfs_dir2_db_t *dbp) /* out: block number added */ 60930f712c9SDave Chinner { 61030f712c9SDave Chinner struct xfs_inode *dp = args->dp; 61130f712c9SDave Chinner struct xfs_mount *mp = dp->i_mount; 61230f712c9SDave Chinner xfs_fileoff_t bno; /* directory offset of new block */ 61330f712c9SDave Chinner int count; /* count of filesystem blocks */ 61430f712c9SDave Chinner int error; 61530f712c9SDave Chinner 61630f712c9SDave Chinner trace_xfs_dir2_grow_inode(args, space); 61730f712c9SDave Chinner 61830f712c9SDave Chinner /* 61930f712c9SDave Chinner * Set lowest possible block in the space requested. 62030f712c9SDave Chinner */ 62130f712c9SDave Chinner bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE); 62230f712c9SDave Chinner count = args->geo->fsbcount; 62330f712c9SDave Chinner 62430f712c9SDave Chinner error = xfs_da_grow_inode_int(args, &bno, count); 62530f712c9SDave Chinner if (error) 62630f712c9SDave Chinner return error; 62730f712c9SDave Chinner 62830f712c9SDave Chinner *dbp = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)bno); 62930f712c9SDave Chinner 63030f712c9SDave Chinner /* 63130f712c9SDave Chinner * Update file's size if this is the data space and it grew. 63230f712c9SDave Chinner */ 63330f712c9SDave Chinner if (space == XFS_DIR2_DATA_SPACE) { 63430f712c9SDave Chinner xfs_fsize_t size; /* directory file (data) size */ 63530f712c9SDave Chinner 63630f712c9SDave Chinner size = XFS_FSB_TO_B(mp, bno + count); 63713d2c10bSChristoph Hellwig if (size > dp->i_disk_size) { 63813d2c10bSChristoph Hellwig dp->i_disk_size = size; 63930f712c9SDave Chinner xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); 64030f712c9SDave Chinner } 64130f712c9SDave Chinner } 64230f712c9SDave Chinner return 0; 64330f712c9SDave Chinner } 64430f712c9SDave Chinner 64530f712c9SDave Chinner /* 64630f712c9SDave Chinner * Remove the given block from the directory. 64730f712c9SDave Chinner * This routine is used for data and free blocks, leaf/node are done 64830f712c9SDave Chinner * by xfs_da_shrink_inode. 64930f712c9SDave Chinner */ 65030f712c9SDave Chinner int 65130f712c9SDave Chinner xfs_dir2_shrink_inode( 65232a9b7c6SBrian Foster struct xfs_da_args *args, 65330f712c9SDave Chinner xfs_dir2_db_t db, 65430f712c9SDave Chinner struct xfs_buf *bp) 65530f712c9SDave Chinner { 65630f712c9SDave Chinner xfs_fileoff_t bno; /* directory file offset */ 65730f712c9SDave Chinner xfs_dablk_t da; /* directory file offset */ 65830f712c9SDave Chinner int done; /* bunmap is finished */ 65932a9b7c6SBrian Foster struct xfs_inode *dp; 66030f712c9SDave Chinner int error; 66132a9b7c6SBrian Foster struct xfs_mount *mp; 66232a9b7c6SBrian Foster struct xfs_trans *tp; 66330f712c9SDave Chinner 66430f712c9SDave Chinner trace_xfs_dir2_shrink_inode(args, db); 66530f712c9SDave Chinner 66630f712c9SDave Chinner dp = args->dp; 66730f712c9SDave Chinner mp = dp->i_mount; 66830f712c9SDave Chinner tp = args->trans; 66930f712c9SDave Chinner da = xfs_dir2_db_to_da(args->geo, db); 670ab7bb610SDave Chinner 671ab7bb610SDave Chinner /* Unmap the fsblock(s). */ 6722af52842SBrian Foster error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, &done); 673ab7bb610SDave Chinner if (error) { 67430f712c9SDave Chinner /* 675ab7bb610SDave Chinner * ENOSPC actually can happen if we're in a removename with no 676ab7bb610SDave Chinner * space reservation, and the resulting block removal would 677ab7bb610SDave Chinner * cause a bmap btree split or conversion from extents to btree. 678ab7bb610SDave Chinner * This can only happen for un-fragmented directory blocks, 679ab7bb610SDave Chinner * since you need to be punching out the middle of an extent. 680ab7bb610SDave Chinner * In this case we need to leave the block in the file, and not 681ab7bb610SDave Chinner * binval it. So the block has to be in a consistent empty 682ab7bb610SDave Chinner * state and appropriately logged. We don't free up the buffer, 683ab7bb610SDave Chinner * the caller can tell it hasn't happened since it got an error 684ab7bb610SDave Chinner * back. 68530f712c9SDave Chinner */ 68630f712c9SDave Chinner return error; 68730f712c9SDave Chinner } 68830f712c9SDave Chinner ASSERT(done); 68930f712c9SDave Chinner /* 69030f712c9SDave Chinner * Invalidate the buffer from the transaction. 69130f712c9SDave Chinner */ 69230f712c9SDave Chinner xfs_trans_binval(tp, bp); 69330f712c9SDave Chinner /* 69430f712c9SDave Chinner * If it's not a data block, we're done. 69530f712c9SDave Chinner */ 69630f712c9SDave Chinner if (db >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET)) 69730f712c9SDave Chinner return 0; 69830f712c9SDave Chinner /* 69930f712c9SDave Chinner * If the block isn't the last one in the directory, we're done. 70030f712c9SDave Chinner */ 70113d2c10bSChristoph Hellwig if (dp->i_disk_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0)) 70230f712c9SDave Chinner return 0; 70330f712c9SDave Chinner bno = da; 70430f712c9SDave Chinner if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) { 70530f712c9SDave Chinner /* 70630f712c9SDave Chinner * This can't really happen unless there's kernel corruption. 70730f712c9SDave Chinner */ 70830f712c9SDave Chinner return error; 70930f712c9SDave Chinner } 71030f712c9SDave Chinner if (db == args->geo->datablk) 71130f712c9SDave Chinner ASSERT(bno == 0); 71230f712c9SDave Chinner else 71330f712c9SDave Chinner ASSERT(bno > 0); 71430f712c9SDave Chinner /* 71530f712c9SDave Chinner * Set the size to the new last block. 71630f712c9SDave Chinner */ 71713d2c10bSChristoph Hellwig dp->i_disk_size = XFS_FSB_TO_B(mp, bno); 71830f712c9SDave Chinner xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 71930f712c9SDave Chinner return 0; 72030f712c9SDave Chinner } 721e5d7d51bSDarrick J. Wong 722e5d7d51bSDarrick J. Wong /* Returns true if the directory entry name is valid. */ 723e5d7d51bSDarrick J. Wong bool 724e5d7d51bSDarrick J. Wong xfs_dir2_namecheck( 725e5d7d51bSDarrick J. Wong const void *name, 726e5d7d51bSDarrick J. Wong size_t length) 727e5d7d51bSDarrick J. Wong { 728e5d7d51bSDarrick J. Wong /* 729e5d7d51bSDarrick J. Wong * MAXNAMELEN includes the trailing null, but (name/length) leave it 730e5d7d51bSDarrick J. Wong * out, so use >= for the length check. 731e5d7d51bSDarrick J. Wong */ 732e5d7d51bSDarrick J. Wong if (length >= MAXNAMELEN) 733e5d7d51bSDarrick J. Wong return false; 734e5d7d51bSDarrick J. Wong 735e5d7d51bSDarrick J. Wong /* There shouldn't be any slashes or nulls here */ 736e5d7d51bSDarrick J. Wong return !memchr(name, '/', length) && !memchr(name, 0, length); 737e5d7d51bSDarrick J. Wong } 738af952aebSDarrick J. Wong 739af952aebSDarrick J. Wong xfs_dahash_t 740af952aebSDarrick J. Wong xfs_dir2_hashname( 741af952aebSDarrick J. Wong struct xfs_mount *mp, 742996b2329SDarrick J. Wong const struct xfs_name *name) 743af952aebSDarrick J. Wong { 744ebd9027dSDave Chinner if (unlikely(xfs_has_asciici(mp))) 745af952aebSDarrick J. Wong return xfs_ascii_ci_hashname(name); 746af952aebSDarrick J. Wong return xfs_da_hashname(name->name, name->len); 747af952aebSDarrick J. Wong } 748af952aebSDarrick J. Wong 749af952aebSDarrick J. Wong enum xfs_dacmp 750af952aebSDarrick J. Wong xfs_dir2_compname( 751af952aebSDarrick J. Wong struct xfs_da_args *args, 752af952aebSDarrick J. Wong const unsigned char *name, 753af952aebSDarrick J. Wong int len) 754af952aebSDarrick J. Wong { 755ebd9027dSDave Chinner if (unlikely(xfs_has_asciici(args->dp->i_mount))) 756af952aebSDarrick J. Wong return xfs_ascii_ci_compname(args, name, len); 757af952aebSDarrick J. Wong return xfs_da_compname(args, name, len); 758af952aebSDarrick J. Wong } 759