162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * namei.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Create and rename file, directory, symlinks 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2002, 2004 Oracle. All rights reserved. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Portions of this code from linux/fs/ext3/dir.c 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Copyright (C) 1992, 1993, 1994, 1995 1262306a36Sopenharmony_ci * Remy Card (card@masi.ibp.fr) 1362306a36Sopenharmony_ci * Laboratoire MASI - Institut Blaise pascal 1462306a36Sopenharmony_ci * Universite Pierre et Marie Curie (Paris VI) 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * from 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * linux/fs/minix/dir.c 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * Copyright (C) 1991, 1992 Linux Torvalds 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include <linux/fs.h> 2462306a36Sopenharmony_ci#include <linux/types.h> 2562306a36Sopenharmony_ci#include <linux/slab.h> 2662306a36Sopenharmony_ci#include <linux/highmem.h> 2762306a36Sopenharmony_ci#include <linux/quotaops.h> 2862306a36Sopenharmony_ci#include <linux/iversion.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#include <cluster/masklog.h> 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#include "ocfs2.h" 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#include "alloc.h" 3562306a36Sopenharmony_ci#include "dcache.h" 3662306a36Sopenharmony_ci#include "dir.h" 3762306a36Sopenharmony_ci#include "dlmglue.h" 3862306a36Sopenharmony_ci#include "extent_map.h" 3962306a36Sopenharmony_ci#include "file.h" 4062306a36Sopenharmony_ci#include "inode.h" 4162306a36Sopenharmony_ci#include "journal.h" 4262306a36Sopenharmony_ci#include "namei.h" 4362306a36Sopenharmony_ci#include "suballoc.h" 4462306a36Sopenharmony_ci#include "super.h" 4562306a36Sopenharmony_ci#include "symlink.h" 4662306a36Sopenharmony_ci#include "sysfile.h" 4762306a36Sopenharmony_ci#include "uptodate.h" 4862306a36Sopenharmony_ci#include "xattr.h" 4962306a36Sopenharmony_ci#include "acl.h" 5062306a36Sopenharmony_ci#include "ocfs2_trace.h" 5162306a36Sopenharmony_ci#include "ioctl.h" 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#include "buffer_head_io.h" 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic int ocfs2_mknod_locked(struct ocfs2_super *osb, 5662306a36Sopenharmony_ci struct inode *dir, 5762306a36Sopenharmony_ci struct inode *inode, 5862306a36Sopenharmony_ci dev_t dev, 5962306a36Sopenharmony_ci struct buffer_head **new_fe_bh, 6062306a36Sopenharmony_ci struct buffer_head *parent_fe_bh, 6162306a36Sopenharmony_ci handle_t *handle, 6262306a36Sopenharmony_ci struct ocfs2_alloc_context *inode_ac); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, 6562306a36Sopenharmony_ci struct inode **ret_orphan_dir, 6662306a36Sopenharmony_ci u64 blkno, 6762306a36Sopenharmony_ci char *name, 6862306a36Sopenharmony_ci struct ocfs2_dir_lookup_result *lookup, 6962306a36Sopenharmony_ci bool dio); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic int ocfs2_orphan_add(struct ocfs2_super *osb, 7262306a36Sopenharmony_ci handle_t *handle, 7362306a36Sopenharmony_ci struct inode *inode, 7462306a36Sopenharmony_ci struct buffer_head *fe_bh, 7562306a36Sopenharmony_ci char *name, 7662306a36Sopenharmony_ci struct ocfs2_dir_lookup_result *lookup, 7762306a36Sopenharmony_ci struct inode *orphan_dir_inode, 7862306a36Sopenharmony_ci bool dio); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic int ocfs2_create_symlink_data(struct ocfs2_super *osb, 8162306a36Sopenharmony_ci handle_t *handle, 8262306a36Sopenharmony_ci struct inode *inode, 8362306a36Sopenharmony_ci const char *symname); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic int ocfs2_double_lock(struct ocfs2_super *osb, 8662306a36Sopenharmony_ci struct buffer_head **bh1, 8762306a36Sopenharmony_ci struct inode *inode1, 8862306a36Sopenharmony_ci struct buffer_head **bh2, 8962306a36Sopenharmony_ci struct inode *inode2, 9062306a36Sopenharmony_ci int rename); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2); 9362306a36Sopenharmony_ci/* An orphan dir name is an 8 byte value, printed as a hex string */ 9462306a36Sopenharmony_ci#define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistatic struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, 9762306a36Sopenharmony_ci unsigned int flags) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci int status; 10062306a36Sopenharmony_ci u64 blkno; 10162306a36Sopenharmony_ci struct inode *inode = NULL; 10262306a36Sopenharmony_ci struct dentry *ret; 10362306a36Sopenharmony_ci struct ocfs2_inode_info *oi; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci trace_ocfs2_lookup(dir, dentry, dentry->d_name.len, 10662306a36Sopenharmony_ci dentry->d_name.name, 10762306a36Sopenharmony_ci (unsigned long long)OCFS2_I(dir)->ip_blkno, 0); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if (dentry->d_name.len > OCFS2_MAX_FILENAME_LEN) { 11062306a36Sopenharmony_ci ret = ERR_PTR(-ENAMETOOLONG); 11162306a36Sopenharmony_ci goto bail; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci status = ocfs2_inode_lock_nested(dir, NULL, 0, OI_LS_PARENT); 11562306a36Sopenharmony_ci if (status < 0) { 11662306a36Sopenharmony_ci if (status != -ENOENT) 11762306a36Sopenharmony_ci mlog_errno(status); 11862306a36Sopenharmony_ci ret = ERR_PTR(status); 11962306a36Sopenharmony_ci goto bail; 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci status = ocfs2_lookup_ino_from_name(dir, dentry->d_name.name, 12362306a36Sopenharmony_ci dentry->d_name.len, &blkno); 12462306a36Sopenharmony_ci if (status < 0) 12562306a36Sopenharmony_ci goto bail_add; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno, 0, 0); 12862306a36Sopenharmony_ci if (IS_ERR(inode)) { 12962306a36Sopenharmony_ci ret = ERR_PTR(-EACCES); 13062306a36Sopenharmony_ci goto bail_unlock; 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci oi = OCFS2_I(inode); 13462306a36Sopenharmony_ci /* Clear any orphaned state... If we were able to look up the 13562306a36Sopenharmony_ci * inode from a directory, it certainly can't be orphaned. We 13662306a36Sopenharmony_ci * might have the bad state from a node which intended to 13762306a36Sopenharmony_ci * orphan this inode but crashed before it could commit the 13862306a36Sopenharmony_ci * unlink. */ 13962306a36Sopenharmony_ci spin_lock(&oi->ip_lock); 14062306a36Sopenharmony_ci oi->ip_flags &= ~OCFS2_INODE_MAYBE_ORPHANED; 14162306a36Sopenharmony_ci spin_unlock(&oi->ip_lock); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cibail_add: 14462306a36Sopenharmony_ci ret = d_splice_alias(inode, dentry); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci if (inode) { 14762306a36Sopenharmony_ci /* 14862306a36Sopenharmony_ci * If d_splice_alias() finds a DCACHE_DISCONNECTED 14962306a36Sopenharmony_ci * dentry, it will d_move() it on top of ourse. The 15062306a36Sopenharmony_ci * return value will indicate this however, so in 15162306a36Sopenharmony_ci * those cases, we switch them around for the locking 15262306a36Sopenharmony_ci * code. 15362306a36Sopenharmony_ci * 15462306a36Sopenharmony_ci * NOTE: This dentry already has ->d_op set from 15562306a36Sopenharmony_ci * ocfs2_get_parent() and ocfs2_get_dentry() 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_ci if (!IS_ERR_OR_NULL(ret)) 15862306a36Sopenharmony_ci dentry = ret; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci status = ocfs2_dentry_attach_lock(dentry, inode, 16162306a36Sopenharmony_ci OCFS2_I(dir)->ip_blkno); 16262306a36Sopenharmony_ci if (status) { 16362306a36Sopenharmony_ci mlog_errno(status); 16462306a36Sopenharmony_ci ret = ERR_PTR(status); 16562306a36Sopenharmony_ci goto bail_unlock; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci } else 16862306a36Sopenharmony_ci ocfs2_dentry_attach_gen(dentry); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cibail_unlock: 17162306a36Sopenharmony_ci /* Don't drop the cluster lock until *after* the d_add -- 17262306a36Sopenharmony_ci * unlink on another node will message us to remove that 17362306a36Sopenharmony_ci * dentry under this lock so otherwise we can race this with 17462306a36Sopenharmony_ci * the downconvert thread and have a stale dentry. */ 17562306a36Sopenharmony_ci ocfs2_inode_unlock(dir, 0); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cibail: 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci trace_ocfs2_lookup_ret(ret); 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci return ret; 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic struct inode *ocfs2_get_init_inode(struct inode *dir, umode_t mode) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci struct inode *inode; 18762306a36Sopenharmony_ci int status; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci inode = new_inode(dir->i_sb); 19062306a36Sopenharmony_ci if (!inode) { 19162306a36Sopenharmony_ci mlog(ML_ERROR, "new_inode failed!\n"); 19262306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 19362306a36Sopenharmony_ci } 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci /* populate as many fields early on as possible - many of 19662306a36Sopenharmony_ci * these are used by the support functions here and in 19762306a36Sopenharmony_ci * callers. */ 19862306a36Sopenharmony_ci if (S_ISDIR(mode)) 19962306a36Sopenharmony_ci set_nlink(inode, 2); 20062306a36Sopenharmony_ci mode = mode_strip_sgid(&nop_mnt_idmap, dir, mode); 20162306a36Sopenharmony_ci inode_init_owner(&nop_mnt_idmap, inode, dir, mode); 20262306a36Sopenharmony_ci status = dquot_initialize(inode); 20362306a36Sopenharmony_ci if (status) 20462306a36Sopenharmony_ci return ERR_PTR(status); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci return inode; 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic void ocfs2_cleanup_add_entry_failure(struct ocfs2_super *osb, 21062306a36Sopenharmony_ci struct dentry *dentry, struct inode *inode) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci struct ocfs2_dentry_lock *dl = dentry->d_fsdata; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); 21562306a36Sopenharmony_ci ocfs2_lock_res_free(&dl->dl_lockres); 21662306a36Sopenharmony_ci BUG_ON(dl->dl_count != 1); 21762306a36Sopenharmony_ci spin_lock(&dentry_attach_lock); 21862306a36Sopenharmony_ci dentry->d_fsdata = NULL; 21962306a36Sopenharmony_ci spin_unlock(&dentry_attach_lock); 22062306a36Sopenharmony_ci kfree(dl); 22162306a36Sopenharmony_ci iput(inode); 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic int ocfs2_mknod(struct mnt_idmap *idmap, 22562306a36Sopenharmony_ci struct inode *dir, 22662306a36Sopenharmony_ci struct dentry *dentry, 22762306a36Sopenharmony_ci umode_t mode, 22862306a36Sopenharmony_ci dev_t dev) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci int status = 0; 23162306a36Sopenharmony_ci struct buffer_head *parent_fe_bh = NULL; 23262306a36Sopenharmony_ci handle_t *handle = NULL; 23362306a36Sopenharmony_ci struct ocfs2_super *osb; 23462306a36Sopenharmony_ci struct ocfs2_dinode *dirfe; 23562306a36Sopenharmony_ci struct ocfs2_dinode *fe = NULL; 23662306a36Sopenharmony_ci struct buffer_head *new_fe_bh = NULL; 23762306a36Sopenharmony_ci struct inode *inode = NULL; 23862306a36Sopenharmony_ci struct ocfs2_alloc_context *inode_ac = NULL; 23962306a36Sopenharmony_ci struct ocfs2_alloc_context *data_ac = NULL; 24062306a36Sopenharmony_ci struct ocfs2_alloc_context *meta_ac = NULL; 24162306a36Sopenharmony_ci int want_clusters = 0; 24262306a36Sopenharmony_ci int want_meta = 0; 24362306a36Sopenharmony_ci int xattr_credits = 0; 24462306a36Sopenharmony_ci struct ocfs2_security_xattr_info si = { 24562306a36Sopenharmony_ci .name = NULL, 24662306a36Sopenharmony_ci .enable = 1, 24762306a36Sopenharmony_ci }; 24862306a36Sopenharmony_ci int did_quota_inode = 0; 24962306a36Sopenharmony_ci struct ocfs2_dir_lookup_result lookup = { NULL, }; 25062306a36Sopenharmony_ci sigset_t oldset; 25162306a36Sopenharmony_ci int did_block_signals = 0; 25262306a36Sopenharmony_ci struct ocfs2_dentry_lock *dl = NULL; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci trace_ocfs2_mknod(dir, dentry, dentry->d_name.len, dentry->d_name.name, 25562306a36Sopenharmony_ci (unsigned long long)OCFS2_I(dir)->ip_blkno, 25662306a36Sopenharmony_ci (unsigned long)dev, mode); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci status = dquot_initialize(dir); 25962306a36Sopenharmony_ci if (status) { 26062306a36Sopenharmony_ci mlog_errno(status); 26162306a36Sopenharmony_ci return status; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci /* get our super block */ 26562306a36Sopenharmony_ci osb = OCFS2_SB(dir->i_sb); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci status = ocfs2_inode_lock(dir, &parent_fe_bh, 1); 26862306a36Sopenharmony_ci if (status < 0) { 26962306a36Sopenharmony_ci if (status != -ENOENT) 27062306a36Sopenharmony_ci mlog_errno(status); 27162306a36Sopenharmony_ci return status; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci if (S_ISDIR(mode) && (dir->i_nlink >= ocfs2_link_max(osb))) { 27562306a36Sopenharmony_ci status = -EMLINK; 27662306a36Sopenharmony_ci goto leave; 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; 28062306a36Sopenharmony_ci if (!ocfs2_read_links_count(dirfe)) { 28162306a36Sopenharmony_ci /* can't make a file in a deleted directory. */ 28262306a36Sopenharmony_ci status = -ENOENT; 28362306a36Sopenharmony_ci goto leave; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci status = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, 28762306a36Sopenharmony_ci dentry->d_name.len); 28862306a36Sopenharmony_ci if (status) 28962306a36Sopenharmony_ci goto leave; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci /* get a spot inside the dir. */ 29262306a36Sopenharmony_ci status = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh, 29362306a36Sopenharmony_ci dentry->d_name.name, 29462306a36Sopenharmony_ci dentry->d_name.len, &lookup); 29562306a36Sopenharmony_ci if (status < 0) { 29662306a36Sopenharmony_ci mlog_errno(status); 29762306a36Sopenharmony_ci goto leave; 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci /* reserve an inode spot */ 30162306a36Sopenharmony_ci status = ocfs2_reserve_new_inode(osb, &inode_ac); 30262306a36Sopenharmony_ci if (status < 0) { 30362306a36Sopenharmony_ci if (status != -ENOSPC) 30462306a36Sopenharmony_ci mlog_errno(status); 30562306a36Sopenharmony_ci goto leave; 30662306a36Sopenharmony_ci } 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci inode = ocfs2_get_init_inode(dir, mode); 30962306a36Sopenharmony_ci if (IS_ERR(inode)) { 31062306a36Sopenharmony_ci status = PTR_ERR(inode); 31162306a36Sopenharmony_ci inode = NULL; 31262306a36Sopenharmony_ci mlog_errno(status); 31362306a36Sopenharmony_ci goto leave; 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* get security xattr */ 31762306a36Sopenharmony_ci status = ocfs2_init_security_get(inode, dir, &dentry->d_name, &si); 31862306a36Sopenharmony_ci if (status) { 31962306a36Sopenharmony_ci if (status == -EOPNOTSUPP) 32062306a36Sopenharmony_ci si.enable = 0; 32162306a36Sopenharmony_ci else { 32262306a36Sopenharmony_ci mlog_errno(status); 32362306a36Sopenharmony_ci goto leave; 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci /* calculate meta data/clusters for setting security and acl xattr */ 32862306a36Sopenharmony_ci status = ocfs2_calc_xattr_init(dir, parent_fe_bh, mode, 32962306a36Sopenharmony_ci &si, &want_clusters, 33062306a36Sopenharmony_ci &xattr_credits, &want_meta); 33162306a36Sopenharmony_ci if (status < 0) { 33262306a36Sopenharmony_ci mlog_errno(status); 33362306a36Sopenharmony_ci goto leave; 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci /* Reserve a cluster if creating an extent based directory. */ 33762306a36Sopenharmony_ci if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) { 33862306a36Sopenharmony_ci want_clusters += 1; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci /* Dir indexing requires extra space as well */ 34162306a36Sopenharmony_ci if (ocfs2_supports_indexed_dirs(osb)) 34262306a36Sopenharmony_ci want_meta++; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci status = ocfs2_reserve_new_metadata_blocks(osb, want_meta, &meta_ac); 34662306a36Sopenharmony_ci if (status < 0) { 34762306a36Sopenharmony_ci if (status != -ENOSPC) 34862306a36Sopenharmony_ci mlog_errno(status); 34962306a36Sopenharmony_ci goto leave; 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci status = ocfs2_reserve_clusters(osb, want_clusters, &data_ac); 35362306a36Sopenharmony_ci if (status < 0) { 35462306a36Sopenharmony_ci if (status != -ENOSPC) 35562306a36Sopenharmony_ci mlog_errno(status); 35662306a36Sopenharmony_ci goto leave; 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb, 36062306a36Sopenharmony_ci S_ISDIR(mode), 36162306a36Sopenharmony_ci xattr_credits)); 36262306a36Sopenharmony_ci if (IS_ERR(handle)) { 36362306a36Sopenharmony_ci status = PTR_ERR(handle); 36462306a36Sopenharmony_ci handle = NULL; 36562306a36Sopenharmony_ci mlog_errno(status); 36662306a36Sopenharmony_ci goto leave; 36762306a36Sopenharmony_ci } 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci /* Starting to change things, restart is no longer possible. */ 37062306a36Sopenharmony_ci ocfs2_block_signals(&oldset); 37162306a36Sopenharmony_ci did_block_signals = 1; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci status = dquot_alloc_inode(inode); 37462306a36Sopenharmony_ci if (status) 37562306a36Sopenharmony_ci goto leave; 37662306a36Sopenharmony_ci did_quota_inode = 1; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci /* do the real work now. */ 37962306a36Sopenharmony_ci status = ocfs2_mknod_locked(osb, dir, inode, dev, 38062306a36Sopenharmony_ci &new_fe_bh, parent_fe_bh, handle, 38162306a36Sopenharmony_ci inode_ac); 38262306a36Sopenharmony_ci if (status < 0) { 38362306a36Sopenharmony_ci mlog_errno(status); 38462306a36Sopenharmony_ci goto leave; 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci fe = (struct ocfs2_dinode *) new_fe_bh->b_data; 38862306a36Sopenharmony_ci if (S_ISDIR(mode)) { 38962306a36Sopenharmony_ci status = ocfs2_fill_new_dir(osb, handle, dir, inode, 39062306a36Sopenharmony_ci new_fe_bh, data_ac, meta_ac); 39162306a36Sopenharmony_ci if (status < 0) { 39262306a36Sopenharmony_ci mlog_errno(status); 39362306a36Sopenharmony_ci goto leave; 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci status = ocfs2_journal_access_di(handle, INODE_CACHE(dir), 39762306a36Sopenharmony_ci parent_fe_bh, 39862306a36Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 39962306a36Sopenharmony_ci if (status < 0) { 40062306a36Sopenharmony_ci mlog_errno(status); 40162306a36Sopenharmony_ci goto leave; 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci ocfs2_add_links_count(dirfe, 1); 40462306a36Sopenharmony_ci ocfs2_journal_dirty(handle, parent_fe_bh); 40562306a36Sopenharmony_ci inc_nlink(dir); 40662306a36Sopenharmony_ci } 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci status = ocfs2_init_acl(handle, inode, dir, new_fe_bh, parent_fe_bh, 40962306a36Sopenharmony_ci meta_ac, data_ac); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci if (status < 0) { 41262306a36Sopenharmony_ci mlog_errno(status); 41362306a36Sopenharmony_ci goto roll_back; 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci if (si.enable) { 41762306a36Sopenharmony_ci status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si, 41862306a36Sopenharmony_ci meta_ac, data_ac); 41962306a36Sopenharmony_ci if (status < 0) { 42062306a36Sopenharmony_ci mlog_errno(status); 42162306a36Sopenharmony_ci goto roll_back; 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci /* 42662306a36Sopenharmony_ci * Do this before adding the entry to the directory. We add 42762306a36Sopenharmony_ci * also set d_op after success so that ->d_iput() will cleanup 42862306a36Sopenharmony_ci * the dentry lock even if ocfs2_add_entry() fails below. 42962306a36Sopenharmony_ci */ 43062306a36Sopenharmony_ci status = ocfs2_dentry_attach_lock(dentry, inode, 43162306a36Sopenharmony_ci OCFS2_I(dir)->ip_blkno); 43262306a36Sopenharmony_ci if (status) { 43362306a36Sopenharmony_ci mlog_errno(status); 43462306a36Sopenharmony_ci goto roll_back; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci dl = dentry->d_fsdata; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci status = ocfs2_add_entry(handle, dentry, inode, 44062306a36Sopenharmony_ci OCFS2_I(inode)->ip_blkno, parent_fe_bh, 44162306a36Sopenharmony_ci &lookup); 44262306a36Sopenharmony_ci if (status < 0) { 44362306a36Sopenharmony_ci mlog_errno(status); 44462306a36Sopenharmony_ci goto roll_back; 44562306a36Sopenharmony_ci } 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci insert_inode_hash(inode); 44862306a36Sopenharmony_ci d_instantiate(dentry, inode); 44962306a36Sopenharmony_ci status = 0; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ciroll_back: 45262306a36Sopenharmony_ci if (status < 0 && S_ISDIR(mode)) { 45362306a36Sopenharmony_ci ocfs2_add_links_count(dirfe, -1); 45462306a36Sopenharmony_ci drop_nlink(dir); 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_cileave: 45862306a36Sopenharmony_ci if (status < 0 && did_quota_inode) 45962306a36Sopenharmony_ci dquot_free_inode(inode); 46062306a36Sopenharmony_ci if (handle) { 46162306a36Sopenharmony_ci if (status < 0 && fe) 46262306a36Sopenharmony_ci ocfs2_set_links_count(fe, 0); 46362306a36Sopenharmony_ci ocfs2_commit_trans(osb, handle); 46462306a36Sopenharmony_ci } 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci ocfs2_inode_unlock(dir, 1); 46762306a36Sopenharmony_ci if (did_block_signals) 46862306a36Sopenharmony_ci ocfs2_unblock_signals(&oldset); 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci brelse(new_fe_bh); 47162306a36Sopenharmony_ci brelse(parent_fe_bh); 47262306a36Sopenharmony_ci kfree(si.value); 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci ocfs2_free_dir_lookup_result(&lookup); 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci if (inode_ac) 47762306a36Sopenharmony_ci ocfs2_free_alloc_context(inode_ac); 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci if (data_ac) 48062306a36Sopenharmony_ci ocfs2_free_alloc_context(data_ac); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci if (meta_ac) 48362306a36Sopenharmony_ci ocfs2_free_alloc_context(meta_ac); 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci /* 48662306a36Sopenharmony_ci * We should call iput after the i_rwsem of the bitmap been 48762306a36Sopenharmony_ci * unlocked in ocfs2_free_alloc_context, or the 48862306a36Sopenharmony_ci * ocfs2_delete_inode will mutex_lock again. 48962306a36Sopenharmony_ci */ 49062306a36Sopenharmony_ci if ((status < 0) && inode) { 49162306a36Sopenharmony_ci if (dl) 49262306a36Sopenharmony_ci ocfs2_cleanup_add_entry_failure(osb, dentry, inode); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SKIP_ORPHAN_DIR; 49562306a36Sopenharmony_ci clear_nlink(inode); 49662306a36Sopenharmony_ci iput(inode); 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci if (status) 50062306a36Sopenharmony_ci mlog_errno(status); 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci return status; 50362306a36Sopenharmony_ci} 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_cistatic int __ocfs2_mknod_locked(struct inode *dir, 50662306a36Sopenharmony_ci struct inode *inode, 50762306a36Sopenharmony_ci dev_t dev, 50862306a36Sopenharmony_ci struct buffer_head **new_fe_bh, 50962306a36Sopenharmony_ci struct buffer_head *parent_fe_bh, 51062306a36Sopenharmony_ci handle_t *handle, 51162306a36Sopenharmony_ci struct ocfs2_alloc_context *inode_ac, 51262306a36Sopenharmony_ci u64 fe_blkno, u64 suballoc_loc, u16 suballoc_bit) 51362306a36Sopenharmony_ci{ 51462306a36Sopenharmony_ci int status = 0; 51562306a36Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); 51662306a36Sopenharmony_ci struct ocfs2_dinode *fe = NULL; 51762306a36Sopenharmony_ci struct ocfs2_extent_list *fel; 51862306a36Sopenharmony_ci u16 feat; 51962306a36Sopenharmony_ci struct ocfs2_inode_info *oi = OCFS2_I(inode); 52062306a36Sopenharmony_ci struct timespec64 ts; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci *new_fe_bh = NULL; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci /* populate as many fields early on as possible - many of 52562306a36Sopenharmony_ci * these are used by the support functions here and in 52662306a36Sopenharmony_ci * callers. */ 52762306a36Sopenharmony_ci inode->i_ino = ino_from_blkno(osb->sb, fe_blkno); 52862306a36Sopenharmony_ci oi->ip_blkno = fe_blkno; 52962306a36Sopenharmony_ci spin_lock(&osb->osb_lock); 53062306a36Sopenharmony_ci inode->i_generation = osb->s_next_generation++; 53162306a36Sopenharmony_ci spin_unlock(&osb->osb_lock); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci *new_fe_bh = sb_getblk(osb->sb, fe_blkno); 53462306a36Sopenharmony_ci if (!*new_fe_bh) { 53562306a36Sopenharmony_ci status = -ENOMEM; 53662306a36Sopenharmony_ci mlog_errno(status); 53762306a36Sopenharmony_ci goto leave; 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci ocfs2_set_new_buffer_uptodate(INODE_CACHE(inode), *new_fe_bh); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), 54262306a36Sopenharmony_ci *new_fe_bh, 54362306a36Sopenharmony_ci OCFS2_JOURNAL_ACCESS_CREATE); 54462306a36Sopenharmony_ci if (status < 0) { 54562306a36Sopenharmony_ci mlog_errno(status); 54662306a36Sopenharmony_ci goto leave; 54762306a36Sopenharmony_ci } 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci fe = (struct ocfs2_dinode *) (*new_fe_bh)->b_data; 55062306a36Sopenharmony_ci memset(fe, 0, osb->sb->s_blocksize); 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci fe->i_generation = cpu_to_le32(inode->i_generation); 55362306a36Sopenharmony_ci fe->i_fs_generation = cpu_to_le32(osb->fs_generation); 55462306a36Sopenharmony_ci fe->i_blkno = cpu_to_le64(fe_blkno); 55562306a36Sopenharmony_ci fe->i_suballoc_loc = cpu_to_le64(suballoc_loc); 55662306a36Sopenharmony_ci fe->i_suballoc_bit = cpu_to_le16(suballoc_bit); 55762306a36Sopenharmony_ci fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot); 55862306a36Sopenharmony_ci fe->i_uid = cpu_to_le32(i_uid_read(inode)); 55962306a36Sopenharmony_ci fe->i_gid = cpu_to_le32(i_gid_read(inode)); 56062306a36Sopenharmony_ci fe->i_mode = cpu_to_le16(inode->i_mode); 56162306a36Sopenharmony_ci if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) 56262306a36Sopenharmony_ci fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev)); 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci ocfs2_set_links_count(fe, inode->i_nlink); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci fe->i_last_eb_blk = 0; 56762306a36Sopenharmony_ci strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE); 56862306a36Sopenharmony_ci fe->i_flags |= cpu_to_le32(OCFS2_VALID_FL); 56962306a36Sopenharmony_ci ktime_get_real_ts64(&ts); 57062306a36Sopenharmony_ci fe->i_atime = fe->i_ctime = fe->i_mtime = 57162306a36Sopenharmony_ci cpu_to_le64(ts.tv_sec); 57262306a36Sopenharmony_ci fe->i_mtime_nsec = fe->i_ctime_nsec = fe->i_atime_nsec = 57362306a36Sopenharmony_ci cpu_to_le32(ts.tv_nsec); 57462306a36Sopenharmony_ci fe->i_dtime = 0; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci /* 57762306a36Sopenharmony_ci * If supported, directories start with inline data. If inline 57862306a36Sopenharmony_ci * isn't supported, but indexing is, we start them as indexed. 57962306a36Sopenharmony_ci */ 58062306a36Sopenharmony_ci feat = le16_to_cpu(fe->i_dyn_features); 58162306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode) && ocfs2_supports_inline_data(osb)) { 58262306a36Sopenharmony_ci fe->i_dyn_features = cpu_to_le16(feat | OCFS2_INLINE_DATA_FL); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci fe->id2.i_data.id_count = cpu_to_le16( 58562306a36Sopenharmony_ci ocfs2_max_inline_data_with_xattr(osb->sb, fe)); 58662306a36Sopenharmony_ci } else { 58762306a36Sopenharmony_ci fel = &fe->id2.i_list; 58862306a36Sopenharmony_ci fel->l_tree_depth = 0; 58962306a36Sopenharmony_ci fel->l_next_free_rec = 0; 59062306a36Sopenharmony_ci fel->l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(osb->sb)); 59162306a36Sopenharmony_ci } 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci ocfs2_journal_dirty(handle, *new_fe_bh); 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci ocfs2_populate_inode(inode, fe, 1); 59662306a36Sopenharmony_ci ocfs2_ci_set_new(osb, INODE_CACHE(inode)); 59762306a36Sopenharmony_ci if (!ocfs2_mount_local(osb)) { 59862306a36Sopenharmony_ci status = ocfs2_create_new_inode_locks(inode); 59962306a36Sopenharmony_ci if (status < 0) 60062306a36Sopenharmony_ci mlog_errno(status); 60162306a36Sopenharmony_ci } 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci ocfs2_update_inode_fsync_trans(handle, inode, 1); 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_cileave: 60662306a36Sopenharmony_ci if (status < 0) { 60762306a36Sopenharmony_ci if (*new_fe_bh) { 60862306a36Sopenharmony_ci brelse(*new_fe_bh); 60962306a36Sopenharmony_ci *new_fe_bh = NULL; 61062306a36Sopenharmony_ci } 61162306a36Sopenharmony_ci } 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci if (status) 61462306a36Sopenharmony_ci mlog_errno(status); 61562306a36Sopenharmony_ci return status; 61662306a36Sopenharmony_ci} 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_cistatic int ocfs2_mknod_locked(struct ocfs2_super *osb, 61962306a36Sopenharmony_ci struct inode *dir, 62062306a36Sopenharmony_ci struct inode *inode, 62162306a36Sopenharmony_ci dev_t dev, 62262306a36Sopenharmony_ci struct buffer_head **new_fe_bh, 62362306a36Sopenharmony_ci struct buffer_head *parent_fe_bh, 62462306a36Sopenharmony_ci handle_t *handle, 62562306a36Sopenharmony_ci struct ocfs2_alloc_context *inode_ac) 62662306a36Sopenharmony_ci{ 62762306a36Sopenharmony_ci int status = 0; 62862306a36Sopenharmony_ci u64 suballoc_loc, fe_blkno = 0; 62962306a36Sopenharmony_ci u16 suballoc_bit; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci *new_fe_bh = NULL; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci status = ocfs2_claim_new_inode(handle, dir, parent_fe_bh, 63462306a36Sopenharmony_ci inode_ac, &suballoc_loc, 63562306a36Sopenharmony_ci &suballoc_bit, &fe_blkno); 63662306a36Sopenharmony_ci if (status < 0) { 63762306a36Sopenharmony_ci mlog_errno(status); 63862306a36Sopenharmony_ci return status; 63962306a36Sopenharmony_ci } 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci return __ocfs2_mknod_locked(dir, inode, dev, new_fe_bh, 64262306a36Sopenharmony_ci parent_fe_bh, handle, inode_ac, 64362306a36Sopenharmony_ci fe_blkno, suballoc_loc, suballoc_bit); 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_cistatic int ocfs2_mkdir(struct mnt_idmap *idmap, 64762306a36Sopenharmony_ci struct inode *dir, 64862306a36Sopenharmony_ci struct dentry *dentry, 64962306a36Sopenharmony_ci umode_t mode) 65062306a36Sopenharmony_ci{ 65162306a36Sopenharmony_ci int ret; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci trace_ocfs2_mkdir(dir, dentry, dentry->d_name.len, dentry->d_name.name, 65462306a36Sopenharmony_ci OCFS2_I(dir)->ip_blkno, mode); 65562306a36Sopenharmony_ci ret = ocfs2_mknod(&nop_mnt_idmap, dir, dentry, mode | S_IFDIR, 0); 65662306a36Sopenharmony_ci if (ret) 65762306a36Sopenharmony_ci mlog_errno(ret); 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci return ret; 66062306a36Sopenharmony_ci} 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_cistatic int ocfs2_create(struct mnt_idmap *idmap, 66362306a36Sopenharmony_ci struct inode *dir, 66462306a36Sopenharmony_ci struct dentry *dentry, 66562306a36Sopenharmony_ci umode_t mode, 66662306a36Sopenharmony_ci bool excl) 66762306a36Sopenharmony_ci{ 66862306a36Sopenharmony_ci int ret; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci trace_ocfs2_create(dir, dentry, dentry->d_name.len, dentry->d_name.name, 67162306a36Sopenharmony_ci (unsigned long long)OCFS2_I(dir)->ip_blkno, mode); 67262306a36Sopenharmony_ci ret = ocfs2_mknod(&nop_mnt_idmap, dir, dentry, mode | S_IFREG, 0); 67362306a36Sopenharmony_ci if (ret) 67462306a36Sopenharmony_ci mlog_errno(ret); 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci return ret; 67762306a36Sopenharmony_ci} 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_cistatic int ocfs2_link(struct dentry *old_dentry, 68062306a36Sopenharmony_ci struct inode *dir, 68162306a36Sopenharmony_ci struct dentry *dentry) 68262306a36Sopenharmony_ci{ 68362306a36Sopenharmony_ci handle_t *handle; 68462306a36Sopenharmony_ci struct inode *inode = d_inode(old_dentry); 68562306a36Sopenharmony_ci struct inode *old_dir = d_inode(old_dentry->d_parent); 68662306a36Sopenharmony_ci int err; 68762306a36Sopenharmony_ci struct buffer_head *fe_bh = NULL; 68862306a36Sopenharmony_ci struct buffer_head *old_dir_bh = NULL; 68962306a36Sopenharmony_ci struct buffer_head *parent_fe_bh = NULL; 69062306a36Sopenharmony_ci struct ocfs2_dinode *fe = NULL; 69162306a36Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); 69262306a36Sopenharmony_ci struct ocfs2_dir_lookup_result lookup = { NULL, }; 69362306a36Sopenharmony_ci sigset_t oldset; 69462306a36Sopenharmony_ci u64 old_de_ino; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci trace_ocfs2_link((unsigned long long)OCFS2_I(inode)->ip_blkno, 69762306a36Sopenharmony_ci old_dentry->d_name.len, old_dentry->d_name.name, 69862306a36Sopenharmony_ci dentry->d_name.len, dentry->d_name.name); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 70162306a36Sopenharmony_ci return -EPERM; 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci err = dquot_initialize(dir); 70462306a36Sopenharmony_ci if (err) { 70562306a36Sopenharmony_ci mlog_errno(err); 70662306a36Sopenharmony_ci return err; 70762306a36Sopenharmony_ci } 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci err = ocfs2_double_lock(osb, &old_dir_bh, old_dir, 71062306a36Sopenharmony_ci &parent_fe_bh, dir, 0); 71162306a36Sopenharmony_ci if (err < 0) { 71262306a36Sopenharmony_ci if (err != -ENOENT) 71362306a36Sopenharmony_ci mlog_errno(err); 71462306a36Sopenharmony_ci return err; 71562306a36Sopenharmony_ci } 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci /* make sure both dirs have bhs 71862306a36Sopenharmony_ci * get an extra ref on old_dir_bh if old==new */ 71962306a36Sopenharmony_ci if (!parent_fe_bh) { 72062306a36Sopenharmony_ci if (old_dir_bh) { 72162306a36Sopenharmony_ci parent_fe_bh = old_dir_bh; 72262306a36Sopenharmony_ci get_bh(parent_fe_bh); 72362306a36Sopenharmony_ci } else { 72462306a36Sopenharmony_ci mlog(ML_ERROR, "%s: no old_dir_bh!\n", osb->uuid_str); 72562306a36Sopenharmony_ci err = -EIO; 72662306a36Sopenharmony_ci goto out; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci if (!dir->i_nlink) { 73162306a36Sopenharmony_ci err = -ENOENT; 73262306a36Sopenharmony_ci goto out; 73362306a36Sopenharmony_ci } 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci err = ocfs2_lookup_ino_from_name(old_dir, old_dentry->d_name.name, 73662306a36Sopenharmony_ci old_dentry->d_name.len, &old_de_ino); 73762306a36Sopenharmony_ci if (err) { 73862306a36Sopenharmony_ci err = -ENOENT; 73962306a36Sopenharmony_ci goto out; 74062306a36Sopenharmony_ci } 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci /* 74362306a36Sopenharmony_ci * Check whether another node removed the source inode while we 74462306a36Sopenharmony_ci * were in the vfs. 74562306a36Sopenharmony_ci */ 74662306a36Sopenharmony_ci if (old_de_ino != OCFS2_I(inode)->ip_blkno) { 74762306a36Sopenharmony_ci err = -ENOENT; 74862306a36Sopenharmony_ci goto out; 74962306a36Sopenharmony_ci } 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, 75262306a36Sopenharmony_ci dentry->d_name.len); 75362306a36Sopenharmony_ci if (err) 75462306a36Sopenharmony_ci goto out; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci err = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh, 75762306a36Sopenharmony_ci dentry->d_name.name, 75862306a36Sopenharmony_ci dentry->d_name.len, &lookup); 75962306a36Sopenharmony_ci if (err < 0) { 76062306a36Sopenharmony_ci mlog_errno(err); 76162306a36Sopenharmony_ci goto out; 76262306a36Sopenharmony_ci } 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci err = ocfs2_inode_lock(inode, &fe_bh, 1); 76562306a36Sopenharmony_ci if (err < 0) { 76662306a36Sopenharmony_ci if (err != -ENOENT) 76762306a36Sopenharmony_ci mlog_errno(err); 76862306a36Sopenharmony_ci goto out; 76962306a36Sopenharmony_ci } 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci fe = (struct ocfs2_dinode *) fe_bh->b_data; 77262306a36Sopenharmony_ci if (ocfs2_read_links_count(fe) >= ocfs2_link_max(osb)) { 77362306a36Sopenharmony_ci err = -EMLINK; 77462306a36Sopenharmony_ci goto out_unlock_inode; 77562306a36Sopenharmony_ci } 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci handle = ocfs2_start_trans(osb, ocfs2_link_credits(osb->sb)); 77862306a36Sopenharmony_ci if (IS_ERR(handle)) { 77962306a36Sopenharmony_ci err = PTR_ERR(handle); 78062306a36Sopenharmony_ci handle = NULL; 78162306a36Sopenharmony_ci mlog_errno(err); 78262306a36Sopenharmony_ci goto out_unlock_inode; 78362306a36Sopenharmony_ci } 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci /* Starting to change things, restart is no longer possible. */ 78662306a36Sopenharmony_ci ocfs2_block_signals(&oldset); 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci err = ocfs2_journal_access_di(handle, INODE_CACHE(inode), fe_bh, 78962306a36Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 79062306a36Sopenharmony_ci if (err < 0) { 79162306a36Sopenharmony_ci mlog_errno(err); 79262306a36Sopenharmony_ci goto out_commit; 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci inc_nlink(inode); 79662306a36Sopenharmony_ci inode_set_ctime_current(inode); 79762306a36Sopenharmony_ci ocfs2_set_links_count(fe, inode->i_nlink); 79862306a36Sopenharmony_ci fe->i_ctime = cpu_to_le64(inode_get_ctime(inode).tv_sec); 79962306a36Sopenharmony_ci fe->i_ctime_nsec = cpu_to_le32(inode_get_ctime(inode).tv_nsec); 80062306a36Sopenharmony_ci ocfs2_journal_dirty(handle, fe_bh); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci err = ocfs2_add_entry(handle, dentry, inode, 80362306a36Sopenharmony_ci OCFS2_I(inode)->ip_blkno, 80462306a36Sopenharmony_ci parent_fe_bh, &lookup); 80562306a36Sopenharmony_ci if (err) { 80662306a36Sopenharmony_ci ocfs2_add_links_count(fe, -1); 80762306a36Sopenharmony_ci drop_nlink(inode); 80862306a36Sopenharmony_ci mlog_errno(err); 80962306a36Sopenharmony_ci goto out_commit; 81062306a36Sopenharmony_ci } 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci err = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno); 81362306a36Sopenharmony_ci if (err) { 81462306a36Sopenharmony_ci mlog_errno(err); 81562306a36Sopenharmony_ci goto out_commit; 81662306a36Sopenharmony_ci } 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci ihold(inode); 81962306a36Sopenharmony_ci d_instantiate(dentry, inode); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ciout_commit: 82262306a36Sopenharmony_ci ocfs2_commit_trans(osb, handle); 82362306a36Sopenharmony_ci ocfs2_unblock_signals(&oldset); 82462306a36Sopenharmony_ciout_unlock_inode: 82562306a36Sopenharmony_ci ocfs2_inode_unlock(inode, 1); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ciout: 82862306a36Sopenharmony_ci ocfs2_double_unlock(old_dir, dir); 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci brelse(fe_bh); 83162306a36Sopenharmony_ci brelse(parent_fe_bh); 83262306a36Sopenharmony_ci brelse(old_dir_bh); 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci ocfs2_free_dir_lookup_result(&lookup); 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci if (err) 83762306a36Sopenharmony_ci mlog_errno(err); 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci return err; 84062306a36Sopenharmony_ci} 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci/* 84362306a36Sopenharmony_ci * Takes and drops an exclusive lock on the given dentry. This will 84462306a36Sopenharmony_ci * force other nodes to drop it. 84562306a36Sopenharmony_ci */ 84662306a36Sopenharmony_cistatic int ocfs2_remote_dentry_delete(struct dentry *dentry) 84762306a36Sopenharmony_ci{ 84862306a36Sopenharmony_ci int ret; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci ret = ocfs2_dentry_lock(dentry, 1); 85162306a36Sopenharmony_ci if (ret) 85262306a36Sopenharmony_ci mlog_errno(ret); 85362306a36Sopenharmony_ci else 85462306a36Sopenharmony_ci ocfs2_dentry_unlock(dentry, 1); 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci return ret; 85762306a36Sopenharmony_ci} 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_cistatic inline int ocfs2_inode_is_unlinkable(struct inode *inode) 86062306a36Sopenharmony_ci{ 86162306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode)) { 86262306a36Sopenharmony_ci if (inode->i_nlink == 2) 86362306a36Sopenharmony_ci return 1; 86462306a36Sopenharmony_ci return 0; 86562306a36Sopenharmony_ci } 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci if (inode->i_nlink == 1) 86862306a36Sopenharmony_ci return 1; 86962306a36Sopenharmony_ci return 0; 87062306a36Sopenharmony_ci} 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_cistatic int ocfs2_unlink(struct inode *dir, 87362306a36Sopenharmony_ci struct dentry *dentry) 87462306a36Sopenharmony_ci{ 87562306a36Sopenharmony_ci int status; 87662306a36Sopenharmony_ci int child_locked = 0; 87762306a36Sopenharmony_ci bool is_unlinkable = false; 87862306a36Sopenharmony_ci struct inode *inode = d_inode(dentry); 87962306a36Sopenharmony_ci struct inode *orphan_dir = NULL; 88062306a36Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); 88162306a36Sopenharmony_ci u64 blkno; 88262306a36Sopenharmony_ci struct ocfs2_dinode *fe = NULL; 88362306a36Sopenharmony_ci struct buffer_head *fe_bh = NULL; 88462306a36Sopenharmony_ci struct buffer_head *parent_node_bh = NULL; 88562306a36Sopenharmony_ci handle_t *handle = NULL; 88662306a36Sopenharmony_ci char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; 88762306a36Sopenharmony_ci struct ocfs2_dir_lookup_result lookup = { NULL, }; 88862306a36Sopenharmony_ci struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci trace_ocfs2_unlink(dir, dentry, dentry->d_name.len, 89162306a36Sopenharmony_ci dentry->d_name.name, 89262306a36Sopenharmony_ci (unsigned long long)OCFS2_I(dir)->ip_blkno, 89362306a36Sopenharmony_ci (unsigned long long)OCFS2_I(inode)->ip_blkno); 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci status = dquot_initialize(dir); 89662306a36Sopenharmony_ci if (status) { 89762306a36Sopenharmony_ci mlog_errno(status); 89862306a36Sopenharmony_ci return status; 89962306a36Sopenharmony_ci } 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci BUG_ON(d_inode(dentry->d_parent) != dir); 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci if (inode == osb->root_inode) 90462306a36Sopenharmony_ci return -EPERM; 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci status = ocfs2_inode_lock_nested(dir, &parent_node_bh, 1, 90762306a36Sopenharmony_ci OI_LS_PARENT); 90862306a36Sopenharmony_ci if (status < 0) { 90962306a36Sopenharmony_ci if (status != -ENOENT) 91062306a36Sopenharmony_ci mlog_errno(status); 91162306a36Sopenharmony_ci return status; 91262306a36Sopenharmony_ci } 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci status = ocfs2_find_files_on_disk(dentry->d_name.name, 91562306a36Sopenharmony_ci dentry->d_name.len, &blkno, dir, 91662306a36Sopenharmony_ci &lookup); 91762306a36Sopenharmony_ci if (status < 0) { 91862306a36Sopenharmony_ci if (status != -ENOENT) 91962306a36Sopenharmony_ci mlog_errno(status); 92062306a36Sopenharmony_ci goto leave; 92162306a36Sopenharmony_ci } 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci if (OCFS2_I(inode)->ip_blkno != blkno) { 92462306a36Sopenharmony_ci status = -ENOENT; 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci trace_ocfs2_unlink_noent( 92762306a36Sopenharmony_ci (unsigned long long)OCFS2_I(inode)->ip_blkno, 92862306a36Sopenharmony_ci (unsigned long long)blkno, 92962306a36Sopenharmony_ci OCFS2_I(inode)->ip_flags); 93062306a36Sopenharmony_ci goto leave; 93162306a36Sopenharmony_ci } 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci status = ocfs2_inode_lock(inode, &fe_bh, 1); 93462306a36Sopenharmony_ci if (status < 0) { 93562306a36Sopenharmony_ci if (status != -ENOENT) 93662306a36Sopenharmony_ci mlog_errno(status); 93762306a36Sopenharmony_ci goto leave; 93862306a36Sopenharmony_ci } 93962306a36Sopenharmony_ci child_locked = 1; 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode)) { 94262306a36Sopenharmony_ci if (inode->i_nlink != 2 || !ocfs2_empty_dir(inode)) { 94362306a36Sopenharmony_ci status = -ENOTEMPTY; 94462306a36Sopenharmony_ci goto leave; 94562306a36Sopenharmony_ci } 94662306a36Sopenharmony_ci } 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci status = ocfs2_remote_dentry_delete(dentry); 94962306a36Sopenharmony_ci if (status < 0) { 95062306a36Sopenharmony_ci /* This remote delete should succeed under all normal 95162306a36Sopenharmony_ci * circumstances. */ 95262306a36Sopenharmony_ci mlog_errno(status); 95362306a36Sopenharmony_ci goto leave; 95462306a36Sopenharmony_ci } 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci if (ocfs2_inode_is_unlinkable(inode)) { 95762306a36Sopenharmony_ci status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, 95862306a36Sopenharmony_ci OCFS2_I(inode)->ip_blkno, 95962306a36Sopenharmony_ci orphan_name, &orphan_insert, 96062306a36Sopenharmony_ci false); 96162306a36Sopenharmony_ci if (status < 0) { 96262306a36Sopenharmony_ci mlog_errno(status); 96362306a36Sopenharmony_ci goto leave; 96462306a36Sopenharmony_ci } 96562306a36Sopenharmony_ci is_unlinkable = true; 96662306a36Sopenharmony_ci } 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci handle = ocfs2_start_trans(osb, ocfs2_unlink_credits(osb->sb)); 96962306a36Sopenharmony_ci if (IS_ERR(handle)) { 97062306a36Sopenharmony_ci status = PTR_ERR(handle); 97162306a36Sopenharmony_ci handle = NULL; 97262306a36Sopenharmony_ci mlog_errno(status); 97362306a36Sopenharmony_ci goto leave; 97462306a36Sopenharmony_ci } 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), fe_bh, 97762306a36Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 97862306a36Sopenharmony_ci if (status < 0) { 97962306a36Sopenharmony_ci mlog_errno(status); 98062306a36Sopenharmony_ci goto leave; 98162306a36Sopenharmony_ci } 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci fe = (struct ocfs2_dinode *) fe_bh->b_data; 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci /* delete the name from the parent dir */ 98662306a36Sopenharmony_ci status = ocfs2_delete_entry(handle, dir, &lookup); 98762306a36Sopenharmony_ci if (status < 0) { 98862306a36Sopenharmony_ci mlog_errno(status); 98962306a36Sopenharmony_ci goto leave; 99062306a36Sopenharmony_ci } 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 99362306a36Sopenharmony_ci drop_nlink(inode); 99462306a36Sopenharmony_ci drop_nlink(inode); 99562306a36Sopenharmony_ci ocfs2_set_links_count(fe, inode->i_nlink); 99662306a36Sopenharmony_ci ocfs2_journal_dirty(handle, fe_bh); 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci dir->i_mtime = inode_set_ctime_current(dir); 99962306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 100062306a36Sopenharmony_ci drop_nlink(dir); 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci status = ocfs2_mark_inode_dirty(handle, dir, parent_node_bh); 100362306a36Sopenharmony_ci if (status < 0) { 100462306a36Sopenharmony_ci mlog_errno(status); 100562306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 100662306a36Sopenharmony_ci inc_nlink(dir); 100762306a36Sopenharmony_ci goto leave; 100862306a36Sopenharmony_ci } 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci if (is_unlinkable) { 101162306a36Sopenharmony_ci status = ocfs2_orphan_add(osb, handle, inode, fe_bh, 101262306a36Sopenharmony_ci orphan_name, &orphan_insert, orphan_dir, false); 101362306a36Sopenharmony_ci if (status < 0) 101462306a36Sopenharmony_ci mlog_errno(status); 101562306a36Sopenharmony_ci } 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_cileave: 101862306a36Sopenharmony_ci if (handle) 101962306a36Sopenharmony_ci ocfs2_commit_trans(osb, handle); 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci if (orphan_dir) { 102262306a36Sopenharmony_ci /* This was locked for us in ocfs2_prepare_orphan_dir() */ 102362306a36Sopenharmony_ci ocfs2_inode_unlock(orphan_dir, 1); 102462306a36Sopenharmony_ci inode_unlock(orphan_dir); 102562306a36Sopenharmony_ci iput(orphan_dir); 102662306a36Sopenharmony_ci } 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci if (child_locked) 102962306a36Sopenharmony_ci ocfs2_inode_unlock(inode, 1); 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci ocfs2_inode_unlock(dir, 1); 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci brelse(fe_bh); 103462306a36Sopenharmony_ci brelse(parent_node_bh); 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci ocfs2_free_dir_lookup_result(&orphan_insert); 103762306a36Sopenharmony_ci ocfs2_free_dir_lookup_result(&lookup); 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci if (status && (status != -ENOTEMPTY) && (status != -ENOENT)) 104062306a36Sopenharmony_ci mlog_errno(status); 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci return status; 104362306a36Sopenharmony_ci} 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_cistatic int ocfs2_check_if_ancestor(struct ocfs2_super *osb, 104662306a36Sopenharmony_ci u64 src_inode_no, u64 dest_inode_no) 104762306a36Sopenharmony_ci{ 104862306a36Sopenharmony_ci int ret = 0, i = 0; 104962306a36Sopenharmony_ci u64 parent_inode_no = 0; 105062306a36Sopenharmony_ci u64 child_inode_no = src_inode_no; 105162306a36Sopenharmony_ci struct inode *child_inode; 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci#define MAX_LOOKUP_TIMES 32 105462306a36Sopenharmony_ci while (1) { 105562306a36Sopenharmony_ci child_inode = ocfs2_iget(osb, child_inode_no, 0, 0); 105662306a36Sopenharmony_ci if (IS_ERR(child_inode)) { 105762306a36Sopenharmony_ci ret = PTR_ERR(child_inode); 105862306a36Sopenharmony_ci break; 105962306a36Sopenharmony_ci } 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci ret = ocfs2_inode_lock(child_inode, NULL, 0); 106262306a36Sopenharmony_ci if (ret < 0) { 106362306a36Sopenharmony_ci iput(child_inode); 106462306a36Sopenharmony_ci if (ret != -ENOENT) 106562306a36Sopenharmony_ci mlog_errno(ret); 106662306a36Sopenharmony_ci break; 106762306a36Sopenharmony_ci } 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci ret = ocfs2_lookup_ino_from_name(child_inode, "..", 2, 107062306a36Sopenharmony_ci &parent_inode_no); 107162306a36Sopenharmony_ci ocfs2_inode_unlock(child_inode, 0); 107262306a36Sopenharmony_ci iput(child_inode); 107362306a36Sopenharmony_ci if (ret < 0) { 107462306a36Sopenharmony_ci ret = -ENOENT; 107562306a36Sopenharmony_ci break; 107662306a36Sopenharmony_ci } 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci if (parent_inode_no == dest_inode_no) { 107962306a36Sopenharmony_ci ret = 1; 108062306a36Sopenharmony_ci break; 108162306a36Sopenharmony_ci } 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci if (parent_inode_no == osb->root_inode->i_ino) { 108462306a36Sopenharmony_ci ret = 0; 108562306a36Sopenharmony_ci break; 108662306a36Sopenharmony_ci } 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci child_inode_no = parent_inode_no; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci if (++i >= MAX_LOOKUP_TIMES) { 109162306a36Sopenharmony_ci mlog_ratelimited(ML_NOTICE, "max lookup times reached, " 109262306a36Sopenharmony_ci "filesystem may have nested directories, " 109362306a36Sopenharmony_ci "src inode: %llu, dest inode: %llu.\n", 109462306a36Sopenharmony_ci (unsigned long long)src_inode_no, 109562306a36Sopenharmony_ci (unsigned long long)dest_inode_no); 109662306a36Sopenharmony_ci ret = 0; 109762306a36Sopenharmony_ci break; 109862306a36Sopenharmony_ci } 109962306a36Sopenharmony_ci } 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci return ret; 110262306a36Sopenharmony_ci} 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci/* 110562306a36Sopenharmony_ci * The only place this should be used is rename and link! 110662306a36Sopenharmony_ci * if they have the same id, then the 1st one is the only one locked. 110762306a36Sopenharmony_ci */ 110862306a36Sopenharmony_cistatic int ocfs2_double_lock(struct ocfs2_super *osb, 110962306a36Sopenharmony_ci struct buffer_head **bh1, 111062306a36Sopenharmony_ci struct inode *inode1, 111162306a36Sopenharmony_ci struct buffer_head **bh2, 111262306a36Sopenharmony_ci struct inode *inode2, 111362306a36Sopenharmony_ci int rename) 111462306a36Sopenharmony_ci{ 111562306a36Sopenharmony_ci int status; 111662306a36Sopenharmony_ci int inode1_is_ancestor, inode2_is_ancestor; 111762306a36Sopenharmony_ci struct ocfs2_inode_info *oi1 = OCFS2_I(inode1); 111862306a36Sopenharmony_ci struct ocfs2_inode_info *oi2 = OCFS2_I(inode2); 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci trace_ocfs2_double_lock((unsigned long long)oi1->ip_blkno, 112162306a36Sopenharmony_ci (unsigned long long)oi2->ip_blkno); 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci if (*bh1) 112462306a36Sopenharmony_ci *bh1 = NULL; 112562306a36Sopenharmony_ci if (*bh2) 112662306a36Sopenharmony_ci *bh2 = NULL; 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci /* we always want to lock the one with the lower lockid first. 112962306a36Sopenharmony_ci * and if they are nested, we lock ancestor first */ 113062306a36Sopenharmony_ci if (oi1->ip_blkno != oi2->ip_blkno) { 113162306a36Sopenharmony_ci inode1_is_ancestor = ocfs2_check_if_ancestor(osb, oi2->ip_blkno, 113262306a36Sopenharmony_ci oi1->ip_blkno); 113362306a36Sopenharmony_ci if (inode1_is_ancestor < 0) { 113462306a36Sopenharmony_ci status = inode1_is_ancestor; 113562306a36Sopenharmony_ci goto bail; 113662306a36Sopenharmony_ci } 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci inode2_is_ancestor = ocfs2_check_if_ancestor(osb, oi1->ip_blkno, 113962306a36Sopenharmony_ci oi2->ip_blkno); 114062306a36Sopenharmony_ci if (inode2_is_ancestor < 0) { 114162306a36Sopenharmony_ci status = inode2_is_ancestor; 114262306a36Sopenharmony_ci goto bail; 114362306a36Sopenharmony_ci } 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci if ((inode1_is_ancestor == 1) || 114662306a36Sopenharmony_ci (oi1->ip_blkno < oi2->ip_blkno && 114762306a36Sopenharmony_ci inode2_is_ancestor == 0)) { 114862306a36Sopenharmony_ci /* switch id1 and id2 around */ 114962306a36Sopenharmony_ci swap(bh2, bh1); 115062306a36Sopenharmony_ci swap(inode2, inode1); 115162306a36Sopenharmony_ci } 115262306a36Sopenharmony_ci /* lock id2 */ 115362306a36Sopenharmony_ci status = ocfs2_inode_lock_nested(inode2, bh2, 1, 115462306a36Sopenharmony_ci rename == 1 ? OI_LS_RENAME1 : OI_LS_PARENT); 115562306a36Sopenharmony_ci if (status < 0) { 115662306a36Sopenharmony_ci if (status != -ENOENT) 115762306a36Sopenharmony_ci mlog_errno(status); 115862306a36Sopenharmony_ci goto bail; 115962306a36Sopenharmony_ci } 116062306a36Sopenharmony_ci } 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci /* lock id1 */ 116362306a36Sopenharmony_ci status = ocfs2_inode_lock_nested(inode1, bh1, 1, 116462306a36Sopenharmony_ci rename == 1 ? OI_LS_RENAME2 : OI_LS_PARENT); 116562306a36Sopenharmony_ci if (status < 0) { 116662306a36Sopenharmony_ci /* 116762306a36Sopenharmony_ci * An error return must mean that no cluster locks 116862306a36Sopenharmony_ci * were held on function exit. 116962306a36Sopenharmony_ci */ 117062306a36Sopenharmony_ci if (oi1->ip_blkno != oi2->ip_blkno) { 117162306a36Sopenharmony_ci ocfs2_inode_unlock(inode2, 1); 117262306a36Sopenharmony_ci brelse(*bh2); 117362306a36Sopenharmony_ci *bh2 = NULL; 117462306a36Sopenharmony_ci } 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci if (status != -ENOENT) 117762306a36Sopenharmony_ci mlog_errno(status); 117862306a36Sopenharmony_ci } 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci trace_ocfs2_double_lock_end( 118162306a36Sopenharmony_ci (unsigned long long)oi1->ip_blkno, 118262306a36Sopenharmony_ci (unsigned long long)oi2->ip_blkno); 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_cibail: 118562306a36Sopenharmony_ci if (status) 118662306a36Sopenharmony_ci mlog_errno(status); 118762306a36Sopenharmony_ci return status; 118862306a36Sopenharmony_ci} 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_cistatic void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2) 119162306a36Sopenharmony_ci{ 119262306a36Sopenharmony_ci ocfs2_inode_unlock(inode1, 1); 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci if (inode1 != inode2) 119562306a36Sopenharmony_ci ocfs2_inode_unlock(inode2, 1); 119662306a36Sopenharmony_ci} 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_cistatic int ocfs2_rename(struct mnt_idmap *idmap, 119962306a36Sopenharmony_ci struct inode *old_dir, 120062306a36Sopenharmony_ci struct dentry *old_dentry, 120162306a36Sopenharmony_ci struct inode *new_dir, 120262306a36Sopenharmony_ci struct dentry *new_dentry, 120362306a36Sopenharmony_ci unsigned int flags) 120462306a36Sopenharmony_ci{ 120562306a36Sopenharmony_ci int status = 0, rename_lock = 0, parents_locked = 0, target_exists = 0; 120662306a36Sopenharmony_ci int old_child_locked = 0, new_child_locked = 0, update_dot_dot = 0; 120762306a36Sopenharmony_ci struct inode *old_inode = d_inode(old_dentry); 120862306a36Sopenharmony_ci struct inode *new_inode = d_inode(new_dentry); 120962306a36Sopenharmony_ci struct inode *orphan_dir = NULL; 121062306a36Sopenharmony_ci struct ocfs2_dinode *newfe = NULL; 121162306a36Sopenharmony_ci char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; 121262306a36Sopenharmony_ci struct buffer_head *newfe_bh = NULL; 121362306a36Sopenharmony_ci struct buffer_head *old_inode_bh = NULL; 121462306a36Sopenharmony_ci struct ocfs2_super *osb = NULL; 121562306a36Sopenharmony_ci u64 newfe_blkno, old_de_ino; 121662306a36Sopenharmony_ci handle_t *handle = NULL; 121762306a36Sopenharmony_ci struct buffer_head *old_dir_bh = NULL; 121862306a36Sopenharmony_ci struct buffer_head *new_dir_bh = NULL; 121962306a36Sopenharmony_ci u32 old_dir_nlink = old_dir->i_nlink; 122062306a36Sopenharmony_ci struct ocfs2_dinode *old_di; 122162306a36Sopenharmony_ci struct ocfs2_dir_lookup_result old_inode_dot_dot_res = { NULL, }; 122262306a36Sopenharmony_ci struct ocfs2_dir_lookup_result target_lookup_res = { NULL, }; 122362306a36Sopenharmony_ci struct ocfs2_dir_lookup_result old_entry_lookup = { NULL, }; 122462306a36Sopenharmony_ci struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; 122562306a36Sopenharmony_ci struct ocfs2_dir_lookup_result target_insert = { NULL, }; 122662306a36Sopenharmony_ci bool should_add_orphan = false; 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci if (flags) 122962306a36Sopenharmony_ci return -EINVAL; 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci /* At some point it might be nice to break this function up a 123262306a36Sopenharmony_ci * bit. */ 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci trace_ocfs2_rename(old_dir, old_dentry, new_dir, new_dentry, 123562306a36Sopenharmony_ci old_dentry->d_name.len, old_dentry->d_name.name, 123662306a36Sopenharmony_ci new_dentry->d_name.len, new_dentry->d_name.name); 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci status = dquot_initialize(old_dir); 123962306a36Sopenharmony_ci if (status) { 124062306a36Sopenharmony_ci mlog_errno(status); 124162306a36Sopenharmony_ci goto bail; 124262306a36Sopenharmony_ci } 124362306a36Sopenharmony_ci status = dquot_initialize(new_dir); 124462306a36Sopenharmony_ci if (status) { 124562306a36Sopenharmony_ci mlog_errno(status); 124662306a36Sopenharmony_ci goto bail; 124762306a36Sopenharmony_ci } 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci osb = OCFS2_SB(old_dir->i_sb); 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci if (new_inode) { 125262306a36Sopenharmony_ci if (!igrab(new_inode)) 125362306a36Sopenharmony_ci BUG(); 125462306a36Sopenharmony_ci } 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci /* Assume a directory hierarchy thusly: 125762306a36Sopenharmony_ci * a/b/c 125862306a36Sopenharmony_ci * a/d 125962306a36Sopenharmony_ci * a,b,c, and d are all directories. 126062306a36Sopenharmony_ci * 126162306a36Sopenharmony_ci * from cwd of 'a' on both nodes: 126262306a36Sopenharmony_ci * node1: mv b/c d 126362306a36Sopenharmony_ci * node2: mv d b/c 126462306a36Sopenharmony_ci * 126562306a36Sopenharmony_ci * And that's why, just like the VFS, we need a file system 126662306a36Sopenharmony_ci * rename lock. */ 126762306a36Sopenharmony_ci if (old_dir != new_dir && S_ISDIR(old_inode->i_mode)) { 126862306a36Sopenharmony_ci status = ocfs2_rename_lock(osb); 126962306a36Sopenharmony_ci if (status < 0) { 127062306a36Sopenharmony_ci mlog_errno(status); 127162306a36Sopenharmony_ci goto bail; 127262306a36Sopenharmony_ci } 127362306a36Sopenharmony_ci rename_lock = 1; 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci /* here we cannot guarantee the inodes haven't just been 127662306a36Sopenharmony_ci * changed, so check if they are nested again */ 127762306a36Sopenharmony_ci status = ocfs2_check_if_ancestor(osb, new_dir->i_ino, 127862306a36Sopenharmony_ci old_inode->i_ino); 127962306a36Sopenharmony_ci if (status < 0) { 128062306a36Sopenharmony_ci mlog_errno(status); 128162306a36Sopenharmony_ci goto bail; 128262306a36Sopenharmony_ci } else if (status == 1) { 128362306a36Sopenharmony_ci status = -EPERM; 128462306a36Sopenharmony_ci trace_ocfs2_rename_not_permitted( 128562306a36Sopenharmony_ci (unsigned long long)old_inode->i_ino, 128662306a36Sopenharmony_ci (unsigned long long)new_dir->i_ino); 128762306a36Sopenharmony_ci goto bail; 128862306a36Sopenharmony_ci } 128962306a36Sopenharmony_ci } 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci /* if old and new are the same, this'll just do one lock. */ 129262306a36Sopenharmony_ci status = ocfs2_double_lock(osb, &old_dir_bh, old_dir, 129362306a36Sopenharmony_ci &new_dir_bh, new_dir, 1); 129462306a36Sopenharmony_ci if (status < 0) { 129562306a36Sopenharmony_ci mlog_errno(status); 129662306a36Sopenharmony_ci goto bail; 129762306a36Sopenharmony_ci } 129862306a36Sopenharmony_ci parents_locked = 1; 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_ci if (!new_dir->i_nlink) { 130162306a36Sopenharmony_ci status = -EACCES; 130262306a36Sopenharmony_ci goto bail; 130362306a36Sopenharmony_ci } 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_ci /* make sure both dirs have bhs 130662306a36Sopenharmony_ci * get an extra ref on old_dir_bh if old==new */ 130762306a36Sopenharmony_ci if (!new_dir_bh) { 130862306a36Sopenharmony_ci if (old_dir_bh) { 130962306a36Sopenharmony_ci new_dir_bh = old_dir_bh; 131062306a36Sopenharmony_ci get_bh(new_dir_bh); 131162306a36Sopenharmony_ci } else { 131262306a36Sopenharmony_ci mlog(ML_ERROR, "no old_dir_bh!\n"); 131362306a36Sopenharmony_ci status = -EIO; 131462306a36Sopenharmony_ci goto bail; 131562306a36Sopenharmony_ci } 131662306a36Sopenharmony_ci } 131762306a36Sopenharmony_ci 131862306a36Sopenharmony_ci /* 131962306a36Sopenharmony_ci * Aside from allowing a meta data update, the locking here 132062306a36Sopenharmony_ci * also ensures that the downconvert thread on other nodes 132162306a36Sopenharmony_ci * won't have to concurrently downconvert the inode and the 132262306a36Sopenharmony_ci * dentry locks. 132362306a36Sopenharmony_ci */ 132462306a36Sopenharmony_ci status = ocfs2_inode_lock_nested(old_inode, &old_inode_bh, 1, 132562306a36Sopenharmony_ci OI_LS_PARENT); 132662306a36Sopenharmony_ci if (status < 0) { 132762306a36Sopenharmony_ci if (status != -ENOENT) 132862306a36Sopenharmony_ci mlog_errno(status); 132962306a36Sopenharmony_ci goto bail; 133062306a36Sopenharmony_ci } 133162306a36Sopenharmony_ci old_child_locked = 1; 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci status = ocfs2_remote_dentry_delete(old_dentry); 133462306a36Sopenharmony_ci if (status < 0) { 133562306a36Sopenharmony_ci mlog_errno(status); 133662306a36Sopenharmony_ci goto bail; 133762306a36Sopenharmony_ci } 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_ci if (S_ISDIR(old_inode->i_mode)) { 134062306a36Sopenharmony_ci u64 old_inode_parent; 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci update_dot_dot = 1; 134362306a36Sopenharmony_ci status = ocfs2_find_files_on_disk("..", 2, &old_inode_parent, 134462306a36Sopenharmony_ci old_inode, 134562306a36Sopenharmony_ci &old_inode_dot_dot_res); 134662306a36Sopenharmony_ci if (status) { 134762306a36Sopenharmony_ci status = -EIO; 134862306a36Sopenharmony_ci goto bail; 134962306a36Sopenharmony_ci } 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci if (old_inode_parent != OCFS2_I(old_dir)->ip_blkno) { 135262306a36Sopenharmony_ci status = -EIO; 135362306a36Sopenharmony_ci goto bail; 135462306a36Sopenharmony_ci } 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci if (!new_inode && new_dir != old_dir && 135762306a36Sopenharmony_ci new_dir->i_nlink >= ocfs2_link_max(osb)) { 135862306a36Sopenharmony_ci status = -EMLINK; 135962306a36Sopenharmony_ci goto bail; 136062306a36Sopenharmony_ci } 136162306a36Sopenharmony_ci } 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci status = ocfs2_lookup_ino_from_name(old_dir, old_dentry->d_name.name, 136462306a36Sopenharmony_ci old_dentry->d_name.len, 136562306a36Sopenharmony_ci &old_de_ino); 136662306a36Sopenharmony_ci if (status) { 136762306a36Sopenharmony_ci status = -ENOENT; 136862306a36Sopenharmony_ci goto bail; 136962306a36Sopenharmony_ci } 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci /* 137262306a36Sopenharmony_ci * Check for inode number is _not_ due to possible IO errors. 137362306a36Sopenharmony_ci * We might rmdir the source, keep it as pwd of some process 137462306a36Sopenharmony_ci * and merrily kill the link to whatever was created under the 137562306a36Sopenharmony_ci * same name. Goodbye sticky bit ;-< 137662306a36Sopenharmony_ci */ 137762306a36Sopenharmony_ci if (old_de_ino != OCFS2_I(old_inode)->ip_blkno) { 137862306a36Sopenharmony_ci status = -ENOENT; 137962306a36Sopenharmony_ci goto bail; 138062306a36Sopenharmony_ci } 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ci /* check if the target already exists (in which case we need 138362306a36Sopenharmony_ci * to delete it */ 138462306a36Sopenharmony_ci status = ocfs2_find_files_on_disk(new_dentry->d_name.name, 138562306a36Sopenharmony_ci new_dentry->d_name.len, 138662306a36Sopenharmony_ci &newfe_blkno, new_dir, 138762306a36Sopenharmony_ci &target_lookup_res); 138862306a36Sopenharmony_ci /* The only error we allow here is -ENOENT because the new 138962306a36Sopenharmony_ci * file not existing is perfectly valid. */ 139062306a36Sopenharmony_ci if ((status < 0) && (status != -ENOENT)) { 139162306a36Sopenharmony_ci /* If we cannot find the file specified we should just */ 139262306a36Sopenharmony_ci /* return the error... */ 139362306a36Sopenharmony_ci mlog_errno(status); 139462306a36Sopenharmony_ci goto bail; 139562306a36Sopenharmony_ci } 139662306a36Sopenharmony_ci if (status == 0) 139762306a36Sopenharmony_ci target_exists = 1; 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci if (!target_exists && new_inode) { 140062306a36Sopenharmony_ci /* 140162306a36Sopenharmony_ci * Target was unlinked by another node while we were 140262306a36Sopenharmony_ci * waiting to get to ocfs2_rename(). There isn't 140362306a36Sopenharmony_ci * anything we can do here to help the situation, so 140462306a36Sopenharmony_ci * bubble up the appropriate error. 140562306a36Sopenharmony_ci */ 140662306a36Sopenharmony_ci status = -ENOENT; 140762306a36Sopenharmony_ci goto bail; 140862306a36Sopenharmony_ci } 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci /* In case we need to overwrite an existing file, we blow it 141162306a36Sopenharmony_ci * away first */ 141262306a36Sopenharmony_ci if (target_exists) { 141362306a36Sopenharmony_ci /* VFS didn't think there existed an inode here, but 141462306a36Sopenharmony_ci * someone else in the cluster must have raced our 141562306a36Sopenharmony_ci * rename to create one. Today we error cleanly, in 141662306a36Sopenharmony_ci * the future we should consider calling iget to build 141762306a36Sopenharmony_ci * a new struct inode for this entry. */ 141862306a36Sopenharmony_ci if (!new_inode) { 141962306a36Sopenharmony_ci status = -EACCES; 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci trace_ocfs2_rename_target_exists(new_dentry->d_name.len, 142262306a36Sopenharmony_ci new_dentry->d_name.name); 142362306a36Sopenharmony_ci goto bail; 142462306a36Sopenharmony_ci } 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci if (OCFS2_I(new_inode)->ip_blkno != newfe_blkno) { 142762306a36Sopenharmony_ci status = -EACCES; 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci trace_ocfs2_rename_disagree( 143062306a36Sopenharmony_ci (unsigned long long)OCFS2_I(new_inode)->ip_blkno, 143162306a36Sopenharmony_ci (unsigned long long)newfe_blkno, 143262306a36Sopenharmony_ci OCFS2_I(new_inode)->ip_flags); 143362306a36Sopenharmony_ci goto bail; 143462306a36Sopenharmony_ci } 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci status = ocfs2_inode_lock(new_inode, &newfe_bh, 1); 143762306a36Sopenharmony_ci if (status < 0) { 143862306a36Sopenharmony_ci if (status != -ENOENT) 143962306a36Sopenharmony_ci mlog_errno(status); 144062306a36Sopenharmony_ci goto bail; 144162306a36Sopenharmony_ci } 144262306a36Sopenharmony_ci new_child_locked = 1; 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci status = ocfs2_remote_dentry_delete(new_dentry); 144562306a36Sopenharmony_ci if (status < 0) { 144662306a36Sopenharmony_ci mlog_errno(status); 144762306a36Sopenharmony_ci goto bail; 144862306a36Sopenharmony_ci } 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci newfe = (struct ocfs2_dinode *) newfe_bh->b_data; 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci trace_ocfs2_rename_over_existing( 145362306a36Sopenharmony_ci (unsigned long long)newfe_blkno, newfe_bh, newfe_bh ? 145462306a36Sopenharmony_ci (unsigned long long)newfe_bh->b_blocknr : 0ULL); 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) { 145762306a36Sopenharmony_ci status = ocfs2_prepare_orphan_dir(osb, &orphan_dir, 145862306a36Sopenharmony_ci OCFS2_I(new_inode)->ip_blkno, 145962306a36Sopenharmony_ci orphan_name, &orphan_insert, 146062306a36Sopenharmony_ci false); 146162306a36Sopenharmony_ci if (status < 0) { 146262306a36Sopenharmony_ci mlog_errno(status); 146362306a36Sopenharmony_ci goto bail; 146462306a36Sopenharmony_ci } 146562306a36Sopenharmony_ci should_add_orphan = true; 146662306a36Sopenharmony_ci } 146762306a36Sopenharmony_ci } else { 146862306a36Sopenharmony_ci BUG_ON(d_inode(new_dentry->d_parent) != new_dir); 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci status = ocfs2_check_dir_for_entry(new_dir, 147162306a36Sopenharmony_ci new_dentry->d_name.name, 147262306a36Sopenharmony_ci new_dentry->d_name.len); 147362306a36Sopenharmony_ci if (status) 147462306a36Sopenharmony_ci goto bail; 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci status = ocfs2_prepare_dir_for_insert(osb, new_dir, new_dir_bh, 147762306a36Sopenharmony_ci new_dentry->d_name.name, 147862306a36Sopenharmony_ci new_dentry->d_name.len, 147962306a36Sopenharmony_ci &target_insert); 148062306a36Sopenharmony_ci if (status < 0) { 148162306a36Sopenharmony_ci mlog_errno(status); 148262306a36Sopenharmony_ci goto bail; 148362306a36Sopenharmony_ci } 148462306a36Sopenharmony_ci } 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci handle = ocfs2_start_trans(osb, ocfs2_rename_credits(osb->sb)); 148762306a36Sopenharmony_ci if (IS_ERR(handle)) { 148862306a36Sopenharmony_ci status = PTR_ERR(handle); 148962306a36Sopenharmony_ci handle = NULL; 149062306a36Sopenharmony_ci mlog_errno(status); 149162306a36Sopenharmony_ci goto bail; 149262306a36Sopenharmony_ci } 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci if (target_exists) { 149562306a36Sopenharmony_ci if (S_ISDIR(new_inode->i_mode)) { 149662306a36Sopenharmony_ci if (new_inode->i_nlink != 2 || 149762306a36Sopenharmony_ci !ocfs2_empty_dir(new_inode)) { 149862306a36Sopenharmony_ci status = -ENOTEMPTY; 149962306a36Sopenharmony_ci goto bail; 150062306a36Sopenharmony_ci } 150162306a36Sopenharmony_ci } 150262306a36Sopenharmony_ci status = ocfs2_journal_access_di(handle, INODE_CACHE(new_inode), 150362306a36Sopenharmony_ci newfe_bh, 150462306a36Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 150562306a36Sopenharmony_ci if (status < 0) { 150662306a36Sopenharmony_ci mlog_errno(status); 150762306a36Sopenharmony_ci goto bail; 150862306a36Sopenharmony_ci } 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci /* change the dirent to point to the correct inode */ 151162306a36Sopenharmony_ci status = ocfs2_update_entry(new_dir, handle, &target_lookup_res, 151262306a36Sopenharmony_ci old_inode); 151362306a36Sopenharmony_ci if (status < 0) { 151462306a36Sopenharmony_ci mlog_errno(status); 151562306a36Sopenharmony_ci goto bail; 151662306a36Sopenharmony_ci } 151762306a36Sopenharmony_ci inode_inc_iversion(new_dir); 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci if (S_ISDIR(new_inode->i_mode)) 152062306a36Sopenharmony_ci ocfs2_set_links_count(newfe, 0); 152162306a36Sopenharmony_ci else 152262306a36Sopenharmony_ci ocfs2_add_links_count(newfe, -1); 152362306a36Sopenharmony_ci ocfs2_journal_dirty(handle, newfe_bh); 152462306a36Sopenharmony_ci if (should_add_orphan) { 152562306a36Sopenharmony_ci status = ocfs2_orphan_add(osb, handle, new_inode, 152662306a36Sopenharmony_ci newfe_bh, orphan_name, 152762306a36Sopenharmony_ci &orphan_insert, orphan_dir, false); 152862306a36Sopenharmony_ci if (status < 0) { 152962306a36Sopenharmony_ci mlog_errno(status); 153062306a36Sopenharmony_ci goto bail; 153162306a36Sopenharmony_ci } 153262306a36Sopenharmony_ci } 153362306a36Sopenharmony_ci } else { 153462306a36Sopenharmony_ci /* if the name was not found in new_dir, add it now */ 153562306a36Sopenharmony_ci status = ocfs2_add_entry(handle, new_dentry, old_inode, 153662306a36Sopenharmony_ci OCFS2_I(old_inode)->ip_blkno, 153762306a36Sopenharmony_ci new_dir_bh, &target_insert); 153862306a36Sopenharmony_ci if (status < 0) { 153962306a36Sopenharmony_ci mlog_errno(status); 154062306a36Sopenharmony_ci goto bail; 154162306a36Sopenharmony_ci } 154262306a36Sopenharmony_ci } 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_ci inode_set_ctime_current(old_inode); 154562306a36Sopenharmony_ci mark_inode_dirty(old_inode); 154662306a36Sopenharmony_ci 154762306a36Sopenharmony_ci status = ocfs2_journal_access_di(handle, INODE_CACHE(old_inode), 154862306a36Sopenharmony_ci old_inode_bh, 154962306a36Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 155062306a36Sopenharmony_ci if (status >= 0) { 155162306a36Sopenharmony_ci old_di = (struct ocfs2_dinode *) old_inode_bh->b_data; 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci old_di->i_ctime = cpu_to_le64(inode_get_ctime(old_inode).tv_sec); 155462306a36Sopenharmony_ci old_di->i_ctime_nsec = cpu_to_le32(inode_get_ctime(old_inode).tv_nsec); 155562306a36Sopenharmony_ci ocfs2_journal_dirty(handle, old_inode_bh); 155662306a36Sopenharmony_ci } else 155762306a36Sopenharmony_ci mlog_errno(status); 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci /* 156062306a36Sopenharmony_ci * Now that the name has been added to new_dir, remove the old name. 156162306a36Sopenharmony_ci * 156262306a36Sopenharmony_ci * We don't keep any directory entry context around until now 156362306a36Sopenharmony_ci * because the insert might have changed the type of directory 156462306a36Sopenharmony_ci * we're dealing with. 156562306a36Sopenharmony_ci */ 156662306a36Sopenharmony_ci status = ocfs2_find_entry(old_dentry->d_name.name, 156762306a36Sopenharmony_ci old_dentry->d_name.len, old_dir, 156862306a36Sopenharmony_ci &old_entry_lookup); 156962306a36Sopenharmony_ci if (status) { 157062306a36Sopenharmony_ci if (!is_journal_aborted(osb->journal->j_journal)) { 157162306a36Sopenharmony_ci ocfs2_error(osb->sb, "new entry %.*s is added, but old entry %.*s " 157262306a36Sopenharmony_ci "is not deleted.", 157362306a36Sopenharmony_ci new_dentry->d_name.len, new_dentry->d_name.name, 157462306a36Sopenharmony_ci old_dentry->d_name.len, old_dentry->d_name.name); 157562306a36Sopenharmony_ci } 157662306a36Sopenharmony_ci goto bail; 157762306a36Sopenharmony_ci } 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci status = ocfs2_delete_entry(handle, old_dir, &old_entry_lookup); 158062306a36Sopenharmony_ci if (status < 0) { 158162306a36Sopenharmony_ci mlog_errno(status); 158262306a36Sopenharmony_ci if (!is_journal_aborted(osb->journal->j_journal)) { 158362306a36Sopenharmony_ci ocfs2_error(osb->sb, "new entry %.*s is added, but old entry %.*s " 158462306a36Sopenharmony_ci "is not deleted.", 158562306a36Sopenharmony_ci new_dentry->d_name.len, new_dentry->d_name.name, 158662306a36Sopenharmony_ci old_dentry->d_name.len, old_dentry->d_name.name); 158762306a36Sopenharmony_ci } 158862306a36Sopenharmony_ci goto bail; 158962306a36Sopenharmony_ci } 159062306a36Sopenharmony_ci 159162306a36Sopenharmony_ci if (new_inode) { 159262306a36Sopenharmony_ci drop_nlink(new_inode); 159362306a36Sopenharmony_ci inode_set_ctime_current(new_inode); 159462306a36Sopenharmony_ci } 159562306a36Sopenharmony_ci old_dir->i_mtime = inode_set_ctime_current(old_dir); 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci if (update_dot_dot) { 159862306a36Sopenharmony_ci status = ocfs2_update_entry(old_inode, handle, 159962306a36Sopenharmony_ci &old_inode_dot_dot_res, new_dir); 160062306a36Sopenharmony_ci drop_nlink(old_dir); 160162306a36Sopenharmony_ci if (new_inode) { 160262306a36Sopenharmony_ci drop_nlink(new_inode); 160362306a36Sopenharmony_ci } else { 160462306a36Sopenharmony_ci inc_nlink(new_dir); 160562306a36Sopenharmony_ci mark_inode_dirty(new_dir); 160662306a36Sopenharmony_ci } 160762306a36Sopenharmony_ci } 160862306a36Sopenharmony_ci mark_inode_dirty(old_dir); 160962306a36Sopenharmony_ci ocfs2_mark_inode_dirty(handle, old_dir, old_dir_bh); 161062306a36Sopenharmony_ci if (new_inode) { 161162306a36Sopenharmony_ci mark_inode_dirty(new_inode); 161262306a36Sopenharmony_ci ocfs2_mark_inode_dirty(handle, new_inode, newfe_bh); 161362306a36Sopenharmony_ci } 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci if (old_dir != new_dir) { 161662306a36Sopenharmony_ci /* Keep the same times on both directories.*/ 161762306a36Sopenharmony_ci new_dir->i_mtime = inode_set_ctime_to_ts(new_dir, 161862306a36Sopenharmony_ci inode_get_ctime(old_dir)); 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci /* 162162306a36Sopenharmony_ci * This will also pick up the i_nlink change from the 162262306a36Sopenharmony_ci * block above. 162362306a36Sopenharmony_ci */ 162462306a36Sopenharmony_ci ocfs2_mark_inode_dirty(handle, new_dir, new_dir_bh); 162562306a36Sopenharmony_ci } 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ci if (old_dir_nlink != old_dir->i_nlink) { 162862306a36Sopenharmony_ci if (!old_dir_bh) { 162962306a36Sopenharmony_ci mlog(ML_ERROR, "need to change nlink for old dir " 163062306a36Sopenharmony_ci "%llu from %d to %d but bh is NULL!\n", 163162306a36Sopenharmony_ci (unsigned long long)OCFS2_I(old_dir)->ip_blkno, 163262306a36Sopenharmony_ci (int)old_dir_nlink, old_dir->i_nlink); 163362306a36Sopenharmony_ci } else { 163462306a36Sopenharmony_ci struct ocfs2_dinode *fe; 163562306a36Sopenharmony_ci status = ocfs2_journal_access_di(handle, 163662306a36Sopenharmony_ci INODE_CACHE(old_dir), 163762306a36Sopenharmony_ci old_dir_bh, 163862306a36Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 163962306a36Sopenharmony_ci fe = (struct ocfs2_dinode *) old_dir_bh->b_data; 164062306a36Sopenharmony_ci ocfs2_set_links_count(fe, old_dir->i_nlink); 164162306a36Sopenharmony_ci ocfs2_journal_dirty(handle, old_dir_bh); 164262306a36Sopenharmony_ci } 164362306a36Sopenharmony_ci } 164462306a36Sopenharmony_ci ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir); 164562306a36Sopenharmony_ci status = 0; 164662306a36Sopenharmony_cibail: 164762306a36Sopenharmony_ci if (handle) 164862306a36Sopenharmony_ci ocfs2_commit_trans(osb, handle); 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_ci if (orphan_dir) { 165162306a36Sopenharmony_ci /* This was locked for us in ocfs2_prepare_orphan_dir() */ 165262306a36Sopenharmony_ci ocfs2_inode_unlock(orphan_dir, 1); 165362306a36Sopenharmony_ci inode_unlock(orphan_dir); 165462306a36Sopenharmony_ci iput(orphan_dir); 165562306a36Sopenharmony_ci } 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci if (new_child_locked) 165862306a36Sopenharmony_ci ocfs2_inode_unlock(new_inode, 1); 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci if (old_child_locked) 166162306a36Sopenharmony_ci ocfs2_inode_unlock(old_inode, 1); 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci if (parents_locked) 166462306a36Sopenharmony_ci ocfs2_double_unlock(old_dir, new_dir); 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci if (rename_lock) 166762306a36Sopenharmony_ci ocfs2_rename_unlock(osb); 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_ci if (new_inode) 167062306a36Sopenharmony_ci sync_mapping_buffers(old_inode->i_mapping); 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci iput(new_inode); 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci ocfs2_free_dir_lookup_result(&target_lookup_res); 167562306a36Sopenharmony_ci ocfs2_free_dir_lookup_result(&old_entry_lookup); 167662306a36Sopenharmony_ci ocfs2_free_dir_lookup_result(&old_inode_dot_dot_res); 167762306a36Sopenharmony_ci ocfs2_free_dir_lookup_result(&orphan_insert); 167862306a36Sopenharmony_ci ocfs2_free_dir_lookup_result(&target_insert); 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_ci brelse(newfe_bh); 168162306a36Sopenharmony_ci brelse(old_inode_bh); 168262306a36Sopenharmony_ci brelse(old_dir_bh); 168362306a36Sopenharmony_ci brelse(new_dir_bh); 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci if (status) 168662306a36Sopenharmony_ci mlog_errno(status); 168762306a36Sopenharmony_ci 168862306a36Sopenharmony_ci return status; 168962306a36Sopenharmony_ci} 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci/* 169262306a36Sopenharmony_ci * we expect i_size = strlen(symname). Copy symname into the file 169362306a36Sopenharmony_ci * data, including the null terminator. 169462306a36Sopenharmony_ci */ 169562306a36Sopenharmony_cistatic int ocfs2_create_symlink_data(struct ocfs2_super *osb, 169662306a36Sopenharmony_ci handle_t *handle, 169762306a36Sopenharmony_ci struct inode *inode, 169862306a36Sopenharmony_ci const char *symname) 169962306a36Sopenharmony_ci{ 170062306a36Sopenharmony_ci struct buffer_head **bhs = NULL; 170162306a36Sopenharmony_ci const char *c; 170262306a36Sopenharmony_ci struct super_block *sb = osb->sb; 170362306a36Sopenharmony_ci u64 p_blkno, p_blocks; 170462306a36Sopenharmony_ci int virtual, blocks, status, i, bytes_left; 170562306a36Sopenharmony_ci 170662306a36Sopenharmony_ci bytes_left = i_size_read(inode) + 1; 170762306a36Sopenharmony_ci /* we can't trust i_blocks because we're actually going to 170862306a36Sopenharmony_ci * write i_size + 1 bytes. */ 170962306a36Sopenharmony_ci blocks = (bytes_left + sb->s_blocksize - 1) >> sb->s_blocksize_bits; 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci trace_ocfs2_create_symlink_data((unsigned long long)inode->i_blocks, 171262306a36Sopenharmony_ci i_size_read(inode), blocks); 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_ci /* Sanity check -- make sure we're going to fit. */ 171562306a36Sopenharmony_ci if (bytes_left > 171662306a36Sopenharmony_ci ocfs2_clusters_to_bytes(sb, OCFS2_I(inode)->ip_clusters)) { 171762306a36Sopenharmony_ci status = -EIO; 171862306a36Sopenharmony_ci mlog_errno(status); 171962306a36Sopenharmony_ci goto bail; 172062306a36Sopenharmony_ci } 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_ci bhs = kcalloc(blocks, sizeof(struct buffer_head *), GFP_KERNEL); 172362306a36Sopenharmony_ci if (!bhs) { 172462306a36Sopenharmony_ci status = -ENOMEM; 172562306a36Sopenharmony_ci mlog_errno(status); 172662306a36Sopenharmony_ci goto bail; 172762306a36Sopenharmony_ci } 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci status = ocfs2_extent_map_get_blocks(inode, 0, &p_blkno, &p_blocks, 173062306a36Sopenharmony_ci NULL); 173162306a36Sopenharmony_ci if (status < 0) { 173262306a36Sopenharmony_ci mlog_errno(status); 173362306a36Sopenharmony_ci goto bail; 173462306a36Sopenharmony_ci } 173562306a36Sopenharmony_ci 173662306a36Sopenharmony_ci /* links can never be larger than one cluster so we know this 173762306a36Sopenharmony_ci * is all going to be contiguous, but do a sanity check 173862306a36Sopenharmony_ci * anyway. */ 173962306a36Sopenharmony_ci if ((p_blocks << sb->s_blocksize_bits) < bytes_left) { 174062306a36Sopenharmony_ci status = -EIO; 174162306a36Sopenharmony_ci mlog_errno(status); 174262306a36Sopenharmony_ci goto bail; 174362306a36Sopenharmony_ci } 174462306a36Sopenharmony_ci 174562306a36Sopenharmony_ci virtual = 0; 174662306a36Sopenharmony_ci while(bytes_left > 0) { 174762306a36Sopenharmony_ci c = &symname[virtual * sb->s_blocksize]; 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_ci bhs[virtual] = sb_getblk(sb, p_blkno); 175062306a36Sopenharmony_ci if (!bhs[virtual]) { 175162306a36Sopenharmony_ci status = -ENOMEM; 175262306a36Sopenharmony_ci mlog_errno(status); 175362306a36Sopenharmony_ci goto bail; 175462306a36Sopenharmony_ci } 175562306a36Sopenharmony_ci ocfs2_set_new_buffer_uptodate(INODE_CACHE(inode), 175662306a36Sopenharmony_ci bhs[virtual]); 175762306a36Sopenharmony_ci 175862306a36Sopenharmony_ci status = ocfs2_journal_access(handle, INODE_CACHE(inode), 175962306a36Sopenharmony_ci bhs[virtual], 176062306a36Sopenharmony_ci OCFS2_JOURNAL_ACCESS_CREATE); 176162306a36Sopenharmony_ci if (status < 0) { 176262306a36Sopenharmony_ci mlog_errno(status); 176362306a36Sopenharmony_ci goto bail; 176462306a36Sopenharmony_ci } 176562306a36Sopenharmony_ci 176662306a36Sopenharmony_ci memset(bhs[virtual]->b_data, 0, sb->s_blocksize); 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_ci memcpy(bhs[virtual]->b_data, c, 176962306a36Sopenharmony_ci (bytes_left > sb->s_blocksize) ? sb->s_blocksize : 177062306a36Sopenharmony_ci bytes_left); 177162306a36Sopenharmony_ci 177262306a36Sopenharmony_ci ocfs2_journal_dirty(handle, bhs[virtual]); 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci virtual++; 177562306a36Sopenharmony_ci p_blkno++; 177662306a36Sopenharmony_ci bytes_left -= sb->s_blocksize; 177762306a36Sopenharmony_ci } 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci status = 0; 178062306a36Sopenharmony_cibail: 178162306a36Sopenharmony_ci 178262306a36Sopenharmony_ci if (bhs) { 178362306a36Sopenharmony_ci for(i = 0; i < blocks; i++) 178462306a36Sopenharmony_ci brelse(bhs[i]); 178562306a36Sopenharmony_ci kfree(bhs); 178662306a36Sopenharmony_ci } 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_ci if (status) 178962306a36Sopenharmony_ci mlog_errno(status); 179062306a36Sopenharmony_ci return status; 179162306a36Sopenharmony_ci} 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_cistatic int ocfs2_symlink(struct mnt_idmap *idmap, 179462306a36Sopenharmony_ci struct inode *dir, 179562306a36Sopenharmony_ci struct dentry *dentry, 179662306a36Sopenharmony_ci const char *symname) 179762306a36Sopenharmony_ci{ 179862306a36Sopenharmony_ci int status, l, credits; 179962306a36Sopenharmony_ci u64 newsize; 180062306a36Sopenharmony_ci struct ocfs2_super *osb = NULL; 180162306a36Sopenharmony_ci struct inode *inode = NULL; 180262306a36Sopenharmony_ci struct super_block *sb; 180362306a36Sopenharmony_ci struct buffer_head *new_fe_bh = NULL; 180462306a36Sopenharmony_ci struct buffer_head *parent_fe_bh = NULL; 180562306a36Sopenharmony_ci struct ocfs2_dinode *fe = NULL; 180662306a36Sopenharmony_ci struct ocfs2_dinode *dirfe; 180762306a36Sopenharmony_ci handle_t *handle = NULL; 180862306a36Sopenharmony_ci struct ocfs2_alloc_context *inode_ac = NULL; 180962306a36Sopenharmony_ci struct ocfs2_alloc_context *data_ac = NULL; 181062306a36Sopenharmony_ci struct ocfs2_alloc_context *xattr_ac = NULL; 181162306a36Sopenharmony_ci int want_clusters = 0; 181262306a36Sopenharmony_ci int xattr_credits = 0; 181362306a36Sopenharmony_ci struct ocfs2_security_xattr_info si = { 181462306a36Sopenharmony_ci .name = NULL, 181562306a36Sopenharmony_ci .enable = 1, 181662306a36Sopenharmony_ci }; 181762306a36Sopenharmony_ci int did_quota = 0, did_quota_inode = 0; 181862306a36Sopenharmony_ci struct ocfs2_dir_lookup_result lookup = { NULL, }; 181962306a36Sopenharmony_ci sigset_t oldset; 182062306a36Sopenharmony_ci int did_block_signals = 0; 182162306a36Sopenharmony_ci struct ocfs2_dentry_lock *dl = NULL; 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci trace_ocfs2_symlink_begin(dir, dentry, symname, 182462306a36Sopenharmony_ci dentry->d_name.len, dentry->d_name.name); 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_ci status = dquot_initialize(dir); 182762306a36Sopenharmony_ci if (status) { 182862306a36Sopenharmony_ci mlog_errno(status); 182962306a36Sopenharmony_ci goto bail; 183062306a36Sopenharmony_ci } 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_ci sb = dir->i_sb; 183362306a36Sopenharmony_ci osb = OCFS2_SB(sb); 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci l = strlen(symname) + 1; 183662306a36Sopenharmony_ci 183762306a36Sopenharmony_ci credits = ocfs2_calc_symlink_credits(sb); 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci /* lock the parent directory */ 184062306a36Sopenharmony_ci status = ocfs2_inode_lock(dir, &parent_fe_bh, 1); 184162306a36Sopenharmony_ci if (status < 0) { 184262306a36Sopenharmony_ci if (status != -ENOENT) 184362306a36Sopenharmony_ci mlog_errno(status); 184462306a36Sopenharmony_ci return status; 184562306a36Sopenharmony_ci } 184662306a36Sopenharmony_ci 184762306a36Sopenharmony_ci dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; 184862306a36Sopenharmony_ci if (!ocfs2_read_links_count(dirfe)) { 184962306a36Sopenharmony_ci /* can't make a file in a deleted directory. */ 185062306a36Sopenharmony_ci status = -ENOENT; 185162306a36Sopenharmony_ci goto bail; 185262306a36Sopenharmony_ci } 185362306a36Sopenharmony_ci 185462306a36Sopenharmony_ci status = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, 185562306a36Sopenharmony_ci dentry->d_name.len); 185662306a36Sopenharmony_ci if (status) 185762306a36Sopenharmony_ci goto bail; 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci status = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh, 186062306a36Sopenharmony_ci dentry->d_name.name, 186162306a36Sopenharmony_ci dentry->d_name.len, &lookup); 186262306a36Sopenharmony_ci if (status < 0) { 186362306a36Sopenharmony_ci mlog_errno(status); 186462306a36Sopenharmony_ci goto bail; 186562306a36Sopenharmony_ci } 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_ci status = ocfs2_reserve_new_inode(osb, &inode_ac); 186862306a36Sopenharmony_ci if (status < 0) { 186962306a36Sopenharmony_ci if (status != -ENOSPC) 187062306a36Sopenharmony_ci mlog_errno(status); 187162306a36Sopenharmony_ci goto bail; 187262306a36Sopenharmony_ci } 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_ci inode = ocfs2_get_init_inode(dir, S_IFLNK | S_IRWXUGO); 187562306a36Sopenharmony_ci if (IS_ERR(inode)) { 187662306a36Sopenharmony_ci status = PTR_ERR(inode); 187762306a36Sopenharmony_ci inode = NULL; 187862306a36Sopenharmony_ci mlog_errno(status); 187962306a36Sopenharmony_ci goto bail; 188062306a36Sopenharmony_ci } 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_ci /* get security xattr */ 188362306a36Sopenharmony_ci status = ocfs2_init_security_get(inode, dir, &dentry->d_name, &si); 188462306a36Sopenharmony_ci if (status) { 188562306a36Sopenharmony_ci if (status == -EOPNOTSUPP) 188662306a36Sopenharmony_ci si.enable = 0; 188762306a36Sopenharmony_ci else { 188862306a36Sopenharmony_ci mlog_errno(status); 188962306a36Sopenharmony_ci goto bail; 189062306a36Sopenharmony_ci } 189162306a36Sopenharmony_ci } 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_ci /* calculate meta data/clusters for setting security xattr */ 189462306a36Sopenharmony_ci if (si.enable) { 189562306a36Sopenharmony_ci status = ocfs2_calc_security_init(dir, &si, &want_clusters, 189662306a36Sopenharmony_ci &xattr_credits, &xattr_ac); 189762306a36Sopenharmony_ci if (status < 0) { 189862306a36Sopenharmony_ci mlog_errno(status); 189962306a36Sopenharmony_ci goto bail; 190062306a36Sopenharmony_ci } 190162306a36Sopenharmony_ci } 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_ci /* don't reserve bitmap space for fast symlinks. */ 190462306a36Sopenharmony_ci if (l > ocfs2_fast_symlink_chars(sb)) 190562306a36Sopenharmony_ci want_clusters += 1; 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci status = ocfs2_reserve_clusters(osb, want_clusters, &data_ac); 190862306a36Sopenharmony_ci if (status < 0) { 190962306a36Sopenharmony_ci if (status != -ENOSPC) 191062306a36Sopenharmony_ci mlog_errno(status); 191162306a36Sopenharmony_ci goto bail; 191262306a36Sopenharmony_ci } 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_ci handle = ocfs2_start_trans(osb, credits + xattr_credits); 191562306a36Sopenharmony_ci if (IS_ERR(handle)) { 191662306a36Sopenharmony_ci status = PTR_ERR(handle); 191762306a36Sopenharmony_ci handle = NULL; 191862306a36Sopenharmony_ci mlog_errno(status); 191962306a36Sopenharmony_ci goto bail; 192062306a36Sopenharmony_ci } 192162306a36Sopenharmony_ci 192262306a36Sopenharmony_ci /* Starting to change things, restart is no longer possible. */ 192362306a36Sopenharmony_ci ocfs2_block_signals(&oldset); 192462306a36Sopenharmony_ci did_block_signals = 1; 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_ci status = dquot_alloc_inode(inode); 192762306a36Sopenharmony_ci if (status) 192862306a36Sopenharmony_ci goto bail; 192962306a36Sopenharmony_ci did_quota_inode = 1; 193062306a36Sopenharmony_ci 193162306a36Sopenharmony_ci trace_ocfs2_symlink_create(dir, dentry, dentry->d_name.len, 193262306a36Sopenharmony_ci dentry->d_name.name, 193362306a36Sopenharmony_ci (unsigned long long)OCFS2_I(dir)->ip_blkno, 193462306a36Sopenharmony_ci inode->i_mode); 193562306a36Sopenharmony_ci 193662306a36Sopenharmony_ci status = ocfs2_mknod_locked(osb, dir, inode, 193762306a36Sopenharmony_ci 0, &new_fe_bh, parent_fe_bh, handle, 193862306a36Sopenharmony_ci inode_ac); 193962306a36Sopenharmony_ci if (status < 0) { 194062306a36Sopenharmony_ci mlog_errno(status); 194162306a36Sopenharmony_ci goto bail; 194262306a36Sopenharmony_ci } 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci fe = (struct ocfs2_dinode *) new_fe_bh->b_data; 194562306a36Sopenharmony_ci inode->i_rdev = 0; 194662306a36Sopenharmony_ci newsize = l - 1; 194762306a36Sopenharmony_ci inode->i_op = &ocfs2_symlink_inode_operations; 194862306a36Sopenharmony_ci inode_nohighmem(inode); 194962306a36Sopenharmony_ci if (l > ocfs2_fast_symlink_chars(sb)) { 195062306a36Sopenharmony_ci u32 offset = 0; 195162306a36Sopenharmony_ci 195262306a36Sopenharmony_ci status = dquot_alloc_space_nodirty(inode, 195362306a36Sopenharmony_ci ocfs2_clusters_to_bytes(osb->sb, 1)); 195462306a36Sopenharmony_ci if (status) 195562306a36Sopenharmony_ci goto bail; 195662306a36Sopenharmony_ci did_quota = 1; 195762306a36Sopenharmony_ci inode->i_mapping->a_ops = &ocfs2_aops; 195862306a36Sopenharmony_ci status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0, 195962306a36Sopenharmony_ci new_fe_bh, 196062306a36Sopenharmony_ci handle, data_ac, NULL, 196162306a36Sopenharmony_ci NULL); 196262306a36Sopenharmony_ci if (status < 0) { 196362306a36Sopenharmony_ci if (status != -ENOSPC && status != -EINTR) { 196462306a36Sopenharmony_ci mlog(ML_ERROR, 196562306a36Sopenharmony_ci "Failed to extend file to %llu\n", 196662306a36Sopenharmony_ci (unsigned long long)newsize); 196762306a36Sopenharmony_ci mlog_errno(status); 196862306a36Sopenharmony_ci status = -ENOSPC; 196962306a36Sopenharmony_ci } 197062306a36Sopenharmony_ci goto bail; 197162306a36Sopenharmony_ci } 197262306a36Sopenharmony_ci i_size_write(inode, newsize); 197362306a36Sopenharmony_ci inode->i_blocks = ocfs2_inode_sector_count(inode); 197462306a36Sopenharmony_ci } else { 197562306a36Sopenharmony_ci inode->i_mapping->a_ops = &ocfs2_fast_symlink_aops; 197662306a36Sopenharmony_ci memcpy((char *) fe->id2.i_symlink, symname, l); 197762306a36Sopenharmony_ci i_size_write(inode, newsize); 197862306a36Sopenharmony_ci inode->i_blocks = 0; 197962306a36Sopenharmony_ci } 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_ci status = ocfs2_mark_inode_dirty(handle, inode, new_fe_bh); 198262306a36Sopenharmony_ci if (status < 0) { 198362306a36Sopenharmony_ci mlog_errno(status); 198462306a36Sopenharmony_ci goto bail; 198562306a36Sopenharmony_ci } 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_ci if (!ocfs2_inode_is_fast_symlink(inode)) { 198862306a36Sopenharmony_ci status = ocfs2_create_symlink_data(osb, handle, inode, 198962306a36Sopenharmony_ci symname); 199062306a36Sopenharmony_ci if (status < 0) { 199162306a36Sopenharmony_ci mlog_errno(status); 199262306a36Sopenharmony_ci goto bail; 199362306a36Sopenharmony_ci } 199462306a36Sopenharmony_ci } 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_ci if (si.enable) { 199762306a36Sopenharmony_ci status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si, 199862306a36Sopenharmony_ci xattr_ac, data_ac); 199962306a36Sopenharmony_ci if (status < 0) { 200062306a36Sopenharmony_ci mlog_errno(status); 200162306a36Sopenharmony_ci goto bail; 200262306a36Sopenharmony_ci } 200362306a36Sopenharmony_ci } 200462306a36Sopenharmony_ci 200562306a36Sopenharmony_ci /* 200662306a36Sopenharmony_ci * Do this before adding the entry to the directory. We add 200762306a36Sopenharmony_ci * also set d_op after success so that ->d_iput() will cleanup 200862306a36Sopenharmony_ci * the dentry lock even if ocfs2_add_entry() fails below. 200962306a36Sopenharmony_ci */ 201062306a36Sopenharmony_ci status = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno); 201162306a36Sopenharmony_ci if (status) { 201262306a36Sopenharmony_ci mlog_errno(status); 201362306a36Sopenharmony_ci goto bail; 201462306a36Sopenharmony_ci } 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci dl = dentry->d_fsdata; 201762306a36Sopenharmony_ci 201862306a36Sopenharmony_ci status = ocfs2_add_entry(handle, dentry, inode, 201962306a36Sopenharmony_ci le64_to_cpu(fe->i_blkno), parent_fe_bh, 202062306a36Sopenharmony_ci &lookup); 202162306a36Sopenharmony_ci if (status < 0) { 202262306a36Sopenharmony_ci mlog_errno(status); 202362306a36Sopenharmony_ci goto bail; 202462306a36Sopenharmony_ci } 202562306a36Sopenharmony_ci 202662306a36Sopenharmony_ci insert_inode_hash(inode); 202762306a36Sopenharmony_ci d_instantiate(dentry, inode); 202862306a36Sopenharmony_cibail: 202962306a36Sopenharmony_ci if (status < 0 && did_quota) 203062306a36Sopenharmony_ci dquot_free_space_nodirty(inode, 203162306a36Sopenharmony_ci ocfs2_clusters_to_bytes(osb->sb, 1)); 203262306a36Sopenharmony_ci if (status < 0 && did_quota_inode) 203362306a36Sopenharmony_ci dquot_free_inode(inode); 203462306a36Sopenharmony_ci if (handle) { 203562306a36Sopenharmony_ci if (status < 0 && fe) 203662306a36Sopenharmony_ci ocfs2_set_links_count(fe, 0); 203762306a36Sopenharmony_ci ocfs2_commit_trans(osb, handle); 203862306a36Sopenharmony_ci } 203962306a36Sopenharmony_ci 204062306a36Sopenharmony_ci ocfs2_inode_unlock(dir, 1); 204162306a36Sopenharmony_ci if (did_block_signals) 204262306a36Sopenharmony_ci ocfs2_unblock_signals(&oldset); 204362306a36Sopenharmony_ci 204462306a36Sopenharmony_ci brelse(new_fe_bh); 204562306a36Sopenharmony_ci brelse(parent_fe_bh); 204662306a36Sopenharmony_ci kfree(si.value); 204762306a36Sopenharmony_ci ocfs2_free_dir_lookup_result(&lookup); 204862306a36Sopenharmony_ci if (inode_ac) 204962306a36Sopenharmony_ci ocfs2_free_alloc_context(inode_ac); 205062306a36Sopenharmony_ci if (data_ac) 205162306a36Sopenharmony_ci ocfs2_free_alloc_context(data_ac); 205262306a36Sopenharmony_ci if (xattr_ac) 205362306a36Sopenharmony_ci ocfs2_free_alloc_context(xattr_ac); 205462306a36Sopenharmony_ci if ((status < 0) && inode) { 205562306a36Sopenharmony_ci if (dl) 205662306a36Sopenharmony_ci ocfs2_cleanup_add_entry_failure(osb, dentry, inode); 205762306a36Sopenharmony_ci 205862306a36Sopenharmony_ci OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SKIP_ORPHAN_DIR; 205962306a36Sopenharmony_ci clear_nlink(inode); 206062306a36Sopenharmony_ci iput(inode); 206162306a36Sopenharmony_ci } 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci if (status) 206462306a36Sopenharmony_ci mlog_errno(status); 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci return status; 206762306a36Sopenharmony_ci} 206862306a36Sopenharmony_ci 206962306a36Sopenharmony_cistatic int ocfs2_blkno_stringify(u64 blkno, char *name) 207062306a36Sopenharmony_ci{ 207162306a36Sopenharmony_ci int status, namelen; 207262306a36Sopenharmony_ci 207362306a36Sopenharmony_ci namelen = snprintf(name, OCFS2_ORPHAN_NAMELEN + 1, "%016llx", 207462306a36Sopenharmony_ci (long long)blkno); 207562306a36Sopenharmony_ci if (namelen <= 0) { 207662306a36Sopenharmony_ci if (namelen) 207762306a36Sopenharmony_ci status = namelen; 207862306a36Sopenharmony_ci else 207962306a36Sopenharmony_ci status = -EINVAL; 208062306a36Sopenharmony_ci mlog_errno(status); 208162306a36Sopenharmony_ci goto bail; 208262306a36Sopenharmony_ci } 208362306a36Sopenharmony_ci if (namelen != OCFS2_ORPHAN_NAMELEN) { 208462306a36Sopenharmony_ci status = -EINVAL; 208562306a36Sopenharmony_ci mlog_errno(status); 208662306a36Sopenharmony_ci goto bail; 208762306a36Sopenharmony_ci } 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_ci trace_ocfs2_blkno_stringify(blkno, name, namelen); 209062306a36Sopenharmony_ci 209162306a36Sopenharmony_ci status = 0; 209262306a36Sopenharmony_cibail: 209362306a36Sopenharmony_ci if (status < 0) 209462306a36Sopenharmony_ci mlog_errno(status); 209562306a36Sopenharmony_ci return status; 209662306a36Sopenharmony_ci} 209762306a36Sopenharmony_ci 209862306a36Sopenharmony_cistatic int ocfs2_lookup_lock_orphan_dir(struct ocfs2_super *osb, 209962306a36Sopenharmony_ci struct inode **ret_orphan_dir, 210062306a36Sopenharmony_ci struct buffer_head **ret_orphan_dir_bh) 210162306a36Sopenharmony_ci{ 210262306a36Sopenharmony_ci struct inode *orphan_dir_inode; 210362306a36Sopenharmony_ci struct buffer_head *orphan_dir_bh = NULL; 210462306a36Sopenharmony_ci int ret = 0; 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_ci orphan_dir_inode = ocfs2_get_system_file_inode(osb, 210762306a36Sopenharmony_ci ORPHAN_DIR_SYSTEM_INODE, 210862306a36Sopenharmony_ci osb->slot_num); 210962306a36Sopenharmony_ci if (!orphan_dir_inode) { 211062306a36Sopenharmony_ci ret = -ENOENT; 211162306a36Sopenharmony_ci mlog_errno(ret); 211262306a36Sopenharmony_ci return ret; 211362306a36Sopenharmony_ci } 211462306a36Sopenharmony_ci 211562306a36Sopenharmony_ci inode_lock(orphan_dir_inode); 211662306a36Sopenharmony_ci 211762306a36Sopenharmony_ci ret = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1); 211862306a36Sopenharmony_ci if (ret < 0) { 211962306a36Sopenharmony_ci inode_unlock(orphan_dir_inode); 212062306a36Sopenharmony_ci iput(orphan_dir_inode); 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_ci mlog_errno(ret); 212362306a36Sopenharmony_ci return ret; 212462306a36Sopenharmony_ci } 212562306a36Sopenharmony_ci 212662306a36Sopenharmony_ci *ret_orphan_dir = orphan_dir_inode; 212762306a36Sopenharmony_ci *ret_orphan_dir_bh = orphan_dir_bh; 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci return 0; 213062306a36Sopenharmony_ci} 213162306a36Sopenharmony_ci 213262306a36Sopenharmony_cistatic int __ocfs2_prepare_orphan_dir(struct inode *orphan_dir_inode, 213362306a36Sopenharmony_ci struct buffer_head *orphan_dir_bh, 213462306a36Sopenharmony_ci u64 blkno, 213562306a36Sopenharmony_ci char *name, 213662306a36Sopenharmony_ci struct ocfs2_dir_lookup_result *lookup, 213762306a36Sopenharmony_ci bool dio) 213862306a36Sopenharmony_ci{ 213962306a36Sopenharmony_ci int ret; 214062306a36Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(orphan_dir_inode->i_sb); 214162306a36Sopenharmony_ci int namelen = dio ? 214262306a36Sopenharmony_ci (OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN) : 214362306a36Sopenharmony_ci OCFS2_ORPHAN_NAMELEN; 214462306a36Sopenharmony_ci 214562306a36Sopenharmony_ci if (dio) { 214662306a36Sopenharmony_ci ret = snprintf(name, OCFS2_DIO_ORPHAN_PREFIX_LEN + 1, "%s", 214762306a36Sopenharmony_ci OCFS2_DIO_ORPHAN_PREFIX); 214862306a36Sopenharmony_ci if (ret != OCFS2_DIO_ORPHAN_PREFIX_LEN) { 214962306a36Sopenharmony_ci ret = -EINVAL; 215062306a36Sopenharmony_ci mlog_errno(ret); 215162306a36Sopenharmony_ci return ret; 215262306a36Sopenharmony_ci } 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_ci ret = ocfs2_blkno_stringify(blkno, 215562306a36Sopenharmony_ci name + OCFS2_DIO_ORPHAN_PREFIX_LEN); 215662306a36Sopenharmony_ci } else 215762306a36Sopenharmony_ci ret = ocfs2_blkno_stringify(blkno, name); 215862306a36Sopenharmony_ci if (ret < 0) { 215962306a36Sopenharmony_ci mlog_errno(ret); 216062306a36Sopenharmony_ci return ret; 216162306a36Sopenharmony_ci } 216262306a36Sopenharmony_ci 216362306a36Sopenharmony_ci ret = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode, 216462306a36Sopenharmony_ci orphan_dir_bh, name, 216562306a36Sopenharmony_ci namelen, lookup); 216662306a36Sopenharmony_ci if (ret < 0) { 216762306a36Sopenharmony_ci mlog_errno(ret); 216862306a36Sopenharmony_ci return ret; 216962306a36Sopenharmony_ci } 217062306a36Sopenharmony_ci 217162306a36Sopenharmony_ci return 0; 217262306a36Sopenharmony_ci} 217362306a36Sopenharmony_ci 217462306a36Sopenharmony_ci/** 217562306a36Sopenharmony_ci * ocfs2_prepare_orphan_dir() - Prepare an orphan directory for 217662306a36Sopenharmony_ci * insertion of an orphan. 217762306a36Sopenharmony_ci * @osb: ocfs2 file system 217862306a36Sopenharmony_ci * @ret_orphan_dir: Orphan dir inode - returned locked! 217962306a36Sopenharmony_ci * @blkno: Actual block number of the inode to be inserted into orphan dir. 218062306a36Sopenharmony_ci * @lookup: dir lookup result, to be passed back into functions like 218162306a36Sopenharmony_ci * ocfs2_orphan_add 218262306a36Sopenharmony_ci * 218362306a36Sopenharmony_ci * Returns zero on success and the ret_orphan_dir, name and lookup 218462306a36Sopenharmony_ci * fields will be populated. 218562306a36Sopenharmony_ci * 218662306a36Sopenharmony_ci * Returns non-zero on failure. 218762306a36Sopenharmony_ci */ 218862306a36Sopenharmony_cistatic int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, 218962306a36Sopenharmony_ci struct inode **ret_orphan_dir, 219062306a36Sopenharmony_ci u64 blkno, 219162306a36Sopenharmony_ci char *name, 219262306a36Sopenharmony_ci struct ocfs2_dir_lookup_result *lookup, 219362306a36Sopenharmony_ci bool dio) 219462306a36Sopenharmony_ci{ 219562306a36Sopenharmony_ci struct inode *orphan_dir_inode = NULL; 219662306a36Sopenharmony_ci struct buffer_head *orphan_dir_bh = NULL; 219762306a36Sopenharmony_ci int ret = 0; 219862306a36Sopenharmony_ci 219962306a36Sopenharmony_ci ret = ocfs2_lookup_lock_orphan_dir(osb, &orphan_dir_inode, 220062306a36Sopenharmony_ci &orphan_dir_bh); 220162306a36Sopenharmony_ci if (ret < 0) { 220262306a36Sopenharmony_ci mlog_errno(ret); 220362306a36Sopenharmony_ci return ret; 220462306a36Sopenharmony_ci } 220562306a36Sopenharmony_ci 220662306a36Sopenharmony_ci ret = __ocfs2_prepare_orphan_dir(orphan_dir_inode, orphan_dir_bh, 220762306a36Sopenharmony_ci blkno, name, lookup, dio); 220862306a36Sopenharmony_ci if (ret < 0) { 220962306a36Sopenharmony_ci mlog_errno(ret); 221062306a36Sopenharmony_ci goto out; 221162306a36Sopenharmony_ci } 221262306a36Sopenharmony_ci 221362306a36Sopenharmony_ci *ret_orphan_dir = orphan_dir_inode; 221462306a36Sopenharmony_ci 221562306a36Sopenharmony_ciout: 221662306a36Sopenharmony_ci brelse(orphan_dir_bh); 221762306a36Sopenharmony_ci 221862306a36Sopenharmony_ci if (ret) { 221962306a36Sopenharmony_ci ocfs2_inode_unlock(orphan_dir_inode, 1); 222062306a36Sopenharmony_ci inode_unlock(orphan_dir_inode); 222162306a36Sopenharmony_ci iput(orphan_dir_inode); 222262306a36Sopenharmony_ci } 222362306a36Sopenharmony_ci 222462306a36Sopenharmony_ci if (ret) 222562306a36Sopenharmony_ci mlog_errno(ret); 222662306a36Sopenharmony_ci return ret; 222762306a36Sopenharmony_ci} 222862306a36Sopenharmony_ci 222962306a36Sopenharmony_cistatic int ocfs2_orphan_add(struct ocfs2_super *osb, 223062306a36Sopenharmony_ci handle_t *handle, 223162306a36Sopenharmony_ci struct inode *inode, 223262306a36Sopenharmony_ci struct buffer_head *fe_bh, 223362306a36Sopenharmony_ci char *name, 223462306a36Sopenharmony_ci struct ocfs2_dir_lookup_result *lookup, 223562306a36Sopenharmony_ci struct inode *orphan_dir_inode, 223662306a36Sopenharmony_ci bool dio) 223762306a36Sopenharmony_ci{ 223862306a36Sopenharmony_ci struct buffer_head *orphan_dir_bh = NULL; 223962306a36Sopenharmony_ci int status = 0; 224062306a36Sopenharmony_ci struct ocfs2_dinode *orphan_fe; 224162306a36Sopenharmony_ci struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data; 224262306a36Sopenharmony_ci int namelen = dio ? 224362306a36Sopenharmony_ci (OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN) : 224462306a36Sopenharmony_ci OCFS2_ORPHAN_NAMELEN; 224562306a36Sopenharmony_ci 224662306a36Sopenharmony_ci trace_ocfs2_orphan_add_begin( 224762306a36Sopenharmony_ci (unsigned long long)OCFS2_I(inode)->ip_blkno); 224862306a36Sopenharmony_ci 224962306a36Sopenharmony_ci status = ocfs2_read_inode_block(orphan_dir_inode, &orphan_dir_bh); 225062306a36Sopenharmony_ci if (status < 0) { 225162306a36Sopenharmony_ci mlog_errno(status); 225262306a36Sopenharmony_ci goto leave; 225362306a36Sopenharmony_ci } 225462306a36Sopenharmony_ci 225562306a36Sopenharmony_ci status = ocfs2_journal_access_di(handle, 225662306a36Sopenharmony_ci INODE_CACHE(orphan_dir_inode), 225762306a36Sopenharmony_ci orphan_dir_bh, 225862306a36Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 225962306a36Sopenharmony_ci if (status < 0) { 226062306a36Sopenharmony_ci mlog_errno(status); 226162306a36Sopenharmony_ci goto leave; 226262306a36Sopenharmony_ci } 226362306a36Sopenharmony_ci 226462306a36Sopenharmony_ci /* 226562306a36Sopenharmony_ci * We're going to journal the change of i_flags and i_orphaned_slot. 226662306a36Sopenharmony_ci * It's safe anyway, though some callers may duplicate the journaling. 226762306a36Sopenharmony_ci * Journaling within the func just make the logic look more 226862306a36Sopenharmony_ci * straightforward. 226962306a36Sopenharmony_ci */ 227062306a36Sopenharmony_ci status = ocfs2_journal_access_di(handle, 227162306a36Sopenharmony_ci INODE_CACHE(inode), 227262306a36Sopenharmony_ci fe_bh, 227362306a36Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 227462306a36Sopenharmony_ci if (status < 0) { 227562306a36Sopenharmony_ci mlog_errno(status); 227662306a36Sopenharmony_ci goto leave; 227762306a36Sopenharmony_ci } 227862306a36Sopenharmony_ci 227962306a36Sopenharmony_ci /* we're a cluster, and nlink can change on disk from 228062306a36Sopenharmony_ci * underneath us... */ 228162306a36Sopenharmony_ci orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data; 228262306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 228362306a36Sopenharmony_ci ocfs2_add_links_count(orphan_fe, 1); 228462306a36Sopenharmony_ci set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe)); 228562306a36Sopenharmony_ci ocfs2_journal_dirty(handle, orphan_dir_bh); 228662306a36Sopenharmony_ci 228762306a36Sopenharmony_ci status = __ocfs2_add_entry(handle, orphan_dir_inode, name, 228862306a36Sopenharmony_ci namelen, inode, 228962306a36Sopenharmony_ci OCFS2_I(inode)->ip_blkno, 229062306a36Sopenharmony_ci orphan_dir_bh, lookup); 229162306a36Sopenharmony_ci if (status < 0) { 229262306a36Sopenharmony_ci mlog_errno(status); 229362306a36Sopenharmony_ci goto rollback; 229462306a36Sopenharmony_ci } 229562306a36Sopenharmony_ci 229662306a36Sopenharmony_ci if (dio) { 229762306a36Sopenharmony_ci /* Update flag OCFS2_DIO_ORPHANED_FL and record the orphan 229862306a36Sopenharmony_ci * slot. 229962306a36Sopenharmony_ci */ 230062306a36Sopenharmony_ci fe->i_flags |= cpu_to_le32(OCFS2_DIO_ORPHANED_FL); 230162306a36Sopenharmony_ci fe->i_dio_orphaned_slot = cpu_to_le16(osb->slot_num); 230262306a36Sopenharmony_ci } else { 230362306a36Sopenharmony_ci fe->i_flags |= cpu_to_le32(OCFS2_ORPHANED_FL); 230462306a36Sopenharmony_ci OCFS2_I(inode)->ip_flags &= ~OCFS2_INODE_SKIP_ORPHAN_DIR; 230562306a36Sopenharmony_ci 230662306a36Sopenharmony_ci /* Record which orphan dir our inode now resides 230762306a36Sopenharmony_ci * in. delete_inode will use this to determine which orphan 230862306a36Sopenharmony_ci * dir to lock. */ 230962306a36Sopenharmony_ci fe->i_orphaned_slot = cpu_to_le16(osb->slot_num); 231062306a36Sopenharmony_ci } 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci ocfs2_journal_dirty(handle, fe_bh); 231362306a36Sopenharmony_ci 231462306a36Sopenharmony_ci trace_ocfs2_orphan_add_end((unsigned long long)OCFS2_I(inode)->ip_blkno, 231562306a36Sopenharmony_ci osb->slot_num); 231662306a36Sopenharmony_ci 231762306a36Sopenharmony_cirollback: 231862306a36Sopenharmony_ci if (status < 0) { 231962306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 232062306a36Sopenharmony_ci ocfs2_add_links_count(orphan_fe, -1); 232162306a36Sopenharmony_ci set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe)); 232262306a36Sopenharmony_ci } 232362306a36Sopenharmony_ci 232462306a36Sopenharmony_cileave: 232562306a36Sopenharmony_ci brelse(orphan_dir_bh); 232662306a36Sopenharmony_ci 232762306a36Sopenharmony_ci return status; 232862306a36Sopenharmony_ci} 232962306a36Sopenharmony_ci 233062306a36Sopenharmony_ci/* unlike orphan_add, we expect the orphan dir to already be locked here. */ 233162306a36Sopenharmony_ciint ocfs2_orphan_del(struct ocfs2_super *osb, 233262306a36Sopenharmony_ci handle_t *handle, 233362306a36Sopenharmony_ci struct inode *orphan_dir_inode, 233462306a36Sopenharmony_ci struct inode *inode, 233562306a36Sopenharmony_ci struct buffer_head *orphan_dir_bh, 233662306a36Sopenharmony_ci bool dio) 233762306a36Sopenharmony_ci{ 233862306a36Sopenharmony_ci char name[OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN + 1]; 233962306a36Sopenharmony_ci struct ocfs2_dinode *orphan_fe; 234062306a36Sopenharmony_ci int status = 0; 234162306a36Sopenharmony_ci struct ocfs2_dir_lookup_result lookup = { NULL, }; 234262306a36Sopenharmony_ci 234362306a36Sopenharmony_ci if (dio) { 234462306a36Sopenharmony_ci status = snprintf(name, OCFS2_DIO_ORPHAN_PREFIX_LEN + 1, "%s", 234562306a36Sopenharmony_ci OCFS2_DIO_ORPHAN_PREFIX); 234662306a36Sopenharmony_ci if (status != OCFS2_DIO_ORPHAN_PREFIX_LEN) { 234762306a36Sopenharmony_ci status = -EINVAL; 234862306a36Sopenharmony_ci mlog_errno(status); 234962306a36Sopenharmony_ci return status; 235062306a36Sopenharmony_ci } 235162306a36Sopenharmony_ci 235262306a36Sopenharmony_ci status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, 235362306a36Sopenharmony_ci name + OCFS2_DIO_ORPHAN_PREFIX_LEN); 235462306a36Sopenharmony_ci } else 235562306a36Sopenharmony_ci status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name); 235662306a36Sopenharmony_ci if (status < 0) { 235762306a36Sopenharmony_ci mlog_errno(status); 235862306a36Sopenharmony_ci goto leave; 235962306a36Sopenharmony_ci } 236062306a36Sopenharmony_ci 236162306a36Sopenharmony_ci trace_ocfs2_orphan_del( 236262306a36Sopenharmony_ci (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno, 236362306a36Sopenharmony_ci name, strlen(name)); 236462306a36Sopenharmony_ci 236562306a36Sopenharmony_ci status = ocfs2_journal_access_di(handle, 236662306a36Sopenharmony_ci INODE_CACHE(orphan_dir_inode), 236762306a36Sopenharmony_ci orphan_dir_bh, 236862306a36Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 236962306a36Sopenharmony_ci if (status < 0) { 237062306a36Sopenharmony_ci mlog_errno(status); 237162306a36Sopenharmony_ci goto leave; 237262306a36Sopenharmony_ci } 237362306a36Sopenharmony_ci 237462306a36Sopenharmony_ci /* find it's spot in the orphan directory */ 237562306a36Sopenharmony_ci status = ocfs2_find_entry(name, strlen(name), orphan_dir_inode, 237662306a36Sopenharmony_ci &lookup); 237762306a36Sopenharmony_ci if (status) { 237862306a36Sopenharmony_ci mlog_errno(status); 237962306a36Sopenharmony_ci goto leave; 238062306a36Sopenharmony_ci } 238162306a36Sopenharmony_ci 238262306a36Sopenharmony_ci /* remove it from the orphan directory */ 238362306a36Sopenharmony_ci status = ocfs2_delete_entry(handle, orphan_dir_inode, &lookup); 238462306a36Sopenharmony_ci if (status < 0) { 238562306a36Sopenharmony_ci mlog_errno(status); 238662306a36Sopenharmony_ci goto leave; 238762306a36Sopenharmony_ci } 238862306a36Sopenharmony_ci 238962306a36Sopenharmony_ci /* do the i_nlink dance! :) */ 239062306a36Sopenharmony_ci orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data; 239162306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 239262306a36Sopenharmony_ci ocfs2_add_links_count(orphan_fe, -1); 239362306a36Sopenharmony_ci set_nlink(orphan_dir_inode, ocfs2_read_links_count(orphan_fe)); 239462306a36Sopenharmony_ci ocfs2_journal_dirty(handle, orphan_dir_bh); 239562306a36Sopenharmony_ci 239662306a36Sopenharmony_cileave: 239762306a36Sopenharmony_ci ocfs2_free_dir_lookup_result(&lookup); 239862306a36Sopenharmony_ci 239962306a36Sopenharmony_ci if (status) 240062306a36Sopenharmony_ci mlog_errno(status); 240162306a36Sopenharmony_ci return status; 240262306a36Sopenharmony_ci} 240362306a36Sopenharmony_ci 240462306a36Sopenharmony_ci/** 240562306a36Sopenharmony_ci * ocfs2_prep_new_orphaned_file() - Prepare the orphan dir to receive a newly 240662306a36Sopenharmony_ci * allocated file. This is different from the typical 'add to orphan dir' 240762306a36Sopenharmony_ci * operation in that the inode does not yet exist. This is a problem because 240862306a36Sopenharmony_ci * the orphan dir stringifies the inode block number to come up with it's 240962306a36Sopenharmony_ci * dirent. Obviously if the inode does not yet exist we have a chicken and egg 241062306a36Sopenharmony_ci * problem. This function works around it by calling deeper into the orphan 241162306a36Sopenharmony_ci * and suballoc code than other callers. Use this only by necessity. 241262306a36Sopenharmony_ci * @dir: The directory which this inode will ultimately wind up under - not the 241362306a36Sopenharmony_ci * orphan dir! 241462306a36Sopenharmony_ci * @dir_bh: buffer_head the @dir inode block 241562306a36Sopenharmony_ci * @orphan_name: string of length (CFS2_ORPHAN_NAMELEN + 1). Will be filled 241662306a36Sopenharmony_ci * with the string to be used for orphan dirent. Pass back to the orphan dir 241762306a36Sopenharmony_ci * code. 241862306a36Sopenharmony_ci * @ret_orphan_dir: orphan dir inode returned to be passed back into orphan 241962306a36Sopenharmony_ci * dir code. 242062306a36Sopenharmony_ci * @ret_di_blkno: block number where the new inode will be allocated. 242162306a36Sopenharmony_ci * @orphan_insert: Dir insert context to be passed back into orphan dir code. 242262306a36Sopenharmony_ci * @ret_inode_ac: Inode alloc context to be passed back to the allocator. 242362306a36Sopenharmony_ci * 242462306a36Sopenharmony_ci * Returns zero on success and the ret_orphan_dir, name and lookup 242562306a36Sopenharmony_ci * fields will be populated. 242662306a36Sopenharmony_ci * 242762306a36Sopenharmony_ci * Returns non-zero on failure. 242862306a36Sopenharmony_ci */ 242962306a36Sopenharmony_cistatic int ocfs2_prep_new_orphaned_file(struct inode *dir, 243062306a36Sopenharmony_ci struct buffer_head *dir_bh, 243162306a36Sopenharmony_ci char *orphan_name, 243262306a36Sopenharmony_ci struct inode **ret_orphan_dir, 243362306a36Sopenharmony_ci u64 *ret_di_blkno, 243462306a36Sopenharmony_ci struct ocfs2_dir_lookup_result *orphan_insert, 243562306a36Sopenharmony_ci struct ocfs2_alloc_context **ret_inode_ac) 243662306a36Sopenharmony_ci{ 243762306a36Sopenharmony_ci int ret; 243862306a36Sopenharmony_ci u64 di_blkno; 243962306a36Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); 244062306a36Sopenharmony_ci struct inode *orphan_dir = NULL; 244162306a36Sopenharmony_ci struct buffer_head *orphan_dir_bh = NULL; 244262306a36Sopenharmony_ci struct ocfs2_alloc_context *inode_ac = NULL; 244362306a36Sopenharmony_ci 244462306a36Sopenharmony_ci ret = ocfs2_lookup_lock_orphan_dir(osb, &orphan_dir, &orphan_dir_bh); 244562306a36Sopenharmony_ci if (ret < 0) { 244662306a36Sopenharmony_ci mlog_errno(ret); 244762306a36Sopenharmony_ci return ret; 244862306a36Sopenharmony_ci } 244962306a36Sopenharmony_ci 245062306a36Sopenharmony_ci /* reserve an inode spot */ 245162306a36Sopenharmony_ci ret = ocfs2_reserve_new_inode(osb, &inode_ac); 245262306a36Sopenharmony_ci if (ret < 0) { 245362306a36Sopenharmony_ci if (ret != -ENOSPC) 245462306a36Sopenharmony_ci mlog_errno(ret); 245562306a36Sopenharmony_ci goto out; 245662306a36Sopenharmony_ci } 245762306a36Sopenharmony_ci 245862306a36Sopenharmony_ci ret = ocfs2_find_new_inode_loc(dir, dir_bh, inode_ac, 245962306a36Sopenharmony_ci &di_blkno); 246062306a36Sopenharmony_ci if (ret) { 246162306a36Sopenharmony_ci mlog_errno(ret); 246262306a36Sopenharmony_ci goto out; 246362306a36Sopenharmony_ci } 246462306a36Sopenharmony_ci 246562306a36Sopenharmony_ci ret = __ocfs2_prepare_orphan_dir(orphan_dir, orphan_dir_bh, 246662306a36Sopenharmony_ci di_blkno, orphan_name, orphan_insert, 246762306a36Sopenharmony_ci false); 246862306a36Sopenharmony_ci if (ret < 0) { 246962306a36Sopenharmony_ci mlog_errno(ret); 247062306a36Sopenharmony_ci goto out; 247162306a36Sopenharmony_ci } 247262306a36Sopenharmony_ci 247362306a36Sopenharmony_ciout: 247462306a36Sopenharmony_ci if (ret == 0) { 247562306a36Sopenharmony_ci *ret_orphan_dir = orphan_dir; 247662306a36Sopenharmony_ci *ret_di_blkno = di_blkno; 247762306a36Sopenharmony_ci *ret_inode_ac = inode_ac; 247862306a36Sopenharmony_ci /* 247962306a36Sopenharmony_ci * orphan_name and orphan_insert are already up to 248062306a36Sopenharmony_ci * date via prepare_orphan_dir 248162306a36Sopenharmony_ci */ 248262306a36Sopenharmony_ci } else { 248362306a36Sopenharmony_ci /* Unroll reserve_new_inode* */ 248462306a36Sopenharmony_ci if (inode_ac) 248562306a36Sopenharmony_ci ocfs2_free_alloc_context(inode_ac); 248662306a36Sopenharmony_ci 248762306a36Sopenharmony_ci /* Unroll orphan dir locking */ 248862306a36Sopenharmony_ci inode_unlock(orphan_dir); 248962306a36Sopenharmony_ci ocfs2_inode_unlock(orphan_dir, 1); 249062306a36Sopenharmony_ci iput(orphan_dir); 249162306a36Sopenharmony_ci } 249262306a36Sopenharmony_ci 249362306a36Sopenharmony_ci brelse(orphan_dir_bh); 249462306a36Sopenharmony_ci 249562306a36Sopenharmony_ci return ret; 249662306a36Sopenharmony_ci} 249762306a36Sopenharmony_ci 249862306a36Sopenharmony_ciint ocfs2_create_inode_in_orphan(struct inode *dir, 249962306a36Sopenharmony_ci int mode, 250062306a36Sopenharmony_ci struct inode **new_inode) 250162306a36Sopenharmony_ci{ 250262306a36Sopenharmony_ci int status, did_quota_inode = 0; 250362306a36Sopenharmony_ci struct inode *inode = NULL; 250462306a36Sopenharmony_ci struct inode *orphan_dir = NULL; 250562306a36Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); 250662306a36Sopenharmony_ci handle_t *handle = NULL; 250762306a36Sopenharmony_ci char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; 250862306a36Sopenharmony_ci struct buffer_head *parent_di_bh = NULL; 250962306a36Sopenharmony_ci struct buffer_head *new_di_bh = NULL; 251062306a36Sopenharmony_ci struct ocfs2_alloc_context *inode_ac = NULL; 251162306a36Sopenharmony_ci struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; 251262306a36Sopenharmony_ci u64 di_blkno, suballoc_loc; 251362306a36Sopenharmony_ci u16 suballoc_bit; 251462306a36Sopenharmony_ci 251562306a36Sopenharmony_ci status = ocfs2_inode_lock(dir, &parent_di_bh, 1); 251662306a36Sopenharmony_ci if (status < 0) { 251762306a36Sopenharmony_ci if (status != -ENOENT) 251862306a36Sopenharmony_ci mlog_errno(status); 251962306a36Sopenharmony_ci return status; 252062306a36Sopenharmony_ci } 252162306a36Sopenharmony_ci 252262306a36Sopenharmony_ci status = ocfs2_prep_new_orphaned_file(dir, parent_di_bh, 252362306a36Sopenharmony_ci orphan_name, &orphan_dir, 252462306a36Sopenharmony_ci &di_blkno, &orphan_insert, &inode_ac); 252562306a36Sopenharmony_ci if (status < 0) { 252662306a36Sopenharmony_ci if (status != -ENOSPC) 252762306a36Sopenharmony_ci mlog_errno(status); 252862306a36Sopenharmony_ci goto leave; 252962306a36Sopenharmony_ci } 253062306a36Sopenharmony_ci 253162306a36Sopenharmony_ci inode = ocfs2_get_init_inode(dir, mode); 253262306a36Sopenharmony_ci if (IS_ERR(inode)) { 253362306a36Sopenharmony_ci status = PTR_ERR(inode); 253462306a36Sopenharmony_ci inode = NULL; 253562306a36Sopenharmony_ci mlog_errno(status); 253662306a36Sopenharmony_ci goto leave; 253762306a36Sopenharmony_ci } 253862306a36Sopenharmony_ci 253962306a36Sopenharmony_ci handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb, 0, 0)); 254062306a36Sopenharmony_ci if (IS_ERR(handle)) { 254162306a36Sopenharmony_ci status = PTR_ERR(handle); 254262306a36Sopenharmony_ci handle = NULL; 254362306a36Sopenharmony_ci mlog_errno(status); 254462306a36Sopenharmony_ci goto leave; 254562306a36Sopenharmony_ci } 254662306a36Sopenharmony_ci 254762306a36Sopenharmony_ci status = dquot_alloc_inode(inode); 254862306a36Sopenharmony_ci if (status) 254962306a36Sopenharmony_ci goto leave; 255062306a36Sopenharmony_ci did_quota_inode = 1; 255162306a36Sopenharmony_ci 255262306a36Sopenharmony_ci status = ocfs2_claim_new_inode_at_loc(handle, dir, inode_ac, 255362306a36Sopenharmony_ci &suballoc_loc, 255462306a36Sopenharmony_ci &suballoc_bit, di_blkno); 255562306a36Sopenharmony_ci if (status < 0) { 255662306a36Sopenharmony_ci mlog_errno(status); 255762306a36Sopenharmony_ci goto leave; 255862306a36Sopenharmony_ci } 255962306a36Sopenharmony_ci 256062306a36Sopenharmony_ci clear_nlink(inode); 256162306a36Sopenharmony_ci /* do the real work now. */ 256262306a36Sopenharmony_ci status = __ocfs2_mknod_locked(dir, inode, 256362306a36Sopenharmony_ci 0, &new_di_bh, parent_di_bh, handle, 256462306a36Sopenharmony_ci inode_ac, di_blkno, suballoc_loc, 256562306a36Sopenharmony_ci suballoc_bit); 256662306a36Sopenharmony_ci if (status < 0) { 256762306a36Sopenharmony_ci mlog_errno(status); 256862306a36Sopenharmony_ci goto leave; 256962306a36Sopenharmony_ci } 257062306a36Sopenharmony_ci 257162306a36Sopenharmony_ci status = ocfs2_orphan_add(osb, handle, inode, new_di_bh, orphan_name, 257262306a36Sopenharmony_ci &orphan_insert, orphan_dir, false); 257362306a36Sopenharmony_ci if (status < 0) { 257462306a36Sopenharmony_ci mlog_errno(status); 257562306a36Sopenharmony_ci goto leave; 257662306a36Sopenharmony_ci } 257762306a36Sopenharmony_ci 257862306a36Sopenharmony_ci /* get open lock so that only nodes can't remove it from orphan dir. */ 257962306a36Sopenharmony_ci status = ocfs2_open_lock(inode); 258062306a36Sopenharmony_ci if (status < 0) 258162306a36Sopenharmony_ci mlog_errno(status); 258262306a36Sopenharmony_ci 258362306a36Sopenharmony_ci insert_inode_hash(inode); 258462306a36Sopenharmony_cileave: 258562306a36Sopenharmony_ci if (status < 0 && did_quota_inode) 258662306a36Sopenharmony_ci dquot_free_inode(inode); 258762306a36Sopenharmony_ci if (handle) 258862306a36Sopenharmony_ci ocfs2_commit_trans(osb, handle); 258962306a36Sopenharmony_ci 259062306a36Sopenharmony_ci if (orphan_dir) { 259162306a36Sopenharmony_ci /* This was locked for us in ocfs2_prepare_orphan_dir() */ 259262306a36Sopenharmony_ci ocfs2_inode_unlock(orphan_dir, 1); 259362306a36Sopenharmony_ci inode_unlock(orphan_dir); 259462306a36Sopenharmony_ci iput(orphan_dir); 259562306a36Sopenharmony_ci } 259662306a36Sopenharmony_ci 259762306a36Sopenharmony_ci if ((status < 0) && inode) { 259862306a36Sopenharmony_ci clear_nlink(inode); 259962306a36Sopenharmony_ci iput(inode); 260062306a36Sopenharmony_ci } 260162306a36Sopenharmony_ci 260262306a36Sopenharmony_ci if (inode_ac) 260362306a36Sopenharmony_ci ocfs2_free_alloc_context(inode_ac); 260462306a36Sopenharmony_ci 260562306a36Sopenharmony_ci brelse(new_di_bh); 260662306a36Sopenharmony_ci 260762306a36Sopenharmony_ci if (!status) 260862306a36Sopenharmony_ci *new_inode = inode; 260962306a36Sopenharmony_ci 261062306a36Sopenharmony_ci ocfs2_free_dir_lookup_result(&orphan_insert); 261162306a36Sopenharmony_ci 261262306a36Sopenharmony_ci ocfs2_inode_unlock(dir, 1); 261362306a36Sopenharmony_ci brelse(parent_di_bh); 261462306a36Sopenharmony_ci return status; 261562306a36Sopenharmony_ci} 261662306a36Sopenharmony_ci 261762306a36Sopenharmony_ciint ocfs2_add_inode_to_orphan(struct ocfs2_super *osb, 261862306a36Sopenharmony_ci struct inode *inode) 261962306a36Sopenharmony_ci{ 262062306a36Sopenharmony_ci char orphan_name[OCFS2_DIO_ORPHAN_PREFIX_LEN + OCFS2_ORPHAN_NAMELEN + 1]; 262162306a36Sopenharmony_ci struct inode *orphan_dir_inode = NULL; 262262306a36Sopenharmony_ci struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; 262362306a36Sopenharmony_ci struct buffer_head *di_bh = NULL; 262462306a36Sopenharmony_ci int status = 0; 262562306a36Sopenharmony_ci handle_t *handle = NULL; 262662306a36Sopenharmony_ci struct ocfs2_dinode *di = NULL; 262762306a36Sopenharmony_ci 262862306a36Sopenharmony_ci status = ocfs2_inode_lock(inode, &di_bh, 1); 262962306a36Sopenharmony_ci if (status < 0) { 263062306a36Sopenharmony_ci mlog_errno(status); 263162306a36Sopenharmony_ci goto bail; 263262306a36Sopenharmony_ci } 263362306a36Sopenharmony_ci 263462306a36Sopenharmony_ci di = (struct ocfs2_dinode *) di_bh->b_data; 263562306a36Sopenharmony_ci /* 263662306a36Sopenharmony_ci * Another append dio crashed? 263762306a36Sopenharmony_ci * If so, manually recover it first. 263862306a36Sopenharmony_ci */ 263962306a36Sopenharmony_ci if (unlikely(di->i_flags & cpu_to_le32(OCFS2_DIO_ORPHANED_FL))) { 264062306a36Sopenharmony_ci status = ocfs2_truncate_file(inode, di_bh, i_size_read(inode)); 264162306a36Sopenharmony_ci if (status < 0) { 264262306a36Sopenharmony_ci if (status != -ENOSPC) 264362306a36Sopenharmony_ci mlog_errno(status); 264462306a36Sopenharmony_ci goto bail_unlock_inode; 264562306a36Sopenharmony_ci } 264662306a36Sopenharmony_ci 264762306a36Sopenharmony_ci status = ocfs2_del_inode_from_orphan(osb, inode, di_bh, 0, 0); 264862306a36Sopenharmony_ci if (status < 0) { 264962306a36Sopenharmony_ci mlog_errno(status); 265062306a36Sopenharmony_ci goto bail_unlock_inode; 265162306a36Sopenharmony_ci } 265262306a36Sopenharmony_ci } 265362306a36Sopenharmony_ci 265462306a36Sopenharmony_ci status = ocfs2_prepare_orphan_dir(osb, &orphan_dir_inode, 265562306a36Sopenharmony_ci OCFS2_I(inode)->ip_blkno, 265662306a36Sopenharmony_ci orphan_name, 265762306a36Sopenharmony_ci &orphan_insert, 265862306a36Sopenharmony_ci true); 265962306a36Sopenharmony_ci if (status < 0) { 266062306a36Sopenharmony_ci mlog_errno(status); 266162306a36Sopenharmony_ci goto bail_unlock_inode; 266262306a36Sopenharmony_ci } 266362306a36Sopenharmony_ci 266462306a36Sopenharmony_ci handle = ocfs2_start_trans(osb, 266562306a36Sopenharmony_ci OCFS2_INODE_ADD_TO_ORPHAN_CREDITS); 266662306a36Sopenharmony_ci if (IS_ERR(handle)) { 266762306a36Sopenharmony_ci status = PTR_ERR(handle); 266862306a36Sopenharmony_ci goto bail_unlock_orphan; 266962306a36Sopenharmony_ci } 267062306a36Sopenharmony_ci 267162306a36Sopenharmony_ci status = ocfs2_orphan_add(osb, handle, inode, di_bh, orphan_name, 267262306a36Sopenharmony_ci &orphan_insert, orphan_dir_inode, true); 267362306a36Sopenharmony_ci if (status) 267462306a36Sopenharmony_ci mlog_errno(status); 267562306a36Sopenharmony_ci 267662306a36Sopenharmony_ci ocfs2_commit_trans(osb, handle); 267762306a36Sopenharmony_ci 267862306a36Sopenharmony_cibail_unlock_orphan: 267962306a36Sopenharmony_ci ocfs2_inode_unlock(orphan_dir_inode, 1); 268062306a36Sopenharmony_ci inode_unlock(orphan_dir_inode); 268162306a36Sopenharmony_ci iput(orphan_dir_inode); 268262306a36Sopenharmony_ci 268362306a36Sopenharmony_ci ocfs2_free_dir_lookup_result(&orphan_insert); 268462306a36Sopenharmony_ci 268562306a36Sopenharmony_cibail_unlock_inode: 268662306a36Sopenharmony_ci ocfs2_inode_unlock(inode, 1); 268762306a36Sopenharmony_ci brelse(di_bh); 268862306a36Sopenharmony_ci 268962306a36Sopenharmony_cibail: 269062306a36Sopenharmony_ci return status; 269162306a36Sopenharmony_ci} 269262306a36Sopenharmony_ci 269362306a36Sopenharmony_ciint ocfs2_del_inode_from_orphan(struct ocfs2_super *osb, 269462306a36Sopenharmony_ci struct inode *inode, struct buffer_head *di_bh, 269562306a36Sopenharmony_ci int update_isize, loff_t end) 269662306a36Sopenharmony_ci{ 269762306a36Sopenharmony_ci struct inode *orphan_dir_inode = NULL; 269862306a36Sopenharmony_ci struct buffer_head *orphan_dir_bh = NULL; 269962306a36Sopenharmony_ci struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; 270062306a36Sopenharmony_ci handle_t *handle = NULL; 270162306a36Sopenharmony_ci int status = 0; 270262306a36Sopenharmony_ci 270362306a36Sopenharmony_ci orphan_dir_inode = ocfs2_get_system_file_inode(osb, 270462306a36Sopenharmony_ci ORPHAN_DIR_SYSTEM_INODE, 270562306a36Sopenharmony_ci le16_to_cpu(di->i_dio_orphaned_slot)); 270662306a36Sopenharmony_ci if (!orphan_dir_inode) { 270762306a36Sopenharmony_ci status = -ENOENT; 270862306a36Sopenharmony_ci mlog_errno(status); 270962306a36Sopenharmony_ci goto bail; 271062306a36Sopenharmony_ci } 271162306a36Sopenharmony_ci 271262306a36Sopenharmony_ci inode_lock(orphan_dir_inode); 271362306a36Sopenharmony_ci status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1); 271462306a36Sopenharmony_ci if (status < 0) { 271562306a36Sopenharmony_ci inode_unlock(orphan_dir_inode); 271662306a36Sopenharmony_ci iput(orphan_dir_inode); 271762306a36Sopenharmony_ci mlog_errno(status); 271862306a36Sopenharmony_ci goto bail; 271962306a36Sopenharmony_ci } 272062306a36Sopenharmony_ci 272162306a36Sopenharmony_ci handle = ocfs2_start_trans(osb, 272262306a36Sopenharmony_ci OCFS2_INODE_DEL_FROM_ORPHAN_CREDITS); 272362306a36Sopenharmony_ci if (IS_ERR(handle)) { 272462306a36Sopenharmony_ci status = PTR_ERR(handle); 272562306a36Sopenharmony_ci goto bail_unlock_orphan; 272662306a36Sopenharmony_ci } 272762306a36Sopenharmony_ci 272862306a36Sopenharmony_ci BUG_ON(!(di->i_flags & cpu_to_le32(OCFS2_DIO_ORPHANED_FL))); 272962306a36Sopenharmony_ci 273062306a36Sopenharmony_ci status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, 273162306a36Sopenharmony_ci inode, orphan_dir_bh, true); 273262306a36Sopenharmony_ci if (status < 0) { 273362306a36Sopenharmony_ci mlog_errno(status); 273462306a36Sopenharmony_ci goto bail_commit; 273562306a36Sopenharmony_ci } 273662306a36Sopenharmony_ci 273762306a36Sopenharmony_ci status = ocfs2_journal_access_di(handle, 273862306a36Sopenharmony_ci INODE_CACHE(inode), 273962306a36Sopenharmony_ci di_bh, 274062306a36Sopenharmony_ci OCFS2_JOURNAL_ACCESS_WRITE); 274162306a36Sopenharmony_ci if (status < 0) { 274262306a36Sopenharmony_ci mlog_errno(status); 274362306a36Sopenharmony_ci goto bail_commit; 274462306a36Sopenharmony_ci } 274562306a36Sopenharmony_ci 274662306a36Sopenharmony_ci di->i_flags &= ~cpu_to_le32(OCFS2_DIO_ORPHANED_FL); 274762306a36Sopenharmony_ci di->i_dio_orphaned_slot = 0; 274862306a36Sopenharmony_ci 274962306a36Sopenharmony_ci if (update_isize) { 275062306a36Sopenharmony_ci status = ocfs2_set_inode_size(handle, inode, di_bh, end); 275162306a36Sopenharmony_ci if (status) 275262306a36Sopenharmony_ci mlog_errno(status); 275362306a36Sopenharmony_ci } else 275462306a36Sopenharmony_ci ocfs2_journal_dirty(handle, di_bh); 275562306a36Sopenharmony_ci 275662306a36Sopenharmony_cibail_commit: 275762306a36Sopenharmony_ci ocfs2_commit_trans(osb, handle); 275862306a36Sopenharmony_ci 275962306a36Sopenharmony_cibail_unlock_orphan: 276062306a36Sopenharmony_ci ocfs2_inode_unlock(orphan_dir_inode, 1); 276162306a36Sopenharmony_ci inode_unlock(orphan_dir_inode); 276262306a36Sopenharmony_ci brelse(orphan_dir_bh); 276362306a36Sopenharmony_ci iput(orphan_dir_inode); 276462306a36Sopenharmony_ci 276562306a36Sopenharmony_cibail: 276662306a36Sopenharmony_ci return status; 276762306a36Sopenharmony_ci} 276862306a36Sopenharmony_ci 276962306a36Sopenharmony_ciint ocfs2_mv_orphaned_inode_to_new(struct inode *dir, 277062306a36Sopenharmony_ci struct inode *inode, 277162306a36Sopenharmony_ci struct dentry *dentry) 277262306a36Sopenharmony_ci{ 277362306a36Sopenharmony_ci int status = 0; 277462306a36Sopenharmony_ci struct buffer_head *parent_di_bh = NULL; 277562306a36Sopenharmony_ci handle_t *handle = NULL; 277662306a36Sopenharmony_ci struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); 277762306a36Sopenharmony_ci struct ocfs2_dinode *dir_di, *di; 277862306a36Sopenharmony_ci struct inode *orphan_dir_inode = NULL; 277962306a36Sopenharmony_ci struct buffer_head *orphan_dir_bh = NULL; 278062306a36Sopenharmony_ci struct buffer_head *di_bh = NULL; 278162306a36Sopenharmony_ci struct ocfs2_dir_lookup_result lookup = { NULL, }; 278262306a36Sopenharmony_ci 278362306a36Sopenharmony_ci trace_ocfs2_mv_orphaned_inode_to_new(dir, dentry, 278462306a36Sopenharmony_ci dentry->d_name.len, dentry->d_name.name, 278562306a36Sopenharmony_ci (unsigned long long)OCFS2_I(dir)->ip_blkno, 278662306a36Sopenharmony_ci (unsigned long long)OCFS2_I(inode)->ip_blkno); 278762306a36Sopenharmony_ci 278862306a36Sopenharmony_ci status = ocfs2_inode_lock(dir, &parent_di_bh, 1); 278962306a36Sopenharmony_ci if (status < 0) { 279062306a36Sopenharmony_ci if (status != -ENOENT) 279162306a36Sopenharmony_ci mlog_errno(status); 279262306a36Sopenharmony_ci return status; 279362306a36Sopenharmony_ci } 279462306a36Sopenharmony_ci 279562306a36Sopenharmony_ci dir_di = (struct ocfs2_dinode *) parent_di_bh->b_data; 279662306a36Sopenharmony_ci if (!dir_di->i_links_count) { 279762306a36Sopenharmony_ci /* can't make a file in a deleted directory. */ 279862306a36Sopenharmony_ci status = -ENOENT; 279962306a36Sopenharmony_ci goto leave; 280062306a36Sopenharmony_ci } 280162306a36Sopenharmony_ci 280262306a36Sopenharmony_ci status = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, 280362306a36Sopenharmony_ci dentry->d_name.len); 280462306a36Sopenharmony_ci if (status) 280562306a36Sopenharmony_ci goto leave; 280662306a36Sopenharmony_ci 280762306a36Sopenharmony_ci /* get a spot inside the dir. */ 280862306a36Sopenharmony_ci status = ocfs2_prepare_dir_for_insert(osb, dir, parent_di_bh, 280962306a36Sopenharmony_ci dentry->d_name.name, 281062306a36Sopenharmony_ci dentry->d_name.len, &lookup); 281162306a36Sopenharmony_ci if (status < 0) { 281262306a36Sopenharmony_ci mlog_errno(status); 281362306a36Sopenharmony_ci goto leave; 281462306a36Sopenharmony_ci } 281562306a36Sopenharmony_ci 281662306a36Sopenharmony_ci orphan_dir_inode = ocfs2_get_system_file_inode(osb, 281762306a36Sopenharmony_ci ORPHAN_DIR_SYSTEM_INODE, 281862306a36Sopenharmony_ci osb->slot_num); 281962306a36Sopenharmony_ci if (!orphan_dir_inode) { 282062306a36Sopenharmony_ci status = -ENOENT; 282162306a36Sopenharmony_ci mlog_errno(status); 282262306a36Sopenharmony_ci goto leave; 282362306a36Sopenharmony_ci } 282462306a36Sopenharmony_ci 282562306a36Sopenharmony_ci inode_lock(orphan_dir_inode); 282662306a36Sopenharmony_ci 282762306a36Sopenharmony_ci status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1); 282862306a36Sopenharmony_ci if (status < 0) { 282962306a36Sopenharmony_ci mlog_errno(status); 283062306a36Sopenharmony_ci inode_unlock(orphan_dir_inode); 283162306a36Sopenharmony_ci iput(orphan_dir_inode); 283262306a36Sopenharmony_ci goto leave; 283362306a36Sopenharmony_ci } 283462306a36Sopenharmony_ci 283562306a36Sopenharmony_ci status = ocfs2_read_inode_block(inode, &di_bh); 283662306a36Sopenharmony_ci if (status < 0) { 283762306a36Sopenharmony_ci mlog_errno(status); 283862306a36Sopenharmony_ci goto orphan_unlock; 283962306a36Sopenharmony_ci } 284062306a36Sopenharmony_ci 284162306a36Sopenharmony_ci handle = ocfs2_start_trans(osb, ocfs2_rename_credits(osb->sb)); 284262306a36Sopenharmony_ci if (IS_ERR(handle)) { 284362306a36Sopenharmony_ci status = PTR_ERR(handle); 284462306a36Sopenharmony_ci handle = NULL; 284562306a36Sopenharmony_ci mlog_errno(status); 284662306a36Sopenharmony_ci goto orphan_unlock; 284762306a36Sopenharmony_ci } 284862306a36Sopenharmony_ci 284962306a36Sopenharmony_ci status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), 285062306a36Sopenharmony_ci di_bh, OCFS2_JOURNAL_ACCESS_WRITE); 285162306a36Sopenharmony_ci if (status < 0) { 285262306a36Sopenharmony_ci mlog_errno(status); 285362306a36Sopenharmony_ci goto out_commit; 285462306a36Sopenharmony_ci } 285562306a36Sopenharmony_ci 285662306a36Sopenharmony_ci status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode, 285762306a36Sopenharmony_ci orphan_dir_bh, false); 285862306a36Sopenharmony_ci if (status < 0) { 285962306a36Sopenharmony_ci mlog_errno(status); 286062306a36Sopenharmony_ci goto out_commit; 286162306a36Sopenharmony_ci } 286262306a36Sopenharmony_ci 286362306a36Sopenharmony_ci di = (struct ocfs2_dinode *)di_bh->b_data; 286462306a36Sopenharmony_ci di->i_flags &= ~cpu_to_le32(OCFS2_ORPHANED_FL); 286562306a36Sopenharmony_ci di->i_orphaned_slot = 0; 286662306a36Sopenharmony_ci set_nlink(inode, 1); 286762306a36Sopenharmony_ci ocfs2_set_links_count(di, inode->i_nlink); 286862306a36Sopenharmony_ci ocfs2_update_inode_fsync_trans(handle, inode, 1); 286962306a36Sopenharmony_ci ocfs2_journal_dirty(handle, di_bh); 287062306a36Sopenharmony_ci 287162306a36Sopenharmony_ci status = ocfs2_add_entry(handle, dentry, inode, 287262306a36Sopenharmony_ci OCFS2_I(inode)->ip_blkno, parent_di_bh, 287362306a36Sopenharmony_ci &lookup); 287462306a36Sopenharmony_ci if (status < 0) { 287562306a36Sopenharmony_ci mlog_errno(status); 287662306a36Sopenharmony_ci goto out_commit; 287762306a36Sopenharmony_ci } 287862306a36Sopenharmony_ci 287962306a36Sopenharmony_ci status = ocfs2_dentry_attach_lock(dentry, inode, 288062306a36Sopenharmony_ci OCFS2_I(dir)->ip_blkno); 288162306a36Sopenharmony_ci if (status) { 288262306a36Sopenharmony_ci mlog_errno(status); 288362306a36Sopenharmony_ci goto out_commit; 288462306a36Sopenharmony_ci } 288562306a36Sopenharmony_ci 288662306a36Sopenharmony_ci d_instantiate(dentry, inode); 288762306a36Sopenharmony_ci status = 0; 288862306a36Sopenharmony_ciout_commit: 288962306a36Sopenharmony_ci ocfs2_commit_trans(osb, handle); 289062306a36Sopenharmony_ciorphan_unlock: 289162306a36Sopenharmony_ci ocfs2_inode_unlock(orphan_dir_inode, 1); 289262306a36Sopenharmony_ci inode_unlock(orphan_dir_inode); 289362306a36Sopenharmony_ci iput(orphan_dir_inode); 289462306a36Sopenharmony_cileave: 289562306a36Sopenharmony_ci 289662306a36Sopenharmony_ci ocfs2_inode_unlock(dir, 1); 289762306a36Sopenharmony_ci 289862306a36Sopenharmony_ci brelse(di_bh); 289962306a36Sopenharmony_ci brelse(parent_di_bh); 290062306a36Sopenharmony_ci brelse(orphan_dir_bh); 290162306a36Sopenharmony_ci 290262306a36Sopenharmony_ci ocfs2_free_dir_lookup_result(&lookup); 290362306a36Sopenharmony_ci 290462306a36Sopenharmony_ci if (status) 290562306a36Sopenharmony_ci mlog_errno(status); 290662306a36Sopenharmony_ci 290762306a36Sopenharmony_ci return status; 290862306a36Sopenharmony_ci} 290962306a36Sopenharmony_ci 291062306a36Sopenharmony_ciconst struct inode_operations ocfs2_dir_iops = { 291162306a36Sopenharmony_ci .create = ocfs2_create, 291262306a36Sopenharmony_ci .lookup = ocfs2_lookup, 291362306a36Sopenharmony_ci .link = ocfs2_link, 291462306a36Sopenharmony_ci .unlink = ocfs2_unlink, 291562306a36Sopenharmony_ci .rmdir = ocfs2_unlink, 291662306a36Sopenharmony_ci .symlink = ocfs2_symlink, 291762306a36Sopenharmony_ci .mkdir = ocfs2_mkdir, 291862306a36Sopenharmony_ci .mknod = ocfs2_mknod, 291962306a36Sopenharmony_ci .rename = ocfs2_rename, 292062306a36Sopenharmony_ci .setattr = ocfs2_setattr, 292162306a36Sopenharmony_ci .getattr = ocfs2_getattr, 292262306a36Sopenharmony_ci .permission = ocfs2_permission, 292362306a36Sopenharmony_ci .listxattr = ocfs2_listxattr, 292462306a36Sopenharmony_ci .fiemap = ocfs2_fiemap, 292562306a36Sopenharmony_ci .get_inode_acl = ocfs2_iop_get_acl, 292662306a36Sopenharmony_ci .set_acl = ocfs2_iop_set_acl, 292762306a36Sopenharmony_ci .fileattr_get = ocfs2_fileattr_get, 292862306a36Sopenharmony_ci .fileattr_set = ocfs2_fileattr_set, 292962306a36Sopenharmony_ci}; 2930