Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 276185
b: refs/heads/master
c: 99b1bb6
h: refs/heads/master
i:
  276183: 264f313
v: v3
  • Loading branch information
Joel Becker committed Aug 22, 2011
1 parent e5eb55a commit 3761ab5
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 17 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: 93862d5e1ab875664c6cc95254fc365028a48bb1
refs/heads/master: 99b1bb61b225c3eb4d3b196d4f1d041695b19a7e
18 changes: 18 additions & 0 deletions trunk/fs/ocfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,15 @@ static int ocfs2_readpage(struct file *file, struct page *page)
}

if (down_read_trylock(&oi->ip_alloc_sem) == 0) {
/*
* Unlock the page and cycle ip_alloc_sem so that we don't
* busyloop waiting for ip_alloc_sem to unlock
*/
ret = AOP_TRUNCATED_PAGE;
unlock_page(page);
unlock = 0;
down_read(&oi->ip_alloc_sem);
up_read(&oi->ip_alloc_sem);
goto out_inode_unlock;
}

Expand Down Expand Up @@ -563,13 +571,23 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
{
struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
int level;
wait_queue_head_t *wq = ocfs2_ioend_wq(inode);

/* this io's submitter should not have unlocked this before we could */
BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));

if (ocfs2_iocb_is_sem_locked(iocb))
ocfs2_iocb_clear_sem_locked(iocb);

if (ocfs2_iocb_is_unaligned_aio(iocb)) {
ocfs2_iocb_clear_unaligned_aio(iocb);

if (atomic_dec_and_test(&OCFS2_I(inode)->ip_unaligned_aio) &&
waitqueue_active(wq)) {
wake_up_all(wq);
}
}

ocfs2_iocb_clear_rw_locked(iocb);

level = ocfs2_iocb_rw_locked_level(iocb);
Expand Down
14 changes: 14 additions & 0 deletions trunk/fs/ocfs2/aops.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ enum ocfs2_iocb_lock_bits {
OCFS2_IOCB_RW_LOCK = 0,
OCFS2_IOCB_RW_LOCK_LEVEL,
OCFS2_IOCB_SEM,
OCFS2_IOCB_UNALIGNED_IO,
OCFS2_IOCB_NUM_LOCKS
};

Expand All @@ -91,4 +92,17 @@ enum ocfs2_iocb_lock_bits {
clear_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private)
#define ocfs2_iocb_is_sem_locked(iocb) \
test_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private)

#define ocfs2_iocb_set_unaligned_aio(iocb) \
set_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private)
#define ocfs2_iocb_clear_unaligned_aio(iocb) \
clear_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private)
#define ocfs2_iocb_is_unaligned_aio(iocb) \
test_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private)

#define OCFS2_IOEND_WQ_HASH_SZ 37
#define ocfs2_ioend_wq(v) (&ocfs2__ioend_wq[((unsigned long)(v)) %\
OCFS2_IOEND_WQ_HASH_SZ])
extern wait_queue_head_t ocfs2__ioend_wq[OCFS2_IOEND_WQ_HASH_SZ];

#endif /* OCFS2_FILE_H */
21 changes: 15 additions & 6 deletions trunk/fs/ocfs2/dlmglue.c
Original file line number Diff line number Diff line change
Expand Up @@ -1692,7 +1692,7 @@ int ocfs2_open_lock(struct inode *inode)
mlog(0, "inode %llu take PRMODE open lock\n",
(unsigned long long)OCFS2_I(inode)->ip_blkno);

if (ocfs2_mount_local(osb))
if (ocfs2_is_hard_readonly(osb) || ocfs2_mount_local(osb))
goto out;

lockres = &OCFS2_I(inode)->ip_open_lockres;
Expand All @@ -1718,6 +1718,12 @@ int ocfs2_try_open_lock(struct inode *inode, int write)
(unsigned long long)OCFS2_I(inode)->ip_blkno,
write ? "EXMODE" : "PRMODE");

if (ocfs2_is_hard_readonly(osb)) {
if (write)
status = -EROFS;
goto out;
}

if (ocfs2_mount_local(osb))
goto out;

Expand Down Expand Up @@ -2298,7 +2304,7 @@ int ocfs2_inode_lock_full_nested(struct inode *inode,
if (ocfs2_is_hard_readonly(osb)) {
if (ex)
status = -EROFS;
goto bail;
goto getbh;
}

if (ocfs2_mount_local(osb))
Expand Down Expand Up @@ -2356,7 +2362,7 @@ int ocfs2_inode_lock_full_nested(struct inode *inode,
mlog_errno(status);
goto bail;
}

getbh:
if (ret_bh) {
status = ocfs2_assign_bh(inode, ret_bh, local_bh);
if (status < 0) {
Expand Down Expand Up @@ -2628,8 +2634,11 @@ int ocfs2_dentry_lock(struct dentry *dentry, int ex)

BUG_ON(!dl);

if (ocfs2_is_hard_readonly(osb))
return -EROFS;
if (ocfs2_is_hard_readonly(osb)) {
if (ex)
return -EROFS;
return 0;
}

if (ocfs2_mount_local(osb))
return 0;
Expand All @@ -2647,7 +2656,7 @@ void ocfs2_dentry_unlock(struct dentry *dentry, int ex)
struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);

if (!ocfs2_mount_local(osb))
if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb))
ocfs2_cluster_unlock(osb, &dl->dl_lockres, level);
}

Expand Down
38 changes: 38 additions & 0 deletions trunk/fs/ocfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -2052,6 +2052,23 @@ int ocfs2_check_range_for_refcount(struct inode *inode, loff_t pos,
return ret;
}

static void ocfs2_aiodio_wait(struct inode *inode)
{
wait_queue_head_t *wq = ocfs2_ioend_wq(inode);

wait_event(*wq, (atomic_read(&OCFS2_I(inode)->ip_unaligned_aio) == 0));
}

static int ocfs2_is_io_unaligned(struct inode *inode, size_t count, loff_t pos)
{
int blockmask = inode->i_sb->s_blocksize - 1;
loff_t final_size = pos + count;

if ((pos & blockmask) || (final_size & blockmask))
return 1;
return 0;
}

static int ocfs2_prepare_inode_for_refcount(struct inode *inode,
struct file *file,
loff_t pos, size_t count,
Expand Down Expand Up @@ -2230,6 +2247,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
int full_coherency = !(osb->s_mount_opt &
OCFS2_MOUNT_COHERENCY_BUFFERED);
int unaligned_dio = 0;

trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry,
(unsigned long long)OCFS2_I(inode)->ip_blkno,
Expand Down Expand Up @@ -2297,6 +2315,10 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
goto out;
}

if (direct_io && !is_sync_kiocb(iocb))
unaligned_dio = ocfs2_is_io_unaligned(inode, iocb->ki_left,
*ppos);

/*
* We can't complete the direct I/O as requested, fall back to
* buffered I/O.
Expand All @@ -2311,6 +2333,18 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
goto relock;
}

if (unaligned_dio) {
/*
* Wait on previous unaligned aio to complete before
* proceeding.
*/
ocfs2_aiodio_wait(inode);

/* Mark the iocb as needing a decrement in ocfs2_dio_end_io */
atomic_inc(&OCFS2_I(inode)->ip_unaligned_aio);
ocfs2_iocb_set_unaligned_aio(iocb);
}

/*
* To later detect whether a journal commit for sync writes is
* necessary, we sample i_size, and cluster count here.
Expand Down Expand Up @@ -2382,8 +2416,12 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
if ((ret == -EIOCBQUEUED) || (!ocfs2_iocb_is_rw_locked(iocb))) {
rw_level = -1;
have_alloc_sem = 0;
unaligned_dio = 0;
}

if (unaligned_dio)
atomic_dec(&OCFS2_I(inode)->ip_unaligned_aio);

out:
if (rw_level != -1)
ocfs2_rw_unlock(inode, rw_level);
Expand Down
3 changes: 3 additions & 0 deletions trunk/fs/ocfs2/inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ struct ocfs2_inode_info
/* protects extended attribute changes on this inode */
struct rw_semaphore ip_xattr_sem;

/* Number of outstanding AIO's which are not page aligned */
atomic_t ip_unaligned_aio;

/* These fields are protected by ip_lock */
spinlock_t ip_lock;
u32 ip_open_count;
Expand Down
8 changes: 4 additions & 4 deletions trunk/fs/ocfs2/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ int ocfs2_info_handle_freeinode(struct inode *inode,
if (!oifi) {
status = -ENOMEM;
mlog_errno(status);
goto bail;
goto out_err;
}

if (o2info_from_user(*oifi, req))
Expand Down Expand Up @@ -431,7 +431,7 @@ int ocfs2_info_handle_freeinode(struct inode *inode,
o2info_set_request_error(&oifi->ifi_req, req);

kfree(oifi);

out_err:
return status;
}

Expand Down Expand Up @@ -666,7 +666,7 @@ int ocfs2_info_handle_freefrag(struct inode *inode,
if (!oiff) {
status = -ENOMEM;
mlog_errno(status);
goto bail;
goto out_err;
}

if (o2info_from_user(*oiff, req))
Expand Down Expand Up @@ -716,7 +716,7 @@ int ocfs2_info_handle_freefrag(struct inode *inode,
o2info_set_request_error(&oiff->iff_req, req);

kfree(oiff);

out_err:
return status;
}

Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/ocfs2/move_extents.c
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ static int ocfs2_move_extent(struct ocfs2_move_extents_context *context,
*/
ocfs2_probe_alloc_group(inode, gd_bh, &goal_bit, len, move_max_hop,
new_phys_cpos);
if (!new_phys_cpos) {
if (!*new_phys_cpos) {
ret = -ENOSPC;
goto out_commit;
}
Expand Down
4 changes: 2 additions & 2 deletions trunk/fs/ocfs2/ocfs2.h
Original file line number Diff line number Diff line change
Expand Up @@ -836,13 +836,13 @@ static inline unsigned int ocfs2_clusters_to_megabytes(struct super_block *sb,

static inline void _ocfs2_set_bit(unsigned int bit, unsigned long *bitmap)
{
__test_and_set_bit_le(bit, bitmap);
__set_bit_le(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)
{
__test_and_clear_bit_le(bit, bitmap);
__clear_bit_le(bit, bitmap);
}
#define ocfs2_clear_bit(bit, addr) _ocfs2_clear_bit((bit), (unsigned long *)(addr))

Expand Down
13 changes: 10 additions & 3 deletions trunk/fs/ocfs2/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#include "ocfs1_fs_compat.h"

#include "alloc.h"
#include "aops.h"
#include "blockcheck.h"
#include "dlmglue.h"
#include "export.h"
Expand Down Expand Up @@ -1616,12 +1617,17 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
return 0;
}

wait_queue_head_t ocfs2__ioend_wq[OCFS2_IOEND_WQ_HASH_SZ];

static int __init ocfs2_init(void)
{
int status;
int status, i;

ocfs2_print_version();

for (i = 0; i < OCFS2_IOEND_WQ_HASH_SZ; i++)
init_waitqueue_head(&ocfs2__ioend_wq[i]);

status = init_ocfs2_uptodate_cache();
if (status < 0) {
mlog_errno(status);
Expand Down Expand Up @@ -1760,7 +1766,7 @@ static void ocfs2_inode_init_once(void *data)
ocfs2_extent_map_init(&oi->vfs_inode);
INIT_LIST_HEAD(&oi->ip_io_markers);
oi->ip_dir_start_lookup = 0;

atomic_set(&oi->ip_unaligned_aio, 0);
init_rwsem(&oi->ip_alloc_sem);
init_rwsem(&oi->ip_xattr_sem);
mutex_init(&oi->ip_io_mutex);
Expand Down Expand Up @@ -1974,7 +1980,8 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
* If we failed before we got a uuid_str yet, we can't stop
* heartbeat. Otherwise, do it.
*/
if (!mnt_err && !ocfs2_mount_local(osb) && osb->uuid_str)
if (!mnt_err && !ocfs2_mount_local(osb) && osb->uuid_str &&
!ocfs2_is_hard_readonly(osb))
hangup_needed = 1;

if (osb->cconn)
Expand Down

0 comments on commit 3761ab5

Please sign in to comment.