Commit e36aeee6 authored by Linus Torvalds's avatar Linus Torvalds

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

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2:
  ocfs2: fix rename vs unlink race
  [PATCH] Fix possibly too long write in o2hb_setup_one_bio()
  ocfs2: fix write() performance regression
  ocfs2: Commit journal on sync writes
  ocfs2: Re-order iput in ocfs2_drop_dentry_lock
  ocfs2: Create locks at initially requested level
  [PATCH] Fix priority mistakes in fs/ocfs2/{alloc.c, dlmglue.c}
  [2.6 patch] make ocfs2_find_entry_el() static
parents b2f051ae e325a88f
...@@ -3946,7 +3946,7 @@ static int __ocfs2_mark_extent_written(struct inode *inode, ...@@ -3946,7 +3946,7 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
struct ocfs2_merge_ctxt ctxt; struct ocfs2_merge_ctxt ctxt;
struct ocfs2_extent_list *rightmost_el; struct ocfs2_extent_list *rightmost_el;
if (!rec->e_flags & OCFS2_EXT_UNWRITTEN) { if (!(rec->e_flags & OCFS2_EXT_UNWRITTEN)) {
ret = -EIO; ret = -EIO;
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
......
...@@ -728,6 +728,27 @@ static void ocfs2_clear_page_regions(struct page *page, ...@@ -728,6 +728,27 @@ static void ocfs2_clear_page_regions(struct page *page,
kunmap_atomic(kaddr, KM_USER0); kunmap_atomic(kaddr, KM_USER0);
} }
/*
* Nonsparse file systems fully allocate before we get to the write
* code. This prevents ocfs2_write() from tagging the write as an
* allocating one, which means ocfs2_map_page_blocks() might try to
* read-in the blocks at the tail of our file. Avoid reading them by
* testing i_size against each block offset.
*/
static int ocfs2_should_read_blk(struct inode *inode, struct page *page,
unsigned int block_start)
{
u64 offset = page_offset(page) + block_start;
if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)))
return 1;
if (i_size_read(inode) > offset)
return 1;
return 0;
}
/* /*
* Some of this taken from block_prepare_write(). We already have our * Some of this taken from block_prepare_write(). We already have our
* mapping by now though, and the entire write will be allocating or * mapping by now though, and the entire write will be allocating or
...@@ -781,6 +802,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno, ...@@ -781,6 +802,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
} else if (!buffer_uptodate(bh) && !buffer_delay(bh) && } else if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
!buffer_new(bh) && !buffer_new(bh) &&
ocfs2_should_read_blk(inode, page, block_start) &&
(block_start < from || block_end > to)) { (block_start < from || block_end > to)) {
ll_rw_block(READ, 1, &bh); ll_rw_block(READ, 1, &bh);
*wait_bh++=bh; *wait_bh++=bh;
......
...@@ -267,7 +267,7 @@ static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg, ...@@ -267,7 +267,7 @@ static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg,
current_page = cs / spp; current_page = cs / spp;
page = reg->hr_slot_data[current_page]; page = reg->hr_slot_data[current_page];
vec_len = min(PAGE_CACHE_SIZE, vec_len = min(PAGE_CACHE_SIZE - vec_start,
(max_slots-cs) * (PAGE_CACHE_SIZE/spp) ); (max_slots-cs) * (PAGE_CACHE_SIZE/spp) );
mlog(ML_HB_BIO, "page %d, vec_len = %u, vec_start = %u\n", mlog(ML_HB_BIO, "page %d, vec_len = %u, vec_start = %u\n",
......
...@@ -318,9 +318,9 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, ...@@ -318,9 +318,9 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry,
static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
struct ocfs2_dentry_lock *dl) struct ocfs2_dentry_lock *dl)
{ {
iput(dl->dl_inode);
ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
ocfs2_lock_res_free(&dl->dl_lockres); ocfs2_lock_res_free(&dl->dl_lockres);
iput(dl->dl_inode);
kfree(dl); kfree(dl);
} }
......
...@@ -208,9 +208,9 @@ static struct buffer_head *ocfs2_find_entry_id(const char *name, ...@@ -208,9 +208,9 @@ static struct buffer_head *ocfs2_find_entry_id(const char *name,
return NULL; return NULL;
} }
struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen, static struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen,
struct inode *dir, struct inode *dir,
struct ocfs2_dir_entry **res_dir) struct ocfs2_dir_entry **res_dir)
{ {
struct super_block *sb; struct super_block *sb;
struct buffer_head *bh_use[NAMEI_RA_SIZE]; struct buffer_head *bh_use[NAMEI_RA_SIZE];
......
...@@ -670,7 +670,7 @@ static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *loc ...@@ -670,7 +670,7 @@ static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *loc
{ {
mlog_entry_void(); mlog_entry_void();
BUG_ON((!lockres->l_flags & OCFS2_LOCK_BUSY)); BUG_ON((!(lockres->l_flags & OCFS2_LOCK_BUSY)));
BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED); BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED);
if (lockres->l_requested > LKM_NLMODE && if (lockres->l_requested > LKM_NLMODE &&
...@@ -980,18 +980,6 @@ static int ocfs2_cluster_lock(struct ocfs2_super *osb, ...@@ -980,18 +980,6 @@ static int ocfs2_cluster_lock(struct ocfs2_super *osb,
goto unlock; goto unlock;
} }
if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) {
/* lock has not been created yet. */
spin_unlock_irqrestore(&lockres->l_lock, flags);
ret = ocfs2_lock_create(osb, lockres, LKM_NLMODE, 0);
if (ret < 0) {
mlog_errno(ret);
goto out;
}
goto again;
}
if (lockres->l_flags & OCFS2_LOCK_BLOCKED && if (lockres->l_flags & OCFS2_LOCK_BLOCKED &&
!ocfs2_may_continue_on_blocked_lock(lockres, level)) { !ocfs2_may_continue_on_blocked_lock(lockres, level)) {
/* is the lock is currently blocked on behalf of /* is the lock is currently blocked on behalf of
...@@ -1006,7 +994,14 @@ static int ocfs2_cluster_lock(struct ocfs2_super *osb, ...@@ -1006,7 +994,14 @@ static int ocfs2_cluster_lock(struct ocfs2_super *osb,
mlog(ML_ERROR, "lockres %s has action %u pending\n", mlog(ML_ERROR, "lockres %s has action %u pending\n",
lockres->l_name, lockres->l_action); lockres->l_name, lockres->l_action);
lockres->l_action = OCFS2_AST_CONVERT; if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) {
lockres->l_action = OCFS2_AST_ATTACH;
lkm_flags &= ~LKM_CONVERT;
} else {
lockres->l_action = OCFS2_AST_CONVERT;
lkm_flags |= LKM_CONVERT;
}
lockres->l_requested = level; lockres->l_requested = level;
lockres_or_flags(lockres, OCFS2_LOCK_BUSY); lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
spin_unlock_irqrestore(&lockres->l_lock, flags); spin_unlock_irqrestore(&lockres->l_lock, flags);
...@@ -1021,7 +1016,7 @@ static int ocfs2_cluster_lock(struct ocfs2_super *osb, ...@@ -1021,7 +1016,7 @@ static int ocfs2_cluster_lock(struct ocfs2_super *osb,
status = dlmlock(osb->dlm, status = dlmlock(osb->dlm,
level, level,
&lockres->l_lksb, &lockres->l_lksb,
lkm_flags|LKM_CONVERT, lkm_flags,
lockres->l_name, lockres->l_name,
OCFS2_LOCK_ID_MAX_LEN - 1, OCFS2_LOCK_ID_MAX_LEN - 1,
ocfs2_locking_ast, ocfs2_locking_ast,
......
...@@ -1891,9 +1891,11 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, ...@@ -1891,9 +1891,11 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
ssize_t written = 0; ssize_t written = 0;
size_t ocount; /* original count */ size_t ocount; /* original count */
size_t count; /* after file limit checks */ size_t count; /* after file limit checks */
loff_t *ppos = &iocb->ki_pos; loff_t old_size, *ppos = &iocb->ki_pos;
u32 old_clusters;
struct file *file = iocb->ki_filp; struct file *file = iocb->ki_filp;
struct inode *inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
mlog_entry("(0x%p, %u, '%.*s')\n", file, mlog_entry("(0x%p, %u, '%.*s')\n", file,
(unsigned int)nr_segs, (unsigned int)nr_segs,
...@@ -1949,6 +1951,13 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, ...@@ -1949,6 +1951,13 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
goto relock; goto relock;
} }
/*
* To later detect whether a journal commit for sync writes is
* necessary, we sample i_size, and cluster count here.
*/
old_size = i_size_read(inode);
old_clusters = OCFS2_I(inode)->ip_clusters;
/* communicate with ocfs2_dio_end_io */ /* communicate with ocfs2_dio_end_io */
ocfs2_iocb_set_rw_locked(iocb, rw_level); ocfs2_iocb_set_rw_locked(iocb, rw_level);
...@@ -1978,6 +1987,21 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, ...@@ -1978,6 +1987,21 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
/* buffered aio wouldn't have proper lock coverage today */ /* buffered aio wouldn't have proper lock coverage today */
BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT));
if ((file->f_flags & O_SYNC && !direct_io) || IS_SYNC(inode)) {
/*
* The generic write paths have handled getting data
* to disk, but since we don't make use of the dirty
* inode list, a manual journal commit is necessary
* here.
*/
if (old_size != i_size_read(inode) ||
old_clusters != OCFS2_I(inode)->ip_clusters) {
ret = journal_force_commit(osb->journal->j_journal);
if (ret < 0)
written = ret;
}
}
/* /*
* deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io
* function pointer which is called when o_direct io completes so that * function pointer which is called when o_direct io completes so that
......
...@@ -1105,9 +1105,16 @@ static int ocfs2_rename(struct inode *old_dir, ...@@ -1105,9 +1105,16 @@ static int ocfs2_rename(struct inode *old_dir,
goto bail; goto bail;
} }
if (!new_de && new_inode) if (!new_de && new_inode) {
mlog(ML_ERROR, "inode %lu does not exist in it's parent " /*
"directory!", new_inode->i_ino); * Target was unlinked by another node while we were
* waiting to get to ocfs2_rename(). There isn't
* anything we can do here to help the situation, so
* bubble up the appropriate error.
*/
status = -ENOENT;
goto bail;
}
/* In case we need to overwrite an existing file, we blow it /* In case we need to overwrite an existing file, we blow it
* away first */ * away first */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment