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
This commit is contained in:
commit
9623e5a237
|
@ -30,6 +30,8 @@
|
|||
#include "alloc.h"
|
||||
#include "dlmglue.h"
|
||||
#include "file.h"
|
||||
#include "inode.h"
|
||||
#include "journal.h"
|
||||
#include "ocfs2_fs.h"
|
||||
|
||||
#include "xattr.h"
|
||||
|
@ -165,6 +167,60 @@ static struct posix_acl *ocfs2_get_acl(struct inode *inode, int type)
|
|||
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.
|
||||
*/
|
||||
|
@ -193,9 +249,14 @@ static int ocfs2_set_acl(handle_t *handle,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
else {
|
||||
inode->i_mode = mode;
|
||||
if (ret == 0)
|
||||
acl = NULL;
|
||||
|
||||
ret = ocfs2_acl_set_mode(inode, di_bh,
|
||||
handle, mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -283,6 +344,7 @@ int ocfs2_init_acl(handle_t *handle,
|
|||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
struct posix_acl *acl = NULL;
|
||||
int ret = 0;
|
||||
mode_t mode;
|
||||
|
||||
if (!S_ISLNK(inode->i_mode)) {
|
||||
if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) {
|
||||
|
@ -291,12 +353,17 @@ int ocfs2_init_acl(handle_t *handle,
|
|||
if (IS_ERR(acl))
|
||||
return PTR_ERR(acl);
|
||||
}
|
||||
if (!acl)
|
||||
inode->i_mode &= ~current_umask();
|
||||
if (!acl) {
|
||||
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) {
|
||||
struct posix_acl *clone;
|
||||
mode_t mode;
|
||||
|
||||
if (S_ISDIR(inode->i_mode)) {
|
||||
ret = ocfs2_set_acl(handle, inode, di_bh,
|
||||
|
@ -313,7 +380,7 @@ int ocfs2_init_acl(handle_t *handle,
|
|||
mode = inode->i_mode;
|
||||
ret = posix_acl_create_masq(clone, &mode);
|
||||
if (ret >= 0) {
|
||||
inode->i_mode = mode;
|
||||
ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
|
||||
if (ret > 0) {
|
||||
ret = ocfs2_set_acl(handle, inode,
|
||||
di_bh, ACL_TYPE_ACCESS,
|
||||
|
|
|
@ -1875,7 +1875,6 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
|
|||
ok:
|
||||
spin_unlock(&res->spinlock);
|
||||
}
|
||||
spin_unlock(&dlm->spinlock);
|
||||
|
||||
// mlog(0, "woo! got an assert_master from node %u!\n",
|
||||
// assert->node_idx);
|
||||
|
@ -1926,7 +1925,6 @@ ok:
|
|||
/* master is known, detach if not already detached.
|
||||
* ensures that only one assert_master call will happen
|
||||
* on this mle. */
|
||||
spin_lock(&dlm->spinlock);
|
||||
spin_lock(&dlm->master_lock);
|
||||
|
||||
rr = atomic_read(&mle->mle_refs.refcount);
|
||||
|
@ -1959,7 +1957,6 @@ ok:
|
|||
__dlm_put_mle(mle);
|
||||
}
|
||||
spin_unlock(&dlm->master_lock);
|
||||
spin_unlock(&dlm->spinlock);
|
||||
} else if (res) {
|
||||
if (res->owner != assert->node_idx) {
|
||||
mlog(0, "assert_master from %u, but current "
|
||||
|
@ -1967,6 +1964,7 @@ ok:
|
|||
res->owner, namelen, name);
|
||||
}
|
||||
}
|
||||
spin_unlock(&dlm->spinlock);
|
||||
|
||||
done:
|
||||
ret = 0;
|
||||
|
|
|
@ -891,6 +891,21 @@ static int ocfs2_query_inode_wipe(struct inode *inode,
|
|||
/* Do some basic inode verification... */
|
||||
di = (struct ocfs2_dinode *) di_bh->b_data;
|
||||
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? */
|
||||
status = -EEXIST;
|
||||
mlog(ML_ERROR,
|
||||
|
|
|
@ -872,8 +872,10 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
|
|||
(unsigned long long)la_start_blk,
|
||||
(unsigned long long)blkno);
|
||||
|
||||
status = ocfs2_free_clusters(handle, main_bm_inode,
|
||||
main_bm_bh, blkno, count);
|
||||
status = ocfs2_release_clusters(handle,
|
||||
main_bm_inode,
|
||||
main_bm_bh, blkno,
|
||||
count);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
|
@ -984,8 +986,7 @@ static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
|
|||
}
|
||||
|
||||
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);
|
||||
if (status == -ENOSPC) {
|
||||
if (ocfs2_recalc_la_window(osb, OCFS2_LA_EVENT_ENOSPC) ==
|
||||
|
@ -1061,6 +1062,7 @@ retry_enospc:
|
|||
OCFS2_LA_DISABLED)
|
||||
goto bail;
|
||||
|
||||
ac->ac_bits_wanted = osb->local_alloc_default_bits;
|
||||
status = ocfs2_claim_clusters(osb, handle, ac,
|
||||
osb->local_alloc_bits,
|
||||
&cluster_off,
|
||||
|
|
|
@ -133,7 +133,7 @@ int ocfs2_lock(struct file *file, int cmd, struct file_lock *fl)
|
|||
|
||||
if (!(fl->fl_flags & FL_POSIX))
|
||||
return -ENOLCK;
|
||||
if (__mandatory_lock(inode))
|
||||
if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
|
||||
return -ENOLCK;
|
||||
|
||||
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,
|
|||
static int ocfs2_orphan_add(struct ocfs2_super *osb,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct ocfs2_dinode *fe,
|
||||
struct buffer_head *fe_bh,
|
||||
char *name,
|
||||
struct ocfs2_dir_lookup_result *lookup,
|
||||
struct inode *orphan_dir_inode);
|
||||
|
@ -879,7 +879,7 @@ static int ocfs2_unlink(struct inode *dir,
|
|||
fe = (struct ocfs2_dinode *) fe_bh->b_data;
|
||||
|
||||
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);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
|
@ -1300,7 +1300,7 @@ static int ocfs2_rename(struct inode *old_dir,
|
|||
if (S_ISDIR(new_inode->i_mode) ||
|
||||
(ocfs2_read_links_count(newfe) == 1)) {
|
||||
status = ocfs2_orphan_add(osb, handle, new_inode,
|
||||
newfe, orphan_name,
|
||||
newfe_bh, orphan_name,
|
||||
&orphan_insert, orphan_dir);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
|
@ -1911,7 +1911,7 @@ leave:
|
|||
static int ocfs2_orphan_add(struct ocfs2_super *osb,
|
||||
handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct ocfs2_dinode *fe,
|
||||
struct buffer_head *fe_bh,
|
||||
char *name,
|
||||
struct ocfs2_dir_lookup_result *lookup,
|
||||
struct inode *orphan_dir_inode)
|
||||
|
@ -1919,6 +1919,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
|
|||
struct buffer_head *orphan_dir_bh = NULL;
|
||||
int status = 0;
|
||||
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);
|
||||
|
||||
|
@ -1959,6 +1960,21 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
|
|||
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);
|
||||
|
||||
/* Record which orphan dir our inode now resides
|
||||
|
@ -1966,6 +1982,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
|
|||
* dir to lock. */
|
||||
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",
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num);
|
||||
|
||||
|
@ -2123,7 +2141,7 @@ int ocfs2_create_inode_in_orphan(struct inode *dir,
|
|||
}
|
||||
|
||||
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);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
#define ocfs2_set_bit ext2_set_bit
|
||||
#define ocfs2_clear_bit ext2_clear_bit
|
||||
static inline void _ocfs2_set_bit(unsigned int bit, unsigned long *bitmap)
|
||||
{
|
||||
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_find_next_zero_bit ext2_find_next_zero_bit
|
||||
#define ocfs2_find_next_bit ext2_find_next_bit
|
||||
|
|
|
@ -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;
|
||||
spin_unlock(&OCFS2_I(t_inode)->ip_lock);
|
||||
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_clusters = s_di->i_clusters;
|
||||
|
|
|
@ -95,13 +95,6 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle,
|
|||
struct buffer_head *group_bh,
|
||||
unsigned int bit_off,
|
||||
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,
|
||||
struct inode *alloc_inode,
|
||||
struct buffer_head *fe_bh,
|
||||
|
@ -152,7 +145,7 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl)
|
|||
|
||||
#define do_error(fmt, ...) \
|
||||
do{ \
|
||||
if (clean_error) \
|
||||
if (resize) \
|
||||
mlog(ML_ERROR, fmt "\n", ##__VA_ARGS__); \
|
||||
else \
|
||||
ocfs2_error(sb, fmt, ##__VA_ARGS__); \
|
||||
|
@ -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,
|
||||
struct buffer_head *bh,
|
||||
int clean_error)
|
||||
int resize)
|
||||
{
|
||||
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,
|
|||
static int ocfs2_validate_gd_parent(struct super_block *sb,
|
||||
struct ocfs2_dinode *di,
|
||||
struct buffer_head *bh,
|
||||
int clean_error)
|
||||
int resize)
|
||||
{
|
||||
unsigned int max_bits;
|
||||
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,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (le16_to_cpu(gd->bg_chain) >=
|
||||
le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) {
|
||||
/* In resize, we may meet the case bg_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",
|
||||
(unsigned long long)bh->b_blocknr,
|
||||
le16_to_cpu(gd->bg_chain));
|
||||
|
@ -1975,18 +1971,18 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
|
|||
bits_wanted, cluster_start, num_clusters);
|
||||
}
|
||||
|
||||
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_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,
|
||||
void (*undo_fn)(unsigned int bit,
|
||||
unsigned long *bmap))
|
||||
{
|
||||
int status;
|
||||
unsigned int tmp;
|
||||
int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;
|
||||
struct ocfs2_group_desc *undo_bg = NULL;
|
||||
int cluster_bitmap = 0;
|
||||
|
||||
mlog_entry_void();
|
||||
|
||||
|
@ -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);
|
||||
|
||||
if (ocfs2_is_cluster_bitmap(alloc_inode))
|
||||
journal_type = OCFS2_JOURNAL_ACCESS_UNDO;
|
||||
|
||||
BUG_ON(undo_fn && !ocfs2_is_cluster_bitmap(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) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (ocfs2_is_cluster_bitmap(alloc_inode))
|
||||
cluster_bitmap = 1;
|
||||
|
||||
if (cluster_bitmap) {
|
||||
if (undo_fn) {
|
||||
jbd_lock_bh_state(group_bh);
|
||||
undo_bg = (struct ocfs2_group_desc *)
|
||||
bh2jh(group_bh)->b_committed_data;
|
||||
|
@ -2020,13 +2014,13 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle,
|
|||
while(tmp--) {
|
||||
ocfs2_clear_bit((bit_off + tmp),
|
||||
(unsigned long *) bg->bg_bitmap);
|
||||
if (cluster_bitmap)
|
||||
ocfs2_set_bit(bit_off + tmp,
|
||||
(unsigned long *) undo_bg->bg_bitmap);
|
||||
if (undo_fn)
|
||||
undo_fn(bit_off + tmp,
|
||||
(unsigned long *) undo_bg->bg_bitmap);
|
||||
}
|
||||
le16_add_cpu(&bg->bg_free_bits_count, num_bits);
|
||||
|
||||
if (cluster_bitmap)
|
||||
if (undo_fn)
|
||||
jbd_unlock_bh_state(group_bh);
|
||||
|
||||
status = ocfs2_journal_dirty(handle, group_bh);
|
||||
|
@ -2039,12 +2033,14 @@ bail:
|
|||
/*
|
||||
* expects the suballoc inode to already be locked.
|
||||
*/
|
||||
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)
|
||||
static 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,
|
||||
void (*undo_fn)(unsigned int bit,
|
||||
unsigned long *bitmap))
|
||||
{
|
||||
int status = 0;
|
||||
u32 tmp_used;
|
||||
|
@ -2079,7 +2075,7 @@ int ocfs2_free_suballoc_bits(handle_t *handle,
|
|||
|
||||
status = ocfs2_block_group_clear_bits(handle, alloc_inode,
|
||||
group, group_bh,
|
||||
start_bit, count);
|
||||
start_bit, count, undo_fn);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
|
@ -2110,6 +2106,17 @@ bail:
|
|||
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,
|
||||
struct inode *inode_alloc_inode,
|
||||
struct buffer_head *inode_alloc_bh,
|
||||
|
@ -2123,11 +2130,13 @@ int ocfs2_free_dinode(handle_t *handle,
|
|||
inode_alloc_bh, bit, bg_blkno, 1);
|
||||
}
|
||||
|
||||
int ocfs2_free_clusters(handle_t *handle,
|
||||
struct inode *bitmap_inode,
|
||||
struct buffer_head *bitmap_bh,
|
||||
u64 start_blk,
|
||||
unsigned int num_clusters)
|
||||
static int _ocfs2_free_clusters(handle_t *handle,
|
||||
struct inode *bitmap_inode,
|
||||
struct buffer_head *bitmap_bh,
|
||||
u64 start_blk,
|
||||
unsigned int num_clusters,
|
||||
void (*undo_fn)(unsigned int bit,
|
||||
unsigned long *bitmap))
|
||||
{
|
||||
int status;
|
||||
u16 bg_start_bit;
|
||||
|
@ -2154,9 +2163,9 @@ int ocfs2_free_clusters(handle_t *handle,
|
|||
mlog(0, "bg_blkno = %llu, bg_start_bit = %u\n",
|
||||
(unsigned long long)bg_blkno, bg_start_bit);
|
||||
|
||||
status = ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
|
||||
bg_start_bit, bg_blkno,
|
||||
num_clusters);
|
||||
status = _ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
|
||||
bg_start_bit, bg_blkno,
|
||||
num_clusters, undo_fn);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto out;
|
||||
|
@ -2170,6 +2179,32 @@ out:
|
|||
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)
|
||||
{
|
||||
printk("Block Group:\n");
|
||||
|
|
|
@ -127,6 +127,11 @@ int ocfs2_free_clusters(handle_t *handle,
|
|||
struct buffer_head *bitmap_bh,
|
||||
u64 start_blk,
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -1622,7 +1622,7 @@ static void ocfs2_xa_block_wipe_namevalue(struct ocfs2_xa_loc *loc)
|
|||
/* Now tell xh->xh_entries about it */
|
||||
for (i = 0; i < count; i++) {
|
||||
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,
|
||||
namevalue_size);
|
||||
}
|
||||
|
@ -6528,13 +6528,11 @@ static int ocfs2_create_empty_xattr_block(struct inode *inode,
|
|||
int indexed)
|
||||
{
|
||||
int ret;
|
||||
struct ocfs2_alloc_context *meta_ac;
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
struct ocfs2_xattr_set_ctxt ctxt = {
|
||||
.meta_ac = meta_ac,
|
||||
};
|
||||
struct ocfs2_xattr_set_ctxt ctxt;
|
||||
|
||||
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) {
|
||||
mlog_errno(ret);
|
||||
return ret;
|
||||
|
@ -6556,7 +6554,7 @@ static int ocfs2_create_empty_xattr_block(struct inode *inode,
|
|||
|
||||
ocfs2_commit_trans(osb, ctxt.handle);
|
||||
out:
|
||||
ocfs2_free_alloc_context(meta_ac);
|
||||
ocfs2_free_alloc_context(ctxt.meta_ac);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue