Loading fs/ocfs2/refcounttree.c +123 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include "extent_map.h" #include "aops.h" #include "xattr.h" #include "namei.h" #include <linux/bio.h> #include <linux/blkdev.h> Loading Loading @@ -4022,3 +4023,125 @@ static int ocfs2_create_reflink_node(struct inode *s_inode, return ret; } static int __ocfs2_reflink(struct dentry *old_dentry, struct buffer_head *old_bh, struct inode *new_inode, bool preserve) { int ret; struct inode *inode = old_dentry->d_inode; struct buffer_head *new_bh = NULL; ret = filemap_fdatawrite(inode->i_mapping); if (ret) { mlog_errno(ret); goto out; } ret = ocfs2_attach_refcount_tree(inode, old_bh); if (ret) { mlog_errno(ret); goto out; } mutex_lock(&new_inode->i_mutex); ret = ocfs2_inode_lock(new_inode, &new_bh, 1); if (ret) { mlog_errno(ret); goto out_unlock; } ret = ocfs2_create_reflink_node(inode, old_bh, new_inode, new_bh, preserve); if (ret) { mlog_errno(ret); goto inode_unlock; } if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_XATTR_FL) { ret = ocfs2_reflink_xattrs(inode, old_bh, new_inode, new_bh, preserve); if (ret) mlog_errno(ret); } inode_unlock: ocfs2_inode_unlock(new_inode, 1); brelse(new_bh); out_unlock: mutex_unlock(&new_inode->i_mutex); out: if (!ret) { ret = filemap_fdatawait(inode->i_mapping); if (ret) mlog_errno(ret); } return ret; } static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry, bool preserve) { int error; struct inode *inode = old_dentry->d_inode; struct buffer_head *old_bh = NULL; struct inode *new_orphan_inode = NULL; if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) return -EOPNOTSUPP; error = ocfs2_create_inode_in_orphan(dir, inode->i_mode, &new_orphan_inode); if (error) { mlog_errno(error); goto out; } error = ocfs2_inode_lock(inode, &old_bh, 1); if (error) { mlog_errno(error); goto out; } down_write(&OCFS2_I(inode)->ip_xattr_sem); down_write(&OCFS2_I(inode)->ip_alloc_sem); error = __ocfs2_reflink(old_dentry, old_bh, new_orphan_inode, preserve); up_write(&OCFS2_I(inode)->ip_alloc_sem); up_write(&OCFS2_I(inode)->ip_xattr_sem); ocfs2_inode_unlock(inode, 1); brelse(old_bh); if (error) { mlog_errno(error); goto out; } /* If the security isn't preserved, we need to re-initialize them. */ if (!preserve) { error = ocfs2_init_security_and_acl(dir, new_orphan_inode); if (error) mlog_errno(error); } out: if (!error) { error = ocfs2_mv_orphaned_inode_to_new(dir, new_orphan_inode, new_dentry); if (error) mlog_errno(error); } if (new_orphan_inode) { /* * We need to open_unlock the inode no matter whether we * succeed or not, so that other nodes can delete it later. */ ocfs2_open_unlock(new_orphan_inode); if (error) iput(new_orphan_inode); } return error; } Loading
fs/ocfs2/refcounttree.c +123 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include "extent_map.h" #include "aops.h" #include "xattr.h" #include "namei.h" #include <linux/bio.h> #include <linux/blkdev.h> Loading Loading @@ -4022,3 +4023,125 @@ static int ocfs2_create_reflink_node(struct inode *s_inode, return ret; } static int __ocfs2_reflink(struct dentry *old_dentry, struct buffer_head *old_bh, struct inode *new_inode, bool preserve) { int ret; struct inode *inode = old_dentry->d_inode; struct buffer_head *new_bh = NULL; ret = filemap_fdatawrite(inode->i_mapping); if (ret) { mlog_errno(ret); goto out; } ret = ocfs2_attach_refcount_tree(inode, old_bh); if (ret) { mlog_errno(ret); goto out; } mutex_lock(&new_inode->i_mutex); ret = ocfs2_inode_lock(new_inode, &new_bh, 1); if (ret) { mlog_errno(ret); goto out_unlock; } ret = ocfs2_create_reflink_node(inode, old_bh, new_inode, new_bh, preserve); if (ret) { mlog_errno(ret); goto inode_unlock; } if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_XATTR_FL) { ret = ocfs2_reflink_xattrs(inode, old_bh, new_inode, new_bh, preserve); if (ret) mlog_errno(ret); } inode_unlock: ocfs2_inode_unlock(new_inode, 1); brelse(new_bh); out_unlock: mutex_unlock(&new_inode->i_mutex); out: if (!ret) { ret = filemap_fdatawait(inode->i_mapping); if (ret) mlog_errno(ret); } return ret; } static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry, bool preserve) { int error; struct inode *inode = old_dentry->d_inode; struct buffer_head *old_bh = NULL; struct inode *new_orphan_inode = NULL; if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) return -EOPNOTSUPP; error = ocfs2_create_inode_in_orphan(dir, inode->i_mode, &new_orphan_inode); if (error) { mlog_errno(error); goto out; } error = ocfs2_inode_lock(inode, &old_bh, 1); if (error) { mlog_errno(error); goto out; } down_write(&OCFS2_I(inode)->ip_xattr_sem); down_write(&OCFS2_I(inode)->ip_alloc_sem); error = __ocfs2_reflink(old_dentry, old_bh, new_orphan_inode, preserve); up_write(&OCFS2_I(inode)->ip_alloc_sem); up_write(&OCFS2_I(inode)->ip_xattr_sem); ocfs2_inode_unlock(inode, 1); brelse(old_bh); if (error) { mlog_errno(error); goto out; } /* If the security isn't preserved, we need to re-initialize them. */ if (!preserve) { error = ocfs2_init_security_and_acl(dir, new_orphan_inode); if (error) mlog_errno(error); } out: if (!error) { error = ocfs2_mv_orphaned_inode_to_new(dir, new_orphan_inode, new_dentry); if (error) mlog_errno(error); } if (new_orphan_inode) { /* * We need to open_unlock the inode no matter whether we * succeed or not, so that other nodes can delete it later. */ ocfs2_open_unlock(new_orphan_inode); if (error) iput(new_orphan_inode); } return error; }