Skip to content

Commit

Permalink
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/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()
  ...
  • Loading branch information
torvalds committed Aug 13, 2009
2 parents d58d2d1 + b409d7a commit bc7af9b
Show file tree
Hide file tree
Showing 16 changed files with 357 additions and 135 deletions.
47 changes: 41 additions & 6 deletions fs/ocfs2/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1914,7 +1914,8 @@ static void ocfs2_adjust_adjacent_records(struct ocfs2_extent_rec *left_rec,
* immediately to their right.
*/
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);
left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos);
}
Expand Down Expand Up @@ -2476,15 +2477,37 @@ static int ocfs2_rotate_tree_right(struct inode *inode,
return ret;
}

static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
struct ocfs2_path *path)
static int ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
int subtree_index, struct ocfs2_path *path)
{
int i, idx;
int i, idx, ret;
struct ocfs2_extent_rec *rec;
struct ocfs2_extent_list *el;
struct ocfs2_extent_block *eb;
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. */
eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
BUG_ON(eb->h_next_leaf_blk != 0ULL);
Expand All @@ -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);
}
out:
return ret;
}

static void ocfs2_unlink_path(struct inode *inode, handle_t *handle,
Expand Down Expand Up @@ -2717,7 +2742,12 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
if (del_right_subtree) {
ocfs2_unlink_subtree(inode, handle, left_path, right_path,
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;
ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
Expand Down Expand Up @@ -3034,7 +3064,12 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,

ocfs2_unlink_subtree(inode, handle, left_path, path,
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;
ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
Expand Down
69 changes: 49 additions & 20 deletions fs/ocfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
(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);
dump_stack();
goto bail;
}

past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode));
Expand Down Expand Up @@ -894,18 +895,17 @@ struct ocfs2_write_cluster_desc {
*/
unsigned c_new;
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 {
/* Logical cluster position / len of write */
u32 w_cpos;
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];

/*
Expand Down Expand Up @@ -983,6 +983,7 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
return -ENOMEM;

wc->w_cpos = pos >> osb->s_clustersize_bits;
wc->w_first_new_cpos = UINT_MAX;
cend = (pos + len - 1) >> osb->s_clustersize_bits;
wc->w_clen = cend - wc->w_cpos + 1;
get_bh(di_bh);
Expand Down Expand Up @@ -1217,20 +1218,18 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping,
*/
static int ocfs2_write_cluster(struct address_space *mapping,
u32 phys, unsigned int unwritten,
unsigned int should_zero,
struct ocfs2_alloc_context *data_ac,
struct ocfs2_alloc_context *meta_ac,
struct ocfs2_write_ctxt *wc, u32 cpos,
loff_t user_pos, unsigned user_len)
{
int ret, i, new, should_zero = 0;
int ret, i, new;
u64 v_blkno, p_blkno;
struct inode *inode = mapping->host;
struct ocfs2_extent_tree et;

new = phys == 0 ? 1 : 0;
if (new || unwritten)
should_zero = 1;

if (new) {
u32 tmp_pos;

Expand Down Expand Up @@ -1301,7 +1300,7 @@ static int ocfs2_write_cluster(struct address_space *mapping,
if (tmpret) {
mlog_errno(tmpret);
if (ret == 0)
tmpret = ret;
ret = tmpret;
}
}

Expand Down Expand Up @@ -1341,7 +1340,9 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping,
local_len = osb->s_clustersize - cluster_off;

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);
if (ret) {
mlog_errno(ret);
Expand Down Expand Up @@ -1391,14 +1392,14 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
* newly allocated cluster.
*/
desc = &wc->w_desc[0];
if (ocfs2_should_zero_cluster(desc))
if (desc->c_needs_zero)
ocfs2_figure_cluster_boundaries(osb,
desc->c_cpos,
&wc->w_target_from,
NULL);

desc = &wc->w_desc[wc->w_clen - 1];
if (ocfs2_should_zero_cluster(desc))
if (desc->c_needs_zero)
ocfs2_figure_cluster_boundaries(osb,
desc->c_cpos,
NULL,
Expand Down Expand Up @@ -1466,13 +1467,28 @@ static int ocfs2_populate_write_desc(struct inode *inode,
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;
if (phys == 0) {
desc->c_new = 1;
desc->c_needs_zero = 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_needs_zero = 1;
}

num_clusters--;
}
Expand Down Expand Up @@ -1632,10 +1648,13 @@ static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos,
if (newsize <= i_size_read(inode))
return 0;

ret = ocfs2_extend_no_holes(inode, newsize, newsize - len);
ret = ocfs2_extend_no_holes(inode, newsize, pos);
if (ret)
mlog_errno(ret);

wc->w_first_new_cpos =
ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode));

return ret;
}

Expand All @@ -1644,7 +1663,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
struct page **pagep, void **fsdata,
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;
struct ocfs2_write_ctxt *wc;
struct inode *inode = mapping->host;
Expand Down Expand Up @@ -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);
if (IS_ERR(handle)) {
Expand Down Expand Up @@ -1756,8 +1786,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
* extent.
*/
ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos,
clusters_to_alloc + extents_to_split,
mmap_page);
cluster_of_pages, mmap_page);
if (ret) {
mlog_errno(ret);
goto out_quota;
Expand Down
35 changes: 27 additions & 8 deletions fs/ocfs2/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,34 +310,52 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry,
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
* this limit so that we don't starve other users of ocfs2_wq. */
#define DL_INODE_DROP_COUNT 64

/* 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;
int drop_count = DL_INODE_DROP_COUNT;

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;
osb->dentry_lock_list = dl->dl_next;
spin_unlock(&dentry_list_lock);
iput(dl->dl_inode);
kfree(dl);
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);
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.
*
Expand Down Expand Up @@ -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
* possibly lead to inode deletion which gets tricky */
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);
dl->dl_next = osb->dentry_lock_list;
osb->dentry_lock_list = dl;
Expand Down
3 changes: 3 additions & 0 deletions fs/ocfs2/dcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,13 @@ struct ocfs2_dentry_lock {
int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode,
u64 parent_blkno);

extern spinlock_t dentry_list_lock;

void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
struct ocfs2_dentry_lock *dl);

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,
int skip_unhashed);
Expand Down
1 change: 0 additions & 1 deletion fs/ocfs2/dlm/dlmast.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ static void __dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
lock->ast_pending, lock->ml.type);
BUG();
}
BUG_ON(!list_empty(&lock->ast_list));
if (lock->ast_pending)
mlog(0, "lock has an ast getting flushed right now\n");

Expand Down
2 changes: 1 addition & 1 deletion fs/ocfs2/dlm/dlmrecovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
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 it */
Expand Down
5 changes: 4 additions & 1 deletion fs/ocfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1851,6 +1851,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
if (ret)
goto out_dio;

count = ocount;
ret = generic_write_checks(file, ppos, &count,
S_ISBLK(inode->i_mode));
if (ret)
Expand Down Expand Up @@ -1918,8 +1919,10 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,

mutex_unlock(&inode->i_mutex);

if (written)
ret = written;
mlog_exit(ret);
return written ? written : ret;
return ret;
}

static int ocfs2_splice_to_file(struct pipe_inode_info *pipe,
Expand Down
Loading

0 comments on commit bc7af9b

Please sign in to comment.