unsigned long offset,
struct ocfs2_dir_entry **res_dir);
-static int ocfs2_delete_entry(struct ocfs2_journal_handle *handle,
+static int ocfs2_delete_entry(handle_t *handle,
struct inode *dir,
struct ocfs2_dir_entry *de_del,
struct buffer_head *bh);
-static int __ocfs2_add_entry(struct ocfs2_journal_handle *handle,
+static int __ocfs2_add_entry(handle_t *handle,
struct inode *dir,
const char *name, int namelen,
struct inode *inode, u64 blkno,
dev_t dev,
struct buffer_head **new_fe_bh,
struct buffer_head *parent_fe_bh,
- struct ocfs2_journal_handle *handle,
+ handle_t *handle,
struct inode **ret_inode,
struct ocfs2_alloc_context *inode_ac);
static int ocfs2_fill_new_dir(struct ocfs2_super *osb,
- struct ocfs2_journal_handle *handle,
+ handle_t *handle,
struct inode *parent,
struct inode *inode,
struct buffer_head *fe_bh,
struct ocfs2_alloc_context *data_ac);
-static int ocfs2_double_lock(struct ocfs2_super *osb,
- struct ocfs2_journal_handle *handle,
- struct buffer_head **bh1,
- struct inode *inode1,
- struct buffer_head **bh2,
- struct inode *inode2);
-
static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
struct inode **ret_orphan_dir,
struct inode *inode,
struct buffer_head **de_bh);
static int ocfs2_orphan_add(struct ocfs2_super *osb,
- struct ocfs2_journal_handle *handle,
+ handle_t *handle,
struct inode *inode,
struct ocfs2_dinode *fe,
char *name,
struct inode *orphan_dir_inode);
static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
- struct ocfs2_journal_handle *handle,
+ handle_t *handle,
struct inode *inode,
const char *symname);
-static inline int ocfs2_add_entry(struct ocfs2_journal_handle *handle,
+static inline int ocfs2_add_entry(handle_t *handle,
struct dentry *dentry,
struct inode *inode, u64 blkno,
struct buffer_head *parent_fe_bh,
mlog(0, "find name %.*s in directory %llu\n", dentry->d_name.len,
dentry->d_name.name, (unsigned long long)OCFS2_I(dir)->ip_blkno);
- status = ocfs2_meta_lock(dir, NULL, NULL, 0);
+ status = ocfs2_meta_lock(dir, NULL, 0);
if (status < 0) {
if (status != -ENOENT)
mlog_errno(status);
}
static int ocfs2_fill_new_dir(struct ocfs2_super *osb,
- struct ocfs2_journal_handle *handle,
+ handle_t *handle,
struct inode *parent,
struct inode *inode,
struct buffer_head *fe_bh,
{
int status = 0;
struct buffer_head *parent_fe_bh = NULL;
- struct ocfs2_journal_handle *handle = NULL;
+ handle_t *handle = NULL;
struct ocfs2_super *osb;
struct ocfs2_dinode *dirfe;
struct buffer_head *new_fe_bh = NULL;
/* get our super block */
osb = OCFS2_SB(dir->i_sb);
- status = ocfs2_meta_lock(dir, NULL, &parent_fe_bh, 1);
+ status = ocfs2_meta_lock(dir, &parent_fe_bh, 1);
if (status < 0) {
if (status != -ENOENT)
mlog_errno(status);
return status;
}
- handle = ocfs2_alloc_handle(osb);
- if (handle == NULL) {
- status = -ENOMEM;
- mlog_errno(status);
- goto leave;
- }
-
if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) {
status = -EMLINK;
goto leave;
}
/* reserve an inode spot */
- status = ocfs2_reserve_new_inode(osb, handle, &inode_ac);
+ status = ocfs2_reserve_new_inode(osb, &inode_ac);
if (status < 0) {
if (status != -ENOSPC)
mlog_errno(status);
/* are we making a directory? If so, reserve a cluster for his
* 1st extent. */
if (S_ISDIR(mode)) {
- status = ocfs2_reserve_clusters(osb, handle, 1, &data_ac);
+ status = ocfs2_reserve_clusters(osb, 1, &data_ac);
if (status < 0) {
if (status != -ENOSPC)
mlog_errno(status);
}
}
- handle = ocfs2_start_trans(osb, handle, OCFS2_MKNOD_CREDITS);
+ handle = ocfs2_start_trans(osb, OCFS2_MKNOD_CREDITS);
if (IS_ERR(handle)) {
status = PTR_ERR(handle);
handle = NULL;
status = 0;
leave:
if (handle)
- ocfs2_commit_trans(handle);
+ ocfs2_commit_trans(osb, handle);
ocfs2_meta_unlock(dir, 1);
dev_t dev,
struct buffer_head **new_fe_bh,
struct buffer_head *parent_fe_bh,
- struct ocfs2_journal_handle *handle,
+ handle_t *handle,
struct inode **ret_inode,
struct ocfs2_alloc_context *inode_ac)
{
struct inode *dir,
struct dentry *dentry)
{
- struct ocfs2_journal_handle *handle;
+ handle_t *handle;
struct inode *inode = old_dentry->d_inode;
int err;
struct buffer_head *fe_bh = NULL;
if (S_ISDIR(inode->i_mode))
return -EPERM;
- err = ocfs2_meta_lock(dir, NULL, &parent_fe_bh, 1);
+ err = ocfs2_meta_lock(dir, &parent_fe_bh, 1);
if (err < 0) {
if (err != -ENOENT)
mlog_errno(err);
goto out;
}
- err = ocfs2_meta_lock(inode, NULL, &fe_bh, 1);
+ err = ocfs2_meta_lock(inode, &fe_bh, 1);
if (err < 0) {
if (err != -ENOENT)
mlog_errno(err);
goto out_unlock_inode;
}
- handle = ocfs2_start_trans(osb, NULL, OCFS2_LINK_CREDITS);
+ handle = ocfs2_start_trans(osb, OCFS2_LINK_CREDITS);
if (IS_ERR(handle)) {
err = PTR_ERR(handle);
handle = NULL;
d_instantiate(dentry, inode);
out_commit:
- ocfs2_commit_trans(handle);
+ ocfs2_commit_trans(osb, handle);
out_unlock_inode:
ocfs2_meta_unlock(inode, 1);
struct dentry *dentry)
{
int status;
+ int child_locked = 0;
struct inode *inode = dentry->d_inode;
struct inode *orphan_dir = NULL;
struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
struct ocfs2_dinode *fe = NULL;
struct buffer_head *fe_bh = NULL;
struct buffer_head *parent_node_bh = NULL;
- struct ocfs2_journal_handle *handle = NULL;
+ handle_t *handle = NULL;
struct ocfs2_dir_entry *dirent = NULL;
struct buffer_head *dirent_bh = NULL;
char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
if (inode == osb->root_inode) {
mlog(0, "Cannot delete the root directory\n");
- status = -EPERM;
- goto leave;
- }
-
- handle = ocfs2_alloc_handle(osb);
- if (handle == NULL) {
- status = -ENOMEM;
- mlog_errno(status);
- goto leave;
+ return -EPERM;
}
- status = ocfs2_meta_lock(dir, handle, &parent_node_bh, 1);
+ status = ocfs2_meta_lock(dir, &parent_node_bh, 1);
if (status < 0) {
if (status != -ENOENT)
mlog_errno(status);
- goto leave;
+ return status;
}
status = ocfs2_find_files_on_disk(dentry->d_name.name,
goto leave;
}
- status = ocfs2_meta_lock(inode, handle, &fe_bh, 1);
+ status = ocfs2_meta_lock(inode, &fe_bh, 1);
if (status < 0) {
if (status != -ENOENT)
mlog_errno(status);
goto leave;
}
+ child_locked = 1;
if (S_ISDIR(inode->i_mode)) {
if (!ocfs2_empty_dir(inode)) {
}
}
- handle = ocfs2_start_trans(osb, handle, OCFS2_UNLINK_CREDITS);
+ handle = ocfs2_start_trans(osb, OCFS2_UNLINK_CREDITS);
if (IS_ERR(handle)) {
status = PTR_ERR(handle);
handle = NULL;
leave:
if (handle)
- ocfs2_commit_trans(handle);
+ ocfs2_commit_trans(osb, handle);
+
+ if (child_locked)
+ ocfs2_meta_unlock(inode, 1);
+
+ ocfs2_meta_unlock(dir, 1);
if (orphan_dir) {
/* This was locked for us in ocfs2_prepare_orphan_dir() */
* if they have the same id, then the 1st one is the only one locked.
*/
static int ocfs2_double_lock(struct ocfs2_super *osb,
- struct ocfs2_journal_handle *handle,
struct buffer_head **bh1,
struct inode *inode1,
struct buffer_head **bh2,
(unsigned long long)oi1->ip_blkno,
(unsigned long long)oi2->ip_blkno);
- BUG_ON(!handle);
-
if (*bh1)
*bh1 = NULL;
if (*bh2)
inode1 = tmpinode;
}
/* lock id2 */
- status = ocfs2_meta_lock(inode2, handle, bh2, 1);
+ status = ocfs2_meta_lock(inode2, bh2, 1);
if (status < 0) {
if (status != -ENOENT)
mlog_errno(status);
goto bail;
}
}
+
/* lock id1 */
- status = ocfs2_meta_lock(inode1, handle, bh1, 1);
+ status = ocfs2_meta_lock(inode1, bh1, 1);
if (status < 0) {
+ /*
+ * An error return must mean that no cluster locks
+ * were held on function exit.
+ */
+ if (oi1->ip_blkno != oi2->ip_blkno)
+ ocfs2_meta_unlock(inode2, 1);
+
if (status != -ENOENT)
mlog_errno(status);
- goto bail;
}
+
bail:
mlog_exit(status);
return status;
}
+static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2)
+{
+ ocfs2_meta_unlock(inode1, 1);
+
+ if (inode1 != inode2)
+ ocfs2_meta_unlock(inode2, 1);
+}
+
#define PARENT_INO(buffer) \
((struct ocfs2_dir_entry *) \
((char *)buffer + \
struct inode *new_dir,
struct dentry *new_dentry)
{
- int status = 0, rename_lock = 0;
+ int status = 0, rename_lock = 0, parents_locked = 0;
+ int old_child_locked = 0, new_child_locked = 0;
struct inode *old_inode = old_dentry->d_inode;
struct inode *new_inode = new_dentry->d_inode;
struct inode *orphan_dir = NULL;
struct buffer_head *insert_entry_bh = NULL;
struct ocfs2_super *osb = NULL;
u64 newfe_blkno;
- struct ocfs2_journal_handle *handle = NULL;
+ handle_t *handle = NULL;
struct buffer_head *old_dir_bh = NULL;
struct buffer_head *new_dir_bh = NULL;
struct ocfs2_dir_entry *old_de = NULL, *new_de = NULL; // dirent for old_dentry
rename_lock = 1;
}
- handle = ocfs2_alloc_handle(osb);
- if (handle == NULL) {
- status = -ENOMEM;
- mlog_errno(status);
- goto bail;
- }
-
/* if old and new are the same, this'll just do one lock. */
- status = ocfs2_double_lock(osb, handle,
- &old_dir_bh, old_dir,
- &new_dir_bh, new_dir);
+ status = ocfs2_double_lock(osb, &old_dir_bh, old_dir,
+ &new_dir_bh, new_dir);
if (status < 0) {
mlog_errno(status);
goto bail;
}
+ parents_locked = 1;
/* make sure both dirs have bhs
* get an extra ref on old_dir_bh if old==new */
* the vote thread on other nodes won't have to concurrently
* downconvert the inode and the dentry locks.
*/
- status = ocfs2_meta_lock(old_inode, handle, NULL, 1);
+ status = ocfs2_meta_lock(old_inode, NULL, 1);
if (status < 0) {
if (status != -ENOENT)
mlog_errno(status);
goto bail;
}
+ old_child_locked = 1;
status = ocfs2_remote_dentry_delete(old_dentry);
if (status < 0) {
goto bail;
}
- status = ocfs2_meta_lock(new_inode, handle, &newfe_bh, 1);
+ status = ocfs2_meta_lock(new_inode, &newfe_bh, 1);
if (status < 0) {
if (status != -ENOENT)
mlog_errno(status);
goto bail;
}
+ new_child_locked = 1;
status = ocfs2_remote_dentry_delete(new_dentry);
if (status < 0) {
}
}
- handle = ocfs2_start_trans(osb, handle, OCFS2_RENAME_CREDITS);
+ handle = ocfs2_start_trans(osb, OCFS2_RENAME_CREDITS);
if (IS_ERR(handle)) {
status = PTR_ERR(handle);
handle = NULL;
ocfs2_rename_unlock(osb);
if (handle)
- ocfs2_commit_trans(handle);
+ ocfs2_commit_trans(osb, handle);
+
+ if (parents_locked)
+ ocfs2_double_unlock(old_dir, new_dir);
+
+ if (old_child_locked)
+ ocfs2_meta_unlock(old_inode, 1);
+
+ if (new_child_locked)
+ ocfs2_meta_unlock(new_inode, 1);
if (orphan_dir) {
/* This was locked for us in ocfs2_prepare_orphan_dir() */
* data, including the null terminator.
*/
static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
- struct ocfs2_journal_handle *handle,
+ handle_t *handle,
struct inode *inode,
const char *symname)
{
struct buffer_head *parent_fe_bh = NULL;
struct ocfs2_dinode *fe = NULL;
struct ocfs2_dinode *dirfe;
- struct ocfs2_journal_handle *handle = NULL;
+ handle_t *handle = NULL;
struct ocfs2_alloc_context *inode_ac = NULL;
struct ocfs2_alloc_context *data_ac = NULL;
credits = ocfs2_calc_symlink_credits(sb);
- handle = ocfs2_alloc_handle(osb);
- if (handle == NULL) {
- status = -ENOMEM;
- mlog_errno(status);
- goto bail;
- }
-
/* lock the parent directory */
- status = ocfs2_meta_lock(dir, handle, &parent_fe_bh, 1);
+ status = ocfs2_meta_lock(dir, &parent_fe_bh, 1);
if (status < 0) {
if (status != -ENOENT)
mlog_errno(status);
- goto bail;
+ return status;
}
dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
goto bail;
}
- status = ocfs2_reserve_new_inode(osb, handle, &inode_ac);
+ status = ocfs2_reserve_new_inode(osb, &inode_ac);
if (status < 0) {
if (status != -ENOSPC)
mlog_errno(status);
/* don't reserve bitmap space for fast symlinks. */
if (l > ocfs2_fast_symlink_chars(sb)) {
- status = ocfs2_reserve_clusters(osb, handle, 1, &data_ac);
+ status = ocfs2_reserve_clusters(osb, 1, &data_ac);
if (status < 0) {
if (status != -ENOSPC)
mlog_errno(status);
}
}
- handle = ocfs2_start_trans(osb, handle, credits);
+ handle = ocfs2_start_trans(osb, credits);
if (IS_ERR(handle)) {
status = PTR_ERR(handle);
handle = NULL;
d_instantiate(dentry, inode);
bail:
if (handle)
- ocfs2_commit_trans(handle);
+ ocfs2_commit_trans(osb, handle);
+
+ ocfs2_meta_unlock(dir, 1);
+
if (new_fe_bh)
brelse(new_fe_bh);
if (parent_fe_bh)
* If you pass me insert_bh, I'll skip the search of the other dir
* blocks and put the record in there.
*/
-static int __ocfs2_add_entry(struct ocfs2_journal_handle *handle,
+static int __ocfs2_add_entry(handle_t *handle,
struct inode *dir,
const char *name, int namelen,
struct inode *inode, u64 blkno,
* ocfs2_delete_entry deletes a directory entry by merging it with the
* previous entry
*/
-static int ocfs2_delete_entry(struct ocfs2_journal_handle *handle,
+static int ocfs2_delete_entry(handle_t *handle,
struct inode *dir,
struct ocfs2_dir_entry *de_del,
struct buffer_head *bh)
mutex_lock(&orphan_dir_inode->i_mutex);
- status = ocfs2_meta_lock(orphan_dir_inode, NULL, &orphan_dir_bh, 1);
+ status = ocfs2_meta_lock(orphan_dir_inode, &orphan_dir_bh, 1);
if (status < 0) {
mlog_errno(status);
goto leave;
}
static int ocfs2_orphan_add(struct ocfs2_super *osb,
- struct ocfs2_journal_handle *handle,
+ handle_t *handle,
struct inode *inode,
struct ocfs2_dinode *fe,
char *name,
/* unlike orphan_add, we expect the orphan dir to already be locked here. */
int ocfs2_orphan_del(struct ocfs2_super *osb,
- struct ocfs2_journal_handle *handle,
+ handle_t *handle,
struct inode *orphan_dir_inode,
struct inode *inode,
struct buffer_head *orphan_dir_bh)
.rename = ocfs2_rename,
.setattr = ocfs2_setattr,
.getattr = ocfs2_getattr,
+ .permission = ocfs2_permission,
};