Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 26766
b: refs/heads/master
c: 53013cb
h: refs/heads/master
v: v3
  • Loading branch information
Mark Fasheh committed May 17, 2006
1 parent 4d10aed commit b8eb077
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 38 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a5d1792847172077d173c959c37d4562b9ec69e6
refs/heads/master: 53013cba4118a5cfe8f7c7ea5e5bc1c48b160f76
4 changes: 2 additions & 2 deletions trunk/arch/ia64/configs/sn2_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
CONFIG_NUMA=y
CONFIG_NODES_SHIFT=10
CONFIG_NODES_SHIFT=8
CONFIG_VIRTUAL_MEM_MAP=y
CONFIG_HOLES_IN_ZONE=y
CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
Expand Down Expand Up @@ -1159,7 +1159,7 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
CONFIG_DEBUG_PREEMPT=y
# CONFIG_DEBUG_MUTEXES is not set
CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
Expand Down
4 changes: 2 additions & 2 deletions trunk/arch/ia64/kernel/iosapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ iosapic_end_level_irq (unsigned int irq)
ia64_vector vec = irq_to_vector(irq);
struct iosapic_rte_info *rte;

move_native_irq(irq);
move_irq(irq);
list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list)
iosapic_eoi(rte->addr, vec);
}
Expand Down Expand Up @@ -458,7 +458,7 @@ iosapic_ack_edge_irq (unsigned int irq)
{
irq_desc_t *idesc = irq_descp(irq);

move_native_irq(irq);
move_irq(irq);
/*
* Once we have recorded IRQ_PENDING already, we can mask the
* interrupt for real. This prevents IRQ storms from unhandled
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/ia64/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ void set_irq_affinity_info (unsigned int irq, int hwid, int redir)

if (irq < NR_IRQS) {
irq_affinity[irq] = mask;
set_irq_info(irq, mask);
irq_redir[irq] = (char) (redir & 0xff);
}
}
Expand Down
46 changes: 39 additions & 7 deletions trunk/fs/ocfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,13 +276,29 @@ static int ocfs2_writepage(struct page *page, struct writeback_control *wbc)
return ret;
}

/* This can also be called from ocfs2_write_zero_page() which has done
* it's own cluster locking. */
int ocfs2_prepare_write_nolock(struct inode *inode, struct page *page,
unsigned from, unsigned to)
{
int ret;

down_read(&OCFS2_I(inode)->ip_alloc_sem);

ret = block_prepare_write(page, from, to, ocfs2_get_block);

up_read(&OCFS2_I(inode)->ip_alloc_sem);

return ret;
}

/*
* ocfs2_prepare_write() can be an outer-most ocfs2 call when it is called
* from loopback. It must be able to perform its own locking around
* ocfs2_get_block().
*/
int ocfs2_prepare_write(struct file *file, struct page *page,
unsigned from, unsigned to)
static int ocfs2_prepare_write(struct file *file, struct page *page,
unsigned from, unsigned to)
{
struct inode *inode = page->mapping->host;
int ret;
Expand All @@ -295,11 +311,7 @@ int ocfs2_prepare_write(struct file *file, struct page *page,
goto out;
}

down_read(&OCFS2_I(inode)->ip_alloc_sem);

ret = block_prepare_write(page, from, to, ocfs2_get_block);

up_read(&OCFS2_I(inode)->ip_alloc_sem);
ret = ocfs2_prepare_write_nolock(inode, page, from, to);

ocfs2_meta_unlock(inode, 0);
out:
Expand Down Expand Up @@ -625,11 +637,31 @@ static ssize_t ocfs2_direct_IO(int rw,
int ret;

mlog_entry_void();

/*
* We get PR data locks even for O_DIRECT. This allows
* concurrent O_DIRECT I/O but doesn't let O_DIRECT with
* extending and buffered zeroing writes race. If they did
* race then the buffered zeroing could be written back after
* the O_DIRECT I/O. It's one thing to tell people not to mix
* buffered and O_DIRECT writes, but expecting them to
* understand that file extension is also an implicit buffered
* write is too much. By getting the PR we force writeback of
* the buffered zeroing before proceeding.
*/
ret = ocfs2_data_lock(inode, 0);
if (ret < 0) {
mlog_errno(ret);
goto out;
}
ocfs2_data_unlock(inode, 0);

ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
inode->i_sb->s_bdev, iov, offset,
nr_segs,
ocfs2_direct_IO_get_blocks,
ocfs2_dio_end_io);
out:
mlog_exit(ret);
return ret;
}
Expand Down
4 changes: 2 additions & 2 deletions trunk/fs/ocfs2/aops.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
#ifndef OCFS2_AOPS_H
#define OCFS2_AOPS_H

int ocfs2_prepare_write(struct file *file, struct page *page,
unsigned from, unsigned to);
int ocfs2_prepare_write_nolock(struct inode *inode, struct page *page,
unsigned from, unsigned to);

struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode,
struct page *page,
Expand Down
70 changes: 46 additions & 24 deletions trunk/fs/ocfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,8 @@ static int ocfs2_extend_allocation(struct inode *inode,

/* Some parts of this taken from generic_cont_expand, which turned out
* to be too fragile to do exactly what we need without us having to
* worry about recursive locking in ->commit_write(). */
* worry about recursive locking in ->prepare_write() and
* ->commit_write(). */
static int ocfs2_write_zero_page(struct inode *inode,
u64 size)
{
Expand Down Expand Up @@ -641,7 +642,7 @@ static int ocfs2_write_zero_page(struct inode *inode,
goto out;
}

ret = ocfs2_prepare_write(NULL, page, offset, offset);
ret = ocfs2_prepare_write_nolock(inode, page, offset, offset);
if (ret < 0) {
mlog_errno(ret);
goto out_unlock;
Expand Down Expand Up @@ -695,13 +696,26 @@ static int ocfs2_zero_extend(struct inode *inode,
return ret;
}

/*
* A tail_to_skip value > 0 indicates that we're being called from
* ocfs2_file_aio_write(). This has the following implications:
*
* - we don't want to update i_size
* - di_bh will be NULL, which is fine because it's only used in the
* case where we want to update i_size.
* - ocfs2_zero_extend() will then only be filling the hole created
* between i_size and the start of the write.
*/
static int ocfs2_extend_file(struct inode *inode,
struct buffer_head *di_bh,
u64 new_i_size)
u64 new_i_size,
size_t tail_to_skip)
{
int ret = 0;
u32 clusters_to_add;

BUG_ON(!tail_to_skip && !di_bh);

/* setattr sometimes calls us like this. */
if (new_i_size == 0)
goto out;
Expand All @@ -714,27 +728,44 @@ static int ocfs2_extend_file(struct inode *inode,
OCFS2_I(inode)->ip_clusters;

if (clusters_to_add) {
ret = ocfs2_extend_allocation(inode, clusters_to_add);
/*
* protect the pages that ocfs2_zero_extend is going to
* be pulling into the page cache.. we do this before the
* metadata extend so that we don't get into the situation
* where we've extended the metadata but can't get the data
* lock to zero.
*/
ret = ocfs2_data_lock(inode, 1);
if (ret < 0) {
mlog_errno(ret);
goto out;
}

ret = ocfs2_zero_extend(inode, new_i_size);
ret = ocfs2_extend_allocation(inode, clusters_to_add);
if (ret < 0) {
mlog_errno(ret);
goto out;
goto out_unlock;
}
}

/* No allocation required, we just use this helper to
* do a trivial update of i_size. */
ret = ocfs2_simple_size_update(inode, di_bh, new_i_size);
if (ret < 0) {
mlog_errno(ret);
goto out;
ret = ocfs2_zero_extend(inode, (u64)new_i_size - tail_to_skip);
if (ret < 0) {
mlog_errno(ret);
goto out_unlock;
}
}

if (!tail_to_skip) {
/* We're being called from ocfs2_setattr() which wants
* us to update i_size */
ret = ocfs2_simple_size_update(inode, di_bh, new_i_size);
if (ret < 0)
mlog_errno(ret);
}

out_unlock:
if (clusters_to_add) /* this is the only case in which we lock */
ocfs2_data_unlock(inode, 1);

out:
return ret;
}
Expand Down Expand Up @@ -793,7 +824,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
if (i_size_read(inode) > attr->ia_size)
status = ocfs2_truncate_file(inode, bh, attr->ia_size);
else
status = ocfs2_extend_file(inode, bh, attr->ia_size);
status = ocfs2_extend_file(inode, bh, attr->ia_size, 0);
if (status < 0) {
if (status != -ENOSPC)
mlog_errno(status);
Expand Down Expand Up @@ -1049,21 +1080,12 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
if (!clusters)
break;

ret = ocfs2_extend_allocation(inode, clusters);
ret = ocfs2_extend_file(inode, NULL, newsize, count);
if (ret < 0) {
if (ret != -ENOSPC)
mlog_errno(ret);
goto out;
}

/* Fill any holes which would've been created by this
* write. If we're O_APPEND, this will wind up
* (correctly) being a noop. */
ret = ocfs2_zero_extend(inode, (u64) newsize - count);
if (ret < 0) {
mlog_errno(ret);
goto out;
}
break;
}

Expand Down

0 comments on commit b8eb077

Please sign in to comment.