18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* -*- mode: c; c-basic-offset: 8; -*- 38c2ecf20Sopenharmony_ci * vim: noexpandtab sw=8 ts=8 sts=0: 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * namei.c 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Create and rename file, directory, symlinks 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Copyright (C) 2002, 2004 Oracle. All rights reserved. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Portions of this code from linux/fs/ext3/dir.c 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Copyright (C) 1992, 1993, 1994, 1995 148c2ecf20Sopenharmony_ci * Remy Card (card@masi.ibp.fr) 158c2ecf20Sopenharmony_ci * Laboratoire MASI - Institut Blaise pascal 168c2ecf20Sopenharmony_ci * Universite Pierre et Marie Curie (Paris VI) 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * from 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * linux/fs/minix/dir.c 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * Copyright (C) 1991, 1992 Linux Torvalds 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include <linux/fs.h> 268c2ecf20Sopenharmony_ci#include <linux/types.h> 278c2ecf20Sopenharmony_ci#include <linux/slab.h> 288c2ecf20Sopenharmony_ci#include <linux/highmem.h> 298c2ecf20Sopenharmony_ci#include <linux/quotaops.h> 308c2ecf20Sopenharmony_ci#include <linux/iversion.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include <cluster/masklog.h> 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#include "ocfs2.h" 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include "alloc.h" 378c2ecf20Sopenharmony_ci#include "dcache.h" 388c2ecf20Sopenharmony_ci#include "dir.h" 398c2ecf20Sopenharmony_ci#include "dlmglue.h" 408c2ecf20Sopenharmony_ci#include "extent_map.h" 418c2ecf20Sopenharmony_ci#include "file.h" 428c2ecf20Sopenharmony_ci#include "inode.h" 438c2ecf20Sopenharmony_ci#include "journal.h" 448c2ecf20Sopenharmony_ci#include "namei.h" 458c2ecf20Sopenharmony_ci#include "suballoc.h" 468c2ecf20Sopenharmony_ci#include "super.h" 478c2ecf20Sopenharmony_ci#include "symlink.h" 488c2ecf20Sopenharmony_ci#include "sysfile.h" 498c2ecf20Sopenharmony_ci#include "uptodate.h" 508c2ecf20Sopenharmony_ci#include "xattr.h" 518c2ecf20Sopenharmony_ci#include "acl.h" 528c2ecf20Sopenharmony_ci#include "ocfs2_trace.h" 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#include "buffer_head_io.h" 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic int ocfs2_mknod_locked(struct ocfs2_super *osb, 578c2ecf20Sopenharmony_ci struct inode *dir, 588c2ecf20Sopenharmony_ci struct inode *inode, 598c2ecf20Sopenharmony_ci dev_t dev, 608c2ecf20Sopenharmony_ci struct buffer_head **new_fe_bh, 618c2ecf20Sopenharmony_ci struct buffer_head *parent_fe_bh, 628c2ecf20Sopenharmony_ci handle_t *handle, 638c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *inode_ac); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, 668c2ecf20Sopenharmony_ci struct inode **ret_orphan_dir, 678c2ecf20Sopenharmony_ci u64 blkno, 688c2ecf20Sopenharmony_ci char *name, 698c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result *lookup, 708c2ecf20Sopenharmony_ci bool dio); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic int ocfs2_orphan_add(struct ocfs2_super *osb, 738c2ecf20Sopenharmony_ci handle_t *handle, 748c2ecf20Sopenharmony_ci struct inode *inode, 758c2ecf20Sopenharmony_ci struct buffer_head *fe_bh, 768c2ecf20Sopenharmony_ci char *name, 778c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result *lookup, 788c2ecf20Sopenharmony_ci struct inode *orphan_dir_inode, 798c2ecf20Sopenharmony_ci bool dio); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic int ocfs2_create_symlink_data(struct ocfs2_super *osb, 828c2ecf20Sopenharmony_ci handle_t *handle, 838c2ecf20Sopenharmony_ci struct inode *inode, 848c2ecf20Sopenharmony_ci const char *symname); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic int ocfs2_double_lock(struct ocfs2_super *osb, 878c2ecf20Sopenharmony_ci struct buffer_head **bh1, 888c2ecf20Sopenharmony_ci struct inode *inode1, 898c2ecf20Sopenharmony_ci struct buffer_head **bh2, 908c2ecf20Sopenharmony_ci struct inode *inode2, 918c2ecf20Sopenharmony_ci int rename); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2); 948c2ecf20Sopenharmony_ci/* An orphan dir name is an 8 byte value, printed as a hex string */ 958c2ecf20Sopenharmony_ci#define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, 988c2ecf20Sopenharmony_ci unsigned int flags) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci int status; 1018c2ecf20Sopenharmony_ci u64 blkno; 1028c2ecf20Sopenharmony_ci struct inode *inode = NULL; 1038c2ecf20Sopenharmony_ci struct dentry *ret; 1048c2ecf20Sopenharmony_ci struct ocfs2_inode_info *oi; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci trace_ocfs2_lookup(dir, dentry, dentry->d_name.len, 1078c2ecf20Sopenharmony_ci dentry->d_name.name, 1088c2ecf20Sopenharmony_ci (unsigned long long)OCFS2_I(dir)->ip_blkno, 0); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (dentry->d_name.len > OCFS2_MAX_FILENAME_LEN) { 1118c2ecf20Sopenharmony_ci ret = ERR_PTR(-ENAMETOOLONG); 1128c2ecf20Sopenharmony_ci goto bail; 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci status = ocfs2_inode_lock_nested(dir, NULL, 0, OI_LS_PARENT); 1168c2ecf20Sopenharmony_ci if (status < 0) { 1178c2ecf20Sopenharmony_ci if (status != -ENOENT) 1188c2ecf20Sopenharmony_ci mlog_errno(status); 1198c2ecf20Sopenharmony_ci ret = ERR_PTR(status); 1208c2ecf20Sopenharmony_ci goto bail; 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci status = ocfs2_lookup_ino_from_name(dir, dentry->d_name.name, 1248c2ecf20Sopenharmony_ci dentry->d_name.len, &blkno); 1258c2ecf20Sopenharmony_ci if (status < 0) 1268c2ecf20Sopenharmony_ci goto bail_add; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno, 0, 0); 1298c2ecf20Sopenharmony_ci if (IS_ERR(inode)) { 1308c2ecf20Sopenharmony_ci ret = ERR_PTR(-EACCES); 1318c2ecf20Sopenharmony_ci goto bail_unlock; 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci oi = OCFS2_I(inode); 1358c2ecf20Sopenharmony_ci /* Clear any orphaned state... If we were able to look up the 1368c2ecf20Sopenharmony_ci * inode from a directory, it certainly can't be orphaned. We 1378c2ecf20Sopenharmony_ci * might have the bad state from a node which intended to 1388c2ecf20Sopenharmony_ci * orphan this inode but crashed before it could commit the 1398c2ecf20Sopenharmony_ci * unlink. */ 1408c2ecf20Sopenharmony_ci spin_lock(&oi->ip_lock); 1418c2ecf20Sopenharmony_ci oi->ip_flags &= ~OCFS2_INODE_MAYBE_ORPHANED; 1428c2ecf20Sopenharmony_ci spin_unlock(&oi->ip_lock); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cibail_add: 1458c2ecf20Sopenharmony_ci ret = d_splice_alias(inode, dentry); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci if (inode) { 1488c2ecf20Sopenharmony_ci /* 1498c2ecf20Sopenharmony_ci * If d_splice_alias() finds a DCACHE_DISCONNECTED 1508c2ecf20Sopenharmony_ci * dentry, it will d_move() it on top of ourse. The 1518c2ecf20Sopenharmony_ci * return value will indicate this however, so in 1528c2ecf20Sopenharmony_ci * those cases, we switch them around for the locking 1538c2ecf20Sopenharmony_ci * code. 1548c2ecf20Sopenharmony_ci * 1558c2ecf20Sopenharmony_ci * NOTE: This dentry already has ->d_op set from 1568c2ecf20Sopenharmony_ci * ocfs2_get_parent() and ocfs2_get_dentry() 1578c2ecf20Sopenharmony_ci */ 1588c2ecf20Sopenharmony_ci if (!IS_ERR_OR_NULL(ret)) 1598c2ecf20Sopenharmony_ci dentry = ret; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci status = ocfs2_dentry_attach_lock(dentry, inode, 1628c2ecf20Sopenharmony_ci OCFS2_I(dir)->ip_blkno); 1638c2ecf20Sopenharmony_ci if (status) { 1648c2ecf20Sopenharmony_ci mlog_errno(status); 1658c2ecf20Sopenharmony_ci ret = ERR_PTR(status); 1668c2ecf20Sopenharmony_ci goto bail_unlock; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci } else 1698c2ecf20Sopenharmony_ci ocfs2_dentry_attach_gen(dentry); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cibail_unlock: 1728c2ecf20Sopenharmony_ci /* Don't drop the cluster lock until *after* the d_add -- 1738c2ecf20Sopenharmony_ci * unlink on another node will message us to remove that 1748c2ecf20Sopenharmony_ci * dentry under this lock so otherwise we can race this with 1758c2ecf20Sopenharmony_ci * the downconvert thread and have a stale dentry. */ 1768c2ecf20Sopenharmony_ci ocfs2_inode_unlock(dir, 0); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cibail: 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci trace_ocfs2_lookup_ret(ret); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci return ret; 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cistatic struct inode *ocfs2_get_init_inode(struct inode *dir, umode_t mode) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci struct inode *inode; 1888c2ecf20Sopenharmony_ci int status; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci inode = new_inode(dir->i_sb); 1918c2ecf20Sopenharmony_ci if (!inode) { 1928c2ecf20Sopenharmony_ci mlog(ML_ERROR, "new_inode failed!\n"); 1938c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci /* populate as many fields early on as possible - many of 1978c2ecf20Sopenharmony_ci * these are used by the support functions here and in 1988c2ecf20Sopenharmony_ci * callers. */ 1998c2ecf20Sopenharmony_ci if (S_ISDIR(mode)) 2008c2ecf20Sopenharmony_ci set_nlink(inode, 2); 2018c2ecf20Sopenharmony_ci mode = mode_strip_sgid(dir, mode); 2028c2ecf20Sopenharmony_ci inode_init_owner(inode, dir, mode); 2038c2ecf20Sopenharmony_ci status = dquot_initialize(inode); 2048c2ecf20Sopenharmony_ci if (status) 2058c2ecf20Sopenharmony_ci return ERR_PTR(status); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci return inode; 2088c2ecf20Sopenharmony_ci} 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_cistatic void ocfs2_cleanup_add_entry_failure(struct ocfs2_super *osb, 2118c2ecf20Sopenharmony_ci struct dentry *dentry, struct inode *inode) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci struct ocfs2_dentry_lock *dl = dentry->d_fsdata; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); 2168c2ecf20Sopenharmony_ci ocfs2_lock_res_free(&dl->dl_lockres); 2178c2ecf20Sopenharmony_ci BUG_ON(dl->dl_count != 1); 2188c2ecf20Sopenharmony_ci spin_lock(&dentry_attach_lock); 2198c2ecf20Sopenharmony_ci dentry->d_fsdata = NULL; 2208c2ecf20Sopenharmony_ci spin_unlock(&dentry_attach_lock); 2218c2ecf20Sopenharmony_ci kfree(dl); 2228c2ecf20Sopenharmony_ci iput(inode); 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic int ocfs2_mknod(struct inode *dir, 2268c2ecf20Sopenharmony_ci struct dentry *dentry, 2278c2ecf20Sopenharmony_ci umode_t mode, 2288c2ecf20Sopenharmony_ci dev_t dev) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci int status = 0; 2318c2ecf20Sopenharmony_ci struct buffer_head *parent_fe_bh = NULL; 2328c2ecf20Sopenharmony_ci handle_t *handle = NULL; 2338c2ecf20Sopenharmony_ci struct ocfs2_super *osb; 2348c2ecf20Sopenharmony_ci struct ocfs2_dinode *dirfe; 2358c2ecf20Sopenharmony_ci struct ocfs2_dinode *fe = NULL; 2368c2ecf20Sopenharmony_ci struct buffer_head *new_fe_bh = NULL; 2378c2ecf20Sopenharmony_ci struct inode *inode = NULL; 2388c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *inode_ac = NULL; 2398c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *data_ac = NULL; 2408c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *meta_ac = NULL; 2418c2ecf20Sopenharmony_ci int want_clusters = 0; 2428c2ecf20Sopenharmony_ci int want_meta = 0; 2438c2ecf20Sopenharmony_ci int xattr_credits = 0; 2448c2ecf20Sopenharmony_ci struct ocfs2_security_xattr_info si = { 2458c2ecf20Sopenharmony_ci .name = NULL, 2468c2ecf20Sopenharmony_ci .enable = 1, 2478c2ecf20Sopenharmony_ci }; 2488c2ecf20Sopenharmony_ci int did_quota_inode = 0; 2498c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result lookup = { NULL, }; 2508c2ecf20Sopenharmony_ci sigset_t oldset; 2518c2ecf20Sopenharmony_ci int did_block_signals = 0; 2528c2ecf20Sopenharmony_ci struct ocfs2_dentry_lock *dl = NULL; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci trace_ocfs2_mknod(dir, dentry, dentry->d_name.len, dentry->d_name.name, 2558c2ecf20Sopenharmony_ci (unsigned long long)OCFS2_I(dir)->ip_blkno, 2568c2ecf20Sopenharmony_ci (unsigned long)dev, mode); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci status = dquot_initialize(dir); 2598c2ecf20Sopenharmony_ci if (status) { 2608c2ecf20Sopenharmony_ci mlog_errno(status); 2618c2ecf20Sopenharmony_ci return status; 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci /* get our super block */ 2658c2ecf20Sopenharmony_ci osb = OCFS2_SB(dir->i_sb); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci status = ocfs2_inode_lock(dir, &parent_fe_bh, 1); 2688c2ecf20Sopenharmony_ci if (status < 0) { 2698c2ecf20Sopenharmony_ci if (status != -ENOENT) 2708c2ecf20Sopenharmony_ci mlog_errno(status); 2718c2ecf20Sopenharmony_ci return status; 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci if (S_ISDIR(mode) && (dir->i_nlink >= ocfs2_link_max(osb))) { 2758c2ecf20Sopenharmony_ci status = -EMLINK; 2768c2ecf20Sopenharmony_ci goto leave; 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; 2808c2ecf20Sopenharmony_ci if (!ocfs2_read_links_count(dirfe)) { 2818c2ecf20Sopenharmony_ci /* can't make a file in a deleted directory. */ 2828c2ecf20Sopenharmony_ci status = -ENOENT; 2838c2ecf20Sopenharmony_ci goto leave; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci status = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, 2878c2ecf20Sopenharmony_ci dentry->d_name.len); 2888c2ecf20Sopenharmony_ci if (status) 2898c2ecf20Sopenharmony_ci goto leave; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci /* get a spot inside the dir. */ 2928c2ecf20Sopenharmony_ci status = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh, 2938c2ecf20Sopenharmony_ci dentry->d_name.name, 2948c2ecf20Sopenharmony_ci dentry->d_name.len, &lookup); 2958c2ecf20Sopenharmony_ci if (status < 0) { 2968c2ecf20Sopenharmony_ci mlog_errno(status); 2978c2ecf20Sopenharmony_ci goto leave; 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci /* reserve an inode spot */ 3018c2ecf20Sopenharmony_ci status = ocfs2_reserve_new_inode(osb, &inode_ac); 3028c2ecf20Sopenharmony_ci if (status < 0) { 3038c2ecf20Sopenharmony_ci if (status != -ENOSPC) 3048c2ecf20Sopenharmony_ci mlog_errno(status); 3058c2ecf20Sopenharmony_ci goto leave; 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci inode = ocfs2_get_init_inode(dir, mode); 3098c2ecf20Sopenharmony_ci if (IS_ERR(inode)) { 3108c2ecf20Sopenharmony_ci status = PTR_ERR(inode); 3118c2ecf20Sopenharmony_ci inode = NULL; 3128c2ecf20Sopenharmony_ci mlog_errno(status); 3138c2ecf20Sopenharmony_ci goto leave; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci /* get security xattr */ 3178c2ecf20Sopenharmony_ci status = ocfs2_init_security_get(inode, dir, &dentry->d_name, &si); 3188c2ecf20Sopenharmony_ci if (status) { 3198c2ecf20Sopenharmony_ci if (status == -EOPNOTSUPP) 3208c2ecf20Sopenharmony_ci si.enable = 0; 3218c2ecf20Sopenharmony_ci else { 3228c2ecf20Sopenharmony_ci mlog_errno(status); 3238c2ecf20Sopenharmony_ci goto leave; 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* calculate meta data/clusters for setting security and acl xattr */ 3288c2ecf20Sopenharmony_ci status = ocfs2_calc_xattr_init(dir, parent_fe_bh, mode, 3298c2ecf20Sopenharmony_ci &si, &want_clusters, 3308c2ecf20Sopenharmony_ci &xattr_credits, &want_meta); 3318c2ecf20Sopenharmony_ci if (status < 0) { 3328c2ecf20Sopenharmony_ci mlog_errno(status); 3338c2ecf20Sopenharmony_ci goto leave; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci /* Reserve a cluster if creating an extent based directory. */ 3378c2ecf20Sopenharmony_ci if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) { 3388c2ecf20Sopenharmony_ci want_clusters += 1; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci /* Dir indexing requires extra space as well */ 3418c2ecf20Sopenharmony_ci if (ocfs2_supports_indexed_dirs(osb)) 3428c2ecf20Sopenharmony_ci want_meta++; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci status = ocfs2_reserve_new_metadata_blocks(osb, want_meta, &meta_ac); 3468c2ecf20Sopenharmony_ci if (status < 0) { 3478c2ecf20Sopenharmony_ci if (status != -ENOSPC) 3488c2ecf20Sopenharmony_ci mlog_errno(status); 3498c2ecf20Sopenharmony_ci goto leave; 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci status = ocfs2_reserve_clusters(osb, want_clusters, &data_ac); 3538c2ecf20Sopenharmony_ci if (status < 0) { 3548c2ecf20Sopenharmony_ci if (status != -ENOSPC) 3558c2ecf20Sopenharmony_ci mlog_errno(status); 3568c2ecf20Sopenharmony_ci goto leave; 3578c2ecf20Sopenharmony_ci } 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb, 3608c2ecf20Sopenharmony_ci S_ISDIR(mode), 3618c2ecf20Sopenharmony_ci xattr_credits)); 3628c2ecf20Sopenharmony_ci if (IS_ERR(handle)) { 3638c2ecf20Sopenharmony_ci status = PTR_ERR(handle); 3648c2ecf20Sopenharmony_ci handle = NULL; 3658c2ecf20Sopenharmony_ci mlog_errno(status); 3668c2ecf20Sopenharmony_ci goto leave; 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci /* Starting to change things, restart is no longer possible. */ 3708c2ecf20Sopenharmony_ci ocfs2_block_signals(&oldset); 3718c2ecf20Sopenharmony_ci did_block_signals = 1; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci status = dquot_alloc_inode(inode); 3748c2ecf20Sopenharmony_ci if (status) 3758c2ecf20Sopenharmony_ci goto leave; 3768c2ecf20Sopenharmony_ci did_quota_inode = 1; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci /* do the real work now. */ 3798c2ecf20Sopenharmony_ci status = ocfs2_mknod_locked(osb, dir, inode, dev, 3808c2ecf20Sopenharmony_ci &new_fe_bh, parent_fe_bh, handle, 3818c2ecf20Sopenharmony_ci inode_ac); 3828c2ecf20Sopenharmony_ci if (status < 0) { 3838c2ecf20Sopenharmony_ci mlog_errno(status); 3848c2ecf20Sopenharmony_ci goto leave; 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci fe = (struct ocfs2_dinode *) new_fe_bh->b_data; 3888c2ecf20Sopenharmony_ci if (S_ISDIR(mode)) { 3898c2ecf20Sopenharmony_ci status = ocfs2_fill_new_dir(osb, handle, dir, inode, 3908c2ecf20Sopenharmony_ci new_fe_bh, data_ac, meta_ac); 3918c2ecf20Sopenharmony_ci if (status < 0) { 3928c2ecf20Sopenharmony_ci mlog_errno(status); 3938c2ecf20Sopenharmony_ci goto leave; 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci status = ocfs2_journal_access_di(handle, INODE_CACHE(dir), 3978c2ecf20Sopenharmony_ci parent_fe_bh, 3988c2ecf20Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 3998c2ecf20Sopenharmony_ci if (status < 0) { 4008c2ecf20Sopenharmony_ci mlog_errno(status); 4018c2ecf20Sopenharmony_ci goto leave; 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci ocfs2_add_links_count(dirfe, 1); 4048c2ecf20Sopenharmony_ci ocfs2_journal_dirty(handle, parent_fe_bh); 4058c2ecf20Sopenharmony_ci inc_nlink(dir); 4068c2ecf20Sopenharmony_ci } 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci status = ocfs2_init_acl(handle, inode, dir, new_fe_bh, parent_fe_bh, 4098c2ecf20Sopenharmony_ci meta_ac, data_ac); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci if (status < 0) { 4128c2ecf20Sopenharmony_ci mlog_errno(status); 4138c2ecf20Sopenharmony_ci goto roll_back; 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci if (si.enable) { 4178c2ecf20Sopenharmony_ci status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si, 4188c2ecf20Sopenharmony_ci meta_ac, data_ac); 4198c2ecf20Sopenharmony_ci if (status < 0) { 4208c2ecf20Sopenharmony_ci mlog_errno(status); 4218c2ecf20Sopenharmony_ci goto roll_back; 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci /* 4268c2ecf20Sopenharmony_ci * Do this before adding the entry to the directory. We add 4278c2ecf20Sopenharmony_ci * also set d_op after success so that ->d_iput() will cleanup 4288c2ecf20Sopenharmony_ci * the dentry lock even if ocfs2_add_entry() fails below. 4298c2ecf20Sopenharmony_ci */ 4308c2ecf20Sopenharmony_ci status = ocfs2_dentry_attach_lock(dentry, inode, 4318c2ecf20Sopenharmony_ci OCFS2_I(dir)->ip_blkno); 4328c2ecf20Sopenharmony_ci if (status) { 4338c2ecf20Sopenharmony_ci mlog_errno(status); 4348c2ecf20Sopenharmony_ci goto roll_back; 4358c2ecf20Sopenharmony_ci } 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci dl = dentry->d_fsdata; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci status = ocfs2_add_entry(handle, dentry, inode, 4408c2ecf20Sopenharmony_ci OCFS2_I(inode)->ip_blkno, parent_fe_bh, 4418c2ecf20Sopenharmony_ci &lookup); 4428c2ecf20Sopenharmony_ci if (status < 0) { 4438c2ecf20Sopenharmony_ci mlog_errno(status); 4448c2ecf20Sopenharmony_ci goto roll_back; 4458c2ecf20Sopenharmony_ci } 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci insert_inode_hash(inode); 4488c2ecf20Sopenharmony_ci d_instantiate(dentry, inode); 4498c2ecf20Sopenharmony_ci status = 0; 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ciroll_back: 4528c2ecf20Sopenharmony_ci if (status < 0 && S_ISDIR(mode)) { 4538c2ecf20Sopenharmony_ci ocfs2_add_links_count(dirfe, -1); 4548c2ecf20Sopenharmony_ci drop_nlink(dir); 4558c2ecf20Sopenharmony_ci } 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_cileave: 4588c2ecf20Sopenharmony_ci if (status < 0 && did_quota_inode) 4598c2ecf20Sopenharmony_ci dquot_free_inode(inode); 4608c2ecf20Sopenharmony_ci if (handle) { 4618c2ecf20Sopenharmony_ci if (status < 0 && fe) 4628c2ecf20Sopenharmony_ci ocfs2_set_links_count(fe, 0); 4638c2ecf20Sopenharmony_ci ocfs2_commit_trans(osb, handle); 4648c2ecf20Sopenharmony_ci } 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci ocfs2_inode_unlock(dir, 1); 4678c2ecf20Sopenharmony_ci if (did_block_signals) 4688c2ecf20Sopenharmony_ci ocfs2_unblock_signals(&oldset); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci brelse(new_fe_bh); 4718c2ecf20Sopenharmony_ci brelse(parent_fe_bh); 4728c2ecf20Sopenharmony_ci kfree(si.value); 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci ocfs2_free_dir_lookup_result(&lookup); 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci if (inode_ac) 4778c2ecf20Sopenharmony_ci ocfs2_free_alloc_context(inode_ac); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci if (data_ac) 4808c2ecf20Sopenharmony_ci ocfs2_free_alloc_context(data_ac); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci if (meta_ac) 4838c2ecf20Sopenharmony_ci ocfs2_free_alloc_context(meta_ac); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci /* 4868c2ecf20Sopenharmony_ci * We should call iput after the i_mutex of the bitmap been 4878c2ecf20Sopenharmony_ci * unlocked in ocfs2_free_alloc_context, or the 4888c2ecf20Sopenharmony_ci * ocfs2_delete_inode will mutex_lock again. 4898c2ecf20Sopenharmony_ci */ 4908c2ecf20Sopenharmony_ci if ((status < 0) && inode) { 4918c2ecf20Sopenharmony_ci if (dl) 4928c2ecf20Sopenharmony_ci ocfs2_cleanup_add_entry_failure(osb, dentry, inode); 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SKIP_ORPHAN_DIR; 4958c2ecf20Sopenharmony_ci clear_nlink(inode); 4968c2ecf20Sopenharmony_ci iput(inode); 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci if (status) 5008c2ecf20Sopenharmony_ci mlog_errno(status); 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci return status; 5038c2ecf20Sopenharmony_ci} 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_cistatic int __ocfs2_mknod_locked(struct inode *dir, 5068c2ecf20Sopenharmony_ci struct inode *inode, 5078c2ecf20Sopenharmony_ci dev_t dev, 5088c2ecf20Sopenharmony_ci struct buffer_head **new_fe_bh, 5098c2ecf20Sopenharmony_ci struct buffer_head *parent_fe_bh, 5108c2ecf20Sopenharmony_ci handle_t *handle, 5118c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *inode_ac, 5128c2ecf20Sopenharmony_ci u64 fe_blkno, u64 suballoc_loc, u16 suballoc_bit) 5138c2ecf20Sopenharmony_ci{ 5148c2ecf20Sopenharmony_ci int status = 0; 5158c2ecf20Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); 5168c2ecf20Sopenharmony_ci struct ocfs2_dinode *fe = NULL; 5178c2ecf20Sopenharmony_ci struct ocfs2_extent_list *fel; 5188c2ecf20Sopenharmony_ci u16 feat; 5198c2ecf20Sopenharmony_ci struct ocfs2_inode_info *oi = OCFS2_I(inode); 5208c2ecf20Sopenharmony_ci struct timespec64 ts; 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci *new_fe_bh = NULL; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci /* populate as many fields early on as possible - many of 5258c2ecf20Sopenharmony_ci * these are used by the support functions here and in 5268c2ecf20Sopenharmony_ci * callers. */ 5278c2ecf20Sopenharmony_ci inode->i_ino = ino_from_blkno(osb->sb, fe_blkno); 5288c2ecf20Sopenharmony_ci oi->ip_blkno = fe_blkno; 5298c2ecf20Sopenharmony_ci spin_lock(&osb->osb_lock); 5308c2ecf20Sopenharmony_ci inode->i_generation = osb->s_next_generation++; 5318c2ecf20Sopenharmony_ci spin_unlock(&osb->osb_lock); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci *new_fe_bh = sb_getblk(osb->sb, fe_blkno); 5348c2ecf20Sopenharmony_ci if (!*new_fe_bh) { 5358c2ecf20Sopenharmony_ci status = -ENOMEM; 5368c2ecf20Sopenharmony_ci mlog_errno(status); 5378c2ecf20Sopenharmony_ci goto leave; 5388c2ecf20Sopenharmony_ci } 5398c2ecf20Sopenharmony_ci ocfs2_set_new_buffer_uptodate(INODE_CACHE(inode), *new_fe_bh); 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), 5428c2ecf20Sopenharmony_ci *new_fe_bh, 5438c2ecf20Sopenharmony_ci OCFS2_JOURNAL_ACCESS_CREATE); 5448c2ecf20Sopenharmony_ci if (status < 0) { 5458c2ecf20Sopenharmony_ci mlog_errno(status); 5468c2ecf20Sopenharmony_ci goto leave; 5478c2ecf20Sopenharmony_ci } 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci fe = (struct ocfs2_dinode *) (*new_fe_bh)->b_data; 5508c2ecf20Sopenharmony_ci memset(fe, 0, osb->sb->s_blocksize); 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci fe->i_generation = cpu_to_le32(inode->i_generation); 5538c2ecf20Sopenharmony_ci fe->i_fs_generation = cpu_to_le32(osb->fs_generation); 5548c2ecf20Sopenharmony_ci fe->i_blkno = cpu_to_le64(fe_blkno); 5558c2ecf20Sopenharmony_ci fe->i_suballoc_loc = cpu_to_le64(suballoc_loc); 5568c2ecf20Sopenharmony_ci fe->i_suballoc_bit = cpu_to_le16(suballoc_bit); 5578c2ecf20Sopenharmony_ci fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot); 5588c2ecf20Sopenharmony_ci fe->i_uid = cpu_to_le32(i_uid_read(inode)); 5598c2ecf20Sopenharmony_ci fe->i_gid = cpu_to_le32(i_gid_read(inode)); 5608c2ecf20Sopenharmony_ci fe->i_mode = cpu_to_le16(inode->i_mode); 5618c2ecf20Sopenharmony_ci if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) 5628c2ecf20Sopenharmony_ci fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev)); 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci ocfs2_set_links_count(fe, inode->i_nlink); 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci fe->i_last_eb_blk = 0; 5678c2ecf20Sopenharmony_ci strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE); 5688c2ecf20Sopenharmony_ci fe->i_flags |= cpu_to_le32(OCFS2_VALID_FL); 5698c2ecf20Sopenharmony_ci ktime_get_real_ts64(&ts); 5708c2ecf20Sopenharmony_ci fe->i_atime = fe->i_ctime = fe->i_mtime = 5718c2ecf20Sopenharmony_ci cpu_to_le64(ts.tv_sec); 5728c2ecf20Sopenharmony_ci fe->i_mtime_nsec = fe->i_ctime_nsec = fe->i_atime_nsec = 5738c2ecf20Sopenharmony_ci cpu_to_le32(ts.tv_nsec); 5748c2ecf20Sopenharmony_ci fe->i_dtime = 0; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci /* 5778c2ecf20Sopenharmony_ci * If supported, directories start with inline data. If inline 5788c2ecf20Sopenharmony_ci * isn't supported, but indexing is, we start them as indexed. 5798c2ecf20Sopenharmony_ci */ 5808c2ecf20Sopenharmony_ci feat = le16_to_cpu(fe->i_dyn_features); 5818c2ecf20Sopenharmony_ci if (S_ISDIR(inode->i_mode) && ocfs2_supports_inline_data(osb)) { 5828c2ecf20Sopenharmony_ci fe->i_dyn_features = cpu_to_le16(feat | OCFS2_INLINE_DATA_FL); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci fe->id2.i_data.id_count = cpu_to_le16( 5858c2ecf20Sopenharmony_ci ocfs2_max_inline_data_with_xattr(osb->sb, fe)); 5868c2ecf20Sopenharmony_ci } else { 5878c2ecf20Sopenharmony_ci fel = &fe->id2.i_list; 5888c2ecf20Sopenharmony_ci fel->l_tree_depth = 0; 5898c2ecf20Sopenharmony_ci fel->l_next_free_rec = 0; 5908c2ecf20Sopenharmony_ci fel->l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(osb->sb)); 5918c2ecf20Sopenharmony_ci } 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci ocfs2_journal_dirty(handle, *new_fe_bh); 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci ocfs2_populate_inode(inode, fe, 1); 5968c2ecf20Sopenharmony_ci ocfs2_ci_set_new(osb, INODE_CACHE(inode)); 5978c2ecf20Sopenharmony_ci if (!ocfs2_mount_local(osb)) { 5988c2ecf20Sopenharmony_ci status = ocfs2_create_new_inode_locks(inode); 5998c2ecf20Sopenharmony_ci if (status < 0) 6008c2ecf20Sopenharmony_ci mlog_errno(status); 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci ocfs2_update_inode_fsync_trans(handle, inode, 1); 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_cileave: 6068c2ecf20Sopenharmony_ci if (status < 0) { 6078c2ecf20Sopenharmony_ci if (*new_fe_bh) { 6088c2ecf20Sopenharmony_ci brelse(*new_fe_bh); 6098c2ecf20Sopenharmony_ci *new_fe_bh = NULL; 6108c2ecf20Sopenharmony_ci } 6118c2ecf20Sopenharmony_ci } 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci if (status) 6148c2ecf20Sopenharmony_ci mlog_errno(status); 6158c2ecf20Sopenharmony_ci return status; 6168c2ecf20Sopenharmony_ci} 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_cistatic int ocfs2_mknod_locked(struct ocfs2_super *osb, 6198c2ecf20Sopenharmony_ci struct inode *dir, 6208c2ecf20Sopenharmony_ci struct inode *inode, 6218c2ecf20Sopenharmony_ci dev_t dev, 6228c2ecf20Sopenharmony_ci struct buffer_head **new_fe_bh, 6238c2ecf20Sopenharmony_ci struct buffer_head *parent_fe_bh, 6248c2ecf20Sopenharmony_ci handle_t *handle, 6258c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *inode_ac) 6268c2ecf20Sopenharmony_ci{ 6278c2ecf20Sopenharmony_ci int status = 0; 6288c2ecf20Sopenharmony_ci u64 suballoc_loc, fe_blkno = 0; 6298c2ecf20Sopenharmony_ci u16 suballoc_bit; 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci *new_fe_bh = NULL; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci status = ocfs2_claim_new_inode(handle, dir, parent_fe_bh, 6348c2ecf20Sopenharmony_ci inode_ac, &suballoc_loc, 6358c2ecf20Sopenharmony_ci &suballoc_bit, &fe_blkno); 6368c2ecf20Sopenharmony_ci if (status < 0) { 6378c2ecf20Sopenharmony_ci mlog_errno(status); 6388c2ecf20Sopenharmony_ci return status; 6398c2ecf20Sopenharmony_ci } 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci return __ocfs2_mknod_locked(dir, inode, dev, new_fe_bh, 6428c2ecf20Sopenharmony_ci parent_fe_bh, handle, inode_ac, 6438c2ecf20Sopenharmony_ci fe_blkno, suballoc_loc, suballoc_bit); 6448c2ecf20Sopenharmony_ci} 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_cistatic int ocfs2_mkdir(struct inode *dir, 6478c2ecf20Sopenharmony_ci struct dentry *dentry, 6488c2ecf20Sopenharmony_ci umode_t mode) 6498c2ecf20Sopenharmony_ci{ 6508c2ecf20Sopenharmony_ci int ret; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci trace_ocfs2_mkdir(dir, dentry, dentry->d_name.len, dentry->d_name.name, 6538c2ecf20Sopenharmony_ci OCFS2_I(dir)->ip_blkno, mode); 6548c2ecf20Sopenharmony_ci ret = ocfs2_mknod(dir, dentry, mode | S_IFDIR, 0); 6558c2ecf20Sopenharmony_ci if (ret) 6568c2ecf20Sopenharmony_ci mlog_errno(ret); 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci return ret; 6598c2ecf20Sopenharmony_ci} 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_cistatic int ocfs2_create(struct inode *dir, 6628c2ecf20Sopenharmony_ci struct dentry *dentry, 6638c2ecf20Sopenharmony_ci umode_t mode, 6648c2ecf20Sopenharmony_ci bool excl) 6658c2ecf20Sopenharmony_ci{ 6668c2ecf20Sopenharmony_ci int ret; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci trace_ocfs2_create(dir, dentry, dentry->d_name.len, dentry->d_name.name, 6698c2ecf20Sopenharmony_ci (unsigned long long)OCFS2_I(dir)->ip_blkno, mode); 6708c2ecf20Sopenharmony_ci ret = ocfs2_mknod(dir, dentry, mode | S_IFREG, 0); 6718c2ecf20Sopenharmony_ci if (ret) 6728c2ecf20Sopenharmony_ci mlog_errno(ret); 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci return ret; 6758c2ecf20Sopenharmony_ci} 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_cistatic int ocfs2_link(struct dentry *old_dentry, 6788c2ecf20Sopenharmony_ci struct inode *dir, 6798c2ecf20Sopenharmony_ci struct dentry *dentry) 6808c2ecf20Sopenharmony_ci{ 6818c2ecf20Sopenharmony_ci handle_t *handle; 6828c2ecf20Sopenharmony_ci struct inode *inode = d_inode(old_dentry); 6838c2ecf20Sopenharmony_ci struct inode *old_dir = d_inode(old_dentry->d_parent); 6848c2ecf20Sopenharmony_ci int err; 6858c2ecf20Sopenharmony_ci struct buffer_head *fe_bh = NULL; 6868c2ecf20Sopenharmony_ci struct buffer_head *old_dir_bh = NULL; 6878c2ecf20Sopenharmony_ci struct buffer_head *parent_fe_bh = NULL; 6888c2ecf20Sopenharmony_ci struct ocfs2_dinode *fe = NULL; 6898c2ecf20Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); 6908c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result lookup = { NULL, }; 6918c2ecf20Sopenharmony_ci sigset_t oldset; 6928c2ecf20Sopenharmony_ci u64 old_de_ino; 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci trace_ocfs2_link((unsigned long long)OCFS2_I(inode)->ip_blkno, 6958c2ecf20Sopenharmony_ci old_dentry->d_name.len, old_dentry->d_name.name, 6968c2ecf20Sopenharmony_ci dentry->d_name.len, dentry->d_name.name); 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 6998c2ecf20Sopenharmony_ci return -EPERM; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci err = dquot_initialize(dir); 7028c2ecf20Sopenharmony_ci if (err) { 7038c2ecf20Sopenharmony_ci mlog_errno(err); 7048c2ecf20Sopenharmony_ci return err; 7058c2ecf20Sopenharmony_ci } 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci err = ocfs2_double_lock(osb, &old_dir_bh, old_dir, 7088c2ecf20Sopenharmony_ci &parent_fe_bh, dir, 0); 7098c2ecf20Sopenharmony_ci if (err < 0) { 7108c2ecf20Sopenharmony_ci if (err != -ENOENT) 7118c2ecf20Sopenharmony_ci mlog_errno(err); 7128c2ecf20Sopenharmony_ci return err; 7138c2ecf20Sopenharmony_ci } 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci /* make sure both dirs have bhs 7168c2ecf20Sopenharmony_ci * get an extra ref on old_dir_bh if old==new */ 7178c2ecf20Sopenharmony_ci if (!parent_fe_bh) { 7188c2ecf20Sopenharmony_ci if (old_dir_bh) { 7198c2ecf20Sopenharmony_ci parent_fe_bh = old_dir_bh; 7208c2ecf20Sopenharmony_ci get_bh(parent_fe_bh); 7218c2ecf20Sopenharmony_ci } else { 7228c2ecf20Sopenharmony_ci mlog(ML_ERROR, "%s: no old_dir_bh!\n", osb->uuid_str); 7238c2ecf20Sopenharmony_ci err = -EIO; 7248c2ecf20Sopenharmony_ci goto out; 7258c2ecf20Sopenharmony_ci } 7268c2ecf20Sopenharmony_ci } 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci if (!dir->i_nlink) { 7298c2ecf20Sopenharmony_ci err = -ENOENT; 7308c2ecf20Sopenharmony_ci goto out; 7318c2ecf20Sopenharmony_ci } 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci err = ocfs2_lookup_ino_from_name(old_dir, old_dentry->d_name.name, 7348c2ecf20Sopenharmony_ci old_dentry->d_name.len, &old_de_ino); 7358c2ecf20Sopenharmony_ci if (err) { 7368c2ecf20Sopenharmony_ci err = -ENOENT; 7378c2ecf20Sopenharmony_ci goto out; 7388c2ecf20Sopenharmony_ci } 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci /* 7418c2ecf20Sopenharmony_ci * Check whether another node removed the source inode while we 7428c2ecf20Sopenharmony_ci * were in the vfs. 7438c2ecf20Sopenharmony_ci */ 7448c2ecf20Sopenharmony_ci if (old_de_ino != OCFS2_I(inode)->ip_blkno) { 7458c2ecf20Sopenharmony_ci err = -ENOENT; 7468c2ecf20Sopenharmony_ci goto out; 7478c2ecf20Sopenharmony_ci } 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, 7508c2ecf20Sopenharmony_ci dentry->d_name.len); 7518c2ecf20Sopenharmony_ci if (err) 7528c2ecf20Sopenharmony_ci goto out; 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci err = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh, 7558c2ecf20Sopenharmony_ci dentry->d_name.name, 7568c2ecf20Sopenharmony_ci dentry->d_name.len, &lookup); 7578c2ecf20Sopenharmony_ci if (err < 0) { 7588c2ecf20Sopenharmony_ci mlog_errno(err); 7598c2ecf20Sopenharmony_ci goto out; 7608c2ecf20Sopenharmony_ci } 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci err = ocfs2_inode_lock(inode, &fe_bh, 1); 7638c2ecf20Sopenharmony_ci if (err < 0) { 7648c2ecf20Sopenharmony_ci if (err != -ENOENT) 7658c2ecf20Sopenharmony_ci mlog_errno(err); 7668c2ecf20Sopenharmony_ci goto out; 7678c2ecf20Sopenharmony_ci } 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci fe = (struct ocfs2_dinode *) fe_bh->b_data; 7708c2ecf20Sopenharmony_ci if (ocfs2_read_links_count(fe) >= ocfs2_link_max(osb)) { 7718c2ecf20Sopenharmony_ci err = -EMLINK; 7728c2ecf20Sopenharmony_ci goto out_unlock_inode; 7738c2ecf20Sopenharmony_ci } 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci handle = ocfs2_start_trans(osb, ocfs2_link_credits(osb->sb)); 7768c2ecf20Sopenharmony_ci if (IS_ERR(handle)) { 7778c2ecf20Sopenharmony_ci err = PTR_ERR(handle); 7788c2ecf20Sopenharmony_ci handle = NULL; 7798c2ecf20Sopenharmony_ci mlog_errno(err); 7808c2ecf20Sopenharmony_ci goto out_unlock_inode; 7818c2ecf20Sopenharmony_ci } 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci /* Starting to change things, restart is no longer possible. */ 7848c2ecf20Sopenharmony_ci ocfs2_block_signals(&oldset); 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci err = ocfs2_journal_access_di(handle, INODE_CACHE(inode), fe_bh, 7878c2ecf20Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 7888c2ecf20Sopenharmony_ci if (err < 0) { 7898c2ecf20Sopenharmony_ci mlog_errno(err); 7908c2ecf20Sopenharmony_ci goto out_commit; 7918c2ecf20Sopenharmony_ci } 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci inc_nlink(inode); 7948c2ecf20Sopenharmony_ci inode->i_ctime = current_time(inode); 7958c2ecf20Sopenharmony_ci ocfs2_set_links_count(fe, inode->i_nlink); 7968c2ecf20Sopenharmony_ci fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); 7978c2ecf20Sopenharmony_ci fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); 7988c2ecf20Sopenharmony_ci ocfs2_journal_dirty(handle, fe_bh); 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci err = ocfs2_add_entry(handle, dentry, inode, 8018c2ecf20Sopenharmony_ci OCFS2_I(inode)->ip_blkno, 8028c2ecf20Sopenharmony_ci parent_fe_bh, &lookup); 8038c2ecf20Sopenharmony_ci if (err) { 8048c2ecf20Sopenharmony_ci ocfs2_add_links_count(fe, -1); 8058c2ecf20Sopenharmony_ci drop_nlink(inode); 8068c2ecf20Sopenharmony_ci mlog_errno(err); 8078c2ecf20Sopenharmony_ci goto out_commit; 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci err = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno); 8118c2ecf20Sopenharmony_ci if (err) { 8128c2ecf20Sopenharmony_ci mlog_errno(err); 8138c2ecf20Sopenharmony_ci goto out_commit; 8148c2ecf20Sopenharmony_ci } 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci ihold(inode); 8178c2ecf20Sopenharmony_ci d_instantiate(dentry, inode); 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ciout_commit: 8208c2ecf20Sopenharmony_ci ocfs2_commit_trans(osb, handle); 8218c2ecf20Sopenharmony_ci ocfs2_unblock_signals(&oldset); 8228c2ecf20Sopenharmony_ciout_unlock_inode: 8238c2ecf20Sopenharmony_ci ocfs2_inode_unlock(inode, 1); 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ciout: 8268c2ecf20Sopenharmony_ci ocfs2_double_unlock(old_dir, dir); 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci brelse(fe_bh); 8298c2ecf20Sopenharmony_ci brelse(parent_fe_bh); 8308c2ecf20Sopenharmony_ci brelse(old_dir_bh); 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci ocfs2_free_dir_lookup_result(&lookup); 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci if (err) 8358c2ecf20Sopenharmony_ci mlog_errno(err); 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci return err; 8388c2ecf20Sopenharmony_ci} 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci/* 8418c2ecf20Sopenharmony_ci * Takes and drops an exclusive lock on the given dentry. This will 8428c2ecf20Sopenharmony_ci * force other nodes to drop it. 8438c2ecf20Sopenharmony_ci */ 8448c2ecf20Sopenharmony_cistatic int ocfs2_remote_dentry_delete(struct dentry *dentry) 8458c2ecf20Sopenharmony_ci{ 8468c2ecf20Sopenharmony_ci int ret; 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci ret = ocfs2_dentry_lock(dentry, 1); 8498c2ecf20Sopenharmony_ci if (ret) 8508c2ecf20Sopenharmony_ci mlog_errno(ret); 8518c2ecf20Sopenharmony_ci else 8528c2ecf20Sopenharmony_ci ocfs2_dentry_unlock(dentry, 1); 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci return ret; 8558c2ecf20Sopenharmony_ci} 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_cistatic inline int ocfs2_inode_is_unlinkable(struct inode *inode) 8588c2ecf20Sopenharmony_ci{ 8598c2ecf20Sopenharmony_ci if (S_ISDIR(inode->i_mode)) { 8608c2ecf20Sopenharmony_ci if (inode->i_nlink == 2) 8618c2ecf20Sopenharmony_ci return 1; 8628c2ecf20Sopenharmony_ci return 0; 8638c2ecf20Sopenharmony_ci } 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci if (inode->i_nlink == 1) 8668c2ecf20Sopenharmony_ci return 1; 8678c2ecf20Sopenharmony_ci return 0; 8688c2ecf20Sopenharmony_ci} 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_cistatic int ocfs2_unlink(struct inode *dir, 8718c2ecf20Sopenharmony_ci struct dentry *dentry) 8728c2ecf20Sopenharmony_ci{ 8738c2ecf20Sopenharmony_ci int status; 8748c2ecf20Sopenharmony_ci int child_locked = 0; 8758c2ecf20Sopenharmony_ci bool is_unlinkable = false; 8768c2ecf20Sopenharmony_ci struct inode *inode = d_inode(dentry); 8778c2ecf20Sopenharmony_ci struct inode *orphan_dir = NULL; 8788c2ecf20Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); 8798c2ecf20Sopenharmony_ci u64 blkno; 8808c2ecf20Sopenharmony_ci struct ocfs2_dinode *fe = NULL; 8818c2ecf20Sopenharmony_ci struct buffer_head *fe_bh = NULL; 8828c2ecf20Sopenharmony_ci struct buffer_head *parent_node_bh = NULL; 8838c2ecf20Sopenharmony_ci handle_t *handle = NULL; 8848c2ecf20Sopenharmony_ci char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; 8858c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result lookup = { NULL, }; 8868c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci trace_ocfs2_unlink(dir, dentry, dentry->d_name.len, 8898c2ecf20Sopenharmony_ci dentry->d_name.name, 8908c2ecf20Sopenharmony_ci (unsigned long long)OCFS2_I(dir)->ip_blkno, 8918c2ecf20Sopenharmony_ci (unsigned long long)OCFS2_I(inode)->ip_blkno); 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci status = dquot_initialize(dir); 8948c2ecf20Sopenharmony_ci if (status) { 8958c2ecf20Sopenharmony_ci mlog_errno(status); 8968c2ecf20Sopenharmony_ci return status; 8978c2ecf20Sopenharmony_ci } 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci BUG_ON(d_inode(dentry->d_parent) != dir); 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci if (inode == osb->root_inode) 9028c2ecf20Sopenharmony_ci return -EPERM; 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci status = ocfs2_inode_lock_nested(dir, &parent_node_bh, 1, 9058c2ecf20Sopenharmony_ci OI_LS_PARENT); 9068c2ecf20Sopenharmony_ci if (status < 0) { 9078c2ecf20Sopenharmony_ci if (status != -ENOENT) 9088c2ecf20Sopenharmony_ci mlog_errno(status); 9098c2ecf20Sopenharmony_ci return status; 9108c2ecf20Sopenharmony_ci } 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci status = ocfs2_find_files_on_disk(dentry->d_name.name, 9138c2ecf20Sopenharmony_ci dentry->d_name.len, &blkno, dir, 9148c2ecf20Sopenharmony_ci &lookup); 9158c2ecf20Sopenharmony_ci if (status < 0) { 9168c2ecf20Sopenharmony_ci if (status != -ENOENT) 9178c2ecf20Sopenharmony_ci mlog_errno(status); 9188c2ecf20Sopenharmony_ci goto leave; 9198c2ecf20Sopenharmony_ci } 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci if (OCFS2_I(inode)->ip_blkno != blkno) { 9228c2ecf20Sopenharmony_ci status = -ENOENT; 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci trace_ocfs2_unlink_noent( 9258c2ecf20Sopenharmony_ci (unsigned long long)OCFS2_I(inode)->ip_blkno, 9268c2ecf20Sopenharmony_ci (unsigned long long)blkno, 9278c2ecf20Sopenharmony_ci OCFS2_I(inode)->ip_flags); 9288c2ecf20Sopenharmony_ci goto leave; 9298c2ecf20Sopenharmony_ci } 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci status = ocfs2_inode_lock(inode, &fe_bh, 1); 9328c2ecf20Sopenharmony_ci if (status < 0) { 9338c2ecf20Sopenharmony_ci if (status != -ENOENT) 9348c2ecf20Sopenharmony_ci mlog_errno(status); 9358c2ecf20Sopenharmony_ci goto leave; 9368c2ecf20Sopenharmony_ci } 9378c2ecf20Sopenharmony_ci child_locked = 1; 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci if (S_ISDIR(inode->i_mode)) { 9408c2ecf20Sopenharmony_ci if (inode->i_nlink != 2 || !ocfs2_empty_dir(inode)) { 9418c2ecf20Sopenharmony_ci status = -ENOTEMPTY; 9428c2ecf20Sopenharmony_ci goto leave; 9438c2ecf20Sopenharmony_ci } 9448c2ecf20Sopenharmony_ci } 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci status = ocfs2_remote_dentry_delete(dentry); 9478c2ecf20Sopenharmony_ci if (status < 0) { 9488c2ecf20Sopenharmony_ci /* This remote delete should succeed under all normal 9498c2ecf20Sopenharmony_ci * circumstances. */ 9508c2ecf20Sopenharmony_ci mlog_errno(status); 9518c2ecf20Sopenharmony_ci goto leave; 9528c2ecf20Sopenharmony_ci } 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci if (ocfs2_inode_is_unlinkable(inode)) { 9558c2ecf20Sopenharmony_ci status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, 9568c2ecf20Sopenharmony_ci OCFS2_I(inode)->ip_blkno, 9578c2ecf20Sopenharmony_ci orphan_name, &orphan_insert, 9588c2ecf20Sopenharmony_ci false); 9598c2ecf20Sopenharmony_ci if (status < 0) { 9608c2ecf20Sopenharmony_ci mlog_errno(status); 9618c2ecf20Sopenharmony_ci goto leave; 9628c2ecf20Sopenharmony_ci } 9638c2ecf20Sopenharmony_ci is_unlinkable = true; 9648c2ecf20Sopenharmony_ci } 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci handle = ocfs2_start_trans(osb, ocfs2_unlink_credits(osb->sb)); 9678c2ecf20Sopenharmony_ci if (IS_ERR(handle)) { 9688c2ecf20Sopenharmony_ci status = PTR_ERR(handle); 9698c2ecf20Sopenharmony_ci handle = NULL; 9708c2ecf20Sopenharmony_ci mlog_errno(status); 9718c2ecf20Sopenharmony_ci goto leave; 9728c2ecf20Sopenharmony_ci } 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), fe_bh, 9758c2ecf20Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 9768c2ecf20Sopenharmony_ci if (status < 0) { 9778c2ecf20Sopenharmony_ci mlog_errno(status); 9788c2ecf20Sopenharmony_ci goto leave; 9798c2ecf20Sopenharmony_ci } 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci fe = (struct ocfs2_dinode *) fe_bh->b_data; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci /* delete the name from the parent dir */ 9848c2ecf20Sopenharmony_ci status = ocfs2_delete_entry(handle, dir, &lookup); 9858c2ecf20Sopenharmony_ci if (status < 0) { 9868c2ecf20Sopenharmony_ci mlog_errno(status); 9878c2ecf20Sopenharmony_ci goto leave; 9888c2ecf20Sopenharmony_ci } 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 9918c2ecf20Sopenharmony_ci drop_nlink(inode); 9928c2ecf20Sopenharmony_ci drop_nlink(inode); 9938c2ecf20Sopenharmony_ci ocfs2_set_links_count(fe, inode->i_nlink); 9948c2ecf20Sopenharmony_ci ocfs2_journal_dirty(handle, fe_bh); 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci dir->i_ctime = dir->i_mtime = current_time(dir); 9978c2ecf20Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 9988c2ecf20Sopenharmony_ci drop_nlink(dir); 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci status = ocfs2_mark_inode_dirty(handle, dir, parent_node_bh); 10018c2ecf20Sopenharmony_ci if (status < 0) { 10028c2ecf20Sopenharmony_ci mlog_errno(status); 10038c2ecf20Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 10048c2ecf20Sopenharmony_ci inc_nlink(dir); 10058c2ecf20Sopenharmony_ci goto leave; 10068c2ecf20Sopenharmony_ci } 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ci if (is_unlinkable) { 10098c2ecf20Sopenharmony_ci status = ocfs2_orphan_add(osb, handle, inode, fe_bh, 10108c2ecf20Sopenharmony_ci orphan_name, &orphan_insert, orphan_dir, false); 10118c2ecf20Sopenharmony_ci if (status < 0) 10128c2ecf20Sopenharmony_ci mlog_errno(status); 10138c2ecf20Sopenharmony_ci } 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_cileave: 10168c2ecf20Sopenharmony_ci if (handle) 10178c2ecf20Sopenharmony_ci ocfs2_commit_trans(osb, handle); 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci if (orphan_dir) { 10208c2ecf20Sopenharmony_ci /* This was locked for us in ocfs2_prepare_orphan_dir() */ 10218c2ecf20Sopenharmony_ci ocfs2_inode_unlock(orphan_dir, 1); 10228c2ecf20Sopenharmony_ci inode_unlock(orphan_dir); 10238c2ecf20Sopenharmony_ci iput(orphan_dir); 10248c2ecf20Sopenharmony_ci } 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci if (child_locked) 10278c2ecf20Sopenharmony_ci ocfs2_inode_unlock(inode, 1); 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci ocfs2_inode_unlock(dir, 1); 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci brelse(fe_bh); 10328c2ecf20Sopenharmony_ci brelse(parent_node_bh); 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci ocfs2_free_dir_lookup_result(&orphan_insert); 10358c2ecf20Sopenharmony_ci ocfs2_free_dir_lookup_result(&lookup); 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci if (status && (status != -ENOTEMPTY) && (status != -ENOENT)) 10388c2ecf20Sopenharmony_ci mlog_errno(status); 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_ci return status; 10418c2ecf20Sopenharmony_ci} 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_cistatic int ocfs2_check_if_ancestor(struct ocfs2_super *osb, 10448c2ecf20Sopenharmony_ci u64 src_inode_no, u64 dest_inode_no) 10458c2ecf20Sopenharmony_ci{ 10468c2ecf20Sopenharmony_ci int ret = 0, i = 0; 10478c2ecf20Sopenharmony_ci u64 parent_inode_no = 0; 10488c2ecf20Sopenharmony_ci u64 child_inode_no = src_inode_no; 10498c2ecf20Sopenharmony_ci struct inode *child_inode; 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci#define MAX_LOOKUP_TIMES 32 10528c2ecf20Sopenharmony_ci while (1) { 10538c2ecf20Sopenharmony_ci child_inode = ocfs2_iget(osb, child_inode_no, 0, 0); 10548c2ecf20Sopenharmony_ci if (IS_ERR(child_inode)) { 10558c2ecf20Sopenharmony_ci ret = PTR_ERR(child_inode); 10568c2ecf20Sopenharmony_ci break; 10578c2ecf20Sopenharmony_ci } 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci ret = ocfs2_inode_lock(child_inode, NULL, 0); 10608c2ecf20Sopenharmony_ci if (ret < 0) { 10618c2ecf20Sopenharmony_ci iput(child_inode); 10628c2ecf20Sopenharmony_ci if (ret != -ENOENT) 10638c2ecf20Sopenharmony_ci mlog_errno(ret); 10648c2ecf20Sopenharmony_ci break; 10658c2ecf20Sopenharmony_ci } 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci ret = ocfs2_lookup_ino_from_name(child_inode, "..", 2, 10688c2ecf20Sopenharmony_ci &parent_inode_no); 10698c2ecf20Sopenharmony_ci ocfs2_inode_unlock(child_inode, 0); 10708c2ecf20Sopenharmony_ci iput(child_inode); 10718c2ecf20Sopenharmony_ci if (ret < 0) { 10728c2ecf20Sopenharmony_ci ret = -ENOENT; 10738c2ecf20Sopenharmony_ci break; 10748c2ecf20Sopenharmony_ci } 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci if (parent_inode_no == dest_inode_no) { 10778c2ecf20Sopenharmony_ci ret = 1; 10788c2ecf20Sopenharmony_ci break; 10798c2ecf20Sopenharmony_ci } 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci if (parent_inode_no == osb->root_inode->i_ino) { 10828c2ecf20Sopenharmony_ci ret = 0; 10838c2ecf20Sopenharmony_ci break; 10848c2ecf20Sopenharmony_ci } 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci child_inode_no = parent_inode_no; 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci if (++i >= MAX_LOOKUP_TIMES) { 10898c2ecf20Sopenharmony_ci mlog(ML_NOTICE, "max lookup times reached, filesystem " 10908c2ecf20Sopenharmony_ci "may have nested directories, " 10918c2ecf20Sopenharmony_ci "src inode: %llu, dest inode: %llu.\n", 10928c2ecf20Sopenharmony_ci (unsigned long long)src_inode_no, 10938c2ecf20Sopenharmony_ci (unsigned long long)dest_inode_no); 10948c2ecf20Sopenharmony_ci ret = 0; 10958c2ecf20Sopenharmony_ci break; 10968c2ecf20Sopenharmony_ci } 10978c2ecf20Sopenharmony_ci } 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci return ret; 11008c2ecf20Sopenharmony_ci} 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci/* 11038c2ecf20Sopenharmony_ci * The only place this should be used is rename and link! 11048c2ecf20Sopenharmony_ci * if they have the same id, then the 1st one is the only one locked. 11058c2ecf20Sopenharmony_ci */ 11068c2ecf20Sopenharmony_cistatic int ocfs2_double_lock(struct ocfs2_super *osb, 11078c2ecf20Sopenharmony_ci struct buffer_head **bh1, 11088c2ecf20Sopenharmony_ci struct inode *inode1, 11098c2ecf20Sopenharmony_ci struct buffer_head **bh2, 11108c2ecf20Sopenharmony_ci struct inode *inode2, 11118c2ecf20Sopenharmony_ci int rename) 11128c2ecf20Sopenharmony_ci{ 11138c2ecf20Sopenharmony_ci int status; 11148c2ecf20Sopenharmony_ci int inode1_is_ancestor, inode2_is_ancestor; 11158c2ecf20Sopenharmony_ci struct ocfs2_inode_info *oi1 = OCFS2_I(inode1); 11168c2ecf20Sopenharmony_ci struct ocfs2_inode_info *oi2 = OCFS2_I(inode2); 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci trace_ocfs2_double_lock((unsigned long long)oi1->ip_blkno, 11198c2ecf20Sopenharmony_ci (unsigned long long)oi2->ip_blkno); 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci if (*bh1) 11228c2ecf20Sopenharmony_ci *bh1 = NULL; 11238c2ecf20Sopenharmony_ci if (*bh2) 11248c2ecf20Sopenharmony_ci *bh2 = NULL; 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci /* we always want to lock the one with the lower lockid first. 11278c2ecf20Sopenharmony_ci * and if they are nested, we lock ancestor first */ 11288c2ecf20Sopenharmony_ci if (oi1->ip_blkno != oi2->ip_blkno) { 11298c2ecf20Sopenharmony_ci inode1_is_ancestor = ocfs2_check_if_ancestor(osb, oi2->ip_blkno, 11308c2ecf20Sopenharmony_ci oi1->ip_blkno); 11318c2ecf20Sopenharmony_ci if (inode1_is_ancestor < 0) { 11328c2ecf20Sopenharmony_ci status = inode1_is_ancestor; 11338c2ecf20Sopenharmony_ci goto bail; 11348c2ecf20Sopenharmony_ci } 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci inode2_is_ancestor = ocfs2_check_if_ancestor(osb, oi1->ip_blkno, 11378c2ecf20Sopenharmony_ci oi2->ip_blkno); 11388c2ecf20Sopenharmony_ci if (inode2_is_ancestor < 0) { 11398c2ecf20Sopenharmony_ci status = inode2_is_ancestor; 11408c2ecf20Sopenharmony_ci goto bail; 11418c2ecf20Sopenharmony_ci } 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci if ((inode1_is_ancestor == 1) || 11448c2ecf20Sopenharmony_ci (oi1->ip_blkno < oi2->ip_blkno && 11458c2ecf20Sopenharmony_ci inode2_is_ancestor == 0)) { 11468c2ecf20Sopenharmony_ci /* switch id1 and id2 around */ 11478c2ecf20Sopenharmony_ci swap(bh2, bh1); 11488c2ecf20Sopenharmony_ci swap(inode2, inode1); 11498c2ecf20Sopenharmony_ci } 11508c2ecf20Sopenharmony_ci /* lock id2 */ 11518c2ecf20Sopenharmony_ci status = ocfs2_inode_lock_nested(inode2, bh2, 1, 11528c2ecf20Sopenharmony_ci rename == 1 ? OI_LS_RENAME1 : OI_LS_PARENT); 11538c2ecf20Sopenharmony_ci if (status < 0) { 11548c2ecf20Sopenharmony_ci if (status != -ENOENT) 11558c2ecf20Sopenharmony_ci mlog_errno(status); 11568c2ecf20Sopenharmony_ci goto bail; 11578c2ecf20Sopenharmony_ci } 11588c2ecf20Sopenharmony_ci } 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci /* lock id1 */ 11618c2ecf20Sopenharmony_ci status = ocfs2_inode_lock_nested(inode1, bh1, 1, 11628c2ecf20Sopenharmony_ci rename == 1 ? OI_LS_RENAME2 : OI_LS_PARENT); 11638c2ecf20Sopenharmony_ci if (status < 0) { 11648c2ecf20Sopenharmony_ci /* 11658c2ecf20Sopenharmony_ci * An error return must mean that no cluster locks 11668c2ecf20Sopenharmony_ci * were held on function exit. 11678c2ecf20Sopenharmony_ci */ 11688c2ecf20Sopenharmony_ci if (oi1->ip_blkno != oi2->ip_blkno) { 11698c2ecf20Sopenharmony_ci ocfs2_inode_unlock(inode2, 1); 11708c2ecf20Sopenharmony_ci brelse(*bh2); 11718c2ecf20Sopenharmony_ci *bh2 = NULL; 11728c2ecf20Sopenharmony_ci } 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci if (status != -ENOENT) 11758c2ecf20Sopenharmony_ci mlog_errno(status); 11768c2ecf20Sopenharmony_ci } 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci trace_ocfs2_double_lock_end( 11798c2ecf20Sopenharmony_ci (unsigned long long)oi1->ip_blkno, 11808c2ecf20Sopenharmony_ci (unsigned long long)oi2->ip_blkno); 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_cibail: 11838c2ecf20Sopenharmony_ci if (status) 11848c2ecf20Sopenharmony_ci mlog_errno(status); 11858c2ecf20Sopenharmony_ci return status; 11868c2ecf20Sopenharmony_ci} 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_cistatic void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2) 11898c2ecf20Sopenharmony_ci{ 11908c2ecf20Sopenharmony_ci ocfs2_inode_unlock(inode1, 1); 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci if (inode1 != inode2) 11938c2ecf20Sopenharmony_ci ocfs2_inode_unlock(inode2, 1); 11948c2ecf20Sopenharmony_ci} 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_cistatic int ocfs2_rename(struct inode *old_dir, 11978c2ecf20Sopenharmony_ci struct dentry *old_dentry, 11988c2ecf20Sopenharmony_ci struct inode *new_dir, 11998c2ecf20Sopenharmony_ci struct dentry *new_dentry, 12008c2ecf20Sopenharmony_ci unsigned int flags) 12018c2ecf20Sopenharmony_ci{ 12028c2ecf20Sopenharmony_ci int status = 0, rename_lock = 0, parents_locked = 0, target_exists = 0; 12038c2ecf20Sopenharmony_ci int old_child_locked = 0, new_child_locked = 0, update_dot_dot = 0; 12048c2ecf20Sopenharmony_ci struct inode *old_inode = d_inode(old_dentry); 12058c2ecf20Sopenharmony_ci struct inode *new_inode = d_inode(new_dentry); 12068c2ecf20Sopenharmony_ci struct inode *orphan_dir = NULL; 12078c2ecf20Sopenharmony_ci struct ocfs2_dinode *newfe = NULL; 12088c2ecf20Sopenharmony_ci char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; 12098c2ecf20Sopenharmony_ci struct buffer_head *newfe_bh = NULL; 12108c2ecf20Sopenharmony_ci struct buffer_head *old_inode_bh = NULL; 12118c2ecf20Sopenharmony_ci struct ocfs2_super *osb = NULL; 12128c2ecf20Sopenharmony_ci u64 newfe_blkno, old_de_ino; 12138c2ecf20Sopenharmony_ci handle_t *handle = NULL; 12148c2ecf20Sopenharmony_ci struct buffer_head *old_dir_bh = NULL; 12158c2ecf20Sopenharmony_ci struct buffer_head *new_dir_bh = NULL; 12168c2ecf20Sopenharmony_ci u32 old_dir_nlink = old_dir->i_nlink; 12178c2ecf20Sopenharmony_ci struct ocfs2_dinode *old_di; 12188c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result old_inode_dot_dot_res = { NULL, }; 12198c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result target_lookup_res = { NULL, }; 12208c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result old_entry_lookup = { NULL, }; 12218c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; 12228c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result target_insert = { NULL, }; 12238c2ecf20Sopenharmony_ci bool should_add_orphan = false; 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci if (flags) 12268c2ecf20Sopenharmony_ci return -EINVAL; 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci /* At some point it might be nice to break this function up a 12298c2ecf20Sopenharmony_ci * bit. */ 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci trace_ocfs2_rename(old_dir, old_dentry, new_dir, new_dentry, 12328c2ecf20Sopenharmony_ci old_dentry->d_name.len, old_dentry->d_name.name, 12338c2ecf20Sopenharmony_ci new_dentry->d_name.len, new_dentry->d_name.name); 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci status = dquot_initialize(old_dir); 12368c2ecf20Sopenharmony_ci if (status) { 12378c2ecf20Sopenharmony_ci mlog_errno(status); 12388c2ecf20Sopenharmony_ci goto bail; 12398c2ecf20Sopenharmony_ci } 12408c2ecf20Sopenharmony_ci status = dquot_initialize(new_dir); 12418c2ecf20Sopenharmony_ci if (status) { 12428c2ecf20Sopenharmony_ci mlog_errno(status); 12438c2ecf20Sopenharmony_ci goto bail; 12448c2ecf20Sopenharmony_ci } 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci osb = OCFS2_SB(old_dir->i_sb); 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci if (new_inode) { 12498c2ecf20Sopenharmony_ci if (!igrab(new_inode)) 12508c2ecf20Sopenharmony_ci BUG(); 12518c2ecf20Sopenharmony_ci } 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci /* Assume a directory hierarchy thusly: 12548c2ecf20Sopenharmony_ci * a/b/c 12558c2ecf20Sopenharmony_ci * a/d 12568c2ecf20Sopenharmony_ci * a,b,c, and d are all directories. 12578c2ecf20Sopenharmony_ci * 12588c2ecf20Sopenharmony_ci * from cwd of 'a' on both nodes: 12598c2ecf20Sopenharmony_ci * node1: mv b/c d 12608c2ecf20Sopenharmony_ci * node2: mv d b/c 12618c2ecf20Sopenharmony_ci * 12628c2ecf20Sopenharmony_ci * And that's why, just like the VFS, we need a file system 12638c2ecf20Sopenharmony_ci * rename lock. */ 12648c2ecf20Sopenharmony_ci if (old_dir != new_dir && S_ISDIR(old_inode->i_mode)) { 12658c2ecf20Sopenharmony_ci status = ocfs2_rename_lock(osb); 12668c2ecf20Sopenharmony_ci if (status < 0) { 12678c2ecf20Sopenharmony_ci mlog_errno(status); 12688c2ecf20Sopenharmony_ci goto bail; 12698c2ecf20Sopenharmony_ci } 12708c2ecf20Sopenharmony_ci rename_lock = 1; 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci /* here we cannot guarantee the inodes haven't just been 12738c2ecf20Sopenharmony_ci * changed, so check if they are nested again */ 12748c2ecf20Sopenharmony_ci status = ocfs2_check_if_ancestor(osb, new_dir->i_ino, 12758c2ecf20Sopenharmony_ci old_inode->i_ino); 12768c2ecf20Sopenharmony_ci if (status < 0) { 12778c2ecf20Sopenharmony_ci mlog_errno(status); 12788c2ecf20Sopenharmony_ci goto bail; 12798c2ecf20Sopenharmony_ci } else if (status == 1) { 12808c2ecf20Sopenharmony_ci status = -EPERM; 12818c2ecf20Sopenharmony_ci trace_ocfs2_rename_not_permitted( 12828c2ecf20Sopenharmony_ci (unsigned long long)old_inode->i_ino, 12838c2ecf20Sopenharmony_ci (unsigned long long)new_dir->i_ino); 12848c2ecf20Sopenharmony_ci goto bail; 12858c2ecf20Sopenharmony_ci } 12868c2ecf20Sopenharmony_ci } 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci /* if old and new are the same, this'll just do one lock. */ 12898c2ecf20Sopenharmony_ci status = ocfs2_double_lock(osb, &old_dir_bh, old_dir, 12908c2ecf20Sopenharmony_ci &new_dir_bh, new_dir, 1); 12918c2ecf20Sopenharmony_ci if (status < 0) { 12928c2ecf20Sopenharmony_ci mlog_errno(status); 12938c2ecf20Sopenharmony_ci goto bail; 12948c2ecf20Sopenharmony_ci } 12958c2ecf20Sopenharmony_ci parents_locked = 1; 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci if (!new_dir->i_nlink) { 12988c2ecf20Sopenharmony_ci status = -EACCES; 12998c2ecf20Sopenharmony_ci goto bail; 13008c2ecf20Sopenharmony_ci } 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci /* make sure both dirs have bhs 13038c2ecf20Sopenharmony_ci * get an extra ref on old_dir_bh if old==new */ 13048c2ecf20Sopenharmony_ci if (!new_dir_bh) { 13058c2ecf20Sopenharmony_ci if (old_dir_bh) { 13068c2ecf20Sopenharmony_ci new_dir_bh = old_dir_bh; 13078c2ecf20Sopenharmony_ci get_bh(new_dir_bh); 13088c2ecf20Sopenharmony_ci } else { 13098c2ecf20Sopenharmony_ci mlog(ML_ERROR, "no old_dir_bh!\n"); 13108c2ecf20Sopenharmony_ci status = -EIO; 13118c2ecf20Sopenharmony_ci goto bail; 13128c2ecf20Sopenharmony_ci } 13138c2ecf20Sopenharmony_ci } 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci /* 13168c2ecf20Sopenharmony_ci * Aside from allowing a meta data update, the locking here 13178c2ecf20Sopenharmony_ci * also ensures that the downconvert thread on other nodes 13188c2ecf20Sopenharmony_ci * won't have to concurrently downconvert the inode and the 13198c2ecf20Sopenharmony_ci * dentry locks. 13208c2ecf20Sopenharmony_ci */ 13218c2ecf20Sopenharmony_ci status = ocfs2_inode_lock_nested(old_inode, &old_inode_bh, 1, 13228c2ecf20Sopenharmony_ci OI_LS_PARENT); 13238c2ecf20Sopenharmony_ci if (status < 0) { 13248c2ecf20Sopenharmony_ci if (status != -ENOENT) 13258c2ecf20Sopenharmony_ci mlog_errno(status); 13268c2ecf20Sopenharmony_ci goto bail; 13278c2ecf20Sopenharmony_ci } 13288c2ecf20Sopenharmony_ci old_child_locked = 1; 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci status = ocfs2_remote_dentry_delete(old_dentry); 13318c2ecf20Sopenharmony_ci if (status < 0) { 13328c2ecf20Sopenharmony_ci mlog_errno(status); 13338c2ecf20Sopenharmony_ci goto bail; 13348c2ecf20Sopenharmony_ci } 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci if (S_ISDIR(old_inode->i_mode)) { 13378c2ecf20Sopenharmony_ci u64 old_inode_parent; 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci update_dot_dot = 1; 13408c2ecf20Sopenharmony_ci status = ocfs2_find_files_on_disk("..", 2, &old_inode_parent, 13418c2ecf20Sopenharmony_ci old_inode, 13428c2ecf20Sopenharmony_ci &old_inode_dot_dot_res); 13438c2ecf20Sopenharmony_ci if (status) { 13448c2ecf20Sopenharmony_ci status = -EIO; 13458c2ecf20Sopenharmony_ci goto bail; 13468c2ecf20Sopenharmony_ci } 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci if (old_inode_parent != OCFS2_I(old_dir)->ip_blkno) { 13498c2ecf20Sopenharmony_ci status = -EIO; 13508c2ecf20Sopenharmony_ci goto bail; 13518c2ecf20Sopenharmony_ci } 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci if (!new_inode && new_dir != old_dir && 13548c2ecf20Sopenharmony_ci new_dir->i_nlink >= ocfs2_link_max(osb)) { 13558c2ecf20Sopenharmony_ci status = -EMLINK; 13568c2ecf20Sopenharmony_ci goto bail; 13578c2ecf20Sopenharmony_ci } 13588c2ecf20Sopenharmony_ci } 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci status = ocfs2_lookup_ino_from_name(old_dir, old_dentry->d_name.name, 13618c2ecf20Sopenharmony_ci old_dentry->d_name.len, 13628c2ecf20Sopenharmony_ci &old_de_ino); 13638c2ecf20Sopenharmony_ci if (status) { 13648c2ecf20Sopenharmony_ci status = -ENOENT; 13658c2ecf20Sopenharmony_ci goto bail; 13668c2ecf20Sopenharmony_ci } 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci /* 13698c2ecf20Sopenharmony_ci * Check for inode number is _not_ due to possible IO errors. 13708c2ecf20Sopenharmony_ci * We might rmdir the source, keep it as pwd of some process 13718c2ecf20Sopenharmony_ci * and merrily kill the link to whatever was created under the 13728c2ecf20Sopenharmony_ci * same name. Goodbye sticky bit ;-< 13738c2ecf20Sopenharmony_ci */ 13748c2ecf20Sopenharmony_ci if (old_de_ino != OCFS2_I(old_inode)->ip_blkno) { 13758c2ecf20Sopenharmony_ci status = -ENOENT; 13768c2ecf20Sopenharmony_ci goto bail; 13778c2ecf20Sopenharmony_ci } 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci /* check if the target already exists (in which case we need 13808c2ecf20Sopenharmony_ci * to delete it */ 13818c2ecf20Sopenharmony_ci status = ocfs2_find_files_on_disk(new_dentry->d_name.name, 13828c2ecf20Sopenharmony_ci new_dentry->d_name.len, 13838c2ecf20Sopenharmony_ci &newfe_blkno, new_dir, 13848c2ecf20Sopenharmony_ci &target_lookup_res); 13858c2ecf20Sopenharmony_ci /* The only error we allow here is -ENOENT because the new 13868c2ecf20Sopenharmony_ci * file not existing is perfectly valid. */ 13878c2ecf20Sopenharmony_ci if ((status < 0) && (status != -ENOENT)) { 13888c2ecf20Sopenharmony_ci /* If we cannot find the file specified we should just */ 13898c2ecf20Sopenharmony_ci /* return the error... */ 13908c2ecf20Sopenharmony_ci mlog_errno(status); 13918c2ecf20Sopenharmony_ci goto bail; 13928c2ecf20Sopenharmony_ci } 13938c2ecf20Sopenharmony_ci if (status == 0) 13948c2ecf20Sopenharmony_ci target_exists = 1; 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci if (!target_exists && new_inode) { 13978c2ecf20Sopenharmony_ci /* 13988c2ecf20Sopenharmony_ci * Target was unlinked by another node while we were 13998c2ecf20Sopenharmony_ci * waiting to get to ocfs2_rename(). There isn't 14008c2ecf20Sopenharmony_ci * anything we can do here to help the situation, so 14018c2ecf20Sopenharmony_ci * bubble up the appropriate error. 14028c2ecf20Sopenharmony_ci */ 14038c2ecf20Sopenharmony_ci status = -ENOENT; 14048c2ecf20Sopenharmony_ci goto bail; 14058c2ecf20Sopenharmony_ci } 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci /* In case we need to overwrite an existing file, we blow it 14088c2ecf20Sopenharmony_ci * away first */ 14098c2ecf20Sopenharmony_ci if (target_exists) { 14108c2ecf20Sopenharmony_ci /* VFS didn't think there existed an inode here, but 14118c2ecf20Sopenharmony_ci * someone else in the cluster must have raced our 14128c2ecf20Sopenharmony_ci * rename to create one. Today we error cleanly, in 14138c2ecf20Sopenharmony_ci * the future we should consider calling iget to build 14148c2ecf20Sopenharmony_ci * a new struct inode for this entry. */ 14158c2ecf20Sopenharmony_ci if (!new_inode) { 14168c2ecf20Sopenharmony_ci status = -EACCES; 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ci trace_ocfs2_rename_target_exists(new_dentry->d_name.len, 14198c2ecf20Sopenharmony_ci new_dentry->d_name.name); 14208c2ecf20Sopenharmony_ci goto bail; 14218c2ecf20Sopenharmony_ci } 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci if (OCFS2_I(new_inode)->ip_blkno != newfe_blkno) { 14248c2ecf20Sopenharmony_ci status = -EACCES; 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci trace_ocfs2_rename_disagree( 14278c2ecf20Sopenharmony_ci (unsigned long long)OCFS2_I(new_inode)->ip_blkno, 14288c2ecf20Sopenharmony_ci (unsigned long long)newfe_blkno, 14298c2ecf20Sopenharmony_ci OCFS2_I(new_inode)->ip_flags); 14308c2ecf20Sopenharmony_ci goto bail; 14318c2ecf20Sopenharmony_ci } 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_ci status = ocfs2_inode_lock(new_inode, &newfe_bh, 1); 14348c2ecf20Sopenharmony_ci if (status < 0) { 14358c2ecf20Sopenharmony_ci if (status != -ENOENT) 14368c2ecf20Sopenharmony_ci mlog_errno(status); 14378c2ecf20Sopenharmony_ci goto bail; 14388c2ecf20Sopenharmony_ci } 14398c2ecf20Sopenharmony_ci new_child_locked = 1; 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci status = ocfs2_remote_dentry_delete(new_dentry); 14428c2ecf20Sopenharmony_ci if (status < 0) { 14438c2ecf20Sopenharmony_ci mlog_errno(status); 14448c2ecf20Sopenharmony_ci goto bail; 14458c2ecf20Sopenharmony_ci } 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci newfe = (struct ocfs2_dinode *) newfe_bh->b_data; 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci trace_ocfs2_rename_over_existing( 14508c2ecf20Sopenharmony_ci (unsigned long long)newfe_blkno, newfe_bh, newfe_bh ? 14518c2ecf20Sopenharmony_ci (unsigned long long)newfe_bh->b_blocknr : 0ULL); 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) { 14548c2ecf20Sopenharmony_ci status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, 14558c2ecf20Sopenharmony_ci OCFS2_I(new_inode)->ip_blkno, 14568c2ecf20Sopenharmony_ci orphan_name, &orphan_insert, 14578c2ecf20Sopenharmony_ci false); 14588c2ecf20Sopenharmony_ci if (status < 0) { 14598c2ecf20Sopenharmony_ci mlog_errno(status); 14608c2ecf20Sopenharmony_ci goto bail; 14618c2ecf20Sopenharmony_ci } 14628c2ecf20Sopenharmony_ci should_add_orphan = true; 14638c2ecf20Sopenharmony_ci } 14648c2ecf20Sopenharmony_ci } else { 14658c2ecf20Sopenharmony_ci BUG_ON(d_inode(new_dentry->d_parent) != new_dir); 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci status = ocfs2_check_dir_for_entry(new_dir, 14688c2ecf20Sopenharmony_ci new_dentry->d_name.name, 14698c2ecf20Sopenharmony_ci new_dentry->d_name.len); 14708c2ecf20Sopenharmony_ci if (status) 14718c2ecf20Sopenharmony_ci goto bail; 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci status = ocfs2_prepare_dir_for_insert(osb, new_dir, new_dir_bh, 14748c2ecf20Sopenharmony_ci new_dentry->d_name.name, 14758c2ecf20Sopenharmony_ci new_dentry->d_name.len, 14768c2ecf20Sopenharmony_ci &target_insert); 14778c2ecf20Sopenharmony_ci if (status < 0) { 14788c2ecf20Sopenharmony_ci mlog_errno(status); 14798c2ecf20Sopenharmony_ci goto bail; 14808c2ecf20Sopenharmony_ci } 14818c2ecf20Sopenharmony_ci } 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci handle = ocfs2_start_trans(osb, ocfs2_rename_credits(osb->sb)); 14848c2ecf20Sopenharmony_ci if (IS_ERR(handle)) { 14858c2ecf20Sopenharmony_ci status = PTR_ERR(handle); 14868c2ecf20Sopenharmony_ci handle = NULL; 14878c2ecf20Sopenharmony_ci mlog_errno(status); 14888c2ecf20Sopenharmony_ci goto bail; 14898c2ecf20Sopenharmony_ci } 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci if (target_exists) { 14928c2ecf20Sopenharmony_ci if (S_ISDIR(new_inode->i_mode)) { 14938c2ecf20Sopenharmony_ci if (new_inode->i_nlink != 2 || 14948c2ecf20Sopenharmony_ci !ocfs2_empty_dir(new_inode)) { 14958c2ecf20Sopenharmony_ci status = -ENOTEMPTY; 14968c2ecf20Sopenharmony_ci goto bail; 14978c2ecf20Sopenharmony_ci } 14988c2ecf20Sopenharmony_ci } 14998c2ecf20Sopenharmony_ci status = ocfs2_journal_access_di(handle, INODE_CACHE(new_inode), 15008c2ecf20Sopenharmony_ci newfe_bh, 15018c2ecf20Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 15028c2ecf20Sopenharmony_ci if (status < 0) { 15038c2ecf20Sopenharmony_ci mlog_errno(status); 15048c2ecf20Sopenharmony_ci goto bail; 15058c2ecf20Sopenharmony_ci } 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci /* change the dirent to point to the correct inode */ 15088c2ecf20Sopenharmony_ci status = ocfs2_update_entry(new_dir, handle, &target_lookup_res, 15098c2ecf20Sopenharmony_ci old_inode); 15108c2ecf20Sopenharmony_ci if (status < 0) { 15118c2ecf20Sopenharmony_ci mlog_errno(status); 15128c2ecf20Sopenharmony_ci goto bail; 15138c2ecf20Sopenharmony_ci } 15148c2ecf20Sopenharmony_ci inode_inc_iversion(new_dir); 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_ci if (S_ISDIR(new_inode->i_mode)) 15178c2ecf20Sopenharmony_ci ocfs2_set_links_count(newfe, 0); 15188c2ecf20Sopenharmony_ci else 15198c2ecf20Sopenharmony_ci ocfs2_add_links_count(newfe, -1); 15208c2ecf20Sopenharmony_ci ocfs2_journal_dirty(handle, newfe_bh); 15218c2ecf20Sopenharmony_ci if (should_add_orphan) { 15228c2ecf20Sopenharmony_ci status = ocfs2_orphan_add(osb, handle, new_inode, 15238c2ecf20Sopenharmony_ci newfe_bh, orphan_name, 15248c2ecf20Sopenharmony_ci &orphan_insert, orphan_dir, false); 15258c2ecf20Sopenharmony_ci if (status < 0) { 15268c2ecf20Sopenharmony_ci mlog_errno(status); 15278c2ecf20Sopenharmony_ci goto bail; 15288c2ecf20Sopenharmony_ci } 15298c2ecf20Sopenharmony_ci } 15308c2ecf20Sopenharmony_ci } else { 15318c2ecf20Sopenharmony_ci /* if the name was not found in new_dir, add it now */ 15328c2ecf20Sopenharmony_ci status = ocfs2_add_entry(handle, new_dentry, old_inode, 15338c2ecf20Sopenharmony_ci OCFS2_I(old_inode)->ip_blkno, 15348c2ecf20Sopenharmony_ci new_dir_bh, &target_insert); 15358c2ecf20Sopenharmony_ci if (status < 0) { 15368c2ecf20Sopenharmony_ci mlog_errno(status); 15378c2ecf20Sopenharmony_ci goto bail; 15388c2ecf20Sopenharmony_ci } 15398c2ecf20Sopenharmony_ci } 15408c2ecf20Sopenharmony_ci 15418c2ecf20Sopenharmony_ci old_inode->i_ctime = current_time(old_inode); 15428c2ecf20Sopenharmony_ci mark_inode_dirty(old_inode); 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci status = ocfs2_journal_access_di(handle, INODE_CACHE(old_inode), 15458c2ecf20Sopenharmony_ci old_inode_bh, 15468c2ecf20Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 15478c2ecf20Sopenharmony_ci if (status >= 0) { 15488c2ecf20Sopenharmony_ci old_di = (struct ocfs2_dinode *) old_inode_bh->b_data; 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci old_di->i_ctime = cpu_to_le64(old_inode->i_ctime.tv_sec); 15518c2ecf20Sopenharmony_ci old_di->i_ctime_nsec = cpu_to_le32(old_inode->i_ctime.tv_nsec); 15528c2ecf20Sopenharmony_ci ocfs2_journal_dirty(handle, old_inode_bh); 15538c2ecf20Sopenharmony_ci } else 15548c2ecf20Sopenharmony_ci mlog_errno(status); 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci /* 15578c2ecf20Sopenharmony_ci * Now that the name has been added to new_dir, remove the old name. 15588c2ecf20Sopenharmony_ci * 15598c2ecf20Sopenharmony_ci * We don't keep any directory entry context around until now 15608c2ecf20Sopenharmony_ci * because the insert might have changed the type of directory 15618c2ecf20Sopenharmony_ci * we're dealing with. 15628c2ecf20Sopenharmony_ci */ 15638c2ecf20Sopenharmony_ci status = ocfs2_find_entry(old_dentry->d_name.name, 15648c2ecf20Sopenharmony_ci old_dentry->d_name.len, old_dir, 15658c2ecf20Sopenharmony_ci &old_entry_lookup); 15668c2ecf20Sopenharmony_ci if (status) { 15678c2ecf20Sopenharmony_ci if (!is_journal_aborted(osb->journal->j_journal)) { 15688c2ecf20Sopenharmony_ci ocfs2_error(osb->sb, "new entry %.*s is added, but old entry %.*s " 15698c2ecf20Sopenharmony_ci "is not deleted.", 15708c2ecf20Sopenharmony_ci new_dentry->d_name.len, new_dentry->d_name.name, 15718c2ecf20Sopenharmony_ci old_dentry->d_name.len, old_dentry->d_name.name); 15728c2ecf20Sopenharmony_ci } 15738c2ecf20Sopenharmony_ci goto bail; 15748c2ecf20Sopenharmony_ci } 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_ci status = ocfs2_delete_entry(handle, old_dir, &old_entry_lookup); 15778c2ecf20Sopenharmony_ci if (status < 0) { 15788c2ecf20Sopenharmony_ci mlog_errno(status); 15798c2ecf20Sopenharmony_ci if (!is_journal_aborted(osb->journal->j_journal)) { 15808c2ecf20Sopenharmony_ci ocfs2_error(osb->sb, "new entry %.*s is added, but old entry %.*s " 15818c2ecf20Sopenharmony_ci "is not deleted.", 15828c2ecf20Sopenharmony_ci new_dentry->d_name.len, new_dentry->d_name.name, 15838c2ecf20Sopenharmony_ci old_dentry->d_name.len, old_dentry->d_name.name); 15848c2ecf20Sopenharmony_ci } 15858c2ecf20Sopenharmony_ci goto bail; 15868c2ecf20Sopenharmony_ci } 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci if (new_inode) { 15898c2ecf20Sopenharmony_ci drop_nlink(new_inode); 15908c2ecf20Sopenharmony_ci new_inode->i_ctime = current_time(new_inode); 15918c2ecf20Sopenharmony_ci } 15928c2ecf20Sopenharmony_ci old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir); 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_ci if (update_dot_dot) { 15958c2ecf20Sopenharmony_ci status = ocfs2_update_entry(old_inode, handle, 15968c2ecf20Sopenharmony_ci &old_inode_dot_dot_res, new_dir); 15978c2ecf20Sopenharmony_ci drop_nlink(old_dir); 15988c2ecf20Sopenharmony_ci if (new_inode) { 15998c2ecf20Sopenharmony_ci drop_nlink(new_inode); 16008c2ecf20Sopenharmony_ci } else { 16018c2ecf20Sopenharmony_ci inc_nlink(new_dir); 16028c2ecf20Sopenharmony_ci mark_inode_dirty(new_dir); 16038c2ecf20Sopenharmony_ci } 16048c2ecf20Sopenharmony_ci } 16058c2ecf20Sopenharmony_ci mark_inode_dirty(old_dir); 16068c2ecf20Sopenharmony_ci ocfs2_mark_inode_dirty(handle, old_dir, old_dir_bh); 16078c2ecf20Sopenharmony_ci if (new_inode) { 16088c2ecf20Sopenharmony_ci mark_inode_dirty(new_inode); 16098c2ecf20Sopenharmony_ci ocfs2_mark_inode_dirty(handle, new_inode, newfe_bh); 16108c2ecf20Sopenharmony_ci } 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci if (old_dir != new_dir) { 16138c2ecf20Sopenharmony_ci /* Keep the same times on both directories.*/ 16148c2ecf20Sopenharmony_ci new_dir->i_ctime = new_dir->i_mtime = old_dir->i_ctime; 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci /* 16178c2ecf20Sopenharmony_ci * This will also pick up the i_nlink change from the 16188c2ecf20Sopenharmony_ci * block above. 16198c2ecf20Sopenharmony_ci */ 16208c2ecf20Sopenharmony_ci ocfs2_mark_inode_dirty(handle, new_dir, new_dir_bh); 16218c2ecf20Sopenharmony_ci } 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_ci if (old_dir_nlink != old_dir->i_nlink) { 16248c2ecf20Sopenharmony_ci if (!old_dir_bh) { 16258c2ecf20Sopenharmony_ci mlog(ML_ERROR, "need to change nlink for old dir " 16268c2ecf20Sopenharmony_ci "%llu from %d to %d but bh is NULL!\n", 16278c2ecf20Sopenharmony_ci (unsigned long long)OCFS2_I(old_dir)->ip_blkno, 16288c2ecf20Sopenharmony_ci (int)old_dir_nlink, old_dir->i_nlink); 16298c2ecf20Sopenharmony_ci } else { 16308c2ecf20Sopenharmony_ci struct ocfs2_dinode *fe; 16318c2ecf20Sopenharmony_ci status = ocfs2_journal_access_di(handle, 16328c2ecf20Sopenharmony_ci INODE_CACHE(old_dir), 16338c2ecf20Sopenharmony_ci old_dir_bh, 16348c2ecf20Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 16358c2ecf20Sopenharmony_ci fe = (struct ocfs2_dinode *) old_dir_bh->b_data; 16368c2ecf20Sopenharmony_ci ocfs2_set_links_count(fe, old_dir->i_nlink); 16378c2ecf20Sopenharmony_ci ocfs2_journal_dirty(handle, old_dir_bh); 16388c2ecf20Sopenharmony_ci } 16398c2ecf20Sopenharmony_ci } 16408c2ecf20Sopenharmony_ci ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir); 16418c2ecf20Sopenharmony_ci status = 0; 16428c2ecf20Sopenharmony_cibail: 16438c2ecf20Sopenharmony_ci if (handle) 16448c2ecf20Sopenharmony_ci ocfs2_commit_trans(osb, handle); 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci if (orphan_dir) { 16478c2ecf20Sopenharmony_ci /* This was locked for us in ocfs2_prepare_orphan_dir() */ 16488c2ecf20Sopenharmony_ci ocfs2_inode_unlock(orphan_dir, 1); 16498c2ecf20Sopenharmony_ci inode_unlock(orphan_dir); 16508c2ecf20Sopenharmony_ci iput(orphan_dir); 16518c2ecf20Sopenharmony_ci } 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_ci if (new_child_locked) 16548c2ecf20Sopenharmony_ci ocfs2_inode_unlock(new_inode, 1); 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_ci if (old_child_locked) 16578c2ecf20Sopenharmony_ci ocfs2_inode_unlock(old_inode, 1); 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci if (parents_locked) 16608c2ecf20Sopenharmony_ci ocfs2_double_unlock(old_dir, new_dir); 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci if (rename_lock) 16638c2ecf20Sopenharmony_ci ocfs2_rename_unlock(osb); 16648c2ecf20Sopenharmony_ci 16658c2ecf20Sopenharmony_ci if (new_inode) 16668c2ecf20Sopenharmony_ci sync_mapping_buffers(old_inode->i_mapping); 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci iput(new_inode); 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci ocfs2_free_dir_lookup_result(&target_lookup_res); 16718c2ecf20Sopenharmony_ci ocfs2_free_dir_lookup_result(&old_entry_lookup); 16728c2ecf20Sopenharmony_ci ocfs2_free_dir_lookup_result(&old_inode_dot_dot_res); 16738c2ecf20Sopenharmony_ci ocfs2_free_dir_lookup_result(&orphan_insert); 16748c2ecf20Sopenharmony_ci ocfs2_free_dir_lookup_result(&target_insert); 16758c2ecf20Sopenharmony_ci 16768c2ecf20Sopenharmony_ci brelse(newfe_bh); 16778c2ecf20Sopenharmony_ci brelse(old_inode_bh); 16788c2ecf20Sopenharmony_ci brelse(old_dir_bh); 16798c2ecf20Sopenharmony_ci brelse(new_dir_bh); 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_ci if (status) 16828c2ecf20Sopenharmony_ci mlog_errno(status); 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_ci return status; 16858c2ecf20Sopenharmony_ci} 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci/* 16888c2ecf20Sopenharmony_ci * we expect i_size = strlen(symname). Copy symname into the file 16898c2ecf20Sopenharmony_ci * data, including the null terminator. 16908c2ecf20Sopenharmony_ci */ 16918c2ecf20Sopenharmony_cistatic int ocfs2_create_symlink_data(struct ocfs2_super *osb, 16928c2ecf20Sopenharmony_ci handle_t *handle, 16938c2ecf20Sopenharmony_ci struct inode *inode, 16948c2ecf20Sopenharmony_ci const char *symname) 16958c2ecf20Sopenharmony_ci{ 16968c2ecf20Sopenharmony_ci struct buffer_head **bhs = NULL; 16978c2ecf20Sopenharmony_ci const char *c; 16988c2ecf20Sopenharmony_ci struct super_block *sb = osb->sb; 16998c2ecf20Sopenharmony_ci u64 p_blkno, p_blocks; 17008c2ecf20Sopenharmony_ci int virtual, blocks, status, i, bytes_left; 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci bytes_left = i_size_read(inode) + 1; 17038c2ecf20Sopenharmony_ci /* we can't trust i_blocks because we're actually going to 17048c2ecf20Sopenharmony_ci * write i_size + 1 bytes. */ 17058c2ecf20Sopenharmony_ci blocks = (bytes_left + sb->s_blocksize - 1) >> sb->s_blocksize_bits; 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci trace_ocfs2_create_symlink_data((unsigned long long)inode->i_blocks, 17088c2ecf20Sopenharmony_ci i_size_read(inode), blocks); 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci /* Sanity check -- make sure we're going to fit. */ 17118c2ecf20Sopenharmony_ci if (bytes_left > 17128c2ecf20Sopenharmony_ci ocfs2_clusters_to_bytes(sb, OCFS2_I(inode)->ip_clusters)) { 17138c2ecf20Sopenharmony_ci status = -EIO; 17148c2ecf20Sopenharmony_ci mlog_errno(status); 17158c2ecf20Sopenharmony_ci goto bail; 17168c2ecf20Sopenharmony_ci } 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_ci bhs = kcalloc(blocks, sizeof(struct buffer_head *), GFP_KERNEL); 17198c2ecf20Sopenharmony_ci if (!bhs) { 17208c2ecf20Sopenharmony_ci status = -ENOMEM; 17218c2ecf20Sopenharmony_ci mlog_errno(status); 17228c2ecf20Sopenharmony_ci goto bail; 17238c2ecf20Sopenharmony_ci } 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci status = ocfs2_extent_map_get_blocks(inode, 0, &p_blkno, &p_blocks, 17268c2ecf20Sopenharmony_ci NULL); 17278c2ecf20Sopenharmony_ci if (status < 0) { 17288c2ecf20Sopenharmony_ci mlog_errno(status); 17298c2ecf20Sopenharmony_ci goto bail; 17308c2ecf20Sopenharmony_ci } 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci /* links can never be larger than one cluster so we know this 17338c2ecf20Sopenharmony_ci * is all going to be contiguous, but do a sanity check 17348c2ecf20Sopenharmony_ci * anyway. */ 17358c2ecf20Sopenharmony_ci if ((p_blocks << sb->s_blocksize_bits) < bytes_left) { 17368c2ecf20Sopenharmony_ci status = -EIO; 17378c2ecf20Sopenharmony_ci mlog_errno(status); 17388c2ecf20Sopenharmony_ci goto bail; 17398c2ecf20Sopenharmony_ci } 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci virtual = 0; 17428c2ecf20Sopenharmony_ci while(bytes_left > 0) { 17438c2ecf20Sopenharmony_ci c = &symname[virtual * sb->s_blocksize]; 17448c2ecf20Sopenharmony_ci 17458c2ecf20Sopenharmony_ci bhs[virtual] = sb_getblk(sb, p_blkno); 17468c2ecf20Sopenharmony_ci if (!bhs[virtual]) { 17478c2ecf20Sopenharmony_ci status = -ENOMEM; 17488c2ecf20Sopenharmony_ci mlog_errno(status); 17498c2ecf20Sopenharmony_ci goto bail; 17508c2ecf20Sopenharmony_ci } 17518c2ecf20Sopenharmony_ci ocfs2_set_new_buffer_uptodate(INODE_CACHE(inode), 17528c2ecf20Sopenharmony_ci bhs[virtual]); 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci status = ocfs2_journal_access(handle, INODE_CACHE(inode), 17558c2ecf20Sopenharmony_ci bhs[virtual], 17568c2ecf20Sopenharmony_ci OCFS2_JOURNAL_ACCESS_CREATE); 17578c2ecf20Sopenharmony_ci if (status < 0) { 17588c2ecf20Sopenharmony_ci mlog_errno(status); 17598c2ecf20Sopenharmony_ci goto bail; 17608c2ecf20Sopenharmony_ci } 17618c2ecf20Sopenharmony_ci 17628c2ecf20Sopenharmony_ci memset(bhs[virtual]->b_data, 0, sb->s_blocksize); 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci memcpy(bhs[virtual]->b_data, c, 17658c2ecf20Sopenharmony_ci (bytes_left > sb->s_blocksize) ? sb->s_blocksize : 17668c2ecf20Sopenharmony_ci bytes_left); 17678c2ecf20Sopenharmony_ci 17688c2ecf20Sopenharmony_ci ocfs2_journal_dirty(handle, bhs[virtual]); 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci virtual++; 17718c2ecf20Sopenharmony_ci p_blkno++; 17728c2ecf20Sopenharmony_ci bytes_left -= sb->s_blocksize; 17738c2ecf20Sopenharmony_ci } 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_ci status = 0; 17768c2ecf20Sopenharmony_cibail: 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_ci if (bhs) { 17798c2ecf20Sopenharmony_ci for(i = 0; i < blocks; i++) 17808c2ecf20Sopenharmony_ci brelse(bhs[i]); 17818c2ecf20Sopenharmony_ci kfree(bhs); 17828c2ecf20Sopenharmony_ci } 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci if (status) 17858c2ecf20Sopenharmony_ci mlog_errno(status); 17868c2ecf20Sopenharmony_ci return status; 17878c2ecf20Sopenharmony_ci} 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_cistatic int ocfs2_symlink(struct inode *dir, 17908c2ecf20Sopenharmony_ci struct dentry *dentry, 17918c2ecf20Sopenharmony_ci const char *symname) 17928c2ecf20Sopenharmony_ci{ 17938c2ecf20Sopenharmony_ci int status, l, credits; 17948c2ecf20Sopenharmony_ci u64 newsize; 17958c2ecf20Sopenharmony_ci struct ocfs2_super *osb = NULL; 17968c2ecf20Sopenharmony_ci struct inode *inode = NULL; 17978c2ecf20Sopenharmony_ci struct super_block *sb; 17988c2ecf20Sopenharmony_ci struct buffer_head *new_fe_bh = NULL; 17998c2ecf20Sopenharmony_ci struct buffer_head *parent_fe_bh = NULL; 18008c2ecf20Sopenharmony_ci struct ocfs2_dinode *fe = NULL; 18018c2ecf20Sopenharmony_ci struct ocfs2_dinode *dirfe; 18028c2ecf20Sopenharmony_ci handle_t *handle = NULL; 18038c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *inode_ac = NULL; 18048c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *data_ac = NULL; 18058c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *xattr_ac = NULL; 18068c2ecf20Sopenharmony_ci int want_clusters = 0; 18078c2ecf20Sopenharmony_ci int xattr_credits = 0; 18088c2ecf20Sopenharmony_ci struct ocfs2_security_xattr_info si = { 18098c2ecf20Sopenharmony_ci .name = NULL, 18108c2ecf20Sopenharmony_ci .enable = 1, 18118c2ecf20Sopenharmony_ci }; 18128c2ecf20Sopenharmony_ci int did_quota = 0, did_quota_inode = 0; 18138c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result lookup = { NULL, }; 18148c2ecf20Sopenharmony_ci sigset_t oldset; 18158c2ecf20Sopenharmony_ci int did_block_signals = 0; 18168c2ecf20Sopenharmony_ci struct ocfs2_dentry_lock *dl = NULL; 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_ci trace_ocfs2_symlink_begin(dir, dentry, symname, 18198c2ecf20Sopenharmony_ci dentry->d_name.len, dentry->d_name.name); 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci status = dquot_initialize(dir); 18228c2ecf20Sopenharmony_ci if (status) { 18238c2ecf20Sopenharmony_ci mlog_errno(status); 18248c2ecf20Sopenharmony_ci goto bail; 18258c2ecf20Sopenharmony_ci } 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_ci sb = dir->i_sb; 18288c2ecf20Sopenharmony_ci osb = OCFS2_SB(sb); 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci l = strlen(symname) + 1; 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_ci credits = ocfs2_calc_symlink_credits(sb); 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_ci /* lock the parent directory */ 18358c2ecf20Sopenharmony_ci status = ocfs2_inode_lock(dir, &parent_fe_bh, 1); 18368c2ecf20Sopenharmony_ci if (status < 0) { 18378c2ecf20Sopenharmony_ci if (status != -ENOENT) 18388c2ecf20Sopenharmony_ci mlog_errno(status); 18398c2ecf20Sopenharmony_ci return status; 18408c2ecf20Sopenharmony_ci } 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_ci dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; 18438c2ecf20Sopenharmony_ci if (!ocfs2_read_links_count(dirfe)) { 18448c2ecf20Sopenharmony_ci /* can't make a file in a deleted directory. */ 18458c2ecf20Sopenharmony_ci status = -ENOENT; 18468c2ecf20Sopenharmony_ci goto bail; 18478c2ecf20Sopenharmony_ci } 18488c2ecf20Sopenharmony_ci 18498c2ecf20Sopenharmony_ci status = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, 18508c2ecf20Sopenharmony_ci dentry->d_name.len); 18518c2ecf20Sopenharmony_ci if (status) 18528c2ecf20Sopenharmony_ci goto bail; 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_ci status = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh, 18558c2ecf20Sopenharmony_ci dentry->d_name.name, 18568c2ecf20Sopenharmony_ci dentry->d_name.len, &lookup); 18578c2ecf20Sopenharmony_ci if (status < 0) { 18588c2ecf20Sopenharmony_ci mlog_errno(status); 18598c2ecf20Sopenharmony_ci goto bail; 18608c2ecf20Sopenharmony_ci } 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_ci status = ocfs2_reserve_new_inode(osb, &inode_ac); 18638c2ecf20Sopenharmony_ci if (status < 0) { 18648c2ecf20Sopenharmony_ci if (status != -ENOSPC) 18658c2ecf20Sopenharmony_ci mlog_errno(status); 18668c2ecf20Sopenharmony_ci goto bail; 18678c2ecf20Sopenharmony_ci } 18688c2ecf20Sopenharmony_ci 18698c2ecf20Sopenharmony_ci inode = ocfs2_get_init_inode(dir, S_IFLNK | S_IRWXUGO); 18708c2ecf20Sopenharmony_ci if (IS_ERR(inode)) { 18718c2ecf20Sopenharmony_ci status = PTR_ERR(inode); 18728c2ecf20Sopenharmony_ci inode = NULL; 18738c2ecf20Sopenharmony_ci mlog_errno(status); 18748c2ecf20Sopenharmony_ci goto bail; 18758c2ecf20Sopenharmony_ci } 18768c2ecf20Sopenharmony_ci 18778c2ecf20Sopenharmony_ci /* get security xattr */ 18788c2ecf20Sopenharmony_ci status = ocfs2_init_security_get(inode, dir, &dentry->d_name, &si); 18798c2ecf20Sopenharmony_ci if (status) { 18808c2ecf20Sopenharmony_ci if (status == -EOPNOTSUPP) 18818c2ecf20Sopenharmony_ci si.enable = 0; 18828c2ecf20Sopenharmony_ci else { 18838c2ecf20Sopenharmony_ci mlog_errno(status); 18848c2ecf20Sopenharmony_ci goto bail; 18858c2ecf20Sopenharmony_ci } 18868c2ecf20Sopenharmony_ci } 18878c2ecf20Sopenharmony_ci 18888c2ecf20Sopenharmony_ci /* calculate meta data/clusters for setting security xattr */ 18898c2ecf20Sopenharmony_ci if (si.enable) { 18908c2ecf20Sopenharmony_ci status = ocfs2_calc_security_init(dir, &si, &want_clusters, 18918c2ecf20Sopenharmony_ci &xattr_credits, &xattr_ac); 18928c2ecf20Sopenharmony_ci if (status < 0) { 18938c2ecf20Sopenharmony_ci mlog_errno(status); 18948c2ecf20Sopenharmony_ci goto bail; 18958c2ecf20Sopenharmony_ci } 18968c2ecf20Sopenharmony_ci } 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci /* don't reserve bitmap space for fast symlinks. */ 18998c2ecf20Sopenharmony_ci if (l > ocfs2_fast_symlink_chars(sb)) 19008c2ecf20Sopenharmony_ci want_clusters += 1; 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci status = ocfs2_reserve_clusters(osb, want_clusters, &data_ac); 19038c2ecf20Sopenharmony_ci if (status < 0) { 19048c2ecf20Sopenharmony_ci if (status != -ENOSPC) 19058c2ecf20Sopenharmony_ci mlog_errno(status); 19068c2ecf20Sopenharmony_ci goto bail; 19078c2ecf20Sopenharmony_ci } 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci handle = ocfs2_start_trans(osb, credits + xattr_credits); 19108c2ecf20Sopenharmony_ci if (IS_ERR(handle)) { 19118c2ecf20Sopenharmony_ci status = PTR_ERR(handle); 19128c2ecf20Sopenharmony_ci handle = NULL; 19138c2ecf20Sopenharmony_ci mlog_errno(status); 19148c2ecf20Sopenharmony_ci goto bail; 19158c2ecf20Sopenharmony_ci } 19168c2ecf20Sopenharmony_ci 19178c2ecf20Sopenharmony_ci /* Starting to change things, restart is no longer possible. */ 19188c2ecf20Sopenharmony_ci ocfs2_block_signals(&oldset); 19198c2ecf20Sopenharmony_ci did_block_signals = 1; 19208c2ecf20Sopenharmony_ci 19218c2ecf20Sopenharmony_ci status = dquot_alloc_inode(inode); 19228c2ecf20Sopenharmony_ci if (status) 19238c2ecf20Sopenharmony_ci goto bail; 19248c2ecf20Sopenharmony_ci did_quota_inode = 1; 19258c2ecf20Sopenharmony_ci 19268c2ecf20Sopenharmony_ci trace_ocfs2_symlink_create(dir, dentry, dentry->d_name.len, 19278c2ecf20Sopenharmony_ci dentry->d_name.name, 19288c2ecf20Sopenharmony_ci (unsigned long long)OCFS2_I(dir)->ip_blkno, 19298c2ecf20Sopenharmony_ci inode->i_mode); 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci status = ocfs2_mknod_locked(osb, dir, inode, 19328c2ecf20Sopenharmony_ci 0, &new_fe_bh, parent_fe_bh, handle, 19338c2ecf20Sopenharmony_ci inode_ac); 19348c2ecf20Sopenharmony_ci if (status < 0) { 19358c2ecf20Sopenharmony_ci mlog_errno(status); 19368c2ecf20Sopenharmony_ci goto bail; 19378c2ecf20Sopenharmony_ci } 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_ci fe = (struct ocfs2_dinode *) new_fe_bh->b_data; 19408c2ecf20Sopenharmony_ci inode->i_rdev = 0; 19418c2ecf20Sopenharmony_ci newsize = l - 1; 19428c2ecf20Sopenharmony_ci inode->i_op = &ocfs2_symlink_inode_operations; 19438c2ecf20Sopenharmony_ci inode_nohighmem(inode); 19448c2ecf20Sopenharmony_ci if (l > ocfs2_fast_symlink_chars(sb)) { 19458c2ecf20Sopenharmony_ci u32 offset = 0; 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci status = dquot_alloc_space_nodirty(inode, 19488c2ecf20Sopenharmony_ci ocfs2_clusters_to_bytes(osb->sb, 1)); 19498c2ecf20Sopenharmony_ci if (status) 19508c2ecf20Sopenharmony_ci goto bail; 19518c2ecf20Sopenharmony_ci did_quota = 1; 19528c2ecf20Sopenharmony_ci inode->i_mapping->a_ops = &ocfs2_aops; 19538c2ecf20Sopenharmony_ci status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0, 19548c2ecf20Sopenharmony_ci new_fe_bh, 19558c2ecf20Sopenharmony_ci handle, data_ac, NULL, 19568c2ecf20Sopenharmony_ci NULL); 19578c2ecf20Sopenharmony_ci if (status < 0) { 19588c2ecf20Sopenharmony_ci if (status != -ENOSPC && status != -EINTR) { 19598c2ecf20Sopenharmony_ci mlog(ML_ERROR, 19608c2ecf20Sopenharmony_ci "Failed to extend file to %llu\n", 19618c2ecf20Sopenharmony_ci (unsigned long long)newsize); 19628c2ecf20Sopenharmony_ci mlog_errno(status); 19638c2ecf20Sopenharmony_ci status = -ENOSPC; 19648c2ecf20Sopenharmony_ci } 19658c2ecf20Sopenharmony_ci goto bail; 19668c2ecf20Sopenharmony_ci } 19678c2ecf20Sopenharmony_ci i_size_write(inode, newsize); 19688c2ecf20Sopenharmony_ci inode->i_blocks = ocfs2_inode_sector_count(inode); 19698c2ecf20Sopenharmony_ci } else { 19708c2ecf20Sopenharmony_ci inode->i_mapping->a_ops = &ocfs2_fast_symlink_aops; 19718c2ecf20Sopenharmony_ci memcpy((char *) fe->id2.i_symlink, symname, l); 19728c2ecf20Sopenharmony_ci i_size_write(inode, newsize); 19738c2ecf20Sopenharmony_ci inode->i_blocks = 0; 19748c2ecf20Sopenharmony_ci } 19758c2ecf20Sopenharmony_ci 19768c2ecf20Sopenharmony_ci status = ocfs2_mark_inode_dirty(handle, inode, new_fe_bh); 19778c2ecf20Sopenharmony_ci if (status < 0) { 19788c2ecf20Sopenharmony_ci mlog_errno(status); 19798c2ecf20Sopenharmony_ci goto bail; 19808c2ecf20Sopenharmony_ci } 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci if (!ocfs2_inode_is_fast_symlink(inode)) { 19838c2ecf20Sopenharmony_ci status = ocfs2_create_symlink_data(osb, handle, inode, 19848c2ecf20Sopenharmony_ci symname); 19858c2ecf20Sopenharmony_ci if (status < 0) { 19868c2ecf20Sopenharmony_ci mlog_errno(status); 19878c2ecf20Sopenharmony_ci goto bail; 19888c2ecf20Sopenharmony_ci } 19898c2ecf20Sopenharmony_ci } 19908c2ecf20Sopenharmony_ci 19918c2ecf20Sopenharmony_ci if (si.enable) { 19928c2ecf20Sopenharmony_ci status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si, 19938c2ecf20Sopenharmony_ci xattr_ac, data_ac); 19948c2ecf20Sopenharmony_ci if (status < 0) { 19958c2ecf20Sopenharmony_ci mlog_errno(status); 19968c2ecf20Sopenharmony_ci goto bail; 19978c2ecf20Sopenharmony_ci } 19988c2ecf20Sopenharmony_ci } 19998c2ecf20Sopenharmony_ci 20008c2ecf20Sopenharmony_ci /* 20018c2ecf20Sopenharmony_ci * Do this before adding the entry to the directory. We add 20028c2ecf20Sopenharmony_ci * also set d_op after success so that ->d_iput() will cleanup 20038c2ecf20Sopenharmony_ci * the dentry lock even if ocfs2_add_entry() fails below. 20048c2ecf20Sopenharmony_ci */ 20058c2ecf20Sopenharmony_ci status = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno); 20068c2ecf20Sopenharmony_ci if (status) { 20078c2ecf20Sopenharmony_ci mlog_errno(status); 20088c2ecf20Sopenharmony_ci goto bail; 20098c2ecf20Sopenharmony_ci } 20108c2ecf20Sopenharmony_ci 20118c2ecf20Sopenharmony_ci dl = dentry->d_fsdata; 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_ci status = ocfs2_add_entry(handle, dentry, inode, 20148c2ecf20Sopenharmony_ci le64_to_cpu(fe->i_blkno), parent_fe_bh, 20158c2ecf20Sopenharmony_ci &lookup); 20168c2ecf20Sopenharmony_ci if (status < 0) { 20178c2ecf20Sopenharmony_ci mlog_errno(status); 20188c2ecf20Sopenharmony_ci goto bail; 20198c2ecf20Sopenharmony_ci } 20208c2ecf20Sopenharmony_ci 20218c2ecf20Sopenharmony_ci insert_inode_hash(inode); 20228c2ecf20Sopenharmony_ci d_instantiate(dentry, inode); 20238c2ecf20Sopenharmony_cibail: 20248c2ecf20Sopenharmony_ci if (status < 0 && did_quota) 20258c2ecf20Sopenharmony_ci dquot_free_space_nodirty(inode, 20268c2ecf20Sopenharmony_ci ocfs2_clusters_to_bytes(osb->sb, 1)); 20278c2ecf20Sopenharmony_ci if (status < 0 && did_quota_inode) 20288c2ecf20Sopenharmony_ci dquot_free_inode(inode); 20298c2ecf20Sopenharmony_ci if (handle) { 20308c2ecf20Sopenharmony_ci if (status < 0 && fe) 20318c2ecf20Sopenharmony_ci ocfs2_set_links_count(fe, 0); 20328c2ecf20Sopenharmony_ci ocfs2_commit_trans(osb, handle); 20338c2ecf20Sopenharmony_ci } 20348c2ecf20Sopenharmony_ci 20358c2ecf20Sopenharmony_ci ocfs2_inode_unlock(dir, 1); 20368c2ecf20Sopenharmony_ci if (did_block_signals) 20378c2ecf20Sopenharmony_ci ocfs2_unblock_signals(&oldset); 20388c2ecf20Sopenharmony_ci 20398c2ecf20Sopenharmony_ci brelse(new_fe_bh); 20408c2ecf20Sopenharmony_ci brelse(parent_fe_bh); 20418c2ecf20Sopenharmony_ci kfree(si.value); 20428c2ecf20Sopenharmony_ci ocfs2_free_dir_lookup_result(&lookup); 20438c2ecf20Sopenharmony_ci if (inode_ac) 20448c2ecf20Sopenharmony_ci ocfs2_free_alloc_context(inode_ac); 20458c2ecf20Sopenharmony_ci if (data_ac) 20468c2ecf20Sopenharmony_ci ocfs2_free_alloc_context(data_ac); 20478c2ecf20Sopenharmony_ci if (xattr_ac) 20488c2ecf20Sopenharmony_ci ocfs2_free_alloc_context(xattr_ac); 20498c2ecf20Sopenharmony_ci if ((status < 0) && inode) { 20508c2ecf20Sopenharmony_ci if (dl) 20518c2ecf20Sopenharmony_ci ocfs2_cleanup_add_entry_failure(osb, dentry, inode); 20528c2ecf20Sopenharmony_ci 20538c2ecf20Sopenharmony_ci OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SKIP_ORPHAN_DIR; 20548c2ecf20Sopenharmony_ci clear_nlink(inode); 20558c2ecf20Sopenharmony_ci iput(inode); 20568c2ecf20Sopenharmony_ci } 20578c2ecf20Sopenharmony_ci 20588c2ecf20Sopenharmony_ci if (status) 20598c2ecf20Sopenharmony_ci mlog_errno(status); 20608c2ecf20Sopenharmony_ci 20618c2ecf20Sopenharmony_ci return status; 20628c2ecf20Sopenharmony_ci} 20638c2ecf20Sopenharmony_ci 20648c2ecf20Sopenharmony_cistatic int ocfs2_blkno_stringify(u64 blkno, char *name) 20658c2ecf20Sopenharmony_ci{ 20668c2ecf20Sopenharmony_ci int status, namelen; 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci namelen = snprintf(name, OCFS2_ORPHAN_NAMELEN + 1, "%016llx", 20698c2ecf20Sopenharmony_ci (long long)blkno); 20708c2ecf20Sopenharmony_ci if (namelen <= 0) { 20718c2ecf20Sopenharmony_ci if (namelen) 20728c2ecf20Sopenharmony_ci status = namelen; 20738c2ecf20Sopenharmony_ci else 20748c2ecf20Sopenharmony_ci status = -EINVAL; 20758c2ecf20Sopenharmony_ci mlog_errno(status); 20768c2ecf20Sopenharmony_ci goto bail; 20778c2ecf20Sopenharmony_ci } 20788c2ecf20Sopenharmony_ci if (namelen != OCFS2_ORPHAN_NAMELEN) { 20798c2ecf20Sopenharmony_ci status = -EINVAL; 20808c2ecf20Sopenharmony_ci mlog_errno(status); 20818c2ecf20Sopenharmony_ci goto bail; 20828c2ecf20Sopenharmony_ci } 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci trace_ocfs2_blkno_stringify(blkno, name, namelen); 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci status = 0; 20878c2ecf20Sopenharmony_cibail: 20888c2ecf20Sopenharmony_ci if (status < 0) 20898c2ecf20Sopenharmony_ci mlog_errno(status); 20908c2ecf20Sopenharmony_ci return status; 20918c2ecf20Sopenharmony_ci} 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_cistatic int ocfs2_lookup_lock_orphan_dir(struct ocfs2_super *osb, 20948c2ecf20Sopenharmony_ci struct inode **ret_orphan_dir, 20958c2ecf20Sopenharmony_ci struct buffer_head **ret_orphan_dir_bh) 20968c2ecf20Sopenharmony_ci{ 20978c2ecf20Sopenharmony_ci struct inode *orphan_dir_inode; 20988c2ecf20Sopenharmony_ci struct buffer_head *orphan_dir_bh = NULL; 20998c2ecf20Sopenharmony_ci int ret = 0; 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci orphan_dir_inode = ocfs2_get_system_file_inode(osb, 21028c2ecf20Sopenharmony_ci ORPHAN_DIR_SYSTEM_INODE, 21038c2ecf20Sopenharmony_ci osb->slot_num); 21048c2ecf20Sopenharmony_ci if (!orphan_dir_inode) { 21058c2ecf20Sopenharmony_ci ret = -ENOENT; 21068c2ecf20Sopenharmony_ci mlog_errno(ret); 21078c2ecf20Sopenharmony_ci return ret; 21088c2ecf20Sopenharmony_ci } 21098c2ecf20Sopenharmony_ci 21108c2ecf20Sopenharmony_ci inode_lock(orphan_dir_inode); 21118c2ecf20Sopenharmony_ci 21128c2ecf20Sopenharmony_ci ret = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1); 21138c2ecf20Sopenharmony_ci if (ret < 0) { 21148c2ecf20Sopenharmony_ci inode_unlock(orphan_dir_inode); 21158c2ecf20Sopenharmony_ci iput(orphan_dir_inode); 21168c2ecf20Sopenharmony_ci 21178c2ecf20Sopenharmony_ci mlog_errno(ret); 21188c2ecf20Sopenharmony_ci return ret; 21198c2ecf20Sopenharmony_ci } 21208c2ecf20Sopenharmony_ci 21218c2ecf20Sopenharmony_ci *ret_orphan_dir = orphan_dir_inode; 21228c2ecf20Sopenharmony_ci *ret_orphan_dir_bh = orphan_dir_bh; 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci return 0; 21258c2ecf20Sopenharmony_ci} 21268c2ecf20Sopenharmony_ci 21278c2ecf20Sopenharmony_cistatic int __ocfs2_prepare_orphan_dir(struct inode *orphan_dir_inode, 21288c2ecf20Sopenharmony_ci struct buffer_head *orphan_dir_bh, 21298c2ecf20Sopenharmony_ci u64 blkno, 21308c2ecf20Sopenharmony_ci char *name, 21318c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result *lookup, 21328c2ecf20Sopenharmony_ci bool dio) 21338c2ecf20Sopenharmony_ci{ 21348c2ecf20Sopenharmony_ci int ret; 21358c2ecf20Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(orphan_dir_inode->i_sb); 21368c2ecf20Sopenharmony_ci int namelen = dio ? 21378c2ecf20Sopenharmony_ci (OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN) : 21388c2ecf20Sopenharmony_ci OCFS2_ORPHAN_NAMELEN; 21398c2ecf20Sopenharmony_ci 21408c2ecf20Sopenharmony_ci if (dio) { 21418c2ecf20Sopenharmony_ci ret = snprintf(name, OCFS2_DIO_ORPHAN_PREFIX_LEN + 1, "%s", 21428c2ecf20Sopenharmony_ci OCFS2_DIO_ORPHAN_PREFIX); 21438c2ecf20Sopenharmony_ci if (ret != OCFS2_DIO_ORPHAN_PREFIX_LEN) { 21448c2ecf20Sopenharmony_ci ret = -EINVAL; 21458c2ecf20Sopenharmony_ci mlog_errno(ret); 21468c2ecf20Sopenharmony_ci return ret; 21478c2ecf20Sopenharmony_ci } 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_ci ret = ocfs2_blkno_stringify(blkno, 21508c2ecf20Sopenharmony_ci name + OCFS2_DIO_ORPHAN_PREFIX_LEN); 21518c2ecf20Sopenharmony_ci } else 21528c2ecf20Sopenharmony_ci ret = ocfs2_blkno_stringify(blkno, name); 21538c2ecf20Sopenharmony_ci if (ret < 0) { 21548c2ecf20Sopenharmony_ci mlog_errno(ret); 21558c2ecf20Sopenharmony_ci return ret; 21568c2ecf20Sopenharmony_ci } 21578c2ecf20Sopenharmony_ci 21588c2ecf20Sopenharmony_ci ret = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode, 21598c2ecf20Sopenharmony_ci orphan_dir_bh, name, 21608c2ecf20Sopenharmony_ci namelen, lookup); 21618c2ecf20Sopenharmony_ci if (ret < 0) { 21628c2ecf20Sopenharmony_ci mlog_errno(ret); 21638c2ecf20Sopenharmony_ci return ret; 21648c2ecf20Sopenharmony_ci } 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ci return 0; 21678c2ecf20Sopenharmony_ci} 21688c2ecf20Sopenharmony_ci 21698c2ecf20Sopenharmony_ci/** 21708c2ecf20Sopenharmony_ci * ocfs2_prepare_orphan_dir() - Prepare an orphan directory for 21718c2ecf20Sopenharmony_ci * insertion of an orphan. 21728c2ecf20Sopenharmony_ci * @osb: ocfs2 file system 21738c2ecf20Sopenharmony_ci * @ret_orphan_dir: Orphan dir inode - returned locked! 21748c2ecf20Sopenharmony_ci * @blkno: Actual block number of the inode to be inserted into orphan dir. 21758c2ecf20Sopenharmony_ci * @lookup: dir lookup result, to be passed back into functions like 21768c2ecf20Sopenharmony_ci * ocfs2_orphan_add 21778c2ecf20Sopenharmony_ci * 21788c2ecf20Sopenharmony_ci * Returns zero on success and the ret_orphan_dir, name and lookup 21798c2ecf20Sopenharmony_ci * fields will be populated. 21808c2ecf20Sopenharmony_ci * 21818c2ecf20Sopenharmony_ci * Returns non-zero on failure. 21828c2ecf20Sopenharmony_ci */ 21838c2ecf20Sopenharmony_cistatic int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, 21848c2ecf20Sopenharmony_ci struct inode **ret_orphan_dir, 21858c2ecf20Sopenharmony_ci u64 blkno, 21868c2ecf20Sopenharmony_ci char *name, 21878c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result *lookup, 21888c2ecf20Sopenharmony_ci bool dio) 21898c2ecf20Sopenharmony_ci{ 21908c2ecf20Sopenharmony_ci struct inode *orphan_dir_inode = NULL; 21918c2ecf20Sopenharmony_ci struct buffer_head *orphan_dir_bh = NULL; 21928c2ecf20Sopenharmony_ci int ret = 0; 21938c2ecf20Sopenharmony_ci 21948c2ecf20Sopenharmony_ci ret = ocfs2_lookup_lock_orphan_dir(osb, &orphan_dir_inode, 21958c2ecf20Sopenharmony_ci &orphan_dir_bh); 21968c2ecf20Sopenharmony_ci if (ret < 0) { 21978c2ecf20Sopenharmony_ci mlog_errno(ret); 21988c2ecf20Sopenharmony_ci return ret; 21998c2ecf20Sopenharmony_ci } 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci ret = __ocfs2_prepare_orphan_dir(orphan_dir_inode, orphan_dir_bh, 22028c2ecf20Sopenharmony_ci blkno, name, lookup, dio); 22038c2ecf20Sopenharmony_ci if (ret < 0) { 22048c2ecf20Sopenharmony_ci mlog_errno(ret); 22058c2ecf20Sopenharmony_ci goto out; 22068c2ecf20Sopenharmony_ci } 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci *ret_orphan_dir = orphan_dir_inode; 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ciout: 22118c2ecf20Sopenharmony_ci brelse(orphan_dir_bh); 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_ci if (ret) { 22148c2ecf20Sopenharmony_ci ocfs2_inode_unlock(orphan_dir_inode, 1); 22158c2ecf20Sopenharmony_ci inode_unlock(orphan_dir_inode); 22168c2ecf20Sopenharmony_ci iput(orphan_dir_inode); 22178c2ecf20Sopenharmony_ci } 22188c2ecf20Sopenharmony_ci 22198c2ecf20Sopenharmony_ci if (ret) 22208c2ecf20Sopenharmony_ci mlog_errno(ret); 22218c2ecf20Sopenharmony_ci return ret; 22228c2ecf20Sopenharmony_ci} 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_cistatic int ocfs2_orphan_add(struct ocfs2_super *osb, 22258c2ecf20Sopenharmony_ci handle_t *handle, 22268c2ecf20Sopenharmony_ci struct inode *inode, 22278c2ecf20Sopenharmony_ci struct buffer_head *fe_bh, 22288c2ecf20Sopenharmony_ci char *name, 22298c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result *lookup, 22308c2ecf20Sopenharmony_ci struct inode *orphan_dir_inode, 22318c2ecf20Sopenharmony_ci bool dio) 22328c2ecf20Sopenharmony_ci{ 22338c2ecf20Sopenharmony_ci struct buffer_head *orphan_dir_bh = NULL; 22348c2ecf20Sopenharmony_ci int status = 0; 22358c2ecf20Sopenharmony_ci struct ocfs2_dinode *orphan_fe; 22368c2ecf20Sopenharmony_ci struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data; 22378c2ecf20Sopenharmony_ci int namelen = dio ? 22388c2ecf20Sopenharmony_ci (OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN) : 22398c2ecf20Sopenharmony_ci OCFS2_ORPHAN_NAMELEN; 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ci trace_ocfs2_orphan_add_begin( 22428c2ecf20Sopenharmony_ci (unsigned long long)OCFS2_I(inode)->ip_blkno); 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_ci status = ocfs2_read_inode_block(orphan_dir_inode, &orphan_dir_bh); 22458c2ecf20Sopenharmony_ci if (status < 0) { 22468c2ecf20Sopenharmony_ci mlog_errno(status); 22478c2ecf20Sopenharmony_ci goto leave; 22488c2ecf20Sopenharmony_ci } 22498c2ecf20Sopenharmony_ci 22508c2ecf20Sopenharmony_ci status = ocfs2_journal_access_di(handle, 22518c2ecf20Sopenharmony_ci INODE_CACHE(orphan_dir_inode), 22528c2ecf20Sopenharmony_ci orphan_dir_bh, 22538c2ecf20Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 22548c2ecf20Sopenharmony_ci if (status < 0) { 22558c2ecf20Sopenharmony_ci mlog_errno(status); 22568c2ecf20Sopenharmony_ci goto leave; 22578c2ecf20Sopenharmony_ci } 22588c2ecf20Sopenharmony_ci 22598c2ecf20Sopenharmony_ci /* 22608c2ecf20Sopenharmony_ci * We're going to journal the change of i_flags and i_orphaned_slot. 22618c2ecf20Sopenharmony_ci * It's safe anyway, though some callers may duplicate the journaling. 22628c2ecf20Sopenharmony_ci * Journaling within the func just make the logic look more 22638c2ecf20Sopenharmony_ci * straightforward. 22648c2ecf20Sopenharmony_ci */ 22658c2ecf20Sopenharmony_ci status = ocfs2_journal_access_di(handle, 22668c2ecf20Sopenharmony_ci INODE_CACHE(inode), 22678c2ecf20Sopenharmony_ci fe_bh, 22688c2ecf20Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 22698c2ecf20Sopenharmony_ci if (status < 0) { 22708c2ecf20Sopenharmony_ci mlog_errno(status); 22718c2ecf20Sopenharmony_ci goto leave; 22728c2ecf20Sopenharmony_ci } 22738c2ecf20Sopenharmony_ci 22748c2ecf20Sopenharmony_ci /* we're a cluster, and nlink can change on disk from 22758c2ecf20Sopenharmony_ci * underneath us... */ 22768c2ecf20Sopenharmony_ci orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data; 22778c2ecf20Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 22788c2ecf20Sopenharmony_ci ocfs2_add_links_count(orphan_fe, 1); 22798c2ecf20Sopenharmony_ci set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe)); 22808c2ecf20Sopenharmony_ci ocfs2_journal_dirty(handle, orphan_dir_bh); 22818c2ecf20Sopenharmony_ci 22828c2ecf20Sopenharmony_ci status = __ocfs2_add_entry(handle, orphan_dir_inode, name, 22838c2ecf20Sopenharmony_ci namelen, inode, 22848c2ecf20Sopenharmony_ci OCFS2_I(inode)->ip_blkno, 22858c2ecf20Sopenharmony_ci orphan_dir_bh, lookup); 22868c2ecf20Sopenharmony_ci if (status < 0) { 22878c2ecf20Sopenharmony_ci mlog_errno(status); 22888c2ecf20Sopenharmony_ci goto rollback; 22898c2ecf20Sopenharmony_ci } 22908c2ecf20Sopenharmony_ci 22918c2ecf20Sopenharmony_ci if (dio) { 22928c2ecf20Sopenharmony_ci /* Update flag OCFS2_DIO_ORPHANED_FL and record the orphan 22938c2ecf20Sopenharmony_ci * slot. 22948c2ecf20Sopenharmony_ci */ 22958c2ecf20Sopenharmony_ci fe->i_flags |= cpu_to_le32(OCFS2_DIO_ORPHANED_FL); 22968c2ecf20Sopenharmony_ci fe->i_dio_orphaned_slot = cpu_to_le16(osb->slot_num); 22978c2ecf20Sopenharmony_ci } else { 22988c2ecf20Sopenharmony_ci fe->i_flags |= cpu_to_le32(OCFS2_ORPHANED_FL); 22998c2ecf20Sopenharmony_ci OCFS2_I(inode)->ip_flags &= ~OCFS2_INODE_SKIP_ORPHAN_DIR; 23008c2ecf20Sopenharmony_ci 23018c2ecf20Sopenharmony_ci /* Record which orphan dir our inode now resides 23028c2ecf20Sopenharmony_ci * in. delete_inode will use this to determine which orphan 23038c2ecf20Sopenharmony_ci * dir to lock. */ 23048c2ecf20Sopenharmony_ci fe->i_orphaned_slot = cpu_to_le16(osb->slot_num); 23058c2ecf20Sopenharmony_ci } 23068c2ecf20Sopenharmony_ci 23078c2ecf20Sopenharmony_ci ocfs2_journal_dirty(handle, fe_bh); 23088c2ecf20Sopenharmony_ci 23098c2ecf20Sopenharmony_ci trace_ocfs2_orphan_add_end((unsigned long long)OCFS2_I(inode)->ip_blkno, 23108c2ecf20Sopenharmony_ci osb->slot_num); 23118c2ecf20Sopenharmony_ci 23128c2ecf20Sopenharmony_cirollback: 23138c2ecf20Sopenharmony_ci if (status < 0) { 23148c2ecf20Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 23158c2ecf20Sopenharmony_ci ocfs2_add_links_count(orphan_fe, -1); 23168c2ecf20Sopenharmony_ci set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe)); 23178c2ecf20Sopenharmony_ci } 23188c2ecf20Sopenharmony_ci 23198c2ecf20Sopenharmony_cileave: 23208c2ecf20Sopenharmony_ci brelse(orphan_dir_bh); 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_ci return status; 23238c2ecf20Sopenharmony_ci} 23248c2ecf20Sopenharmony_ci 23258c2ecf20Sopenharmony_ci/* unlike orphan_add, we expect the orphan dir to already be locked here. */ 23268c2ecf20Sopenharmony_ciint ocfs2_orphan_del(struct ocfs2_super *osb, 23278c2ecf20Sopenharmony_ci handle_t *handle, 23288c2ecf20Sopenharmony_ci struct inode *orphan_dir_inode, 23298c2ecf20Sopenharmony_ci struct inode *inode, 23308c2ecf20Sopenharmony_ci struct buffer_head *orphan_dir_bh, 23318c2ecf20Sopenharmony_ci bool dio) 23328c2ecf20Sopenharmony_ci{ 23338c2ecf20Sopenharmony_ci char name[OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN + 1]; 23348c2ecf20Sopenharmony_ci struct ocfs2_dinode *orphan_fe; 23358c2ecf20Sopenharmony_ci int status = 0; 23368c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result lookup = { NULL, }; 23378c2ecf20Sopenharmony_ci 23388c2ecf20Sopenharmony_ci if (dio) { 23398c2ecf20Sopenharmony_ci status = snprintf(name, OCFS2_DIO_ORPHAN_PREFIX_LEN + 1, "%s", 23408c2ecf20Sopenharmony_ci OCFS2_DIO_ORPHAN_PREFIX); 23418c2ecf20Sopenharmony_ci if (status != OCFS2_DIO_ORPHAN_PREFIX_LEN) { 23428c2ecf20Sopenharmony_ci status = -EINVAL; 23438c2ecf20Sopenharmony_ci mlog_errno(status); 23448c2ecf20Sopenharmony_ci return status; 23458c2ecf20Sopenharmony_ci } 23468c2ecf20Sopenharmony_ci 23478c2ecf20Sopenharmony_ci status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, 23488c2ecf20Sopenharmony_ci name + OCFS2_DIO_ORPHAN_PREFIX_LEN); 23498c2ecf20Sopenharmony_ci } else 23508c2ecf20Sopenharmony_ci status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name); 23518c2ecf20Sopenharmony_ci if (status < 0) { 23528c2ecf20Sopenharmony_ci mlog_errno(status); 23538c2ecf20Sopenharmony_ci goto leave; 23548c2ecf20Sopenharmony_ci } 23558c2ecf20Sopenharmony_ci 23568c2ecf20Sopenharmony_ci trace_ocfs2_orphan_del( 23578c2ecf20Sopenharmony_ci (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno, 23588c2ecf20Sopenharmony_ci name, strlen(name)); 23598c2ecf20Sopenharmony_ci 23608c2ecf20Sopenharmony_ci status = ocfs2_journal_access_di(handle, 23618c2ecf20Sopenharmony_ci INODE_CACHE(orphan_dir_inode), 23628c2ecf20Sopenharmony_ci orphan_dir_bh, 23638c2ecf20Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 23648c2ecf20Sopenharmony_ci if (status < 0) { 23658c2ecf20Sopenharmony_ci mlog_errno(status); 23668c2ecf20Sopenharmony_ci goto leave; 23678c2ecf20Sopenharmony_ci } 23688c2ecf20Sopenharmony_ci 23698c2ecf20Sopenharmony_ci /* find it's spot in the orphan directory */ 23708c2ecf20Sopenharmony_ci status = ocfs2_find_entry(name, strlen(name), orphan_dir_inode, 23718c2ecf20Sopenharmony_ci &lookup); 23728c2ecf20Sopenharmony_ci if (status) { 23738c2ecf20Sopenharmony_ci mlog_errno(status); 23748c2ecf20Sopenharmony_ci goto leave; 23758c2ecf20Sopenharmony_ci } 23768c2ecf20Sopenharmony_ci 23778c2ecf20Sopenharmony_ci /* remove it from the orphan directory */ 23788c2ecf20Sopenharmony_ci status = ocfs2_delete_entry(handle, orphan_dir_inode, &lookup); 23798c2ecf20Sopenharmony_ci if (status < 0) { 23808c2ecf20Sopenharmony_ci mlog_errno(status); 23818c2ecf20Sopenharmony_ci goto leave; 23828c2ecf20Sopenharmony_ci } 23838c2ecf20Sopenharmony_ci 23848c2ecf20Sopenharmony_ci /* do the i_nlink dance! :) */ 23858c2ecf20Sopenharmony_ci orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data; 23868c2ecf20Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 23878c2ecf20Sopenharmony_ci ocfs2_add_links_count(orphan_fe, -1); 23888c2ecf20Sopenharmony_ci set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe)); 23898c2ecf20Sopenharmony_ci ocfs2_journal_dirty(handle, orphan_dir_bh); 23908c2ecf20Sopenharmony_ci 23918c2ecf20Sopenharmony_cileave: 23928c2ecf20Sopenharmony_ci ocfs2_free_dir_lookup_result(&lookup); 23938c2ecf20Sopenharmony_ci 23948c2ecf20Sopenharmony_ci if (status) 23958c2ecf20Sopenharmony_ci mlog_errno(status); 23968c2ecf20Sopenharmony_ci return status; 23978c2ecf20Sopenharmony_ci} 23988c2ecf20Sopenharmony_ci 23998c2ecf20Sopenharmony_ci/** 24008c2ecf20Sopenharmony_ci * ocfs2_prep_new_orphaned_file() - Prepare the orphan dir to receive a newly 24018c2ecf20Sopenharmony_ci * allocated file. This is different from the typical 'add to orphan dir' 24028c2ecf20Sopenharmony_ci * operation in that the inode does not yet exist. This is a problem because 24038c2ecf20Sopenharmony_ci * the orphan dir stringifies the inode block number to come up with it's 24048c2ecf20Sopenharmony_ci * dirent. Obviously if the inode does not yet exist we have a chicken and egg 24058c2ecf20Sopenharmony_ci * problem. This function works around it by calling deeper into the orphan 24068c2ecf20Sopenharmony_ci * and suballoc code than other callers. Use this only by necessity. 24078c2ecf20Sopenharmony_ci * @dir: The directory which this inode will ultimately wind up under - not the 24088c2ecf20Sopenharmony_ci * orphan dir! 24098c2ecf20Sopenharmony_ci * @dir_bh: buffer_head the @dir inode block 24108c2ecf20Sopenharmony_ci * @orphan_name: string of length (CFS2_ORPHAN_NAMELEN + 1). Will be filled 24118c2ecf20Sopenharmony_ci * with the string to be used for orphan dirent. Pass back to the orphan dir 24128c2ecf20Sopenharmony_ci * code. 24138c2ecf20Sopenharmony_ci * @ret_orphan_dir: orphan dir inode returned to be passed back into orphan 24148c2ecf20Sopenharmony_ci * dir code. 24158c2ecf20Sopenharmony_ci * @ret_di_blkno: block number where the new inode will be allocated. 24168c2ecf20Sopenharmony_ci * @orphan_insert: Dir insert context to be passed back into orphan dir code. 24178c2ecf20Sopenharmony_ci * @ret_inode_ac: Inode alloc context to be passed back to the allocator. 24188c2ecf20Sopenharmony_ci * 24198c2ecf20Sopenharmony_ci * Returns zero on success and the ret_orphan_dir, name and lookup 24208c2ecf20Sopenharmony_ci * fields will be populated. 24218c2ecf20Sopenharmony_ci * 24228c2ecf20Sopenharmony_ci * Returns non-zero on failure. 24238c2ecf20Sopenharmony_ci */ 24248c2ecf20Sopenharmony_cistatic int ocfs2_prep_new_orphaned_file(struct inode *dir, 24258c2ecf20Sopenharmony_ci struct buffer_head *dir_bh, 24268c2ecf20Sopenharmony_ci char *orphan_name, 24278c2ecf20Sopenharmony_ci struct inode **ret_orphan_dir, 24288c2ecf20Sopenharmony_ci u64 *ret_di_blkno, 24298c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result *orphan_insert, 24308c2ecf20Sopenharmony_ci struct ocfs2_alloc_context **ret_inode_ac) 24318c2ecf20Sopenharmony_ci{ 24328c2ecf20Sopenharmony_ci int ret; 24338c2ecf20Sopenharmony_ci u64 di_blkno; 24348c2ecf20Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); 24358c2ecf20Sopenharmony_ci struct inode *orphan_dir = NULL; 24368c2ecf20Sopenharmony_ci struct buffer_head *orphan_dir_bh = NULL; 24378c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *inode_ac = NULL; 24388c2ecf20Sopenharmony_ci 24398c2ecf20Sopenharmony_ci ret = ocfs2_lookup_lock_orphan_dir(osb, &orphan_dir, &orphan_dir_bh); 24408c2ecf20Sopenharmony_ci if (ret < 0) { 24418c2ecf20Sopenharmony_ci mlog_errno(ret); 24428c2ecf20Sopenharmony_ci return ret; 24438c2ecf20Sopenharmony_ci } 24448c2ecf20Sopenharmony_ci 24458c2ecf20Sopenharmony_ci /* reserve an inode spot */ 24468c2ecf20Sopenharmony_ci ret = ocfs2_reserve_new_inode(osb, &inode_ac); 24478c2ecf20Sopenharmony_ci if (ret < 0) { 24488c2ecf20Sopenharmony_ci if (ret != -ENOSPC) 24498c2ecf20Sopenharmony_ci mlog_errno(ret); 24508c2ecf20Sopenharmony_ci goto out; 24518c2ecf20Sopenharmony_ci } 24528c2ecf20Sopenharmony_ci 24538c2ecf20Sopenharmony_ci ret = ocfs2_find_new_inode_loc(dir, dir_bh, inode_ac, 24548c2ecf20Sopenharmony_ci &di_blkno); 24558c2ecf20Sopenharmony_ci if (ret) { 24568c2ecf20Sopenharmony_ci mlog_errno(ret); 24578c2ecf20Sopenharmony_ci goto out; 24588c2ecf20Sopenharmony_ci } 24598c2ecf20Sopenharmony_ci 24608c2ecf20Sopenharmony_ci ret = __ocfs2_prepare_orphan_dir(orphan_dir, orphan_dir_bh, 24618c2ecf20Sopenharmony_ci di_blkno, orphan_name, orphan_insert, 24628c2ecf20Sopenharmony_ci false); 24638c2ecf20Sopenharmony_ci if (ret < 0) { 24648c2ecf20Sopenharmony_ci mlog_errno(ret); 24658c2ecf20Sopenharmony_ci goto out; 24668c2ecf20Sopenharmony_ci } 24678c2ecf20Sopenharmony_ci 24688c2ecf20Sopenharmony_ciout: 24698c2ecf20Sopenharmony_ci if (ret == 0) { 24708c2ecf20Sopenharmony_ci *ret_orphan_dir = orphan_dir; 24718c2ecf20Sopenharmony_ci *ret_di_blkno = di_blkno; 24728c2ecf20Sopenharmony_ci *ret_inode_ac = inode_ac; 24738c2ecf20Sopenharmony_ci /* 24748c2ecf20Sopenharmony_ci * orphan_name and orphan_insert are already up to 24758c2ecf20Sopenharmony_ci * date via prepare_orphan_dir 24768c2ecf20Sopenharmony_ci */ 24778c2ecf20Sopenharmony_ci } else { 24788c2ecf20Sopenharmony_ci /* Unroll reserve_new_inode* */ 24798c2ecf20Sopenharmony_ci if (inode_ac) 24808c2ecf20Sopenharmony_ci ocfs2_free_alloc_context(inode_ac); 24818c2ecf20Sopenharmony_ci 24828c2ecf20Sopenharmony_ci /* Unroll orphan dir locking */ 24838c2ecf20Sopenharmony_ci inode_unlock(orphan_dir); 24848c2ecf20Sopenharmony_ci ocfs2_inode_unlock(orphan_dir, 1); 24858c2ecf20Sopenharmony_ci iput(orphan_dir); 24868c2ecf20Sopenharmony_ci } 24878c2ecf20Sopenharmony_ci 24888c2ecf20Sopenharmony_ci brelse(orphan_dir_bh); 24898c2ecf20Sopenharmony_ci 24908c2ecf20Sopenharmony_ci return ret; 24918c2ecf20Sopenharmony_ci} 24928c2ecf20Sopenharmony_ci 24938c2ecf20Sopenharmony_ciint ocfs2_create_inode_in_orphan(struct inode *dir, 24948c2ecf20Sopenharmony_ci int mode, 24958c2ecf20Sopenharmony_ci struct inode **new_inode) 24968c2ecf20Sopenharmony_ci{ 24978c2ecf20Sopenharmony_ci int status, did_quota_inode = 0; 24988c2ecf20Sopenharmony_ci struct inode *inode = NULL; 24998c2ecf20Sopenharmony_ci struct inode *orphan_dir = NULL; 25008c2ecf20Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); 25018c2ecf20Sopenharmony_ci handle_t *handle = NULL; 25028c2ecf20Sopenharmony_ci char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; 25038c2ecf20Sopenharmony_ci struct buffer_head *parent_di_bh = NULL; 25048c2ecf20Sopenharmony_ci struct buffer_head *new_di_bh = NULL; 25058c2ecf20Sopenharmony_ci struct ocfs2_alloc_context *inode_ac = NULL; 25068c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; 25078c2ecf20Sopenharmony_ci u64 di_blkno, suballoc_loc; 25088c2ecf20Sopenharmony_ci u16 suballoc_bit; 25098c2ecf20Sopenharmony_ci 25108c2ecf20Sopenharmony_ci status = ocfs2_inode_lock(dir, &parent_di_bh, 1); 25118c2ecf20Sopenharmony_ci if (status < 0) { 25128c2ecf20Sopenharmony_ci if (status != -ENOENT) 25138c2ecf20Sopenharmony_ci mlog_errno(status); 25148c2ecf20Sopenharmony_ci return status; 25158c2ecf20Sopenharmony_ci } 25168c2ecf20Sopenharmony_ci 25178c2ecf20Sopenharmony_ci status = ocfs2_prep_new_orphaned_file(dir, parent_di_bh, 25188c2ecf20Sopenharmony_ci orphan_name, &orphan_dir, 25198c2ecf20Sopenharmony_ci &di_blkno, &orphan_insert, &inode_ac); 25208c2ecf20Sopenharmony_ci if (status < 0) { 25218c2ecf20Sopenharmony_ci if (status != -ENOSPC) 25228c2ecf20Sopenharmony_ci mlog_errno(status); 25238c2ecf20Sopenharmony_ci goto leave; 25248c2ecf20Sopenharmony_ci } 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_ci inode = ocfs2_get_init_inode(dir, mode); 25278c2ecf20Sopenharmony_ci if (IS_ERR(inode)) { 25288c2ecf20Sopenharmony_ci status = PTR_ERR(inode); 25298c2ecf20Sopenharmony_ci inode = NULL; 25308c2ecf20Sopenharmony_ci mlog_errno(status); 25318c2ecf20Sopenharmony_ci goto leave; 25328c2ecf20Sopenharmony_ci } 25338c2ecf20Sopenharmony_ci 25348c2ecf20Sopenharmony_ci handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb, 0, 0)); 25358c2ecf20Sopenharmony_ci if (IS_ERR(handle)) { 25368c2ecf20Sopenharmony_ci status = PTR_ERR(handle); 25378c2ecf20Sopenharmony_ci handle = NULL; 25388c2ecf20Sopenharmony_ci mlog_errno(status); 25398c2ecf20Sopenharmony_ci goto leave; 25408c2ecf20Sopenharmony_ci } 25418c2ecf20Sopenharmony_ci 25428c2ecf20Sopenharmony_ci status = dquot_alloc_inode(inode); 25438c2ecf20Sopenharmony_ci if (status) 25448c2ecf20Sopenharmony_ci goto leave; 25458c2ecf20Sopenharmony_ci did_quota_inode = 1; 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_ci status = ocfs2_claim_new_inode_at_loc(handle, dir, inode_ac, 25488c2ecf20Sopenharmony_ci &suballoc_loc, 25498c2ecf20Sopenharmony_ci &suballoc_bit, di_blkno); 25508c2ecf20Sopenharmony_ci if (status < 0) { 25518c2ecf20Sopenharmony_ci mlog_errno(status); 25528c2ecf20Sopenharmony_ci goto leave; 25538c2ecf20Sopenharmony_ci } 25548c2ecf20Sopenharmony_ci 25558c2ecf20Sopenharmony_ci clear_nlink(inode); 25568c2ecf20Sopenharmony_ci /* do the real work now. */ 25578c2ecf20Sopenharmony_ci status = __ocfs2_mknod_locked(dir, inode, 25588c2ecf20Sopenharmony_ci 0, &new_di_bh, parent_di_bh, handle, 25598c2ecf20Sopenharmony_ci inode_ac, di_blkno, suballoc_loc, 25608c2ecf20Sopenharmony_ci suballoc_bit); 25618c2ecf20Sopenharmony_ci if (status < 0) { 25628c2ecf20Sopenharmony_ci mlog_errno(status); 25638c2ecf20Sopenharmony_ci goto leave; 25648c2ecf20Sopenharmony_ci } 25658c2ecf20Sopenharmony_ci 25668c2ecf20Sopenharmony_ci status = ocfs2_orphan_add(osb, handle, inode, new_di_bh, orphan_name, 25678c2ecf20Sopenharmony_ci &orphan_insert, orphan_dir, false); 25688c2ecf20Sopenharmony_ci if (status < 0) { 25698c2ecf20Sopenharmony_ci mlog_errno(status); 25708c2ecf20Sopenharmony_ci goto leave; 25718c2ecf20Sopenharmony_ci } 25728c2ecf20Sopenharmony_ci 25738c2ecf20Sopenharmony_ci /* get open lock so that only nodes can't remove it from orphan dir. */ 25748c2ecf20Sopenharmony_ci status = ocfs2_open_lock(inode); 25758c2ecf20Sopenharmony_ci if (status < 0) 25768c2ecf20Sopenharmony_ci mlog_errno(status); 25778c2ecf20Sopenharmony_ci 25788c2ecf20Sopenharmony_ci insert_inode_hash(inode); 25798c2ecf20Sopenharmony_cileave: 25808c2ecf20Sopenharmony_ci if (status < 0 && did_quota_inode) 25818c2ecf20Sopenharmony_ci dquot_free_inode(inode); 25828c2ecf20Sopenharmony_ci if (handle) 25838c2ecf20Sopenharmony_ci ocfs2_commit_trans(osb, handle); 25848c2ecf20Sopenharmony_ci 25858c2ecf20Sopenharmony_ci if (orphan_dir) { 25868c2ecf20Sopenharmony_ci /* This was locked for us in ocfs2_prepare_orphan_dir() */ 25878c2ecf20Sopenharmony_ci ocfs2_inode_unlock(orphan_dir, 1); 25888c2ecf20Sopenharmony_ci inode_unlock(orphan_dir); 25898c2ecf20Sopenharmony_ci iput(orphan_dir); 25908c2ecf20Sopenharmony_ci } 25918c2ecf20Sopenharmony_ci 25928c2ecf20Sopenharmony_ci if ((status < 0) && inode) { 25938c2ecf20Sopenharmony_ci clear_nlink(inode); 25948c2ecf20Sopenharmony_ci iput(inode); 25958c2ecf20Sopenharmony_ci } 25968c2ecf20Sopenharmony_ci 25978c2ecf20Sopenharmony_ci if (inode_ac) 25988c2ecf20Sopenharmony_ci ocfs2_free_alloc_context(inode_ac); 25998c2ecf20Sopenharmony_ci 26008c2ecf20Sopenharmony_ci brelse(new_di_bh); 26018c2ecf20Sopenharmony_ci 26028c2ecf20Sopenharmony_ci if (!status) 26038c2ecf20Sopenharmony_ci *new_inode = inode; 26048c2ecf20Sopenharmony_ci 26058c2ecf20Sopenharmony_ci ocfs2_free_dir_lookup_result(&orphan_insert); 26068c2ecf20Sopenharmony_ci 26078c2ecf20Sopenharmony_ci ocfs2_inode_unlock(dir, 1); 26088c2ecf20Sopenharmony_ci brelse(parent_di_bh); 26098c2ecf20Sopenharmony_ci return status; 26108c2ecf20Sopenharmony_ci} 26118c2ecf20Sopenharmony_ci 26128c2ecf20Sopenharmony_ciint ocfs2_add_inode_to_orphan(struct ocfs2_super *osb, 26138c2ecf20Sopenharmony_ci struct inode *inode) 26148c2ecf20Sopenharmony_ci{ 26158c2ecf20Sopenharmony_ci char orphan_name[OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN + 1]; 26168c2ecf20Sopenharmony_ci struct inode *orphan_dir_inode = NULL; 26178c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; 26188c2ecf20Sopenharmony_ci struct buffer_head *di_bh = NULL; 26198c2ecf20Sopenharmony_ci int status = 0; 26208c2ecf20Sopenharmony_ci handle_t *handle = NULL; 26218c2ecf20Sopenharmony_ci struct ocfs2_dinode *di = NULL; 26228c2ecf20Sopenharmony_ci 26238c2ecf20Sopenharmony_ci status = ocfs2_inode_lock(inode, &di_bh, 1); 26248c2ecf20Sopenharmony_ci if (status < 0) { 26258c2ecf20Sopenharmony_ci mlog_errno(status); 26268c2ecf20Sopenharmony_ci goto bail; 26278c2ecf20Sopenharmony_ci } 26288c2ecf20Sopenharmony_ci 26298c2ecf20Sopenharmony_ci di = (struct ocfs2_dinode *) di_bh->b_data; 26308c2ecf20Sopenharmony_ci /* 26318c2ecf20Sopenharmony_ci * Another append dio crashed? 26328c2ecf20Sopenharmony_ci * If so, manually recover it first. 26338c2ecf20Sopenharmony_ci */ 26348c2ecf20Sopenharmony_ci if (unlikely(di->i_flags & cpu_to_le32(OCFS2_DIO_ORPHANED_FL))) { 26358c2ecf20Sopenharmony_ci status = ocfs2_truncate_file(inode, di_bh, i_size_read(inode)); 26368c2ecf20Sopenharmony_ci if (status < 0) { 26378c2ecf20Sopenharmony_ci if (status != -ENOSPC) 26388c2ecf20Sopenharmony_ci mlog_errno(status); 26398c2ecf20Sopenharmony_ci goto bail_unlock_inode; 26408c2ecf20Sopenharmony_ci } 26418c2ecf20Sopenharmony_ci 26428c2ecf20Sopenharmony_ci status = ocfs2_del_inode_from_orphan(osb, inode, di_bh, 0, 0); 26438c2ecf20Sopenharmony_ci if (status < 0) { 26448c2ecf20Sopenharmony_ci mlog_errno(status); 26458c2ecf20Sopenharmony_ci goto bail_unlock_inode; 26468c2ecf20Sopenharmony_ci } 26478c2ecf20Sopenharmony_ci } 26488c2ecf20Sopenharmony_ci 26498c2ecf20Sopenharmony_ci status = ocfs2_prepare_orphan_dir(osb, &orphan_dir_inode, 26508c2ecf20Sopenharmony_ci OCFS2_I(inode)->ip_blkno, 26518c2ecf20Sopenharmony_ci orphan_name, 26528c2ecf20Sopenharmony_ci &orphan_insert, 26538c2ecf20Sopenharmony_ci true); 26548c2ecf20Sopenharmony_ci if (status < 0) { 26558c2ecf20Sopenharmony_ci mlog_errno(status); 26568c2ecf20Sopenharmony_ci goto bail_unlock_inode; 26578c2ecf20Sopenharmony_ci } 26588c2ecf20Sopenharmony_ci 26598c2ecf20Sopenharmony_ci handle = ocfs2_start_trans(osb, 26608c2ecf20Sopenharmony_ci OCFS2_INODE_ADD_TO_ORPHAN_CREDITS); 26618c2ecf20Sopenharmony_ci if (IS_ERR(handle)) { 26628c2ecf20Sopenharmony_ci status = PTR_ERR(handle); 26638c2ecf20Sopenharmony_ci goto bail_unlock_orphan; 26648c2ecf20Sopenharmony_ci } 26658c2ecf20Sopenharmony_ci 26668c2ecf20Sopenharmony_ci status = ocfs2_orphan_add(osb, handle, inode, di_bh, orphan_name, 26678c2ecf20Sopenharmony_ci &orphan_insert, orphan_dir_inode, true); 26688c2ecf20Sopenharmony_ci if (status) 26698c2ecf20Sopenharmony_ci mlog_errno(status); 26708c2ecf20Sopenharmony_ci 26718c2ecf20Sopenharmony_ci ocfs2_commit_trans(osb, handle); 26728c2ecf20Sopenharmony_ci 26738c2ecf20Sopenharmony_cibail_unlock_orphan: 26748c2ecf20Sopenharmony_ci ocfs2_inode_unlock(orphan_dir_inode, 1); 26758c2ecf20Sopenharmony_ci inode_unlock(orphan_dir_inode); 26768c2ecf20Sopenharmony_ci iput(orphan_dir_inode); 26778c2ecf20Sopenharmony_ci 26788c2ecf20Sopenharmony_ci ocfs2_free_dir_lookup_result(&orphan_insert); 26798c2ecf20Sopenharmony_ci 26808c2ecf20Sopenharmony_cibail_unlock_inode: 26818c2ecf20Sopenharmony_ci ocfs2_inode_unlock(inode, 1); 26828c2ecf20Sopenharmony_ci brelse(di_bh); 26838c2ecf20Sopenharmony_ci 26848c2ecf20Sopenharmony_cibail: 26858c2ecf20Sopenharmony_ci return status; 26868c2ecf20Sopenharmony_ci} 26878c2ecf20Sopenharmony_ci 26888c2ecf20Sopenharmony_ciint ocfs2_del_inode_from_orphan(struct ocfs2_super *osb, 26898c2ecf20Sopenharmony_ci struct inode *inode, struct buffer_head *di_bh, 26908c2ecf20Sopenharmony_ci int update_isize, loff_t end) 26918c2ecf20Sopenharmony_ci{ 26928c2ecf20Sopenharmony_ci struct inode *orphan_dir_inode = NULL; 26938c2ecf20Sopenharmony_ci struct buffer_head *orphan_dir_bh = NULL; 26948c2ecf20Sopenharmony_ci struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; 26958c2ecf20Sopenharmony_ci handle_t *handle = NULL; 26968c2ecf20Sopenharmony_ci int status = 0; 26978c2ecf20Sopenharmony_ci 26988c2ecf20Sopenharmony_ci orphan_dir_inode = ocfs2_get_system_file_inode(osb, 26998c2ecf20Sopenharmony_ci ORPHAN_DIR_SYSTEM_INODE, 27008c2ecf20Sopenharmony_ci le16_to_cpu(di->i_dio_orphaned_slot)); 27018c2ecf20Sopenharmony_ci if (!orphan_dir_inode) { 27028c2ecf20Sopenharmony_ci status = -ENOENT; 27038c2ecf20Sopenharmony_ci mlog_errno(status); 27048c2ecf20Sopenharmony_ci goto bail; 27058c2ecf20Sopenharmony_ci } 27068c2ecf20Sopenharmony_ci 27078c2ecf20Sopenharmony_ci inode_lock(orphan_dir_inode); 27088c2ecf20Sopenharmony_ci status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1); 27098c2ecf20Sopenharmony_ci if (status < 0) { 27108c2ecf20Sopenharmony_ci inode_unlock(orphan_dir_inode); 27118c2ecf20Sopenharmony_ci iput(orphan_dir_inode); 27128c2ecf20Sopenharmony_ci mlog_errno(status); 27138c2ecf20Sopenharmony_ci goto bail; 27148c2ecf20Sopenharmony_ci } 27158c2ecf20Sopenharmony_ci 27168c2ecf20Sopenharmony_ci handle = ocfs2_start_trans(osb, 27178c2ecf20Sopenharmony_ci OCFS2_INODE_DEL_FROM_ORPHAN_CREDITS); 27188c2ecf20Sopenharmony_ci if (IS_ERR(handle)) { 27198c2ecf20Sopenharmony_ci status = PTR_ERR(handle); 27208c2ecf20Sopenharmony_ci goto bail_unlock_orphan; 27218c2ecf20Sopenharmony_ci } 27228c2ecf20Sopenharmony_ci 27238c2ecf20Sopenharmony_ci BUG_ON(!(di->i_flags & cpu_to_le32(OCFS2_DIO_ORPHANED_FL))); 27248c2ecf20Sopenharmony_ci 27258c2ecf20Sopenharmony_ci status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, 27268c2ecf20Sopenharmony_ci inode, orphan_dir_bh, true); 27278c2ecf20Sopenharmony_ci if (status < 0) { 27288c2ecf20Sopenharmony_ci mlog_errno(status); 27298c2ecf20Sopenharmony_ci goto bail_commit; 27308c2ecf20Sopenharmony_ci } 27318c2ecf20Sopenharmony_ci 27328c2ecf20Sopenharmony_ci status = ocfs2_journal_access_di(handle, 27338c2ecf20Sopenharmony_ci INODE_CACHE(inode), 27348c2ecf20Sopenharmony_ci di_bh, 27358c2ecf20Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 27368c2ecf20Sopenharmony_ci if (status < 0) { 27378c2ecf20Sopenharmony_ci mlog_errno(status); 27388c2ecf20Sopenharmony_ci goto bail_commit; 27398c2ecf20Sopenharmony_ci } 27408c2ecf20Sopenharmony_ci 27418c2ecf20Sopenharmony_ci di->i_flags &= ~cpu_to_le32(OCFS2_DIO_ORPHANED_FL); 27428c2ecf20Sopenharmony_ci di->i_dio_orphaned_slot = 0; 27438c2ecf20Sopenharmony_ci 27448c2ecf20Sopenharmony_ci if (update_isize) { 27458c2ecf20Sopenharmony_ci status = ocfs2_set_inode_size(handle, inode, di_bh, end); 27468c2ecf20Sopenharmony_ci if (status) 27478c2ecf20Sopenharmony_ci mlog_errno(status); 27488c2ecf20Sopenharmony_ci } else 27498c2ecf20Sopenharmony_ci ocfs2_journal_dirty(handle, di_bh); 27508c2ecf20Sopenharmony_ci 27518c2ecf20Sopenharmony_cibail_commit: 27528c2ecf20Sopenharmony_ci ocfs2_commit_trans(osb, handle); 27538c2ecf20Sopenharmony_ci 27548c2ecf20Sopenharmony_cibail_unlock_orphan: 27558c2ecf20Sopenharmony_ci ocfs2_inode_unlock(orphan_dir_inode, 1); 27568c2ecf20Sopenharmony_ci inode_unlock(orphan_dir_inode); 27578c2ecf20Sopenharmony_ci brelse(orphan_dir_bh); 27588c2ecf20Sopenharmony_ci iput(orphan_dir_inode); 27598c2ecf20Sopenharmony_ci 27608c2ecf20Sopenharmony_cibail: 27618c2ecf20Sopenharmony_ci return status; 27628c2ecf20Sopenharmony_ci} 27638c2ecf20Sopenharmony_ci 27648c2ecf20Sopenharmony_ciint ocfs2_mv_orphaned_inode_to_new(struct inode *dir, 27658c2ecf20Sopenharmony_ci struct inode *inode, 27668c2ecf20Sopenharmony_ci struct dentry *dentry) 27678c2ecf20Sopenharmony_ci{ 27688c2ecf20Sopenharmony_ci int status = 0; 27698c2ecf20Sopenharmony_ci struct buffer_head *parent_di_bh = NULL; 27708c2ecf20Sopenharmony_ci handle_t *handle = NULL; 27718c2ecf20Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); 27728c2ecf20Sopenharmony_ci struct ocfs2_dinode *dir_di, *di; 27738c2ecf20Sopenharmony_ci struct inode *orphan_dir_inode = NULL; 27748c2ecf20Sopenharmony_ci struct buffer_head *orphan_dir_bh = NULL; 27758c2ecf20Sopenharmony_ci struct buffer_head *di_bh = NULL; 27768c2ecf20Sopenharmony_ci struct ocfs2_dir_lookup_result lookup = { NULL, }; 27778c2ecf20Sopenharmony_ci 27788c2ecf20Sopenharmony_ci trace_ocfs2_mv_orphaned_inode_to_new(dir, dentry, 27798c2ecf20Sopenharmony_ci dentry->d_name.len, dentry->d_name.name, 27808c2ecf20Sopenharmony_ci (unsigned long long)OCFS2_I(dir)->ip_blkno, 27818c2ecf20Sopenharmony_ci (unsigned long long)OCFS2_I(inode)->ip_blkno); 27828c2ecf20Sopenharmony_ci 27838c2ecf20Sopenharmony_ci status = ocfs2_inode_lock(dir, &parent_di_bh, 1); 27848c2ecf20Sopenharmony_ci if (status < 0) { 27858c2ecf20Sopenharmony_ci if (status != -ENOENT) 27868c2ecf20Sopenharmony_ci mlog_errno(status); 27878c2ecf20Sopenharmony_ci return status; 27888c2ecf20Sopenharmony_ci } 27898c2ecf20Sopenharmony_ci 27908c2ecf20Sopenharmony_ci dir_di = (struct ocfs2_dinode *) parent_di_bh->b_data; 27918c2ecf20Sopenharmony_ci if (!dir_di->i_links_count) { 27928c2ecf20Sopenharmony_ci /* can't make a file in a deleted directory. */ 27938c2ecf20Sopenharmony_ci status = -ENOENT; 27948c2ecf20Sopenharmony_ci goto leave; 27958c2ecf20Sopenharmony_ci } 27968c2ecf20Sopenharmony_ci 27978c2ecf20Sopenharmony_ci status = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, 27988c2ecf20Sopenharmony_ci dentry->d_name.len); 27998c2ecf20Sopenharmony_ci if (status) 28008c2ecf20Sopenharmony_ci goto leave; 28018c2ecf20Sopenharmony_ci 28028c2ecf20Sopenharmony_ci /* get a spot inside the dir. */ 28038c2ecf20Sopenharmony_ci status = ocfs2_prepare_dir_for_insert(osb, dir, parent_di_bh, 28048c2ecf20Sopenharmony_ci dentry->d_name.name, 28058c2ecf20Sopenharmony_ci dentry->d_name.len, &lookup); 28068c2ecf20Sopenharmony_ci if (status < 0) { 28078c2ecf20Sopenharmony_ci mlog_errno(status); 28088c2ecf20Sopenharmony_ci goto leave; 28098c2ecf20Sopenharmony_ci } 28108c2ecf20Sopenharmony_ci 28118c2ecf20Sopenharmony_ci orphan_dir_inode = ocfs2_get_system_file_inode(osb, 28128c2ecf20Sopenharmony_ci ORPHAN_DIR_SYSTEM_INODE, 28138c2ecf20Sopenharmony_ci osb->slot_num); 28148c2ecf20Sopenharmony_ci if (!orphan_dir_inode) { 28158c2ecf20Sopenharmony_ci status = -ENOENT; 28168c2ecf20Sopenharmony_ci mlog_errno(status); 28178c2ecf20Sopenharmony_ci goto leave; 28188c2ecf20Sopenharmony_ci } 28198c2ecf20Sopenharmony_ci 28208c2ecf20Sopenharmony_ci inode_lock(orphan_dir_inode); 28218c2ecf20Sopenharmony_ci 28228c2ecf20Sopenharmony_ci status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1); 28238c2ecf20Sopenharmony_ci if (status < 0) { 28248c2ecf20Sopenharmony_ci mlog_errno(status); 28258c2ecf20Sopenharmony_ci inode_unlock(orphan_dir_inode); 28268c2ecf20Sopenharmony_ci iput(orphan_dir_inode); 28278c2ecf20Sopenharmony_ci goto leave; 28288c2ecf20Sopenharmony_ci } 28298c2ecf20Sopenharmony_ci 28308c2ecf20Sopenharmony_ci status = ocfs2_read_inode_block(inode, &di_bh); 28318c2ecf20Sopenharmony_ci if (status < 0) { 28328c2ecf20Sopenharmony_ci mlog_errno(status); 28338c2ecf20Sopenharmony_ci goto orphan_unlock; 28348c2ecf20Sopenharmony_ci } 28358c2ecf20Sopenharmony_ci 28368c2ecf20Sopenharmony_ci handle = ocfs2_start_trans(osb, ocfs2_rename_credits(osb->sb)); 28378c2ecf20Sopenharmony_ci if (IS_ERR(handle)) { 28388c2ecf20Sopenharmony_ci status = PTR_ERR(handle); 28398c2ecf20Sopenharmony_ci handle = NULL; 28408c2ecf20Sopenharmony_ci mlog_errno(status); 28418c2ecf20Sopenharmony_ci goto orphan_unlock; 28428c2ecf20Sopenharmony_ci } 28438c2ecf20Sopenharmony_ci 28448c2ecf20Sopenharmony_ci status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), 28458c2ecf20Sopenharmony_ci di_bh, OCFS2_JOURNAL_ACCESS_WRITE); 28468c2ecf20Sopenharmony_ci if (status < 0) { 28478c2ecf20Sopenharmony_ci mlog_errno(status); 28488c2ecf20Sopenharmony_ci goto out_commit; 28498c2ecf20Sopenharmony_ci } 28508c2ecf20Sopenharmony_ci 28518c2ecf20Sopenharmony_ci status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode, 28528c2ecf20Sopenharmony_ci orphan_dir_bh, false); 28538c2ecf20Sopenharmony_ci if (status < 0) { 28548c2ecf20Sopenharmony_ci mlog_errno(status); 28558c2ecf20Sopenharmony_ci goto out_commit; 28568c2ecf20Sopenharmony_ci } 28578c2ecf20Sopenharmony_ci 28588c2ecf20Sopenharmony_ci di = (struct ocfs2_dinode *)di_bh->b_data; 28598c2ecf20Sopenharmony_ci di->i_flags &= ~cpu_to_le32(OCFS2_ORPHANED_FL); 28608c2ecf20Sopenharmony_ci di->i_orphaned_slot = 0; 28618c2ecf20Sopenharmony_ci set_nlink(inode, 1); 28628c2ecf20Sopenharmony_ci ocfs2_set_links_count(di, inode->i_nlink); 28638c2ecf20Sopenharmony_ci ocfs2_update_inode_fsync_trans(handle, inode, 1); 28648c2ecf20Sopenharmony_ci ocfs2_journal_dirty(handle, di_bh); 28658c2ecf20Sopenharmony_ci 28668c2ecf20Sopenharmony_ci status = ocfs2_add_entry(handle, dentry, inode, 28678c2ecf20Sopenharmony_ci OCFS2_I(inode)->ip_blkno, parent_di_bh, 28688c2ecf20Sopenharmony_ci &lookup); 28698c2ecf20Sopenharmony_ci if (status < 0) { 28708c2ecf20Sopenharmony_ci mlog_errno(status); 28718c2ecf20Sopenharmony_ci goto out_commit; 28728c2ecf20Sopenharmony_ci } 28738c2ecf20Sopenharmony_ci 28748c2ecf20Sopenharmony_ci status = ocfs2_dentry_attach_lock(dentry, inode, 28758c2ecf20Sopenharmony_ci OCFS2_I(dir)->ip_blkno); 28768c2ecf20Sopenharmony_ci if (status) { 28778c2ecf20Sopenharmony_ci mlog_errno(status); 28788c2ecf20Sopenharmony_ci goto out_commit; 28798c2ecf20Sopenharmony_ci } 28808c2ecf20Sopenharmony_ci 28818c2ecf20Sopenharmony_ci d_instantiate(dentry, inode); 28828c2ecf20Sopenharmony_ci status = 0; 28838c2ecf20Sopenharmony_ciout_commit: 28848c2ecf20Sopenharmony_ci ocfs2_commit_trans(osb, handle); 28858c2ecf20Sopenharmony_ciorphan_unlock: 28868c2ecf20Sopenharmony_ci ocfs2_inode_unlock(orphan_dir_inode, 1); 28878c2ecf20Sopenharmony_ci inode_unlock(orphan_dir_inode); 28888c2ecf20Sopenharmony_ci iput(orphan_dir_inode); 28898c2ecf20Sopenharmony_cileave: 28908c2ecf20Sopenharmony_ci 28918c2ecf20Sopenharmony_ci ocfs2_inode_unlock(dir, 1); 28928c2ecf20Sopenharmony_ci 28938c2ecf20Sopenharmony_ci brelse(di_bh); 28948c2ecf20Sopenharmony_ci brelse(parent_di_bh); 28958c2ecf20Sopenharmony_ci brelse(orphan_dir_bh); 28968c2ecf20Sopenharmony_ci 28978c2ecf20Sopenharmony_ci ocfs2_free_dir_lookup_result(&lookup); 28988c2ecf20Sopenharmony_ci 28998c2ecf20Sopenharmony_ci if (status) 29008c2ecf20Sopenharmony_ci mlog_errno(status); 29018c2ecf20Sopenharmony_ci 29028c2ecf20Sopenharmony_ci return status; 29038c2ecf20Sopenharmony_ci} 29048c2ecf20Sopenharmony_ci 29058c2ecf20Sopenharmony_ciconst struct inode_operations ocfs2_dir_iops = { 29068c2ecf20Sopenharmony_ci .create = ocfs2_create, 29078c2ecf20Sopenharmony_ci .lookup = ocfs2_lookup, 29088c2ecf20Sopenharmony_ci .link = ocfs2_link, 29098c2ecf20Sopenharmony_ci .unlink = ocfs2_unlink, 29108c2ecf20Sopenharmony_ci .rmdir = ocfs2_unlink, 29118c2ecf20Sopenharmony_ci .symlink = ocfs2_symlink, 29128c2ecf20Sopenharmony_ci .mkdir = ocfs2_mkdir, 29138c2ecf20Sopenharmony_ci .mknod = ocfs2_mknod, 29148c2ecf20Sopenharmony_ci .rename = ocfs2_rename, 29158c2ecf20Sopenharmony_ci .setattr = ocfs2_setattr, 29168c2ecf20Sopenharmony_ci .getattr = ocfs2_getattr, 29178c2ecf20Sopenharmony_ci .permission = ocfs2_permission, 29188c2ecf20Sopenharmony_ci .listxattr = ocfs2_listxattr, 29198c2ecf20Sopenharmony_ci .fiemap = ocfs2_fiemap, 29208c2ecf20Sopenharmony_ci .get_acl = ocfs2_iop_get_acl, 29218c2ecf20Sopenharmony_ci .set_acl = ocfs2_iop_set_acl, 29228c2ecf20Sopenharmony_ci}; 2923