mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
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: (22 commits) ocfs2: Fix possible deadlock when extending quota file ocfs2: keep index within status_map[] ocfs2: Initialize the cluster we're writing to in a non-sparse extend ocfs2: Remove redundant BUG_ON in __dlm_queue_ast() ocfs2/quota: Release lock for error in ocfs2_quota_write. ocfs2: Define credit counts for quota operations ocfs2: Remove syncjiff field from quota info ocfs2: Fix initialization of blockcheck stats ocfs2: Zero out padding of on disk dquot structure ocfs2: Initialize blocks allocated to local quota file ocfs2: Mark buffer uptodate before calling ocfs2_journal_access_dq() ocfs2: Make global quota files blocksize aligned ocfs2: Use ocfs2_rec_clusters in ocfs2_adjust_adjacent_records. ocfs2: Fix deadlock on umount ocfs2: Add extra credits and access the modified bh in update_edge_lengths. ocfs2: Fail ocfs2_get_block() immediately when a block needs allocation ocfs2: Fix error return in ocfs2_write_cluster() ocfs2: Fix compilation warning for fs/ocfs2/xattr.c ocfs2: Initialize count in aio_write before generic_write_checks ocfs2: log the actual return value of ocfs2_file_aio_write() ...
This commit is contained in:
commit
bc7af9ba15
16 changed files with 366 additions and 144 deletions
|
@ -1914,7 +1914,8 @@ static void ocfs2_adjust_adjacent_records(struct ocfs2_extent_rec *left_rec,
|
||||||
* immediately to their right.
|
* immediately to their right.
|
||||||
*/
|
*/
|
||||||
left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos);
|
left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos);
|
||||||
if (ocfs2_is_empty_extent(&right_child_el->l_recs[0])) {
|
if (!ocfs2_rec_clusters(right_child_el, &right_child_el->l_recs[0])) {
|
||||||
|
BUG_ON(right_child_el->l_tree_depth);
|
||||||
BUG_ON(le16_to_cpu(right_child_el->l_next_free_rec) <= 1);
|
BUG_ON(le16_to_cpu(right_child_el->l_next_free_rec) <= 1);
|
||||||
left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos);
|
left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos);
|
||||||
}
|
}
|
||||||
|
@ -2476,15 +2477,37 @@ out_ret_path:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
|
static int ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
|
||||||
struct ocfs2_path *path)
|
int subtree_index, struct ocfs2_path *path)
|
||||||
{
|
{
|
||||||
int i, idx;
|
int i, idx, ret;
|
||||||
struct ocfs2_extent_rec *rec;
|
struct ocfs2_extent_rec *rec;
|
||||||
struct ocfs2_extent_list *el;
|
struct ocfs2_extent_list *el;
|
||||||
struct ocfs2_extent_block *eb;
|
struct ocfs2_extent_block *eb;
|
||||||
u32 range;
|
u32 range;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In normal tree rotation process, we will never touch the
|
||||||
|
* tree branch above subtree_index and ocfs2_extend_rotate_transaction
|
||||||
|
* doesn't reserve the credits for them either.
|
||||||
|
*
|
||||||
|
* But we do have a special case here which will update the rightmost
|
||||||
|
* records for all the bh in the path.
|
||||||
|
* So we have to allocate extra credits and access them.
|
||||||
|
*/
|
||||||
|
ret = ocfs2_extend_trans(handle,
|
||||||
|
handle->h_buffer_credits + subtree_index);
|
||||||
|
if (ret) {
|
||||||
|
mlog_errno(ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ocfs2_journal_access_path(inode, handle, path);
|
||||||
|
if (ret) {
|
||||||
|
mlog_errno(ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* Path should always be rightmost. */
|
/* Path should always be rightmost. */
|
||||||
eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
|
eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
|
||||||
BUG_ON(eb->h_next_leaf_blk != 0ULL);
|
BUG_ON(eb->h_next_leaf_blk != 0ULL);
|
||||||
|
@ -2505,6 +2528,8 @@ static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
|
||||||
|
|
||||||
ocfs2_journal_dirty(handle, path->p_node[i].bh);
|
ocfs2_journal_dirty(handle, path->p_node[i].bh);
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ocfs2_unlink_path(struct inode *inode, handle_t *handle,
|
static void ocfs2_unlink_path(struct inode *inode, handle_t *handle,
|
||||||
|
@ -2717,7 +2742,12 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
|
||||||
if (del_right_subtree) {
|
if (del_right_subtree) {
|
||||||
ocfs2_unlink_subtree(inode, handle, left_path, right_path,
|
ocfs2_unlink_subtree(inode, handle, left_path, right_path,
|
||||||
subtree_index, dealloc);
|
subtree_index, dealloc);
|
||||||
ocfs2_update_edge_lengths(inode, handle, left_path);
|
ret = ocfs2_update_edge_lengths(inode, handle, subtree_index,
|
||||||
|
left_path);
|
||||||
|
if (ret) {
|
||||||
|
mlog_errno(ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
|
eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
|
||||||
ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
|
ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
|
||||||
|
@ -3034,7 +3064,12 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
|
||||||
|
|
||||||
ocfs2_unlink_subtree(inode, handle, left_path, path,
|
ocfs2_unlink_subtree(inode, handle, left_path, path,
|
||||||
subtree_index, dealloc);
|
subtree_index, dealloc);
|
||||||
ocfs2_update_edge_lengths(inode, handle, left_path);
|
ret = ocfs2_update_edge_lengths(inode, handle, subtree_index,
|
||||||
|
left_path);
|
||||||
|
if (ret) {
|
||||||
|
mlog_errno(ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
|
eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
|
||||||
ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
|
ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
|
||||||
|
|
|
@ -193,6 +193,7 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
|
||||||
(unsigned long long)OCFS2_I(inode)->ip_blkno);
|
(unsigned long long)OCFS2_I(inode)->ip_blkno);
|
||||||
mlog(ML_ERROR, "Size %llu, clusters %u\n", (unsigned long long)i_size_read(inode), OCFS2_I(inode)->ip_clusters);
|
mlog(ML_ERROR, "Size %llu, clusters %u\n", (unsigned long long)i_size_read(inode), OCFS2_I(inode)->ip_clusters);
|
||||||
dump_stack();
|
dump_stack();
|
||||||
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode));
|
past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode));
|
||||||
|
@ -894,18 +895,17 @@ struct ocfs2_write_cluster_desc {
|
||||||
*/
|
*/
|
||||||
unsigned c_new;
|
unsigned c_new;
|
||||||
unsigned c_unwritten;
|
unsigned c_unwritten;
|
||||||
|
unsigned c_needs_zero;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d)
|
|
||||||
{
|
|
||||||
return d->c_new || d->c_unwritten;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ocfs2_write_ctxt {
|
struct ocfs2_write_ctxt {
|
||||||
/* Logical cluster position / len of write */
|
/* Logical cluster position / len of write */
|
||||||
u32 w_cpos;
|
u32 w_cpos;
|
||||||
u32 w_clen;
|
u32 w_clen;
|
||||||
|
|
||||||
|
/* First cluster allocated in a nonsparse extend */
|
||||||
|
u32 w_first_new_cpos;
|
||||||
|
|
||||||
struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE];
|
struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -983,6 +983,7 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
wc->w_cpos = pos >> osb->s_clustersize_bits;
|
wc->w_cpos = pos >> osb->s_clustersize_bits;
|
||||||
|
wc->w_first_new_cpos = UINT_MAX;
|
||||||
cend = (pos + len - 1) >> osb->s_clustersize_bits;
|
cend = (pos + len - 1) >> osb->s_clustersize_bits;
|
||||||
wc->w_clen = cend - wc->w_cpos + 1;
|
wc->w_clen = cend - wc->w_cpos + 1;
|
||||||
get_bh(di_bh);
|
get_bh(di_bh);
|
||||||
|
@ -1217,20 +1218,18 @@ out:
|
||||||
*/
|
*/
|
||||||
static int ocfs2_write_cluster(struct address_space *mapping,
|
static int ocfs2_write_cluster(struct address_space *mapping,
|
||||||
u32 phys, unsigned int unwritten,
|
u32 phys, unsigned int unwritten,
|
||||||
|
unsigned int should_zero,
|
||||||
struct ocfs2_alloc_context *data_ac,
|
struct ocfs2_alloc_context *data_ac,
|
||||||
struct ocfs2_alloc_context *meta_ac,
|
struct ocfs2_alloc_context *meta_ac,
|
||||||
struct ocfs2_write_ctxt *wc, u32 cpos,
|
struct ocfs2_write_ctxt *wc, u32 cpos,
|
||||||
loff_t user_pos, unsigned user_len)
|
loff_t user_pos, unsigned user_len)
|
||||||
{
|
{
|
||||||
int ret, i, new, should_zero = 0;
|
int ret, i, new;
|
||||||
u64 v_blkno, p_blkno;
|
u64 v_blkno, p_blkno;
|
||||||
struct inode *inode = mapping->host;
|
struct inode *inode = mapping->host;
|
||||||
struct ocfs2_extent_tree et;
|
struct ocfs2_extent_tree et;
|
||||||
|
|
||||||
new = phys == 0 ? 1 : 0;
|
new = phys == 0 ? 1 : 0;
|
||||||
if (new || unwritten)
|
|
||||||
should_zero = 1;
|
|
||||||
|
|
||||||
if (new) {
|
if (new) {
|
||||||
u32 tmp_pos;
|
u32 tmp_pos;
|
||||||
|
|
||||||
|
@ -1301,7 +1300,7 @@ static int ocfs2_write_cluster(struct address_space *mapping,
|
||||||
if (tmpret) {
|
if (tmpret) {
|
||||||
mlog_errno(tmpret);
|
mlog_errno(tmpret);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
tmpret = ret;
|
ret = tmpret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1341,7 +1340,9 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping,
|
||||||
local_len = osb->s_clustersize - cluster_off;
|
local_len = osb->s_clustersize - cluster_off;
|
||||||
|
|
||||||
ret = ocfs2_write_cluster(mapping, desc->c_phys,
|
ret = ocfs2_write_cluster(mapping, desc->c_phys,
|
||||||
desc->c_unwritten, data_ac, meta_ac,
|
desc->c_unwritten,
|
||||||
|
desc->c_needs_zero,
|
||||||
|
data_ac, meta_ac,
|
||||||
wc, desc->c_cpos, pos, local_len);
|
wc, desc->c_cpos, pos, local_len);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mlog_errno(ret);
|
mlog_errno(ret);
|
||||||
|
@ -1391,14 +1392,14 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
|
||||||
* newly allocated cluster.
|
* newly allocated cluster.
|
||||||
*/
|
*/
|
||||||
desc = &wc->w_desc[0];
|
desc = &wc->w_desc[0];
|
||||||
if (ocfs2_should_zero_cluster(desc))
|
if (desc->c_needs_zero)
|
||||||
ocfs2_figure_cluster_boundaries(osb,
|
ocfs2_figure_cluster_boundaries(osb,
|
||||||
desc->c_cpos,
|
desc->c_cpos,
|
||||||
&wc->w_target_from,
|
&wc->w_target_from,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
desc = &wc->w_desc[wc->w_clen - 1];
|
desc = &wc->w_desc[wc->w_clen - 1];
|
||||||
if (ocfs2_should_zero_cluster(desc))
|
if (desc->c_needs_zero)
|
||||||
ocfs2_figure_cluster_boundaries(osb,
|
ocfs2_figure_cluster_boundaries(osb,
|
||||||
desc->c_cpos,
|
desc->c_cpos,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -1466,13 +1467,28 @@ static int ocfs2_populate_write_desc(struct inode *inode,
|
||||||
phys++;
|
phys++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If w_first_new_cpos is < UINT_MAX, we have a non-sparse
|
||||||
|
* file that got extended. w_first_new_cpos tells us
|
||||||
|
* where the newly allocated clusters are so we can
|
||||||
|
* zero them.
|
||||||
|
*/
|
||||||
|
if (desc->c_cpos >= wc->w_first_new_cpos) {
|
||||||
|
BUG_ON(phys == 0);
|
||||||
|
desc->c_needs_zero = 1;
|
||||||
|
}
|
||||||
|
|
||||||
desc->c_phys = phys;
|
desc->c_phys = phys;
|
||||||
if (phys == 0) {
|
if (phys == 0) {
|
||||||
desc->c_new = 1;
|
desc->c_new = 1;
|
||||||
|
desc->c_needs_zero = 1;
|
||||||
*clusters_to_alloc = *clusters_to_alloc + 1;
|
*clusters_to_alloc = *clusters_to_alloc + 1;
|
||||||
}
|
}
|
||||||
if (ext_flags & OCFS2_EXT_UNWRITTEN)
|
|
||||||
|
if (ext_flags & OCFS2_EXT_UNWRITTEN) {
|
||||||
desc->c_unwritten = 1;
|
desc->c_unwritten = 1;
|
||||||
|
desc->c_needs_zero = 1;
|
||||||
|
}
|
||||||
|
|
||||||
num_clusters--;
|
num_clusters--;
|
||||||
}
|
}
|
||||||
|
@ -1632,10 +1648,13 @@ static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos,
|
||||||
if (newsize <= i_size_read(inode))
|
if (newsize <= i_size_read(inode))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = ocfs2_extend_no_holes(inode, newsize, newsize - len);
|
ret = ocfs2_extend_no_holes(inode, newsize, pos);
|
||||||
if (ret)
|
if (ret)
|
||||||
mlog_errno(ret);
|
mlog_errno(ret);
|
||||||
|
|
||||||
|
wc->w_first_new_cpos =
|
||||||
|
ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1644,7 +1663,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
|
||||||
struct page **pagep, void **fsdata,
|
struct page **pagep, void **fsdata,
|
||||||
struct buffer_head *di_bh, struct page *mmap_page)
|
struct buffer_head *di_bh, struct page *mmap_page)
|
||||||
{
|
{
|
||||||
int ret, credits = OCFS2_INODE_UPDATE_CREDITS;
|
int ret, cluster_of_pages, credits = OCFS2_INODE_UPDATE_CREDITS;
|
||||||
unsigned int clusters_to_alloc, extents_to_split;
|
unsigned int clusters_to_alloc, extents_to_split;
|
||||||
struct ocfs2_write_ctxt *wc;
|
struct ocfs2_write_ctxt *wc;
|
||||||
struct inode *inode = mapping->host;
|
struct inode *inode = mapping->host;
|
||||||
|
@ -1722,8 +1741,19 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ocfs2_set_target_boundaries(osb, wc, pos, len,
|
/*
|
||||||
clusters_to_alloc + extents_to_split);
|
* We have to zero sparse allocated clusters, unwritten extent clusters,
|
||||||
|
* and non-sparse clusters we just extended. For non-sparse writes,
|
||||||
|
* we know zeros will only be needed in the first and/or last cluster.
|
||||||
|
*/
|
||||||
|
if (clusters_to_alloc || extents_to_split ||
|
||||||
|
wc->w_desc[0].c_needs_zero ||
|
||||||
|
wc->w_desc[wc->w_clen - 1].c_needs_zero)
|
||||||
|
cluster_of_pages = 1;
|
||||||
|
else
|
||||||
|
cluster_of_pages = 0;
|
||||||
|
|
||||||
|
ocfs2_set_target_boundaries(osb, wc, pos, len, cluster_of_pages);
|
||||||
|
|
||||||
handle = ocfs2_start_trans(osb, credits);
|
handle = ocfs2_start_trans(osb, credits);
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
|
@ -1756,8 +1786,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
|
||||||
* extent.
|
* extent.
|
||||||
*/
|
*/
|
||||||
ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos,
|
ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos,
|
||||||
clusters_to_alloc + extents_to_split,
|
cluster_of_pages, mmap_page);
|
||||||
mmap_page);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mlog_errno(ret);
|
mlog_errno(ret);
|
||||||
goto out_quota;
|
goto out_quota;
|
||||||
|
|
|
@ -310,22 +310,19 @@ out_attach:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(dentry_list_lock);
|
DEFINE_SPINLOCK(dentry_list_lock);
|
||||||
|
|
||||||
/* We limit the number of dentry locks to drop in one go. We have
|
/* We limit the number of dentry locks to drop in one go. We have
|
||||||
* this limit so that we don't starve other users of ocfs2_wq. */
|
* this limit so that we don't starve other users of ocfs2_wq. */
|
||||||
#define DL_INODE_DROP_COUNT 64
|
#define DL_INODE_DROP_COUNT 64
|
||||||
|
|
||||||
/* Drop inode references from dentry locks */
|
/* Drop inode references from dentry locks */
|
||||||
void ocfs2_drop_dl_inodes(struct work_struct *work)
|
static void __ocfs2_drop_dl_inodes(struct ocfs2_super *osb, int drop_count)
|
||||||
{
|
{
|
||||||
struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
|
|
||||||
dentry_lock_work);
|
|
||||||
struct ocfs2_dentry_lock *dl;
|
struct ocfs2_dentry_lock *dl;
|
||||||
int drop_count = DL_INODE_DROP_COUNT;
|
|
||||||
|
|
||||||
spin_lock(&dentry_list_lock);
|
spin_lock(&dentry_list_lock);
|
||||||
while (osb->dentry_lock_list && drop_count--) {
|
while (osb->dentry_lock_list && (drop_count < 0 || drop_count--)) {
|
||||||
dl = osb->dentry_lock_list;
|
dl = osb->dentry_lock_list;
|
||||||
osb->dentry_lock_list = dl->dl_next;
|
osb->dentry_lock_list = dl->dl_next;
|
||||||
spin_unlock(&dentry_list_lock);
|
spin_unlock(&dentry_list_lock);
|
||||||
|
@ -333,11 +330,32 @@ void ocfs2_drop_dl_inodes(struct work_struct *work)
|
||||||
kfree(dl);
|
kfree(dl);
|
||||||
spin_lock(&dentry_list_lock);
|
spin_lock(&dentry_list_lock);
|
||||||
}
|
}
|
||||||
if (osb->dentry_lock_list)
|
spin_unlock(&dentry_list_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ocfs2_drop_dl_inodes(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
|
||||||
|
dentry_lock_work);
|
||||||
|
|
||||||
|
__ocfs2_drop_dl_inodes(osb, DL_INODE_DROP_COUNT);
|
||||||
|
/*
|
||||||
|
* Don't queue dropping if umount is in progress. We flush the
|
||||||
|
* list in ocfs2_dismount_volume
|
||||||
|
*/
|
||||||
|
spin_lock(&dentry_list_lock);
|
||||||
|
if (osb->dentry_lock_list &&
|
||||||
|
!ocfs2_test_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED))
|
||||||
queue_work(ocfs2_wq, &osb->dentry_lock_work);
|
queue_work(ocfs2_wq, &osb->dentry_lock_work);
|
||||||
spin_unlock(&dentry_list_lock);
|
spin_unlock(&dentry_list_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Flush the whole work queue */
|
||||||
|
void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb)
|
||||||
|
{
|
||||||
|
__ocfs2_drop_dl_inodes(osb, -1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ocfs2_dentry_iput() and friends.
|
* ocfs2_dentry_iput() and friends.
|
||||||
*
|
*
|
||||||
|
@ -368,7 +386,8 @@ static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
|
||||||
/* We leave dropping of inode reference to ocfs2_wq as that can
|
/* We leave dropping of inode reference to ocfs2_wq as that can
|
||||||
* possibly lead to inode deletion which gets tricky */
|
* possibly lead to inode deletion which gets tricky */
|
||||||
spin_lock(&dentry_list_lock);
|
spin_lock(&dentry_list_lock);
|
||||||
if (!osb->dentry_lock_list)
|
if (!osb->dentry_lock_list &&
|
||||||
|
!ocfs2_test_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED))
|
||||||
queue_work(ocfs2_wq, &osb->dentry_lock_work);
|
queue_work(ocfs2_wq, &osb->dentry_lock_work);
|
||||||
dl->dl_next = osb->dentry_lock_list;
|
dl->dl_next = osb->dentry_lock_list;
|
||||||
osb->dentry_lock_list = dl;
|
osb->dentry_lock_list = dl;
|
||||||
|
|
|
@ -49,10 +49,13 @@ struct ocfs2_dentry_lock {
|
||||||
int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode,
|
int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode,
|
||||||
u64 parent_blkno);
|
u64 parent_blkno);
|
||||||
|
|
||||||
|
extern spinlock_t dentry_list_lock;
|
||||||
|
|
||||||
void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
|
void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
|
||||||
struct ocfs2_dentry_lock *dl);
|
struct ocfs2_dentry_lock *dl);
|
||||||
|
|
||||||
void ocfs2_drop_dl_inodes(struct work_struct *work);
|
void ocfs2_drop_dl_inodes(struct work_struct *work);
|
||||||
|
void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb);
|
||||||
|
|
||||||
struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno,
|
struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno,
|
||||||
int skip_unhashed);
|
int skip_unhashed);
|
||||||
|
|
|
@ -103,7 +103,6 @@ static void __dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
|
||||||
lock->ast_pending, lock->ml.type);
|
lock->ast_pending, lock->ml.type);
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
BUG_ON(!list_empty(&lock->ast_list));
|
|
||||||
if (lock->ast_pending)
|
if (lock->ast_pending)
|
||||||
mlog(0, "lock has an ast getting flushed right now\n");
|
mlog(0, "lock has an ast getting flushed right now\n");
|
||||||
|
|
||||||
|
|
|
@ -1118,7 +1118,7 @@ static int dlm_send_mig_lockres_msg(struct dlm_ctxt *dlm,
|
||||||
|
|
||||||
mlog(0, "%s:%.*s: sending mig lockres (%s) to %u\n",
|
mlog(0, "%s:%.*s: sending mig lockres (%s) to %u\n",
|
||||||
dlm->name, res->lockname.len, res->lockname.name,
|
dlm->name, res->lockname.len, res->lockname.name,
|
||||||
orig_flags & DLM_MRES_MIGRATION ? "migrate" : "recovery",
|
orig_flags & DLM_MRES_MIGRATION ? "migration" : "recovery",
|
||||||
send_to);
|
send_to);
|
||||||
|
|
||||||
/* send it */
|
/* send it */
|
||||||
|
|
|
@ -1851,6 +1851,7 @@ relock:
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_dio;
|
goto out_dio;
|
||||||
|
|
||||||
|
count = ocount;
|
||||||
ret = generic_write_checks(file, ppos, &count,
|
ret = generic_write_checks(file, ppos, &count,
|
||||||
S_ISBLK(inode->i_mode));
|
S_ISBLK(inode->i_mode));
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -1918,8 +1919,10 @@ out_sems:
|
||||||
|
|
||||||
mutex_unlock(&inode->i_mutex);
|
mutex_unlock(&inode->i_mutex);
|
||||||
|
|
||||||
|
if (written)
|
||||||
|
ret = written;
|
||||||
mlog_exit(ret);
|
mlog_exit(ret);
|
||||||
return written ? written : ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ocfs2_splice_to_file(struct pipe_inode_info *pipe,
|
static int ocfs2_splice_to_file(struct pipe_inode_info *pipe,
|
||||||
|
|
|
@ -1954,10 +1954,16 @@ void ocfs2_orphan_scan_init(struct ocfs2_super *osb)
|
||||||
os->os_osb = osb;
|
os->os_osb = osb;
|
||||||
os->os_count = 0;
|
os->os_count = 0;
|
||||||
os->os_seqno = 0;
|
os->os_seqno = 0;
|
||||||
os->os_scantime = CURRENT_TIME;
|
|
||||||
mutex_init(&os->os_lock);
|
mutex_init(&os->os_lock);
|
||||||
INIT_DELAYED_WORK(&os->os_orphan_scan_work, ocfs2_orphan_scan_work);
|
INIT_DELAYED_WORK(&os->os_orphan_scan_work, ocfs2_orphan_scan_work);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ocfs2_orphan_scan_start(struct ocfs2_super *osb)
|
||||||
|
{
|
||||||
|
struct ocfs2_orphan_scan *os;
|
||||||
|
|
||||||
|
os = &osb->osb_orphan_scan;
|
||||||
|
os->os_scantime = CURRENT_TIME;
|
||||||
if (ocfs2_is_hard_readonly(osb) || ocfs2_mount_local(osb))
|
if (ocfs2_is_hard_readonly(osb) || ocfs2_mount_local(osb))
|
||||||
atomic_set(&os->os_state, ORPHAN_SCAN_INACTIVE);
|
atomic_set(&os->os_state, ORPHAN_SCAN_INACTIVE);
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -145,6 +145,7 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb,
|
||||||
|
|
||||||
/* Exported only for the journal struct init code in super.c. Do not call. */
|
/* Exported only for the journal struct init code in super.c. Do not call. */
|
||||||
void ocfs2_orphan_scan_init(struct ocfs2_super *osb);
|
void ocfs2_orphan_scan_init(struct ocfs2_super *osb);
|
||||||
|
void ocfs2_orphan_scan_start(struct ocfs2_super *osb);
|
||||||
void ocfs2_orphan_scan_stop(struct ocfs2_super *osb);
|
void ocfs2_orphan_scan_stop(struct ocfs2_super *osb);
|
||||||
void ocfs2_orphan_scan_exit(struct ocfs2_super *osb);
|
void ocfs2_orphan_scan_exit(struct ocfs2_super *osb);
|
||||||
|
|
||||||
|
@ -329,20 +330,27 @@ int ocfs2_journal_dirty(handle_t *handle,
|
||||||
/* extended attribute block update */
|
/* extended attribute block update */
|
||||||
#define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1
|
#define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1
|
||||||
|
|
||||||
/* global quotafile inode update, data block */
|
/* Update of a single quota block */
|
||||||
#define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
|
#define OCFS2_QUOTA_BLOCK_UPDATE_CREDITS 1
|
||||||
|
|
||||||
|
/* global quotafile inode update, data block */
|
||||||
|
#define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + \
|
||||||
|
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS)
|
||||||
|
|
||||||
|
#define OCFS2_LOCAL_QINFO_WRITE_CREDITS OCFS2_QUOTA_BLOCK_UPDATE_CREDITS
|
||||||
/*
|
/*
|
||||||
* The two writes below can accidentally see global info dirty due
|
* The two writes below can accidentally see global info dirty due
|
||||||
* to set_info() quotactl so make them prepared for the writes.
|
* to set_info() quotactl so make them prepared for the writes.
|
||||||
*/
|
*/
|
||||||
/* quota data block, global info */
|
/* quota data block, global info */
|
||||||
/* Write to local quota file */
|
/* Write to local quota file */
|
||||||
#define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + 1)
|
#define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + \
|
||||||
|
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS)
|
||||||
|
|
||||||
/* global quota data block, local quota data block, global quota inode,
|
/* global quota data block, local quota data block, global quota inode,
|
||||||
* global quota info */
|
* global quota info */
|
||||||
#define OCFS2_QSYNC_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 3)
|
#define OCFS2_QSYNC_CREDITS (OCFS2_QINFO_WRITE_CREDITS + \
|
||||||
|
2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS)
|
||||||
|
|
||||||
static inline int ocfs2_quota_trans_credits(struct super_block *sb)
|
static inline int ocfs2_quota_trans_credits(struct super_block *sb)
|
||||||
{
|
{
|
||||||
|
@ -355,11 +363,6 @@ static inline int ocfs2_quota_trans_credits(struct super_block *sb)
|
||||||
return credits;
|
return credits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Number of credits needed for removing quota structure from file */
|
|
||||||
int ocfs2_calc_qdel_credits(struct super_block *sb, int type);
|
|
||||||
/* Number of credits needed for initialization of new quota structure */
|
|
||||||
int ocfs2_calc_qinit_credits(struct super_block *sb, int type);
|
|
||||||
|
|
||||||
/* group extend. inode update and last group update. */
|
/* group extend. inode update and last group update. */
|
||||||
#define OCFS2_GROUP_EXTEND_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
|
#define OCFS2_GROUP_EXTEND_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
|
||||||
|
|
||||||
|
|
|
@ -224,10 +224,12 @@ enum ocfs2_mount_options
|
||||||
OCFS2_MOUNT_GRPQUOTA = 1 << 10, /* We support group quotas */
|
OCFS2_MOUNT_GRPQUOTA = 1 << 10, /* We support group quotas */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define OCFS2_OSB_SOFT_RO 0x0001
|
#define OCFS2_OSB_SOFT_RO 0x0001
|
||||||
#define OCFS2_OSB_HARD_RO 0x0002
|
#define OCFS2_OSB_HARD_RO 0x0002
|
||||||
#define OCFS2_OSB_ERROR_FS 0x0004
|
#define OCFS2_OSB_ERROR_FS 0x0004
|
||||||
#define OCFS2_DEFAULT_ATIME_QUANTUM 60
|
#define OCFS2_OSB_DROP_DENTRY_LOCK_IMMED 0x0008
|
||||||
|
|
||||||
|
#define OCFS2_DEFAULT_ATIME_QUANTUM 60
|
||||||
|
|
||||||
struct ocfs2_journal;
|
struct ocfs2_journal;
|
||||||
struct ocfs2_slot_info;
|
struct ocfs2_slot_info;
|
||||||
|
@ -490,6 +492,18 @@ static inline void ocfs2_set_osb_flag(struct ocfs2_super *osb,
|
||||||
spin_unlock(&osb->osb_lock);
|
spin_unlock(&osb->osb_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline unsigned long ocfs2_test_osb_flag(struct ocfs2_super *osb,
|
||||||
|
unsigned long flag)
|
||||||
|
{
|
||||||
|
unsigned long ret;
|
||||||
|
|
||||||
|
spin_lock(&osb->osb_lock);
|
||||||
|
ret = osb->osb_flags & flag;
|
||||||
|
spin_unlock(&osb->osb_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void ocfs2_set_ro_flag(struct ocfs2_super *osb,
|
static inline void ocfs2_set_ro_flag(struct ocfs2_super *osb,
|
||||||
int hard)
|
int hard)
|
||||||
{
|
{
|
||||||
|
|
|
@ -50,7 +50,6 @@ struct ocfs2_mem_dqinfo {
|
||||||
unsigned int dqi_chunks; /* Number of chunks in local quota file */
|
unsigned int dqi_chunks; /* Number of chunks in local quota file */
|
||||||
unsigned int dqi_blocks; /* Number of blocks allocated for local quota file */
|
unsigned int dqi_blocks; /* Number of blocks allocated for local quota file */
|
||||||
unsigned int dqi_syncms; /* How often should we sync with other nodes */
|
unsigned int dqi_syncms; /* How often should we sync with other nodes */
|
||||||
unsigned int dqi_syncjiff; /* Precomputed dqi_syncms in jiffies */
|
|
||||||
struct list_head dqi_chunk; /* List of chunks */
|
struct list_head dqi_chunk; /* List of chunks */
|
||||||
struct inode *dqi_gqinode; /* Global quota file inode */
|
struct inode *dqi_gqinode; /* Global quota file inode */
|
||||||
struct ocfs2_lock_res dqi_gqlock; /* Lock protecting quota information structure */
|
struct ocfs2_lock_res dqi_gqlock; /* Lock protecting quota information structure */
|
||||||
|
|
|
@ -69,6 +69,7 @@ static void ocfs2_global_mem2diskdqb(void *dp, struct dquot *dquot)
|
||||||
d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
|
d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
|
||||||
d->dqb_btime = cpu_to_le64(m->dqb_btime);
|
d->dqb_btime = cpu_to_le64(m->dqb_btime);
|
||||||
d->dqb_itime = cpu_to_le64(m->dqb_itime);
|
d->dqb_itime = cpu_to_le64(m->dqb_itime);
|
||||||
|
d->dqb_pad1 = d->dqb_pad2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ocfs2_global_is_id(void *dp, struct dquot *dquot)
|
static int ocfs2_global_is_id(void *dp, struct dquot *dquot)
|
||||||
|
@ -211,14 +212,13 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type,
|
||||||
|
|
||||||
mutex_lock_nested(&gqinode->i_mutex, I_MUTEX_QUOTA);
|
mutex_lock_nested(&gqinode->i_mutex, I_MUTEX_QUOTA);
|
||||||
if (gqinode->i_size < off + len) {
|
if (gqinode->i_size < off + len) {
|
||||||
down_write(&OCFS2_I(gqinode)->ip_alloc_sem);
|
loff_t rounded_end =
|
||||||
err = ocfs2_extend_no_holes(gqinode, off + len, off);
|
ocfs2_align_bytes_to_blocks(sb, off + len);
|
||||||
up_write(&OCFS2_I(gqinode)->ip_alloc_sem);
|
|
||||||
if (err < 0)
|
/* Space is already allocated in ocfs2_global_read_dquot() */
|
||||||
goto out;
|
|
||||||
err = ocfs2_simple_size_update(gqinode,
|
err = ocfs2_simple_size_update(gqinode,
|
||||||
oinfo->dqi_gqi_bh,
|
oinfo->dqi_gqi_bh,
|
||||||
off + len);
|
rounded_end);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out;
|
goto out;
|
||||||
new = 1;
|
new = 1;
|
||||||
|
@ -234,7 +234,7 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type,
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
mlog_errno(err);
|
mlog_errno(err);
|
||||||
return err;
|
goto out;
|
||||||
}
|
}
|
||||||
lock_buffer(bh);
|
lock_buffer(bh);
|
||||||
if (new)
|
if (new)
|
||||||
|
@ -342,7 +342,6 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
|
||||||
info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
|
info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
|
||||||
info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
|
info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
|
||||||
oinfo->dqi_syncms = le32_to_cpu(dinfo.dqi_syncms);
|
oinfo->dqi_syncms = le32_to_cpu(dinfo.dqi_syncms);
|
||||||
oinfo->dqi_syncjiff = msecs_to_jiffies(oinfo->dqi_syncms);
|
|
||||||
oinfo->dqi_gi.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
|
oinfo->dqi_gi.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
|
||||||
oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
|
oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
|
||||||
oinfo->dqi_gi.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
|
oinfo->dqi_gi.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
|
||||||
|
@ -352,7 +351,7 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
|
||||||
oinfo->dqi_gi.dqi_qtree_depth = qtree_depth(&oinfo->dqi_gi);
|
oinfo->dqi_gi.dqi_qtree_depth = qtree_depth(&oinfo->dqi_gi);
|
||||||
INIT_DELAYED_WORK(&oinfo->dqi_sync_work, qsync_work_fn);
|
INIT_DELAYED_WORK(&oinfo->dqi_sync_work, qsync_work_fn);
|
||||||
queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
|
queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
|
||||||
oinfo->dqi_syncjiff);
|
msecs_to_jiffies(oinfo->dqi_syncms));
|
||||||
|
|
||||||
out_err:
|
out_err:
|
||||||
mlog_exit(status);
|
mlog_exit(status);
|
||||||
|
@ -402,13 +401,36 @@ int ocfs2_global_write_info(struct super_block *sb, int type)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ocfs2_global_qinit_alloc(struct super_block *sb, int type)
|
||||||
|
{
|
||||||
|
struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We may need to allocate tree blocks and a leaf block but not the
|
||||||
|
* root block
|
||||||
|
*/
|
||||||
|
return oinfo->dqi_gi.dqi_qtree_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ocfs2_calc_global_qinit_credits(struct super_block *sb, int type)
|
||||||
|
{
|
||||||
|
/* We modify all the allocated blocks, tree root, and info block */
|
||||||
|
return (ocfs2_global_qinit_alloc(sb, type) + 2) *
|
||||||
|
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read in information from global quota file and acquire a reference to it.
|
/* Read in information from global quota file and acquire a reference to it.
|
||||||
* dquot_acquire() has already started the transaction and locked quota file */
|
* dquot_acquire() has already started the transaction and locked quota file */
|
||||||
int ocfs2_global_read_dquot(struct dquot *dquot)
|
int ocfs2_global_read_dquot(struct dquot *dquot)
|
||||||
{
|
{
|
||||||
int err, err2, ex = 0;
|
int err, err2, ex = 0;
|
||||||
struct ocfs2_mem_dqinfo *info =
|
struct super_block *sb = dquot->dq_sb;
|
||||||
sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
|
int type = dquot->dq_type;
|
||||||
|
struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv;
|
||||||
|
struct ocfs2_super *osb = OCFS2_SB(sb);
|
||||||
|
struct inode *gqinode = info->dqi_gqinode;
|
||||||
|
int need_alloc = ocfs2_global_qinit_alloc(sb, type);
|
||||||
|
handle_t *handle = NULL;
|
||||||
|
|
||||||
err = ocfs2_qinfo_lock(info, 0);
|
err = ocfs2_qinfo_lock(info, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
@ -419,14 +441,33 @@ int ocfs2_global_read_dquot(struct dquot *dquot)
|
||||||
OCFS2_DQUOT(dquot)->dq_use_count++;
|
OCFS2_DQUOT(dquot)->dq_use_count++;
|
||||||
OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
|
OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
|
||||||
OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
|
OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
|
||||||
|
ocfs2_qinfo_unlock(info, 0);
|
||||||
|
|
||||||
if (!dquot->dq_off) { /* No real quota entry? */
|
if (!dquot->dq_off) { /* No real quota entry? */
|
||||||
/* Upgrade to exclusive lock for allocation */
|
|
||||||
ocfs2_qinfo_unlock(info, 0);
|
|
||||||
err = ocfs2_qinfo_lock(info, 1);
|
|
||||||
if (err < 0)
|
|
||||||
goto out_qlock;
|
|
||||||
ex = 1;
|
ex = 1;
|
||||||
|
/*
|
||||||
|
* Add blocks to quota file before we start a transaction since
|
||||||
|
* locking allocators ranks above a transaction start
|
||||||
|
*/
|
||||||
|
WARN_ON(journal_current_handle());
|
||||||
|
down_write(&OCFS2_I(gqinode)->ip_alloc_sem);
|
||||||
|
err = ocfs2_extend_no_holes(gqinode,
|
||||||
|
gqinode->i_size + (need_alloc << sb->s_blocksize_bits),
|
||||||
|
gqinode->i_size);
|
||||||
|
up_write(&OCFS2_I(gqinode)->ip_alloc_sem);
|
||||||
|
if (err < 0)
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handle = ocfs2_start_trans(osb,
|
||||||
|
ocfs2_calc_global_qinit_credits(sb, type));
|
||||||
|
if (IS_ERR(handle)) {
|
||||||
|
err = PTR_ERR(handle);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
err = ocfs2_qinfo_lock(info, ex);
|
||||||
|
if (err < 0)
|
||||||
|
goto out_trans;
|
||||||
err = qtree_write_dquot(&info->dqi_gi, dquot);
|
err = qtree_write_dquot(&info->dqi_gi, dquot);
|
||||||
if (ex && info_dirty(sb_dqinfo(dquot->dq_sb, dquot->dq_type))) {
|
if (ex && info_dirty(sb_dqinfo(dquot->dq_sb, dquot->dq_type))) {
|
||||||
err2 = __ocfs2_global_write_info(dquot->dq_sb, dquot->dq_type);
|
err2 = __ocfs2_global_write_info(dquot->dq_sb, dquot->dq_type);
|
||||||
|
@ -438,6 +479,9 @@ out_qlock:
|
||||||
ocfs2_qinfo_unlock(info, 1);
|
ocfs2_qinfo_unlock(info, 1);
|
||||||
else
|
else
|
||||||
ocfs2_qinfo_unlock(info, 0);
|
ocfs2_qinfo_unlock(info, 0);
|
||||||
|
out_trans:
|
||||||
|
if (handle)
|
||||||
|
ocfs2_commit_trans(osb, handle);
|
||||||
out:
|
out:
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
mlog_errno(err);
|
mlog_errno(err);
|
||||||
|
@ -607,7 +651,7 @@ static void qsync_work_fn(struct work_struct *work)
|
||||||
|
|
||||||
dquot_scan_active(sb, ocfs2_sync_dquot_helper, oinfo->dqi_type);
|
dquot_scan_active(sb, ocfs2_sync_dquot_helper, oinfo->dqi_type);
|
||||||
queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
|
queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
|
||||||
oinfo->dqi_syncjiff);
|
msecs_to_jiffies(oinfo->dqi_syncms));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -635,20 +679,18 @@ out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ocfs2_calc_qdel_credits(struct super_block *sb, int type)
|
static int ocfs2_calc_qdel_credits(struct super_block *sb, int type)
|
||||||
{
|
{
|
||||||
struct ocfs2_mem_dqinfo *oinfo;
|
struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
|
||||||
int features[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
|
/*
|
||||||
OCFS2_FEATURE_RO_COMPAT_GRPQUOTA };
|
* We modify tree, leaf block, global info, local chunk header,
|
||||||
|
* global and local inode; OCFS2_QINFO_WRITE_CREDITS already
|
||||||
if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, features[type]))
|
* accounts for inode update
|
||||||
return 0;
|
*/
|
||||||
|
return (oinfo->dqi_gi.dqi_qtree_depth + 2) *
|
||||||
oinfo = sb_dqinfo(sb, type)->dqi_priv;
|
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS +
|
||||||
/* We modify tree, leaf block, global info, local chunk header,
|
OCFS2_QINFO_WRITE_CREDITS +
|
||||||
* global and local inode */
|
OCFS2_INODE_UPDATE_CREDITS;
|
||||||
return oinfo->dqi_gi.dqi_qtree_depth + 2 + 1 +
|
|
||||||
2 * OCFS2_INODE_UPDATE_CREDITS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ocfs2_release_dquot(struct dquot *dquot)
|
static int ocfs2_release_dquot(struct dquot *dquot)
|
||||||
|
@ -680,33 +722,10 @@ out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ocfs2_calc_qinit_credits(struct super_block *sb, int type)
|
|
||||||
{
|
|
||||||
struct ocfs2_mem_dqinfo *oinfo;
|
|
||||||
int features[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
|
|
||||||
OCFS2_FEATURE_RO_COMPAT_GRPQUOTA };
|
|
||||||
struct ocfs2_dinode *lfe, *gfe;
|
|
||||||
|
|
||||||
if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, features[type]))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
oinfo = sb_dqinfo(sb, type)->dqi_priv;
|
|
||||||
gfe = (struct ocfs2_dinode *)oinfo->dqi_gqi_bh->b_data;
|
|
||||||
lfe = (struct ocfs2_dinode *)oinfo->dqi_lqi_bh->b_data;
|
|
||||||
/* We can extend local file + global file. In local file we
|
|
||||||
* can modify info, chunk header block and dquot block. In
|
|
||||||
* global file we can modify info, tree and leaf block */
|
|
||||||
return ocfs2_calc_extend_credits(sb, &lfe->id2.i_list, 0) +
|
|
||||||
ocfs2_calc_extend_credits(sb, &gfe->id2.i_list, 0) +
|
|
||||||
3 + oinfo->dqi_gi.dqi_qtree_depth + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ocfs2_acquire_dquot(struct dquot *dquot)
|
static int ocfs2_acquire_dquot(struct dquot *dquot)
|
||||||
{
|
{
|
||||||
handle_t *handle;
|
|
||||||
struct ocfs2_mem_dqinfo *oinfo =
|
struct ocfs2_mem_dqinfo *oinfo =
|
||||||
sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
|
sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
|
||||||
struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
|
mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
|
||||||
|
@ -715,16 +734,7 @@ static int ocfs2_acquire_dquot(struct dquot *dquot)
|
||||||
status = ocfs2_lock_global_qf(oinfo, 1);
|
status = ocfs2_lock_global_qf(oinfo, 1);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto out;
|
goto out;
|
||||||
handle = ocfs2_start_trans(osb,
|
|
||||||
ocfs2_calc_qinit_credits(dquot->dq_sb, dquot->dq_type));
|
|
||||||
if (IS_ERR(handle)) {
|
|
||||||
status = PTR_ERR(handle);
|
|
||||||
mlog_errno(status);
|
|
||||||
goto out_ilock;
|
|
||||||
}
|
|
||||||
status = dquot_acquire(dquot);
|
status = dquot_acquire(dquot);
|
||||||
ocfs2_commit_trans(osb, handle);
|
|
||||||
out_ilock:
|
|
||||||
ocfs2_unlock_global_qf(oinfo, 1);
|
ocfs2_unlock_global_qf(oinfo, 1);
|
||||||
out:
|
out:
|
||||||
mlog_exit(status);
|
mlog_exit(status);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "sysfile.h"
|
#include "sysfile.h"
|
||||||
#include "dlmglue.h"
|
#include "dlmglue.h"
|
||||||
#include "quota.h"
|
#include "quota.h"
|
||||||
|
#include "uptodate.h"
|
||||||
|
|
||||||
/* Number of local quota structures per block */
|
/* Number of local quota structures per block */
|
||||||
static inline unsigned int ol_quota_entries_per_block(struct super_block *sb)
|
static inline unsigned int ol_quota_entries_per_block(struct super_block *sb)
|
||||||
|
@ -100,7 +101,8 @@ static int ocfs2_modify_bh(struct inode *inode, struct buffer_head *bh,
|
||||||
handle_t *handle;
|
handle_t *handle;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
handle = ocfs2_start_trans(OCFS2_SB(sb), 1);
|
handle = ocfs2_start_trans(OCFS2_SB(sb),
|
||||||
|
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS);
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
status = PTR_ERR(handle);
|
status = PTR_ERR(handle);
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
|
@ -610,7 +612,8 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb,
|
||||||
goto out_bh;
|
goto out_bh;
|
||||||
/* Mark quota file as clean if we are recovering quota file of
|
/* Mark quota file as clean if we are recovering quota file of
|
||||||
* some other node. */
|
* some other node. */
|
||||||
handle = ocfs2_start_trans(osb, 1);
|
handle = ocfs2_start_trans(osb,
|
||||||
|
OCFS2_LOCAL_QINFO_WRITE_CREDITS);
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
status = PTR_ERR(handle);
|
status = PTR_ERR(handle);
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
|
@ -940,7 +943,7 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
|
||||||
struct ocfs2_local_disk_chunk *dchunk;
|
struct ocfs2_local_disk_chunk *dchunk;
|
||||||
int status;
|
int status;
|
||||||
handle_t *handle;
|
handle_t *handle;
|
||||||
struct buffer_head *bh = NULL;
|
struct buffer_head *bh = NULL, *dbh = NULL;
|
||||||
u64 p_blkno;
|
u64 p_blkno;
|
||||||
|
|
||||||
/* We are protected by dqio_sem so no locking needed */
|
/* We are protected by dqio_sem so no locking needed */
|
||||||
|
@ -964,32 +967,35 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
/* Local quota info and two new blocks we initialize */
|
||||||
down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
handle = ocfs2_start_trans(OCFS2_SB(sb),
|
||||||
status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks,
|
OCFS2_LOCAL_QINFO_WRITE_CREDITS +
|
||||||
&p_blkno, NULL, NULL);
|
2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS);
|
||||||
up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
|
||||||
if (status < 0) {
|
|
||||||
mlog_errno(status);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
bh = sb_getblk(sb, p_blkno);
|
|
||||||
if (!bh) {
|
|
||||||
status = -ENOMEM;
|
|
||||||
mlog_errno(status);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data;
|
|
||||||
|
|
||||||
handle = ocfs2_start_trans(OCFS2_SB(sb), 2);
|
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
status = PTR_ERR(handle);
|
status = PTR_ERR(handle);
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize chunk header */
|
||||||
|
down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
||||||
|
status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks,
|
||||||
|
&p_blkno, NULL, NULL);
|
||||||
|
up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
bh = sb_getblk(sb, p_blkno);
|
||||||
|
if (!bh) {
|
||||||
|
status = -ENOMEM;
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data;
|
||||||
|
ocfs2_set_new_buffer_uptodate(lqinode, bh);
|
||||||
status = ocfs2_journal_access_dq(handle, lqinode, bh,
|
status = ocfs2_journal_access_dq(handle, lqinode, bh,
|
||||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
OCFS2_JOURNAL_ACCESS_CREATE);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto out_trans;
|
goto out_trans;
|
||||||
|
@ -999,7 +1005,6 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
|
||||||
memset(dchunk->dqc_bitmap, 0,
|
memset(dchunk->dqc_bitmap, 0,
|
||||||
sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) -
|
sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) -
|
||||||
OCFS2_QBLK_RESERVED_SPACE);
|
OCFS2_QBLK_RESERVED_SPACE);
|
||||||
set_buffer_uptodate(bh);
|
|
||||||
unlock_buffer(bh);
|
unlock_buffer(bh);
|
||||||
status = ocfs2_journal_dirty(handle, bh);
|
status = ocfs2_journal_dirty(handle, bh);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
|
@ -1007,6 +1012,38 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
|
||||||
goto out_trans;
|
goto out_trans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize new block with structures */
|
||||||
|
down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
||||||
|
status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks + 1,
|
||||||
|
&p_blkno, NULL, NULL);
|
||||||
|
up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
dbh = sb_getblk(sb, p_blkno);
|
||||||
|
if (!dbh) {
|
||||||
|
status = -ENOMEM;
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
ocfs2_set_new_buffer_uptodate(lqinode, dbh);
|
||||||
|
status = ocfs2_journal_access_dq(handle, lqinode, dbh,
|
||||||
|
OCFS2_JOURNAL_ACCESS_CREATE);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
lock_buffer(dbh);
|
||||||
|
memset(dbh->b_data, 0, sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE);
|
||||||
|
unlock_buffer(dbh);
|
||||||
|
status = ocfs2_journal_dirty(handle, dbh);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update local quotafile info */
|
||||||
oinfo->dqi_blocks += 2;
|
oinfo->dqi_blocks += 2;
|
||||||
oinfo->dqi_chunks++;
|
oinfo->dqi_chunks++;
|
||||||
status = ocfs2_local_write_info(sb, type);
|
status = ocfs2_local_write_info(sb, type);
|
||||||
|
@ -1031,6 +1068,7 @@ out_trans:
|
||||||
ocfs2_commit_trans(OCFS2_SB(sb), handle);
|
ocfs2_commit_trans(OCFS2_SB(sb), handle);
|
||||||
out:
|
out:
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
|
brelse(dbh);
|
||||||
kmem_cache_free(ocfs2_qf_chunk_cachep, chunk);
|
kmem_cache_free(ocfs2_qf_chunk_cachep, chunk);
|
||||||
return ERR_PTR(status);
|
return ERR_PTR(status);
|
||||||
}
|
}
|
||||||
|
@ -1048,6 +1086,8 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
|
||||||
struct ocfs2_local_disk_chunk *dchunk;
|
struct ocfs2_local_disk_chunk *dchunk;
|
||||||
int epb = ol_quota_entries_per_block(sb);
|
int epb = ol_quota_entries_per_block(sb);
|
||||||
unsigned int chunk_blocks;
|
unsigned int chunk_blocks;
|
||||||
|
struct buffer_head *bh;
|
||||||
|
u64 p_blkno;
|
||||||
int status;
|
int status;
|
||||||
handle_t *handle;
|
handle_t *handle;
|
||||||
|
|
||||||
|
@ -1075,12 +1115,49 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
handle = ocfs2_start_trans(OCFS2_SB(sb), 2);
|
|
||||||
|
/* Get buffer from the just added block */
|
||||||
|
down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
||||||
|
status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks,
|
||||||
|
&p_blkno, NULL, NULL);
|
||||||
|
up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
bh = sb_getblk(sb, p_blkno);
|
||||||
|
if (!bh) {
|
||||||
|
status = -ENOMEM;
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ocfs2_set_new_buffer_uptodate(lqinode, bh);
|
||||||
|
|
||||||
|
/* Local quota info, chunk header and the new block we initialize */
|
||||||
|
handle = ocfs2_start_trans(OCFS2_SB(sb),
|
||||||
|
OCFS2_LOCAL_QINFO_WRITE_CREDITS +
|
||||||
|
2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS);
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
status = PTR_ERR(handle);
|
status = PTR_ERR(handle);
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
/* Zero created block */
|
||||||
|
status = ocfs2_journal_access_dq(handle, lqinode, bh,
|
||||||
|
OCFS2_JOURNAL_ACCESS_CREATE);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
lock_buffer(bh);
|
||||||
|
memset(bh->b_data, 0, sb->s_blocksize);
|
||||||
|
unlock_buffer(bh);
|
||||||
|
status = ocfs2_journal_dirty(handle, bh);
|
||||||
|
if (status < 0) {
|
||||||
|
mlog_errno(status);
|
||||||
|
goto out_trans;
|
||||||
|
}
|
||||||
|
/* Update chunk header */
|
||||||
status = ocfs2_journal_access_dq(handle, lqinode, chunk->qc_headerbh,
|
status = ocfs2_journal_access_dq(handle, lqinode, chunk->qc_headerbh,
|
||||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
OCFS2_JOURNAL_ACCESS_WRITE);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
|
@ -1097,6 +1174,7 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto out_trans;
|
goto out_trans;
|
||||||
}
|
}
|
||||||
|
/* Update file header */
|
||||||
oinfo->dqi_blocks++;
|
oinfo->dqi_blocks++;
|
||||||
status = ocfs2_local_write_info(sb, type);
|
status = ocfs2_local_write_info(sb, type);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
#include <linux/crc32.h>
|
#include <linux/crc32.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
@ -153,7 +154,7 @@ static int status_map[] = {
|
||||||
|
|
||||||
static int dlm_status_to_errno(enum dlm_status status)
|
static int dlm_status_to_errno(enum dlm_status status)
|
||||||
{
|
{
|
||||||
BUG_ON(status > (sizeof(status_map) / sizeof(status_map[0])));
|
BUG_ON(status < 0 || status >= ARRAY_SIZE(status_map));
|
||||||
|
|
||||||
return status_map[status];
|
return status_map[status];
|
||||||
}
|
}
|
||||||
|
|
|
@ -777,6 +777,7 @@ static int ocfs2_sb_probe(struct super_block *sb,
|
||||||
}
|
}
|
||||||
di = (struct ocfs2_dinode *) (*bh)->b_data;
|
di = (struct ocfs2_dinode *) (*bh)->b_data;
|
||||||
memset(stats, 0, sizeof(struct ocfs2_blockcheck_stats));
|
memset(stats, 0, sizeof(struct ocfs2_blockcheck_stats));
|
||||||
|
spin_lock_init(&stats->b_lock);
|
||||||
status = ocfs2_verify_volume(di, *bh, blksize, stats);
|
status = ocfs2_verify_volume(di, *bh, blksize, stats);
|
||||||
if (status >= 0)
|
if (status >= 0)
|
||||||
goto bail;
|
goto bail;
|
||||||
|
@ -1182,7 +1183,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
wake_up(&osb->osb_mount_event);
|
wake_up(&osb->osb_mount_event);
|
||||||
|
|
||||||
/* Start this when the mount is almost sure of being successful */
|
/* Start this when the mount is almost sure of being successful */
|
||||||
ocfs2_orphan_scan_init(osb);
|
ocfs2_orphan_scan_start(osb);
|
||||||
|
|
||||||
mlog_exit(status);
|
mlog_exit(status);
|
||||||
return status;
|
return status;
|
||||||
|
@ -1213,14 +1214,27 @@ static int ocfs2_get_sb(struct file_system_type *fs_type,
|
||||||
mnt);
|
mnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ocfs2_kill_sb(struct super_block *sb)
|
||||||
|
{
|
||||||
|
struct ocfs2_super *osb = OCFS2_SB(sb);
|
||||||
|
|
||||||
|
/* Prevent further queueing of inode drop events */
|
||||||
|
spin_lock(&dentry_list_lock);
|
||||||
|
ocfs2_set_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED);
|
||||||
|
spin_unlock(&dentry_list_lock);
|
||||||
|
/* Wait for work to finish and/or remove it */
|
||||||
|
cancel_work_sync(&osb->dentry_lock_work);
|
||||||
|
|
||||||
|
kill_block_super(sb);
|
||||||
|
}
|
||||||
|
|
||||||
static struct file_system_type ocfs2_fs_type = {
|
static struct file_system_type ocfs2_fs_type = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = "ocfs2",
|
.name = "ocfs2",
|
||||||
.get_sb = ocfs2_get_sb, /* is this called when we mount
|
.get_sb = ocfs2_get_sb, /* is this called when we mount
|
||||||
* the fs? */
|
* the fs? */
|
||||||
.kill_sb = kill_block_super, /* set to the generic one
|
.kill_sb = ocfs2_kill_sb,
|
||||||
* right now, but do we
|
|
||||||
* need to change that? */
|
|
||||||
.fs_flags = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE,
|
.fs_flags = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE,
|
||||||
.next = NULL
|
.next = NULL
|
||||||
};
|
};
|
||||||
|
@ -1819,6 +1833,12 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
|
||||||
|
|
||||||
debugfs_remove(osb->osb_ctxt);
|
debugfs_remove(osb->osb_ctxt);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flush inode dropping work queue so that deletes are
|
||||||
|
* performed while the filesystem is still working
|
||||||
|
*/
|
||||||
|
ocfs2_drop_all_dl_inodes(osb);
|
||||||
|
|
||||||
/* Orphan scan should be stopped as early as possible */
|
/* Orphan scan should be stopped as early as possible */
|
||||||
ocfs2_orphan_scan_stop(osb);
|
ocfs2_orphan_scan_stop(osb);
|
||||||
|
|
||||||
|
@ -1981,6 +2001,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
|
||||||
snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u",
|
snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u",
|
||||||
MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
|
MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
|
||||||
|
|
||||||
|
ocfs2_orphan_scan_init(osb);
|
||||||
|
|
||||||
status = ocfs2_recovery_init(osb);
|
status = ocfs2_recovery_init(osb);
|
||||||
if (status) {
|
if (status) {
|
||||||
mlog(ML_ERROR, "Unable to initialize recovery state\n");
|
mlog(ML_ERROR, "Unable to initialize recovery state\n");
|
||||||
|
|
|
@ -1052,7 +1052,8 @@ static int ocfs2_xattr_block_get(struct inode *inode,
|
||||||
struct ocfs2_xattr_block *xb;
|
struct ocfs2_xattr_block *xb;
|
||||||
struct ocfs2_xattr_value_root *xv;
|
struct ocfs2_xattr_value_root *xv;
|
||||||
size_t size;
|
size_t size;
|
||||||
int ret = -ENODATA, name_offset, name_len, block_off, i;
|
int ret = -ENODATA, name_offset, name_len, i;
|
||||||
|
int uninitialized_var(block_off);
|
||||||
|
|
||||||
xs->bucket = ocfs2_xattr_bucket_new(inode);
|
xs->bucket = ocfs2_xattr_bucket_new(inode);
|
||||||
if (!xs->bucket) {
|
if (!xs->bucket) {
|
||||||
|
|
Loading…
Reference in a new issue