Commit 7572e563 authored by Linus Torvalds's avatar Linus Torvalds

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.
parents a66f6375 d577632e
...@@ -406,6 +406,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb, ...@@ -406,6 +406,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
struct buffer_head *bh) struct buffer_head *bh)
{ {
int ret = 0; int ret = 0;
struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
mlog_entry_void(); mlog_entry_void();
...@@ -425,6 +426,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb, ...@@ -425,6 +426,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb,
get_bh(bh); /* for end_buffer_write_sync() */ get_bh(bh); /* for end_buffer_write_sync() */
bh->b_end_io = 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); submit_bh(WRITE, bh);
wait_on_buffer(bh); wait_on_buffer(bh);
......
...@@ -184,9 +184,8 @@ static void dlm_update_lvb(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, ...@@ -184,9 +184,8 @@ static void dlm_update_lvb(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
BUG_ON(!lksb); BUG_ON(!lksb);
/* only updates if this node masters the lockres */ /* only updates if this node masters the lockres */
spin_lock(&res->spinlock);
if (res->owner == dlm->node_num) { if (res->owner == dlm->node_num) {
spin_lock(&res->spinlock);
/* check the lksb flags for the direction */ /* check the lksb flags for the direction */
if (lksb->flags & DLM_LKSB_GET_LVB) { if (lksb->flags & DLM_LKSB_GET_LVB) {
mlog(0, "getting lvb from lockres for %s node\n", 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, ...@@ -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 * here. In the future we might want to clear it at the time
* the put is actually done. * the put is actually done.
*/ */
spin_unlock(&res->spinlock);
} }
spin_unlock(&res->spinlock);
/* reset any lvb flags on the lksb */ /* reset any lvb flags on the lksb */
lksb->flags &= ~(DLM_LKSB_PUT_LVB|DLM_LKSB_GET_LVB); lksb->flags &= ~(DLM_LKSB_PUT_LVB|DLM_LKSB_GET_LVB);
......
...@@ -112,20 +112,20 @@ MODULE_PARM_DESC(capabilities, DLMFS_CAPABILITIES); ...@@ -112,20 +112,20 @@ MODULE_PARM_DESC(capabilities, DLMFS_CAPABILITIES);
* O_RDONLY -> PRMODE level * O_RDONLY -> PRMODE level
* O_WRONLY -> EXMODE level * O_WRONLY -> EXMODE level
* *
* O_NONBLOCK -> LKM_NOQUEUE * O_NONBLOCK -> NOQUEUE
*/ */
static int dlmfs_decode_open_flags(int open_flags, static int dlmfs_decode_open_flags(int open_flags,
int *level, int *level,
int *flags) int *flags)
{ {
if (open_flags & (O_WRONLY|O_RDWR)) if (open_flags & (O_WRONLY|O_RDWR))
*level = LKM_EXMODE; *level = DLM_LOCK_EX;
else else
*level = LKM_PRMODE; *level = DLM_LOCK_PR;
*flags = 0; *flags = 0;
if (open_flags & O_NONBLOCK) if (open_flags & O_NONBLOCK)
*flags |= LKM_NOQUEUE; *flags |= DLM_LKF_NOQUEUE;
return 0; return 0;
} }
...@@ -166,7 +166,7 @@ static int dlmfs_file_open(struct inode *inode, ...@@ -166,7 +166,7 @@ static int dlmfs_file_open(struct inode *inode,
* to be able userspace to be able to distinguish a * to be able userspace to be able to distinguish a
* valid lock request from one that simply couldn't be * valid lock request from one that simply couldn't be
* granted. */ * granted. */
if (flags & LKM_NOQUEUE && status == -EAGAIN) if (flags & DLM_LKF_NOQUEUE && status == -EAGAIN)
status = -ETXTBSY; status = -ETXTBSY;
kfree(fp); kfree(fp);
goto bail; goto bail;
...@@ -193,7 +193,7 @@ static int dlmfs_file_release(struct inode *inode, ...@@ -193,7 +193,7 @@ static int dlmfs_file_release(struct inode *inode,
status = 0; status = 0;
if (fp) { if (fp) {
level = fp->fp_lock_level; level = fp->fp_lock_level;
if (level != LKM_IVMODE) if (level != DLM_LOCK_IV)
user_dlm_cluster_unlock(&ip->ip_lockres, level); user_dlm_cluster_unlock(&ip->ip_lockres, level);
kfree(fp); kfree(fp);
...@@ -262,7 +262,7 @@ static ssize_t dlmfs_file_read(struct file *filp, ...@@ -262,7 +262,7 @@ static ssize_t dlmfs_file_read(struct file *filp,
if ((count + *ppos) > i_size_read(inode)) if ((count + *ppos) > i_size_read(inode))
readlen = i_size_read(inode) - *ppos; readlen = i_size_read(inode) - *ppos;
else else
readlen = count - *ppos; readlen = count;
lvb_buf = kmalloc(readlen, GFP_NOFS); lvb_buf = kmalloc(readlen, GFP_NOFS);
if (!lvb_buf) if (!lvb_buf)
......
...@@ -684,6 +684,7 @@ restarted_transaction: ...@@ -684,6 +684,7 @@ restarted_transaction:
if (why == RESTART_META) { if (why == RESTART_META) {
mlog(0, "restarting function.\n"); mlog(0, "restarting function.\n");
restart_func = 1; restart_func = 1;
status = 0;
} else { } else {
BUG_ON(why != RESTART_TRANS); BUG_ON(why != RESTART_TRANS);
...@@ -1981,18 +1982,18 @@ relock: ...@@ -1981,18 +1982,18 @@ relock:
/* 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);
if (direct_io) { ret = generic_segment_checks(iov, &nr_segs, &ocount,
ret = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
VERIFY_READ); if (ret)
if (ret) goto out_dio;
goto out_dio;
count = ocount; count = ocount;
ret = generic_write_checks(file, ppos, &count, ret = generic_write_checks(file, ppos, &count,
S_ISBLK(inode->i_mode)); S_ISBLK(inode->i_mode));
if (ret) if (ret)
goto out_dio; goto out_dio;
if (direct_io) {
written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos, written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos,
ppos, count, ocount); ppos, count, ocount);
if (written < 0) { if (written < 0) {
...@@ -2007,7 +2008,10 @@ relock: ...@@ -2007,7 +2008,10 @@ relock:
goto out_dio; goto out_dio;
} }
} else { } 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: out_dio:
...@@ -2021,9 +2025,9 @@ out_dio: ...@@ -2021,9 +2025,9 @@ out_dio:
if (ret < 0) if (ret < 0)
written = ret; written = ret;
if (!ret && (old_size != i_size_read(inode) || if (!ret && ((old_size != i_size_read(inode)) ||
old_clusters != OCFS2_I(inode)->ip_clusters || (old_clusters != OCFS2_I(inode)->ip_clusters) ||
has_refcount)) { has_refcount)) {
ret = jbd2_journal_force_commit(osb->journal->j_journal); ret = jbd2_journal_force_commit(osb->journal->j_journal);
if (ret < 0) if (ret < 0)
written = ret; written = ret;
......
...@@ -558,6 +558,7 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, ...@@ -558,6 +558,7 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
if (IS_ERR(handle)) { if (IS_ERR(handle)) {
status = PTR_ERR(handle); status = PTR_ERR(handle);
handle = NULL;
mlog_errno(status); mlog_errno(status);
goto out; goto out;
} }
...@@ -639,11 +640,13 @@ static int ocfs2_remove_inode(struct inode *inode, ...@@ -639,11 +640,13 @@ static int ocfs2_remove_inode(struct inode *inode,
goto bail_unlock; goto bail_unlock;
} }
status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode, if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) {
orphan_dir_bh); status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode,
if (status < 0) { orphan_dir_bh);
mlog_errno(status); if (status < 0) {
goto bail_commit; mlog_errno(status);
goto bail_commit;
}
} }
/* set the inodes dtime */ /* set the inodes dtime */
...@@ -722,38 +725,39 @@ static void ocfs2_signal_wipe_completion(struct ocfs2_super *osb, ...@@ -722,38 +725,39 @@ static void ocfs2_signal_wipe_completion(struct ocfs2_super *osb,
static int ocfs2_wipe_inode(struct inode *inode, static int ocfs2_wipe_inode(struct inode *inode,
struct buffer_head *di_bh) struct buffer_head *di_bh)
{ {
int status, orphaned_slot; int status, orphaned_slot = -1;
struct inode *orphan_dir_inode = NULL; struct inode *orphan_dir_inode = NULL;
struct buffer_head *orphan_dir_bh = NULL; struct buffer_head *orphan_dir_bh = NULL;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 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; if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) {
orphaned_slot = le16_to_cpu(di->i_orphaned_slot); orphaned_slot = le16_to_cpu(di->i_orphaned_slot);
status = ocfs2_check_orphan_recovery_state(osb, orphaned_slot); status = ocfs2_check_orphan_recovery_state(osb, orphaned_slot);
if (status) if (status)
return status; return status;
orphan_dir_inode = ocfs2_get_system_file_inode(osb, orphan_dir_inode = ocfs2_get_system_file_inode(osb,
ORPHAN_DIR_SYSTEM_INODE, ORPHAN_DIR_SYSTEM_INODE,
orphaned_slot); orphaned_slot);
if (!orphan_dir_inode) { if (!orphan_dir_inode) {
status = -EEXIST; status = -EEXIST;
mlog_errno(status); mlog_errno(status);
goto bail; goto bail;
} }
/* Lock the orphan dir. The lock will be held for the entire /* Lock the orphan dir. The lock will be held for the entire
* delete_inode operation. We do this now to avoid races with * delete_inode operation. We do this now to avoid races with
* recovery completion on other nodes. */ * recovery completion on other nodes. */
mutex_lock(&orphan_dir_inode->i_mutex); mutex_lock(&orphan_dir_inode->i_mutex);
status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1); status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1);
if (status < 0) { if (status < 0) {
mutex_unlock(&orphan_dir_inode->i_mutex); mutex_unlock(&orphan_dir_inode->i_mutex);
mlog_errno(status); mlog_errno(status);
goto bail; goto bail;
}
} }
/* we do this while holding the orphan dir lock because we /* we do this while holding the orphan dir lock because we
...@@ -794,6 +798,9 @@ static int ocfs2_wipe_inode(struct inode *inode, ...@@ -794,6 +798,9 @@ static int ocfs2_wipe_inode(struct inode *inode,
mlog_errno(status); mlog_errno(status);
bail_unlock_dir: bail_unlock_dir:
if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)
return status;
ocfs2_inode_unlock(orphan_dir_inode, 1); ocfs2_inode_unlock(orphan_dir_inode, 1);
mutex_unlock(&orphan_dir_inode->i_mutex); mutex_unlock(&orphan_dir_inode->i_mutex);
brelse(orphan_dir_bh); brelse(orphan_dir_bh);
...@@ -889,7 +896,8 @@ static int ocfs2_query_inode_wipe(struct inode *inode, ...@@ -889,7 +896,8 @@ static int ocfs2_query_inode_wipe(struct inode *inode,
/* Do some basic inode verification... */ /* Do some basic inode verification... */
di = (struct ocfs2_dinode *) di_bh->b_data; 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 in the orphan dir must have ORPHANED_FL. The only
* inodes that come back out of the orphan dir are reflink * inodes that come back out of the orphan dir are reflink
......
...@@ -100,6 +100,8 @@ struct ocfs2_inode_info ...@@ -100,6 +100,8 @@ struct ocfs2_inode_info
#define OCFS2_INODE_MAYBE_ORPHANED 0x00000020 #define OCFS2_INODE_MAYBE_ORPHANED 0x00000020
/* Does someone have the file open O_DIRECT */ /* Does someone have the file open O_DIRECT */
#define OCFS2_INODE_OPEN_DIRECT 0x00000040 #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) static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode)
{ {
......
...@@ -408,23 +408,28 @@ static int ocfs2_mknod(struct inode *dir, ...@@ -408,23 +408,28 @@ static int ocfs2_mknod(struct inode *dir,
} }
} }
status = ocfs2_add_entry(handle, dentry, inode, /*
OCFS2_I(inode)->ip_blkno, parent_fe_bh, * Do this before adding the entry to the directory. We add
&lookup); * also set d_op after success so that ->d_iput() will cleanup
if (status < 0) { * 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); mlog_errno(status);
goto leave; goto leave;
} }
dentry->d_op = &ocfs2_dentry_ops;
status = ocfs2_dentry_attach_lock(dentry, inode, status = ocfs2_add_entry(handle, dentry, inode,
OCFS2_I(dir)->ip_blkno); OCFS2_I(inode)->ip_blkno, parent_fe_bh,
if (status) { &lookup);
if (status < 0) {
mlog_errno(status); mlog_errno(status);
goto leave; goto leave;
} }
insert_inode_hash(inode); insert_inode_hash(inode);
dentry->d_op = &ocfs2_dentry_ops;
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
status = 0; status = 0;
leave: leave:
...@@ -445,11 +450,6 @@ leave: ...@@ -445,11 +450,6 @@ leave:
ocfs2_free_dir_lookup_result(&lookup); ocfs2_free_dir_lookup_result(&lookup);
if ((status < 0) && inode) {
clear_nlink(inode);
iput(inode);
}
if (inode_ac) if (inode_ac)
ocfs2_free_alloc_context(inode_ac); ocfs2_free_alloc_context(inode_ac);
...@@ -459,6 +459,17 @@ leave: ...@@ -459,6 +459,17 @@ leave:
if (meta_ac) if (meta_ac)
ocfs2_free_alloc_context(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); mlog_exit(status);
return status; return status;
...@@ -1771,22 +1782,27 @@ static int ocfs2_symlink(struct inode *dir, ...@@ -1771,22 +1782,27 @@ static int ocfs2_symlink(struct inode *dir,
} }
} }
status = ocfs2_add_entry(handle, dentry, inode, /*
le64_to_cpu(fe->i_blkno), parent_fe_bh, * Do this before adding the entry to the directory. We add
&lookup); * also set d_op after success so that ->d_iput() will cleanup
if (status < 0) { * 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); mlog_errno(status);
goto bail; goto bail;
} }
dentry->d_op = &ocfs2_dentry_ops;
status = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno); status = ocfs2_add_entry(handle, dentry, inode,
if (status) { le64_to_cpu(fe->i_blkno), parent_fe_bh,
&lookup);
if (status < 0) {
mlog_errno(status); mlog_errno(status);
goto bail; goto bail;
} }
insert_inode_hash(inode); insert_inode_hash(inode);
dentry->d_op = &ocfs2_dentry_ops;
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
bail: bail:
if (status < 0 && did_quota) if (status < 0 && did_quota)
...@@ -1811,6 +1827,7 @@ bail: ...@@ -1811,6 +1827,7 @@ bail:
if (xattr_ac) if (xattr_ac)
ocfs2_free_alloc_context(xattr_ac); ocfs2_free_alloc_context(xattr_ac);
if ((status < 0) && inode) { if ((status < 0) && inode) {
OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SKIP_ORPHAN_DIR;
clear_nlink(inode); clear_nlink(inode);
iput(inode); iput(inode);
} }
...@@ -1976,6 +1993,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, ...@@ -1976,6 +1993,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
} }
le32_add_cpu(&fe->i_flags, OCFS2_ORPHANED_FL); 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 /* Record which orphan dir our inode now resides
* in. delete_inode will use this to determine which orphan * in. delete_inode will use this to determine which orphan
......
...@@ -4083,6 +4083,9 @@ static int ocfs2_complete_reflink(struct inode *s_inode, ...@@ -4083,6 +4083,9 @@ static int ocfs2_complete_reflink(struct inode *s_inode,
di->i_attr = s_di->i_attr; di->i_attr = s_di->i_attr;
if (preserve) { 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_uid = s_di->i_uid;
di->i_gid = s_di->i_gid; di->i_gid = s_di->i_gid;
di->i_mode = s_di->i_mode; di->i_mode = s_di->i_mode;
......
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