Commit 9623e5a2 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2:
  ocfs2: Fix a race in o2dlm lockres mastery
  Ocfs2: Handle deletion of reflinked oprhan inodes correctly.
  Ocfs2: Journaling i_flags and i_orphaned_slot when adding inode to orphan dir.
  ocfs2: Clear undo bits when local alloc is freed
  ocfs2: Init meta_ac properly in ocfs2_create_empty_xattr_block.
  ocfs2: Fix the update of name_offset when removing xattrs
  ocfs2: Always try for maximum bits with new local alloc windows
  ocfs2: set i_mode on disk during acl operations
  ocfs2: Update i_blocks in reflink operations.
  ocfs2: Change bg_chain check for ocfs2_validate_gd_parent.
  [PATCH] Skip check for mandatory locks when unlocking
parents 9f321603 14741472
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include "alloc.h" #include "alloc.h"
#include "dlmglue.h" #include "dlmglue.h"
#include "file.h" #include "file.h"
#include "inode.h"
#include "journal.h"
#include "ocfs2_fs.h" #include "ocfs2_fs.h"
#include "xattr.h" #include "xattr.h"
...@@ -165,6 +167,60 @@ static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type) ...@@ -165,6 +167,60 @@ static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type)
return acl; return acl;
} }
/*
* Helper function to set i_mode in memory and disk. Some call paths
* will not have di_bh or a journal handle to pass, in which case it
* will create it's own.
*/
static int ocfs2_acl_set_mode(struct inode *inode, struct buffer_head *di_bh,
handle_t *handle, umode_t new_mode)
{
int ret, commit_handle = 0;
struct ocfs2_dinode *di;
if (di_bh == NULL) {
ret = ocfs2_read_inode_block(inode, &di_bh);
if (ret) {
mlog_errno(ret);
goto out;
}
} else
get_bh(di_bh);
if (handle == NULL) {
handle = ocfs2_start_trans(OCFS2_SB(inode->i_sb),
OCFS2_INODE_UPDATE_CREDITS);
if (IS_ERR(handle)) {
ret = PTR_ERR(handle);
mlog_errno(ret);
goto out_brelse;
}
commit_handle = 1;
}
di = (struct ocfs2_dinode *)di_bh->b_data;
ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
OCFS2_JOURNAL_ACCESS_WRITE);
if (ret) {
mlog_errno(ret);
goto out_commit;
}
inode->i_mode = new_mode;
di->i_mode = cpu_to_le16(inode->i_mode);
ocfs2_journal_dirty(handle, di_bh);
out_commit:
if (commit_handle)
ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
out_brelse:
brelse(di_bh);
out:
return ret;
}
/* /*
* Set the access or default ACL of an inode. * Set the access or default ACL of an inode.
*/ */
...@@ -193,9 +249,14 @@ static int ocfs2_set_acl(handle_t *handle, ...@@ -193,9 +249,14 @@ static int ocfs2_set_acl(handle_t *handle,
if (ret < 0) if (ret < 0)
return ret; return ret;
else { else {
inode->i_mode = mode;
if (ret == 0) if (ret == 0)
acl = NULL; acl = NULL;
ret = ocfs2_acl_set_mode(inode, di_bh,
handle, mode);
if (ret)
return ret;
} }
} }
break; break;
...@@ -283,6 +344,7 @@ int ocfs2_init_acl(handle_t *handle, ...@@ -283,6 +344,7 @@ int ocfs2_init_acl(handle_t *handle,
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct posix_acl *acl = NULL; struct posix_acl *acl = NULL;
int ret = 0; int ret = 0;
mode_t mode;
if (!S_ISLNK(inode->i_mode)) { if (!S_ISLNK(inode->i_mode)) {
if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) { if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
...@@ -291,12 +353,17 @@ int ocfs2_init_acl(handle_t *handle, ...@@ -291,12 +353,17 @@ int ocfs2_init_acl(handle_t *handle,
if (IS_ERR(acl)) if (IS_ERR(acl))
return PTR_ERR(acl); return PTR_ERR(acl);
} }
if (!acl) if (!acl) {
inode->i_mode &= ~current_umask(); mode = inode->i_mode & ~current_umask();
ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
if (ret) {
mlog_errno(ret);
goto cleanup;
}
}
} }
if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) {
struct posix_acl *clone; struct posix_acl *clone;
mode_t mode;
if (S_ISDIR(inode->i_mode)) { if (S_ISDIR(inode->i_mode)) {
ret = ocfs2_set_acl(handle, inode, di_bh, ret = ocfs2_set_acl(handle, inode, di_bh,
...@@ -313,7 +380,7 @@ int ocfs2_init_acl(handle_t *handle, ...@@ -313,7 +380,7 @@ int ocfs2_init_acl(handle_t *handle,
mode = inode->i_mode; mode = inode->i_mode;
ret = posix_acl_create_masq(clone, &mode); ret = posix_acl_create_masq(clone, &mode);
if (ret >= 0) { if (ret >= 0) {
inode->i_mode = mode; ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
if (ret > 0) { if (ret > 0) {
ret = ocfs2_set_acl(handle, inode, ret = ocfs2_set_acl(handle, inode,
di_bh, ACL_TYPE_ACCESS, di_bh, ACL_TYPE_ACCESS,
......
...@@ -1875,7 +1875,6 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data, ...@@ -1875,7 +1875,6 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
ok: ok:
spin_unlock(&res->spinlock); spin_unlock(&res->spinlock);
} }
spin_unlock(&dlm->spinlock);
// mlog(0, "woo! got an assert_master from node %u!\n", // mlog(0, "woo! got an assert_master from node %u!\n",
// assert->node_idx); // assert->node_idx);
...@@ -1926,7 +1925,6 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data, ...@@ -1926,7 +1925,6 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
/* master is known, detach if not already detached. /* master is known, detach if not already detached.
* ensures that only one assert_master call will happen * ensures that only one assert_master call will happen
* on this mle. */ * on this mle. */
spin_lock(&dlm->spinlock);
spin_lock(&dlm->master_lock); spin_lock(&dlm->master_lock);
rr = atomic_read(&mle->mle_refs.refcount); rr = atomic_read(&mle->mle_refs.refcount);
...@@ -1959,7 +1957,6 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data, ...@@ -1959,7 +1957,6 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
__dlm_put_mle(mle); __dlm_put_mle(mle);
} }
spin_unlock(&dlm->master_lock); spin_unlock(&dlm->master_lock);
spin_unlock(&dlm->spinlock);
} else if (res) { } else if (res) {
if (res->owner != assert->node_idx) { if (res->owner != assert->node_idx) {
mlog(0, "assert_master from %u, but current " mlog(0, "assert_master from %u, but current "
...@@ -1967,6 +1964,7 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data, ...@@ -1967,6 +1964,7 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
res->owner, namelen, name); res->owner, namelen, name);
} }
} }
spin_unlock(&dlm->spinlock);
done: done:
ret = 0; ret = 0;
......
...@@ -891,6 +891,21 @@ static int ocfs2_query_inode_wipe(struct inode *inode, ...@@ -891,6 +891,21 @@ static int ocfs2_query_inode_wipe(struct inode *inode,
/* Do some basic inode verification... */ /* Do some basic inode verification... */
di = (struct ocfs2_dinode *) di_bh->b_data; di = (struct ocfs2_dinode *) di_bh->b_data;
if (!(di->i_flags & cpu_to_le32(OCFS2_ORPHANED_FL))) { if (!(di->i_flags & cpu_to_le32(OCFS2_ORPHANED_FL))) {
/*
* Inodes in the orphan dir must have ORPHANED_FL. The only
* inodes that come back out of the orphan dir are reflink
* targets. A reflink target may be moved out of the orphan
* dir between the time we scan the directory and the time we
* process it. This would lead to HAS_REFCOUNT_FL being set but
* ORPHANED_FL not.
*/
if (di->i_dyn_features & cpu_to_le16(OCFS2_HAS_REFCOUNT_FL)) {
mlog(0, "Reflinked inode %llu is no longer orphaned. "
"it shouldn't be deleted\n",
(unsigned long long)oi->ip_blkno);
goto bail;
}
/* for lack of a better error? */ /* for lack of a better error? */
status = -EEXIST; status = -EEXIST;
mlog(ML_ERROR, mlog(ML_ERROR,
......
...@@ -872,8 +872,10 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, ...@@ -872,8 +872,10 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
(unsigned long long)la_start_blk, (unsigned long long)la_start_blk,
(unsigned long long)blkno); (unsigned long long)blkno);
status = ocfs2_free_clusters(handle, main_bm_inode, status = ocfs2_release_clusters(handle,
main_bm_bh, blkno, count); main_bm_inode,
main_bm_bh, blkno,
count);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
goto bail; goto bail;
...@@ -984,8 +986,7 @@ static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb, ...@@ -984,8 +986,7 @@ static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
} }
retry_enospc: retry_enospc:
(*ac)->ac_bits_wanted = osb->local_alloc_bits; (*ac)->ac_bits_wanted = osb->local_alloc_default_bits;
status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac); status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac);
if (status == -ENOSPC) { if (status == -ENOSPC) {
if (ocfs2_recalc_la_window(osb, OCFS2_LA_EVENT_ENOSPC) == if (ocfs2_recalc_la_window(osb, OCFS2_LA_EVENT_ENOSPC) ==
...@@ -1061,6 +1062,7 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb, ...@@ -1061,6 +1062,7 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
OCFS2_LA_DISABLED) OCFS2_LA_DISABLED)
goto bail; goto bail;
ac->ac_bits_wanted = osb->local_alloc_default_bits;
status = ocfs2_claim_clusters(osb, handle, ac, status = ocfs2_claim_clusters(osb, handle, ac,
osb->local_alloc_bits, osb->local_alloc_bits,
&cluster_off, &cluster_off,
......
...@@ -133,7 +133,7 @@ int ocfs2_lock(struct file *file, int cmd, struct file_lock *fl) ...@@ -133,7 +133,7 @@ int ocfs2_lock(struct file *file, int cmd, struct file_lock *fl)
if (!(fl->fl_flags & FL_POSIX)) if (!(fl->fl_flags & FL_POSIX))
return -ENOLCK; return -ENOLCK;
if (__mandatory_lock(inode)) if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
return -ENOLCK; return -ENOLCK;
return ocfs2_plock(osb->cconn, OCFS2_I(inode)->ip_blkno, file, cmd, fl); return ocfs2_plock(osb->cconn, OCFS2_I(inode)->ip_blkno, file, cmd, fl);
......
...@@ -84,7 +84,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, ...@@ -84,7 +84,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
static int ocfs2_orphan_add(struct ocfs2_super *osb, static int ocfs2_orphan_add(struct ocfs2_super *osb,
handle_t *handle, handle_t *handle,
struct inode *inode, struct inode *inode,
struct ocfs2_dinode *fe, struct buffer_head *fe_bh,
char *name, char *name,
struct ocfs2_dir_lookup_result *lookup, struct ocfs2_dir_lookup_result *lookup,
struct inode *orphan_dir_inode); struct inode *orphan_dir_inode);
...@@ -879,7 +879,7 @@ static int ocfs2_unlink(struct inode *dir, ...@@ -879,7 +879,7 @@ static int ocfs2_unlink(struct inode *dir,
fe = (struct ocfs2_dinode *) fe_bh->b_data; fe = (struct ocfs2_dinode *) fe_bh->b_data;
if (inode_is_unlinkable(inode)) { if (inode_is_unlinkable(inode)) {
status = ocfs2_orphan_add(osb, handle, inode, fe, orphan_name, status = ocfs2_orphan_add(osb, handle, inode, fe_bh, orphan_name,
&orphan_insert, orphan_dir); &orphan_insert, orphan_dir);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
...@@ -1300,7 +1300,7 @@ static int ocfs2_rename(struct inode *old_dir, ...@@ -1300,7 +1300,7 @@ static int ocfs2_rename(struct inode *old_dir,
if (S_ISDIR(new_inode->i_mode) || if (S_ISDIR(new_inode->i_mode) ||
(ocfs2_read_links_count(newfe) == 1)) { (ocfs2_read_links_count(newfe) == 1)) {
status = ocfs2_orphan_add(osb, handle, new_inode, status = ocfs2_orphan_add(osb, handle, new_inode,
newfe, orphan_name, newfe_bh, orphan_name,
&orphan_insert, orphan_dir); &orphan_insert, orphan_dir);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
...@@ -1911,7 +1911,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb, ...@@ -1911,7 +1911,7 @@ static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
static int ocfs2_orphan_add(struct ocfs2_super *osb, static int ocfs2_orphan_add(struct ocfs2_super *osb,
handle_t *handle, handle_t *handle,
struct inode *inode, struct inode *inode,
struct ocfs2_dinode *fe, struct buffer_head *fe_bh,
char *name, char *name,
struct ocfs2_dir_lookup_result *lookup, struct ocfs2_dir_lookup_result *lookup,
struct inode *orphan_dir_inode) struct inode *orphan_dir_inode)
...@@ -1919,6 +1919,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, ...@@ -1919,6 +1919,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
struct buffer_head *orphan_dir_bh = NULL; struct buffer_head *orphan_dir_bh = NULL;
int status = 0; int status = 0;
struct ocfs2_dinode *orphan_fe; struct ocfs2_dinode *orphan_fe;
struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data;
mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino); mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
...@@ -1959,6 +1960,21 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, ...@@ -1959,6 +1960,21 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
goto leave; goto leave;
} }
/*
* We're going to journal the change of i_flags and i_orphaned_slot.
* It's safe anyway, though some callers may duplicate the journaling.
* Journaling within the func just make the logic look more
* straightforward.
*/
status = ocfs2_journal_access_di(handle,
INODE_CACHE(inode),
fe_bh,
OCFS2_JOURNAL_ACCESS_WRITE);
if (status < 0) {
mlog_errno(status);
goto leave;
}
le32_add_cpu(&fe->i_flags, OCFS2_ORPHANED_FL); le32_add_cpu(&fe->i_flags, OCFS2_ORPHANED_FL);
/* Record which orphan dir our inode now resides /* Record which orphan dir our inode now resides
...@@ -1966,6 +1982,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, ...@@ -1966,6 +1982,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
* dir to lock. */ * dir to lock. */
fe->i_orphaned_slot = cpu_to_le16(osb->slot_num); fe->i_orphaned_slot = cpu_to_le16(osb->slot_num);
ocfs2_journal_dirty(handle, fe_bh);
mlog(0, "Inode %llu orphaned in slot %d\n", mlog(0, "Inode %llu orphaned in slot %d\n",
(unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num); (unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num);
...@@ -2123,7 +2141,7 @@ int ocfs2_create_inode_in_orphan(struct inode *dir, ...@@ -2123,7 +2141,7 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
} }
di = (struct ocfs2_dinode *)new_di_bh->b_data; di = (struct ocfs2_dinode *)new_di_bh->b_data;
status = ocfs2_orphan_add(osb, handle, inode, di, orphan_name, status = ocfs2_orphan_add(osb, handle, inode, new_di_bh, orphan_name,
&orphan_insert, orphan_dir); &orphan_insert, orphan_dir);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
......
...@@ -763,8 +763,18 @@ static inline unsigned int ocfs2_megabytes_to_clusters(struct super_block *sb, ...@@ -763,8 +763,18 @@ static inline unsigned int ocfs2_megabytes_to_clusters(struct super_block *sb,
return megs << (20 - OCFS2_SB(sb)->s_clustersize_bits); return megs << (20 - OCFS2_SB(sb)->s_clustersize_bits);
} }
#define ocfs2_set_bit ext2_set_bit static inline void _ocfs2_set_bit(unsigned int bit, unsigned long *bitmap)
#define ocfs2_clear_bit ext2_clear_bit {
ext2_set_bit(bit, bitmap);
}
#define ocfs2_set_bit(bit, addr) _ocfs2_set_bit((bit), (unsigned long *)(addr))
static inline void _ocfs2_clear_bit(unsigned int bit, unsigned long *bitmap)
{
ext2_clear_bit(bit, bitmap);
}
#define ocfs2_clear_bit(bit, addr) _ocfs2_clear_bit((bit), (unsigned long *)(addr))
#define ocfs2_test_bit ext2_test_bit #define ocfs2_test_bit ext2_test_bit
#define ocfs2_find_next_zero_bit ext2_find_next_zero_bit #define ocfs2_find_next_zero_bit ext2_find_next_zero_bit
#define ocfs2_find_next_bit ext2_find_next_bit #define ocfs2_find_next_bit ext2_find_next_bit
......
...@@ -4075,6 +4075,7 @@ static int ocfs2_complete_reflink(struct inode *s_inode, ...@@ -4075,6 +4075,7 @@ static int ocfs2_complete_reflink(struct inode *s_inode,
OCFS2_I(t_inode)->ip_dyn_features = OCFS2_I(s_inode)->ip_dyn_features; OCFS2_I(t_inode)->ip_dyn_features = OCFS2_I(s_inode)->ip_dyn_features;
spin_unlock(&OCFS2_I(t_inode)->ip_lock); spin_unlock(&OCFS2_I(t_inode)->ip_lock);
i_size_write(t_inode, size); i_size_write(t_inode, size);
t_inode->i_blocks = s_inode->i_blocks;
di->i_xattr_inline_size = s_di->i_xattr_inline_size; di->i_xattr_inline_size = s_di->i_xattr_inline_size;
di->i_clusters = s_di->i_clusters; di->i_clusters = s_di->i_clusters;
......
...@@ -95,13 +95,6 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle, ...@@ -95,13 +95,6 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle,
struct buffer_head *group_bh, struct buffer_head *group_bh,
unsigned int bit_off, unsigned int bit_off,
unsigned int num_bits); unsigned int num_bits);
static inline int ocfs2_block_group_clear_bits(handle_t *handle,
struct inode *alloc_inode,
struct ocfs2_group_desc *bg,
struct buffer_head *group_bh,
unsigned int bit_off,
unsigned int num_bits);
static int ocfs2_relink_block_group(handle_t *handle, static int ocfs2_relink_block_group(handle_t *handle,
struct inode *alloc_inode, struct inode *alloc_inode,
struct buffer_head *fe_bh, struct buffer_head *fe_bh,
...@@ -152,7 +145,7 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl) ...@@ -152,7 +145,7 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl)
#define do_error(fmt, ...) \ #define do_error(fmt, ...) \
do{ \ do{ \
if (clean_error) \ if (resize) \
mlog(ML_ERROR, fmt "\n", ##__VA_ARGS__); \ mlog(ML_ERROR, fmt "\n", ##__VA_ARGS__); \
else \ else \
ocfs2_error(sb, fmt, ##__VA_ARGS__); \ ocfs2_error(sb, fmt, ##__VA_ARGS__); \
...@@ -160,7 +153,7 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl) ...@@ -160,7 +153,7 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl)
static int ocfs2_validate_gd_self(struct super_block *sb, static int ocfs2_validate_gd_self(struct super_block *sb,
struct buffer_head *bh, struct buffer_head *bh,
int clean_error) int resize)
{ {
struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
...@@ -211,7 +204,7 @@ static int ocfs2_validate_gd_self(struct super_block *sb, ...@@ -211,7 +204,7 @@ static int ocfs2_validate_gd_self(struct super_block *sb,
static int ocfs2_validate_gd_parent(struct super_block *sb, static int ocfs2_validate_gd_parent(struct super_block *sb,
struct ocfs2_dinode *di, struct ocfs2_dinode *di,
struct buffer_head *bh, struct buffer_head *bh,
int clean_error) int resize)
{ {
unsigned int max_bits; unsigned int max_bits;
struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
...@@ -233,8 +226,11 @@ static int ocfs2_validate_gd_parent(struct super_block *sb, ...@@ -233,8 +226,11 @@ static int ocfs2_validate_gd_parent(struct super_block *sb,
return -EINVAL; return -EINVAL;
} }
if (le16_to_cpu(gd->bg_chain) >= /* In resize, we may meet the case bg_chain == cl_next_free_rec. */
le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) { if ((le16_to_cpu(gd->bg_chain) >
le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) ||
((le16_to_cpu(gd->bg_chain) ==
le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) && !resize)) {
do_error("Group descriptor #%llu has bad chain %u", do_error("Group descriptor #%llu has bad chain %u",
(unsigned long long)bh->b_blocknr, (unsigned long long)bh->b_blocknr,
le16_to_cpu(gd->bg_chain)); le16_to_cpu(gd->bg_chain));
...@@ -1975,18 +1971,18 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb, ...@@ -1975,18 +1971,18 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
bits_wanted, cluster_start, num_clusters); bits_wanted, cluster_start, num_clusters);
} }
static inline int ocfs2_block_group_clear_bits(handle_t *handle, static int ocfs2_block_group_clear_bits(handle_t *handle,
struct inode *alloc_inode, struct inode *alloc_inode,
struct ocfs2_group_desc *bg, struct ocfs2_group_desc *bg,
struct buffer_head *group_bh, struct buffer_head *group_bh,
unsigned int bit_off, unsigned int bit_off,
unsigned int num_bits) unsigned int num_bits,
void (*undo_fn)(unsigned int bit,
unsigned long *bmap))
{ {
int status; int status;
unsigned int tmp; unsigned int tmp;
int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;
struct ocfs2_group_desc *undo_bg = NULL; struct ocfs2_group_desc *undo_bg = NULL;
int cluster_bitmap = 0;
mlog_entry_void(); mlog_entry_void();
...@@ -1996,20 +1992,18 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle, ...@@ -1996,20 +1992,18 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle,
mlog(0, "off = %u, num = %u\n", bit_off, num_bits); mlog(0, "off = %u, num = %u\n", bit_off, num_bits);
if (ocfs2_is_cluster_bitmap(alloc_inode)) BUG_ON(undo_fn && !ocfs2_is_cluster_bitmap(alloc_inode));
journal_type = OCFS2_JOURNAL_ACCESS_UNDO;
status = ocfs2_journal_access_gd(handle, INODE_CACHE(alloc_inode), status = ocfs2_journal_access_gd(handle, INODE_CACHE(alloc_inode),
group_bh, journal_type); group_bh,
undo_fn ?
OCFS2_JOURNAL_ACCESS_UNDO :
OCFS2_JOURNAL_ACCESS_WRITE);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
goto bail; goto bail;
} }
if (ocfs2_is_cluster_bitmap(alloc_inode)) if (undo_fn) {
cluster_bitmap = 1;
if (cluster_bitmap) {
jbd_lock_bh_state(group_bh); jbd_lock_bh_state(group_bh);
undo_bg = (struct ocfs2_group_desc *) undo_bg = (struct ocfs2_group_desc *)
bh2jh(group_bh)->b_committed_data; bh2jh(group_bh)->b_committed_data;
...@@ -2020,13 +2014,13 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle, ...@@ -2020,13 +2014,13 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle,
while(tmp--) { while(tmp--) {
ocfs2_clear_bit((bit_off + tmp), ocfs2_clear_bit((bit_off + tmp),
(unsigned long *) bg->bg_bitmap); (unsigned long *) bg->bg_bitmap);
if (cluster_bitmap) if (undo_fn)
ocfs2_set_bit(bit_off + tmp, undo_fn(bit_off + tmp,
(unsigned long *) undo_bg->bg_bitmap); (unsigned long *) undo_bg->bg_bitmap);
} }
le16_add_cpu(&bg->bg_free_bits_count, num_bits); le16_add_cpu(&bg->bg_free_bits_count, num_bits);
if (cluster_bitmap) if (undo_fn)
jbd_unlock_bh_state(group_bh); jbd_unlock_bh_state(group_bh);
status = ocfs2_journal_dirty(handle, group_bh); status = ocfs2_journal_dirty(handle, group_bh);
...@@ -2039,12 +2033,14 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle, ...@@ -2039,12 +2033,14 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle,
/* /*
* expects the suballoc inode to already be locked. * expects the suballoc inode to already be locked.
*/ */
int ocfs2_free_suballoc_bits(handle_t *handle, static int _ocfs2_free_suballoc_bits(handle_t *handle,
struct inode *alloc_inode, struct inode *alloc_inode,
struct buffer_head *alloc_bh, struct buffer_head *alloc_bh,
unsigned int start_bit, unsigned int start_bit,
u64 bg_blkno, u64 bg_blkno,
unsigned int count) unsigned int count,
void (*undo_fn)(unsigned int bit,
unsigned long *bitmap))
{ {
int status = 0; int status = 0;
u32 tmp_used; u32 tmp_used;
...@@ -2079,7 +2075,7 @@ int ocfs2_free_suballoc_bits(handle_t *handle, ...@@ -2079,7 +2075,7 @@ int ocfs2_free_suballoc_bits(handle_t *handle,
status = ocfs2_block_group_clear_bits(handle, alloc_inode, status = ocfs2_block_group_clear_bits(handle, alloc_inode,
group, group_bh, group, group_bh,
start_bit, count); start_bit, count, undo_fn);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
goto bail; goto bail;
...@@ -2110,6 +2106,17 @@ int ocfs2_free_suballoc_bits(handle_t *handle, ...@@ -2110,6 +2106,17 @@ int ocfs2_free_suballoc_bits(handle_t *handle,
return status; return status;
} }
int ocfs2_free_suballoc_bits(handle_t *handle,
struct inode *alloc_inode,
struct buffer_head *alloc_bh,
unsigned int start_bit,
u64 bg_blkno,
unsigned int count)
{
return _ocfs2_free_suballoc_bits(handle, alloc_inode, alloc_bh,
start_bit, bg_blkno, count, NULL);
}
int ocfs2_free_dinode(handle_t *handle, int ocfs2_free_dinode(handle_t *handle,
struct inode *inode_alloc_inode, struct inode *inode_alloc_inode,
struct buffer_head *inode_alloc_bh, struct buffer_head *inode_alloc_bh,
...@@ -2123,11 +2130,13 @@ int ocfs2_free_dinode(handle_t *handle, ...@@ -2123,11 +2130,13 @@ int ocfs2_free_dinode(handle_t *handle,
inode_alloc_bh, bit, bg_blkno, 1); inode_alloc_bh, bit, bg_blkno, 1);
} }
int ocfs2_free_clusters(handle_t *handle, static int _ocfs2_free_clusters(handle_t *handle,
struct inode *bitmap_inode, struct inode *bitmap_inode,
struct buffer_head *bitmap_bh, struct buffer_head *bitmap_bh,
u64 start_blk, u64 start_blk,
unsigned int num_clusters) unsigned int num_clusters,
void (*undo_fn)(unsigned int bit,
unsigned long *bitmap))
{ {
int status; int status;
u16 bg_start_bit; u16 bg_start_bit;
...@@ -2154,9 +2163,9 @@ int ocfs2_free_clusters(handle_t *handle, ...@@ -2154,9 +2163,9 @@ int ocfs2_free_clusters(handle_t *handle,
mlog(0, "bg_blkno = %llu, bg_start_bit = %u\n", mlog(0, "bg_blkno = %llu, bg_start_bit = %u\n",
(unsigned long long)bg_blkno, bg_start_bit); (unsigned long long)bg_blkno, bg_start_bit);
status = ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh, status = _ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
bg_start_bit, bg_blkno, bg_start_bit, bg_blkno,
num_clusters); num_clusters, undo_fn);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
goto out; goto out;
...@@ -2170,6 +2179,32 @@ int ocfs2_free_clusters(handle_t *handle, ...@@ -2170,6 +2179,32 @@ int ocfs2_free_clusters(handle_t *handle,
return status; return status;
} }
int ocfs2_free_clusters(handle_t *handle,
struct inode *bitmap_inode,
struct buffer_head *bitmap_bh,
u64 start_blk,
unsigned int num_clusters)
{
return _ocfs2_free_clusters(handle, bitmap_inode, bitmap_bh,
start_blk, num_clusters,
_ocfs2_set_bit);
}
/*
* Give never-used clusters back to the global bitmap. We don't need
* to protect these bits in the undo buffer.
*/
int ocfs2_release_clusters(handle_t *handle,
struct inode *bitmap_inode,
struct buffer_head *bitmap_bh,
u64 start_blk,
unsigned int num_clusters)
{
return _ocfs2_free_clusters(handle, bitmap_inode, bitmap_bh,
start_blk, num_clusters,
_ocfs2_clear_bit);
}
static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg) static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg)
{ {
printk("Block Group:\n"); printk("Block Group:\n");
......
...@@ -127,6 +127,11 @@ int ocfs2_free_clusters(handle_t *handle, ...@@ -127,6 +127,11 @@ int ocfs2_free_clusters(handle_t *handle,
struct buffer_head *bitmap_bh, struct buffer_head *bitmap_bh,
u64 start_blk, u64 start_blk,
unsigned int num_clusters); unsigned int num_clusters);
int ocfs2_release_clusters(handle_t *handle,
struct inode *bitmap_inode,
struct buffer_head *bitmap_bh,
u64 start_blk,
unsigned int num_clusters);
static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit) static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
{ {
......
...@@ -1622,7 +1622,7 @@ static void ocfs2_xa_block_wipe_namevalue(struct ocfs2_xa_loc *loc) ...@@ -1622,7 +1622,7 @@ static void ocfs2_xa_block_wipe_namevalue(struct ocfs2_xa_loc *loc)
/* Now tell xh->xh_entries about it */ /* Now tell xh->xh_entries about it */
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
offset = le16_to_cpu(xh->xh_entries[i].xe_name_offset); offset = le16_to_cpu(xh->xh_entries[i].xe_name_offset);
if (offset < namevalue_offset) if (offset <= namevalue_offset)
le16_add_cpu(&xh->xh_entries[i].xe_name_offset, le16_add_cpu(&xh->xh_entries[i].xe_name_offset,
namevalue_size); namevalue_size);
} }
...@@ -6528,13 +6528,11 @@ static int ocfs2_create_empty_xattr_block(struct inode *inode, ...@@ -6528,13 +6528,11 @@ static int ocfs2_create_empty_xattr_block(struct inode *inode,
int indexed) int indexed)
{ {
int ret; int ret;
struct ocfs2_alloc_context *meta_ac;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
struct ocfs2_xattr_set_ctxt ctxt = { struct ocfs2_xattr_set_ctxt ctxt;
.meta_ac = meta_ac,
};
ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac); memset(&ctxt, 0, sizeof(ctxt));
ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &ctxt.meta_ac);
if (ret < 0) { if (ret < 0) {
mlog_errno(ret); mlog_errno(ret);
return ret; return ret;
...@@ -6556,7 +6554,7 @@ static int ocfs2_create_empty_xattr_block(struct inode *inode, ...@@ -6556,7 +6554,7 @@ static int ocfs2_create_empty_xattr_block(struct inode *inode,
ocfs2_commit_trans(osb, ctxt.handle); ocfs2_commit_trans(osb, ctxt.handle);
out: out:
ocfs2_free_alloc_context(meta_ac); ocfs2_free_alloc_context(ctxt.meta_ac);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment