Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2
* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2: ocfs2: Avoid a gcc warning in ocfs2_wipe_inode(). ocfs2: Avoid direct write if we fall back to buffered I/O ocfs2_dlmfs: Fix math error when reading LVB. ocfs2: Update VFS inode's id info after reflink. ocfs2: potential ERR_PTR dereference on error paths ocfs2: Add directory entry later in ocfs2_symlink() and ocfs2_mknod() ocfs2: use OCFS2_INODE_SKIP_ORPHAN_DIR in ocfs2_mknod error path ocfs2: use OCFS2_INODE_SKIP_ORPHAN_DIR in ocfs2_symlink error path ocfs2: add OCFS2_INODE_SKIP_ORPHAN_DIR flag and honor it in the inode wipe code ocfs2: Reset status if we want to restart file extension. ocfs2: Compute metaecc for superblocks during online resize. ocfs2: Check the owner of a lockres inside the spinlock ocfs2: one more warning fix in ocfs2_file_aio_write(), v2 ocfs2_dlmfs: User DLM_* when decoding file open flags.
This commit is contained in:
commit
7572e56314
8 changed files with 111 additions and 75 deletions
|
@ -406,6 +406,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
|
|||
struct buffer_head *bh)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
|
||||
|
||||
mlog_entry_void();
|
||||
|
||||
|
@ -425,6 +426,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
|
|||
|
||||
get_bh(bh); /* for end_buffer_write_sync() */
|
||||
bh->b_end_io = end_buffer_write_sync;
|
||||
ocfs2_compute_meta_ecc(osb->sb, bh->b_data, &di->i_check);
|
||||
submit_bh(WRITE, bh);
|
||||
|
||||
wait_on_buffer(bh);
|
||||
|
|
|
@ -184,9 +184,8 @@ static void dlm_update_lvb(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
|
|||
BUG_ON(!lksb);
|
||||
|
||||
/* only updates if this node masters the lockres */
|
||||
spin_lock(&res->spinlock);
|
||||
if (res->owner == dlm->node_num) {
|
||||
|
||||
spin_lock(&res->spinlock);
|
||||
/* check the lksb flags for the direction */
|
||||
if (lksb->flags & DLM_LKSB_GET_LVB) {
|
||||
mlog(0, "getting lvb from lockres for %s node\n",
|
||||
|
@ -201,8 +200,8 @@ static void dlm_update_lvb(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
|
|||
* here. In the future we might want to clear it at the time
|
||||
* the put is actually done.
|
||||
*/
|
||||
spin_unlock(&res->spinlock);
|
||||
}
|
||||
spin_unlock(&res->spinlock);
|
||||
|
||||
/* reset any lvb flags on the lksb */
|
||||
lksb->flags &= ~(DLM_LKSB_PUT_LVB|DLM_LKSB_GET_LVB);
|
||||
|
|
|
@ -112,20 +112,20 @@ MODULE_PARM_DESC(capabilities, DLMFS_CAPABILITIES);
|
|||
* O_RDONLY -> PRMODE level
|
||||
* O_WRONLY -> EXMODE level
|
||||
*
|
||||
* O_NONBLOCK -> LKM_NOQUEUE
|
||||
* O_NONBLOCK -> NOQUEUE
|
||||
*/
|
||||
static int dlmfs_decode_open_flags(int open_flags,
|
||||
int *level,
|
||||
int *flags)
|
||||
{
|
||||
if (open_flags & (O_WRONLY|O_RDWR))
|
||||
*level = LKM_EXMODE;
|
||||
*level = DLM_LOCK_EX;
|
||||
else
|
||||
*level = LKM_PRMODE;
|
||||
*level = DLM_LOCK_PR;
|
||||
|
||||
*flags = 0;
|
||||
if (open_flags & O_NONBLOCK)
|
||||
*flags |= LKM_NOQUEUE;
|
||||
*flags |= DLM_LKF_NOQUEUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ static int dlmfs_file_open(struct inode *inode,
|
|||
* to be able userspace to be able to distinguish a
|
||||
* valid lock request from one that simply couldn't be
|
||||
* granted. */
|
||||
if (flags & LKM_NOQUEUE && status == -EAGAIN)
|
||||
if (flags & DLM_LKF_NOQUEUE && status == -EAGAIN)
|
||||
status = -ETXTBSY;
|
||||
kfree(fp);
|
||||
goto bail;
|
||||
|
@ -193,7 +193,7 @@ static int dlmfs_file_release(struct inode *inode,
|
|||
status = 0;
|
||||
if (fp) {
|
||||
level = fp->fp_lock_level;
|
||||
if (level != LKM_IVMODE)
|
||||
if (level != DLM_LOCK_IV)
|
||||
user_dlm_cluster_unlock(&ip->ip_lockres, level);
|
||||
|
||||
kfree(fp);
|
||||
|
@ -262,7 +262,7 @@ static ssize_t dlmfs_file_read(struct file *filp,
|
|||
if ((count + *ppos) > i_size_read(inode))
|
||||
readlen = i_size_read(inode) - *ppos;
|
||||
else
|
||||
readlen = count - *ppos;
|
||||
readlen = count;
|
||||
|
||||
lvb_buf = kmalloc(readlen, GFP_NOFS);
|
||||
if (!lvb_buf)
|
||||
|
|
|
@ -684,6 +684,7 @@ restarted_transaction:
|
|||
if (why == RESTART_META) {
|
||||
mlog(0, "restarting function.\n");
|
||||
restart_func = 1;
|
||||
status = 0;
|
||||
} else {
|
||||
BUG_ON(why != RESTART_TRANS);
|
||||
|
||||
|
@ -1981,18 +1982,18 @@ relock:
|
|||
/* communicate with ocfs2_dio_end_io */
|
||||
ocfs2_iocb_set_rw_locked(iocb, rw_level);
|
||||
|
||||
ret = generic_segment_checks(iov, &nr_segs, &ocount,
|
||||
VERIFY_READ);
|
||||
if (ret)
|
||||
goto out_dio;
|
||||
|
||||
count = ocount;
|
||||
ret = generic_write_checks(file, ppos, &count,
|
||||
S_ISBLK(inode->i_mode));
|
||||
if (ret)
|
||||
goto out_dio;
|
||||
|
||||
if (direct_io) {
|
||||
ret = generic_segment_checks(iov, &nr_segs, &ocount,
|
||||
VERIFY_READ);
|
||||
if (ret)
|
||||
goto out_dio;
|
||||
|
||||
count = ocount;
|
||||
ret = generic_write_checks(file, ppos, &count,
|
||||
S_ISBLK(inode->i_mode));
|
||||
if (ret)
|
||||
goto out_dio;
|
||||
|
||||
written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos,
|
||||
ppos, count, ocount);
|
||||
if (written < 0) {
|
||||
|
@ -2007,7 +2008,10 @@ relock:
|
|||
goto out_dio;
|
||||
}
|
||||
} else {
|
||||
written = __generic_file_aio_write(iocb, iov, nr_segs, ppos);
|
||||
current->backing_dev_info = file->f_mapping->backing_dev_info;
|
||||
written = generic_file_buffered_write(iocb, iov, nr_segs, *ppos,
|
||||
ppos, count, 0);
|
||||
current->backing_dev_info = NULL;
|
||||
}
|
||||
|
||||
out_dio:
|
||||
|
@ -2021,9 +2025,9 @@ out_dio:
|
|||
if (ret < 0)
|
||||
written = ret;
|
||||
|
||||
if (!ret && (old_size != i_size_read(inode) ||
|
||||
old_clusters != OCFS2_I(inode)->ip_clusters ||
|
||||
has_refcount)) {
|
||||
if (!ret && ((old_size != i_size_read(inode)) ||
|
||||
(old_clusters != OCFS2_I(inode)->ip_clusters) ||
|
||||
has_refcount)) {
|
||||
ret = jbd2_journal_force_commit(osb->journal->j_journal);
|
||||
if (ret < 0)
|
||||
written = ret;
|
||||
|
|
|
@ -558,6 +558,7 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
|
|||
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
|
||||
if (IS_ERR(handle)) {
|
||||
status = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
mlog_errno(status);
|
||||
goto out;
|
||||
}
|
||||
|
@ -639,11 +640,13 @@ static int ocfs2_remove_inode(struct inode *inode,
|
|||
goto bail_unlock;
|
||||
}
|
||||
|
||||
status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode,
|
||||
orphan_dir_bh);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail_commit;
|
||||
if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) {
|
||||
status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode,
|
||||
orphan_dir_bh);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail_commit;
|
||||
}
|
||||
}
|
||||
|
||||
/* set the inodes dtime */
|
||||
|
@ -722,38 +725,39 @@ static void ocfs2_signal_wipe_completion(struct ocfs2_super *osb,
|
|||
static int ocfs2_wipe_inode(struct inode *inode,
|
||||
struct buffer_head *di_bh)
|
||||
{
|
||||
int status, orphaned_slot;
|
||||
int status, orphaned_slot = -1;
|
||||
struct inode *orphan_dir_inode = NULL;
|
||||
struct buffer_head *orphan_dir_bh = NULL;
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
struct ocfs2_dinode *di;
|
||||
struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
|
||||
|
||||
di = (struct ocfs2_dinode *) di_bh->b_data;
|
||||
orphaned_slot = le16_to_cpu(di->i_orphaned_slot);
|
||||
if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) {
|
||||
orphaned_slot = le16_to_cpu(di->i_orphaned_slot);
|
||||
|
||||
status = ocfs2_check_orphan_recovery_state(osb, orphaned_slot);
|
||||
if (status)
|
||||
return status;
|
||||
status = ocfs2_check_orphan_recovery_state(osb, orphaned_slot);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
orphan_dir_inode = ocfs2_get_system_file_inode(osb,
|
||||
ORPHAN_DIR_SYSTEM_INODE,
|
||||
orphaned_slot);
|
||||
if (!orphan_dir_inode) {
|
||||
status = -EEXIST;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
orphan_dir_inode = ocfs2_get_system_file_inode(osb,
|
||||
ORPHAN_DIR_SYSTEM_INODE,
|
||||
orphaned_slot);
|
||||
if (!orphan_dir_inode) {
|
||||
status = -EEXIST;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Lock the orphan dir. The lock will be held for the entire
|
||||
* delete_inode operation. We do this now to avoid races with
|
||||
* recovery completion on other nodes. */
|
||||
mutex_lock(&orphan_dir_inode->i_mutex);
|
||||
status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1);
|
||||
if (status < 0) {
|
||||
mutex_unlock(&orphan_dir_inode->i_mutex);
|
||||
/* Lock the orphan dir. The lock will be held for the entire
|
||||
* delete_inode operation. We do this now to avoid races with
|
||||
* recovery completion on other nodes. */
|
||||
mutex_lock(&orphan_dir_inode->i_mutex);
|
||||
status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1);
|
||||
if (status < 0) {
|
||||
mutex_unlock(&orphan_dir_inode->i_mutex);
|
||||
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
/* we do this while holding the orphan dir lock because we
|
||||
|
@ -794,6 +798,9 @@ static int ocfs2_wipe_inode(struct inode *inode,
|
|||
mlog_errno(status);
|
||||
|
||||
bail_unlock_dir:
|
||||
if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)
|
||||
return status;
|
||||
|
||||
ocfs2_inode_unlock(orphan_dir_inode, 1);
|
||||
mutex_unlock(&orphan_dir_inode->i_mutex);
|
||||
brelse(orphan_dir_bh);
|
||||
|
@ -889,7 +896,8 @@ static int ocfs2_query_inode_wipe(struct inode *inode,
|
|||
|
||||
/* Do some basic inode verification... */
|
||||
di = (struct ocfs2_dinode *) di_bh->b_data;
|
||||
if (!(di->i_flags & cpu_to_le32(OCFS2_ORPHANED_FL))) {
|
||||
if (!(di->i_flags & cpu_to_le32(OCFS2_ORPHANED_FL)) &&
|
||||
!(oi->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) {
|
||||
/*
|
||||
* Inodes in the orphan dir must have ORPHANED_FL. The only
|
||||
* inodes that come back out of the orphan dir are reflink
|
||||
|
|
|
@ -100,6 +100,8 @@ struct ocfs2_inode_info
|
|||
#define OCFS2_INODE_MAYBE_ORPHANED 0x00000020
|
||||
/* Does someone have the file open O_DIRECT */
|
||||
#define OCFS2_INODE_OPEN_DIRECT 0x00000040
|
||||
/* Tell the inode wipe code it's not in orphan dir */
|
||||
#define OCFS2_INODE_SKIP_ORPHAN_DIR 0x00000080
|
||||
|
||||
static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode)
|
||||
{
|
||||
|
|
|
@ -408,6 +408,19 @@ static int ocfs2_mknod(struct inode *dir,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Do this before adding the entry to the directory. We add
|
||||
* also set d_op after success so that ->d_iput() will cleanup
|
||||
* the dentry lock even if ocfs2_add_entry() fails below.
|
||||
*/
|
||||
status = ocfs2_dentry_attach_lock(dentry, inode,
|
||||
OCFS2_I(dir)->ip_blkno);
|
||||
if (status) {
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
dentry->d_op = &ocfs2_dentry_ops;
|
||||
|
||||
status = ocfs2_add_entry(handle, dentry, inode,
|
||||
OCFS2_I(inode)->ip_blkno, parent_fe_bh,
|
||||
&lookup);
|
||||
|
@ -416,15 +429,7 @@ static int ocfs2_mknod(struct inode *dir,
|
|||
goto leave;
|
||||
}
|
||||
|
||||
status = ocfs2_dentry_attach_lock(dentry, inode,
|
||||
OCFS2_I(dir)->ip_blkno);
|
||||
if (status) {
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
insert_inode_hash(inode);
|
||||
dentry->d_op = &ocfs2_dentry_ops;
|
||||
d_instantiate(dentry, inode);
|
||||
status = 0;
|
||||
leave:
|
||||
|
@ -445,11 +450,6 @@ leave:
|
|||
|
||||
ocfs2_free_dir_lookup_result(&lookup);
|
||||
|
||||
if ((status < 0) && inode) {
|
||||
clear_nlink(inode);
|
||||
iput(inode);
|
||||
}
|
||||
|
||||
if (inode_ac)
|
||||
ocfs2_free_alloc_context(inode_ac);
|
||||
|
||||
|
@ -459,6 +459,17 @@ leave:
|
|||
if (meta_ac)
|
||||
ocfs2_free_alloc_context(meta_ac);
|
||||
|
||||
/*
|
||||
* We should call iput after the i_mutex of the bitmap been
|
||||
* unlocked in ocfs2_free_alloc_context, or the
|
||||
* ocfs2_delete_inode will mutex_lock again.
|
||||
*/
|
||||
if ((status < 0) && inode) {
|
||||
OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SKIP_ORPHAN_DIR;
|
||||
clear_nlink(inode);
|
||||
iput(inode);
|
||||
}
|
||||
|
||||
mlog_exit(status);
|
||||
|
||||
return status;
|
||||
|
@ -1771,6 +1782,18 @@ static int ocfs2_symlink(struct inode *dir,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Do this before adding the entry to the directory. We add
|
||||
* also set d_op after success so that ->d_iput() will cleanup
|
||||
* the dentry lock even if ocfs2_add_entry() fails below.
|
||||
*/
|
||||
status = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno);
|
||||
if (status) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
dentry->d_op = &ocfs2_dentry_ops;
|
||||
|
||||
status = ocfs2_add_entry(handle, dentry, inode,
|
||||
le64_to_cpu(fe->i_blkno), parent_fe_bh,
|
||||
&lookup);
|
||||
|
@ -1779,14 +1802,7 @@ static int ocfs2_symlink(struct inode *dir,
|
|||
goto bail;
|
||||
}
|
||||
|
||||
status = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno);
|
||||
if (status) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
insert_inode_hash(inode);
|
||||
dentry->d_op = &ocfs2_dentry_ops;
|
||||
d_instantiate(dentry, inode);
|
||||
bail:
|
||||
if (status < 0 && did_quota)
|
||||
|
@ -1811,6 +1827,7 @@ bail:
|
|||
if (xattr_ac)
|
||||
ocfs2_free_alloc_context(xattr_ac);
|
||||
if ((status < 0) && inode) {
|
||||
OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SKIP_ORPHAN_DIR;
|
||||
clear_nlink(inode);
|
||||
iput(inode);
|
||||
}
|
||||
|
@ -1976,6 +1993,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
|
|||
}
|
||||
|
||||
le32_add_cpu(&fe->i_flags, OCFS2_ORPHANED_FL);
|
||||
OCFS2_I(inode)->ip_flags &= ~OCFS2_INODE_SKIP_ORPHAN_DIR;
|
||||
|
||||
/* Record which orphan dir our inode now resides
|
||||
* in. delete_inode will use this to determine which orphan
|
||||
|
|
|
@ -4083,6 +4083,9 @@ static int ocfs2_complete_reflink(struct inode *s_inode,
|
|||
di->i_attr = s_di->i_attr;
|
||||
|
||||
if (preserve) {
|
||||
t_inode->i_uid = s_inode->i_uid;
|
||||
t_inode->i_gid = s_inode->i_gid;
|
||||
t_inode->i_mode = s_inode->i_mode;
|
||||
di->i_uid = s_di->i_uid;
|
||||
di->i_gid = s_di->i_gid;
|
||||
di->i_mode = s_di->i_mode;
|
||||
|
|
Loading…
Reference in a new issue