Commit a5f28ae4 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/cluster: Make o2net connect messages KERN_NOTICE
  ocfs2/dlm: Fix printing of lockname
  ocfs2: Fix contiguousness check in ocfs2_try_to_merge_extent_map()
  ocfs2/dlm: Remove BUG_ON in dlm recovery when freeing locks of a dead node
  ocfs2: Plugs race between the dc thread and an unlock ast message
  ocfs2: Remove overzealous BUG_ON during blocked lock processing
  ocfs2: Do not downconvert if the lock level is already compatible
  ocfs2: Prevent a livelock in dlmglue
  ocfs2: Fix setting of OCFS2_LOCK_BLOCKED during bast
  ocfs2: Use compat_ptr in reflink_arguments.
  ocfs2/dlm: Handle EAGAIN for compatibility - v2
  ocfs2: Add parenthesis to wrap the check for O_DIRECT.
  ocfs2: Only bug out when page size is larger than cluster size.
  ocfs2: Fix memory overflow in cow_by_page.
  ocfs2/dlm: Print more messages during lock migration
  ocfs2/dlm: Ignore LVBs of locks in the Blocked list
  ocfs2/trivial: Remove trailing whitespaces
  ocfs2: fix a misleading variable name
  ocfs2: Sync max_inline_data_with_xattr from tools.
  ocfs2: Fix refcnt leak on ocfs2_fast_follow_link() error path
parents 8defcaa6 6efd8066
...@@ -599,7 +599,7 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, ...@@ -599,7 +599,7 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
return ret; return ret;
} }
/* /*
* ocfs2_dio_end_io is called by the dio core when a dio is finished. We're * ocfs2_dio_end_io is called by the dio core when a dio is finished. We're
* particularly interested in the aio/dio case. Like the core uses * particularly interested in the aio/dio case. Like the core uses
* i_alloc_sem, we use the rw_lock DLM lock to protect io on one node from * i_alloc_sem, we use the rw_lock DLM lock to protect io on one node from
...@@ -670,7 +670,7 @@ static ssize_t ocfs2_direct_IO(int rw, ...@@ -670,7 +670,7 @@ static ssize_t ocfs2_direct_IO(int rw,
ret = blockdev_direct_IO_no_locking(rw, iocb, inode, ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
inode->i_sb->s_bdev, iov, offset, inode->i_sb->s_bdev, iov, offset,
nr_segs, nr_segs,
ocfs2_direct_IO_get_blocks, ocfs2_direct_IO_get_blocks,
ocfs2_dio_end_io); ocfs2_dio_end_io);
......
...@@ -368,7 +368,7 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, ...@@ -368,7 +368,7 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,
} }
ocfs2_metadata_cache_io_unlock(ci); ocfs2_metadata_cache_io_unlock(ci);
mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n", mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n",
(unsigned long long)block, nr, (unsigned long long)block, nr,
((flags & OCFS2_BH_IGNORE_CACHE) || ignore_cache) ? "no" : "yes", ((flags & OCFS2_BH_IGNORE_CACHE) || ignore_cache) ? "no" : "yes",
flags); flags);
......
...@@ -78,7 +78,7 @@ static struct o2hb_callback *hbcall_from_type(enum o2hb_callback_type type); ...@@ -78,7 +78,7 @@ static struct o2hb_callback *hbcall_from_type(enum o2hb_callback_type type);
unsigned int o2hb_dead_threshold = O2HB_DEFAULT_DEAD_THRESHOLD; unsigned int o2hb_dead_threshold = O2HB_DEFAULT_DEAD_THRESHOLD;
/* Only sets a new threshold if there are no active regions. /* Only sets a new threshold if there are no active regions.
* *
* No locking or otherwise interesting code is required for reading * No locking or otherwise interesting code is required for reading
* o2hb_dead_threshold as it can't change once regions are active and * o2hb_dead_threshold as it can't change once regions are active and
...@@ -170,7 +170,7 @@ static void o2hb_write_timeout(struct work_struct *work) ...@@ -170,7 +170,7 @@ static void o2hb_write_timeout(struct work_struct *work)
mlog(ML_ERROR, "Heartbeat write timeout to device %s after %u " mlog(ML_ERROR, "Heartbeat write timeout to device %s after %u "
"milliseconds\n", reg->hr_dev_name, "milliseconds\n", reg->hr_dev_name,
jiffies_to_msecs(jiffies - reg->hr_last_timeout_start)); jiffies_to_msecs(jiffies - reg->hr_last_timeout_start));
o2quo_disk_timeout(); o2quo_disk_timeout();
} }
...@@ -624,7 +624,7 @@ static int o2hb_check_slot(struct o2hb_region *reg, ...@@ -624,7 +624,7 @@ static int o2hb_check_slot(struct o2hb_region *reg,
"seq %llu last %llu changed %u equal %u\n", "seq %llu last %llu changed %u equal %u\n",
slot->ds_node_num, (long long)slot->ds_last_generation, slot->ds_node_num, (long long)slot->ds_last_generation,
le32_to_cpu(hb_block->hb_cksum), le32_to_cpu(hb_block->hb_cksum),
(unsigned long long)le64_to_cpu(hb_block->hb_seq), (unsigned long long)le64_to_cpu(hb_block->hb_seq),
(unsigned long long)slot->ds_last_time, slot->ds_changed_samples, (unsigned long long)slot->ds_last_time, slot->ds_changed_samples,
slot->ds_equal_samples); slot->ds_equal_samples);
......
...@@ -485,7 +485,7 @@ static void o2net_set_nn_state(struct o2net_node *nn, ...@@ -485,7 +485,7 @@ static void o2net_set_nn_state(struct o2net_node *nn,
} }
if (was_valid && !valid) { if (was_valid && !valid) {
printk(KERN_INFO "o2net: no longer connected to " printk(KERN_NOTICE "o2net: no longer connected to "
SC_NODEF_FMT "\n", SC_NODEF_ARGS(old_sc)); SC_NODEF_FMT "\n", SC_NODEF_ARGS(old_sc));
o2net_complete_nodes_nsw(nn); o2net_complete_nodes_nsw(nn);
} }
...@@ -493,7 +493,7 @@ static void o2net_set_nn_state(struct o2net_node *nn, ...@@ -493,7 +493,7 @@ static void o2net_set_nn_state(struct o2net_node *nn,
if (!was_valid && valid) { if (!was_valid && valid) {
o2quo_conn_up(o2net_num_from_nn(nn)); o2quo_conn_up(o2net_num_from_nn(nn));
cancel_delayed_work(&nn->nn_connect_expired); cancel_delayed_work(&nn->nn_connect_expired);
printk(KERN_INFO "o2net: %s " SC_NODEF_FMT "\n", printk(KERN_NOTICE "o2net: %s " SC_NODEF_FMT "\n",
o2nm_this_node() > sc->sc_node->nd_num ? o2nm_this_node() > sc->sc_node->nd_num ?
"connected to" : "accepted connection from", "connected to" : "accepted connection from",
SC_NODEF_ARGS(sc)); SC_NODEF_ARGS(sc));
...@@ -930,7 +930,7 @@ static void o2net_sendpage(struct o2net_sock_container *sc, ...@@ -930,7 +930,7 @@ static void o2net_sendpage(struct o2net_sock_container *sc,
cond_resched(); cond_resched();
continue; continue;
} }
mlog(ML_ERROR, "sendpage of size %zu to " SC_NODEF_FMT mlog(ML_ERROR, "sendpage of size %zu to " SC_NODEF_FMT
" failed with %zd\n", size, SC_NODEF_ARGS(sc), ret); " failed with %zd\n", size, SC_NODEF_ARGS(sc), ret);
o2net_ensure_shutdown(nn, sc, 0); o2net_ensure_shutdown(nn, sc, 0);
break; break;
...@@ -1476,14 +1476,14 @@ static void o2net_idle_timer(unsigned long data) ...@@ -1476,14 +1476,14 @@ static void o2net_idle_timer(unsigned long data)
do_gettimeofday(&now); do_gettimeofday(&now);
printk(KERN_INFO "o2net: connection to " SC_NODEF_FMT " has been idle for %u.%u " printk(KERN_NOTICE "o2net: connection to " SC_NODEF_FMT " has been idle for %u.%u "
"seconds, shutting it down.\n", SC_NODEF_ARGS(sc), "seconds, shutting it down.\n", SC_NODEF_ARGS(sc),
o2net_idle_timeout() / 1000, o2net_idle_timeout() / 1000,
o2net_idle_timeout() % 1000); o2net_idle_timeout() % 1000);
mlog(ML_NOTICE, "here are some times that might help debug the " mlog(ML_NOTICE, "here are some times that might help debug the "
"situation: (tmr %ld.%ld now %ld.%ld dr %ld.%ld adv " "situation: (tmr %ld.%ld now %ld.%ld dr %ld.%ld adv "
"%ld.%ld:%ld.%ld func (%08x:%u) %ld.%ld:%ld.%ld)\n", "%ld.%ld:%ld.%ld func (%08x:%u) %ld.%ld:%ld.%ld)\n",
sc->sc_tv_timer.tv_sec, (long) sc->sc_tv_timer.tv_usec, sc->sc_tv_timer.tv_sec, (long) sc->sc_tv_timer.tv_usec,
now.tv_sec, (long) now.tv_usec, now.tv_sec, (long) now.tv_usec,
sc->sc_tv_data_ready.tv_sec, (long) sc->sc_tv_data_ready.tv_usec, sc->sc_tv_data_ready.tv_sec, (long) sc->sc_tv_data_ready.tv_usec,
sc->sc_tv_advance_start.tv_sec, sc->sc_tv_advance_start.tv_sec,
......
...@@ -32,10 +32,10 @@ ...@@ -32,10 +32,10 @@
* on their number */ * on their number */
#define O2NET_QUORUM_DELAY_MS ((o2hb_dead_threshold + 2) * O2HB_REGION_TIMEOUT_MS) #define O2NET_QUORUM_DELAY_MS ((o2hb_dead_threshold + 2) * O2HB_REGION_TIMEOUT_MS)
/* /*
* This version number represents quite a lot, unfortunately. It not * This version number represents quite a lot, unfortunately. It not
* only represents the raw network message protocol on the wire but also * only represents the raw network message protocol on the wire but also
* locking semantics of the file system using the protocol. It should * locking semantics of the file system using the protocol. It should
* be somewhere else, I'm sure, but right now it isn't. * be somewhere else, I'm sure, but right now it isn't.
* *
* With version 11, we separate out the filesystem locking portion. The * With version 11, we separate out the filesystem locking portion. The
......
...@@ -95,7 +95,7 @@ const char *dlm_errname(enum dlm_status err); ...@@ -95,7 +95,7 @@ const char *dlm_errname(enum dlm_status err);
mlog(ML_ERROR, "dlm status = %s\n", dlm_errname((st))); \ mlog(ML_ERROR, "dlm status = %s\n", dlm_errname((st))); \
} while (0) } while (0)
#define DLM_LKSB_UNUSED1 0x01 #define DLM_LKSB_UNUSED1 0x01
#define DLM_LKSB_PUT_LVB 0x02 #define DLM_LKSB_PUT_LVB 0x02
#define DLM_LKSB_GET_LVB 0x04 #define DLM_LKSB_GET_LVB 0x04
#define DLM_LKSB_UNUSED2 0x08 #define DLM_LKSB_UNUSED2 0x08
......
...@@ -123,7 +123,7 @@ static void __dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock) ...@@ -123,7 +123,7 @@ static void __dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
dlm_lock_put(lock); dlm_lock_put(lock);
/* free up the reserved bast that we are cancelling. /* free up the reserved bast that we are cancelling.
* guaranteed that this will not be the last reserved * guaranteed that this will not be the last reserved
* ast because *both* an ast and a bast were reserved * ast because *both* an ast and a bast were reserved
* to get to this point. the res->spinlock will not be * to get to this point. the res->spinlock will not be
* taken here */ * taken here */
dlm_lockres_release_ast(dlm, res); dlm_lockres_release_ast(dlm, res);
......
...@@ -396,7 +396,7 @@ static enum dlm_status dlm_send_remote_convert_request(struct dlm_ctxt *dlm, ...@@ -396,7 +396,7 @@ static enum dlm_status dlm_send_remote_convert_request(struct dlm_ctxt *dlm,
/* instead of logging the same network error over /* instead of logging the same network error over
* and over, sleep here and wait for the heartbeat * and over, sleep here and wait for the heartbeat
* to notice the node is dead. times out after 5s. */ * to notice the node is dead. times out after 5s. */
dlm_wait_for_node_death(dlm, res->owner, dlm_wait_for_node_death(dlm, res->owner,
DLM_NODE_DEATH_WAIT_MAX); DLM_NODE_DEATH_WAIT_MAX);
ret = DLM_RECOVERING; ret = DLM_RECOVERING;
mlog(0, "node %u died so returning DLM_RECOVERING " mlog(0, "node %u died so returning DLM_RECOVERING "
......
...@@ -102,7 +102,7 @@ void __dlm_print_one_lock_resource(struct dlm_lock_resource *res) ...@@ -102,7 +102,7 @@ void __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
assert_spin_locked(&res->spinlock); assert_spin_locked(&res->spinlock);
stringify_lockname(res->lockname.name, res->lockname.len, stringify_lockname(res->lockname.name, res->lockname.len,
buf, sizeof(buf) - 1); buf, sizeof(buf));
printk("lockres: %s, owner=%u, state=%u\n", printk("lockres: %s, owner=%u, state=%u\n",
buf, res->owner, res->state); buf, res->owner, res->state);
printk(" last used: %lu, refcnt: %u, on purge list: %s\n", printk(" last used: %lu, refcnt: %u, on purge list: %s\n",
......
...@@ -816,7 +816,7 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, ...@@ -816,7 +816,7 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
} }
/* Once the dlm ctxt is marked as leaving then we don't want /* Once the dlm ctxt is marked as leaving then we don't want
* to be put in someone's domain map. * to be put in someone's domain map.
* Also, explicitly disallow joining at certain troublesome * Also, explicitly disallow joining at certain troublesome
* times (ie. during recovery). */ * times (ie. during recovery). */
if (dlm && dlm->dlm_state != DLM_CTXT_LEAVING) { if (dlm && dlm->dlm_state != DLM_CTXT_LEAVING) {
......
...@@ -269,7 +269,7 @@ static enum dlm_status dlmlock_remote(struct dlm_ctxt *dlm, ...@@ -269,7 +269,7 @@ static enum dlm_status dlmlock_remote(struct dlm_ctxt *dlm,
} }
dlm_revert_pending_lock(res, lock); dlm_revert_pending_lock(res, lock);
dlm_lock_put(lock); dlm_lock_put(lock);
} else if (dlm_is_recovery_lock(res->lockname.name, } else if (dlm_is_recovery_lock(res->lockname.name,
res->lockname.len)) { res->lockname.len)) {
/* special case for the $RECOVERY lock. /* special case for the $RECOVERY lock.
* there will never be an AST delivered to put * there will never be an AST delivered to put
......
...@@ -366,7 +366,7 @@ void dlm_hb_event_notify_attached(struct dlm_ctxt *dlm, int idx, int node_up) ...@@ -366,7 +366,7 @@ void dlm_hb_event_notify_attached(struct dlm_ctxt *dlm, int idx, int node_up)
struct dlm_master_list_entry *mle; struct dlm_master_list_entry *mle;
assert_spin_locked(&dlm->spinlock); assert_spin_locked(&dlm->spinlock);
list_for_each_entry(mle, &dlm->mle_hb_events, hb_events) { list_for_each_entry(mle, &dlm->mle_hb_events, hb_events) {
if (node_up) if (node_up)
dlm_mle_node_up(dlm, mle, NULL, idx); dlm_mle_node_up(dlm, mle, NULL, idx);
...@@ -833,7 +833,7 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm, ...@@ -833,7 +833,7 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm,
__dlm_insert_mle(dlm, mle); __dlm_insert_mle(dlm, mle);
/* still holding the dlm spinlock, check the recovery map /* still holding the dlm spinlock, check the recovery map
* to see if there are any nodes that still need to be * to see if there are any nodes that still need to be
* considered. these will not appear in the mle nodemap * considered. these will not appear in the mle nodemap
* but they might own this lockres. wait on them. */ * but they might own this lockres. wait on them. */
bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0);
...@@ -883,7 +883,7 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm, ...@@ -883,7 +883,7 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm,
msleep(500); msleep(500);
} }
continue; continue;
} }
dlm_kick_recovery_thread(dlm); dlm_kick_recovery_thread(dlm);
msleep(1000); msleep(1000);
...@@ -939,8 +939,8 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm, ...@@ -939,8 +939,8 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm,
res->lockname.name, blocked); res->lockname.name, blocked);
if (++tries > 20) { if (++tries > 20) {
mlog(ML_ERROR, "%s:%.*s: spinning on " mlog(ML_ERROR, "%s:%.*s: spinning on "
"dlm_wait_for_lock_mastery, blocked=%d\n", "dlm_wait_for_lock_mastery, blocked=%d\n",
dlm->name, res->lockname.len, dlm->name, res->lockname.len,
res->lockname.name, blocked); res->lockname.name, blocked);
dlm_print_one_lock_resource(res); dlm_print_one_lock_resource(res);
dlm_print_one_mle(mle); dlm_print_one_mle(mle);
...@@ -1029,7 +1029,7 @@ static int dlm_wait_for_lock_mastery(struct dlm_ctxt *dlm, ...@@ -1029,7 +1029,7 @@ static int dlm_wait_for_lock_mastery(struct dlm_ctxt *dlm,
ret = dlm_restart_lock_mastery(dlm, res, mle, *blocked); ret = dlm_restart_lock_mastery(dlm, res, mle, *blocked);
b = (mle->type == DLM_MLE_BLOCK); b = (mle->type == DLM_MLE_BLOCK);
if ((*blocked && !b) || (!*blocked && b)) { if ((*blocked && !b) || (!*blocked && b)) {
mlog(0, "%s:%.*s: status change: old=%d new=%d\n", mlog(0, "%s:%.*s: status change: old=%d new=%d\n",
dlm->name, res->lockname.len, res->lockname.name, dlm->name, res->lockname.len, res->lockname.name,
*blocked, b); *blocked, b);
*blocked = b; *blocked = b;
...@@ -1602,7 +1602,7 @@ int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data, ...@@ -1602,7 +1602,7 @@ int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data,
} }
mlog(0, "%u is the owner of %.*s, cleaning everyone else\n", mlog(0, "%u is the owner of %.*s, cleaning everyone else\n",
dlm->node_num, res->lockname.len, res->lockname.name); dlm->node_num, res->lockname.len, res->lockname.name);
ret = dlm_dispatch_assert_master(dlm, res, 0, request->node_idx, ret = dlm_dispatch_assert_master(dlm, res, 0, request->node_idx,
DLM_ASSERT_MASTER_MLE_CLEANUP); DLM_ASSERT_MASTER_MLE_CLEANUP);
if (ret < 0) { if (ret < 0) {
mlog(ML_ERROR, "failed to dispatch assert master work\n"); mlog(ML_ERROR, "failed to dispatch assert master work\n");
...@@ -1701,7 +1701,7 @@ static int dlm_do_assert_master(struct dlm_ctxt *dlm, ...@@ -1701,7 +1701,7 @@ static int dlm_do_assert_master(struct dlm_ctxt *dlm,
if (r & DLM_ASSERT_RESPONSE_REASSERT) { if (r & DLM_ASSERT_RESPONSE_REASSERT) {
mlog(0, "%.*s: node %u create mles on other " mlog(0, "%.*s: node %u create mles on other "
"nodes and requests a re-assert\n", "nodes and requests a re-assert\n",
namelen, lockname, to); namelen, lockname, to);
reassert = 1; reassert = 1;
} }
...@@ -1812,7 +1812,7 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data, ...@@ -1812,7 +1812,7 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
spin_unlock(&dlm->master_lock); spin_unlock(&dlm->master_lock);
spin_unlock(&dlm->spinlock); spin_unlock(&dlm->spinlock);
goto done; goto done;
} }
} }
} }
spin_unlock(&dlm->master_lock); spin_unlock(&dlm->master_lock);
...@@ -1883,7 +1883,7 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data, ...@@ -1883,7 +1883,7 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
int extra_ref = 0; int extra_ref = 0;
int nn = -1; int nn = -1;
int rr, err = 0; int rr, err = 0;
spin_lock(&mle->spinlock); spin_lock(&mle->spinlock);
if (mle->type == DLM_MLE_BLOCK || mle->type == DLM_MLE_MIGRATION) if (mle->type == DLM_MLE_BLOCK || mle->type == DLM_MLE_MIGRATION)
extra_ref = 1; extra_ref = 1;
...@@ -1891,7 +1891,7 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data, ...@@ -1891,7 +1891,7 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
/* MASTER mle: if any bits set in the response map /* MASTER mle: if any bits set in the response map
* then the calling node needs to re-assert to clear * then the calling node needs to re-assert to clear
* up nodes that this node contacted */ * up nodes that this node contacted */
while ((nn = find_next_bit (mle->response_map, O2NM_MAX_NODES, while ((nn = find_next_bit (mle->response_map, O2NM_MAX_NODES,
nn+1)) < O2NM_MAX_NODES) { nn+1)) < O2NM_MAX_NODES) {
if (nn != dlm->node_num && nn != assert->node_idx) if (nn != dlm->node_num && nn != assert->node_idx)
master_request = 1; master_request = 1;
...@@ -2002,7 +2002,7 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data, ...@@ -2002,7 +2002,7 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
__dlm_print_one_lock_resource(res); __dlm_print_one_lock_resource(res);
spin_unlock(&res->spinlock); spin_unlock(&res->spinlock);
spin_unlock(&dlm->spinlock); spin_unlock(&dlm->spinlock);
*ret_data = (void *)res; *ret_data = (void *)res;
dlm_put(dlm); dlm_put(dlm);
return -EINVAL; return -EINVAL;
} }
...@@ -2040,10 +2040,10 @@ int dlm_dispatch_assert_master(struct dlm_ctxt *dlm, ...@@ -2040,10 +2040,10 @@ int dlm_dispatch_assert_master(struct dlm_ctxt *dlm,
item->u.am.request_from = request_from; item->u.am.request_from = request_from;
item->u.am.flags = flags; item->u.am.flags = flags;
if (ignore_higher) if (ignore_higher)
mlog(0, "IGNORE HIGHER: %.*s\n", res->lockname.len, mlog(0, "IGNORE HIGHER: %.*s\n", res->lockname.len,
res->lockname.name); res->lockname.name);
spin_lock(&dlm->work_lock); spin_lock(&dlm->work_lock);
list_add_tail(&item->list, &dlm->work_list); list_add_tail(&item->list, &dlm->work_list);
spin_unlock(&dlm->work_lock); spin_unlock(&dlm->work_lock);
...@@ -2133,7 +2133,7 @@ static void dlm_assert_master_worker(struct dlm_work_item *item, void *data) ...@@ -2133,7 +2133,7 @@ static void dlm_assert_master_worker(struct dlm_work_item *item, void *data)
* think that $RECOVERY is currently mastered by a dead node. If so, * think that $RECOVERY is currently mastered by a dead node. If so,
* we wait a short time to allow that node to get notified by its own * we wait a short time to allow that node to get notified by its own
* heartbeat stack, then check again. All $RECOVERY lock resources * heartbeat stack, then check again. All $RECOVERY lock resources
* mastered by dead nodes are purged when the hearbeat callback is * mastered by dead nodes are purged when the hearbeat callback is
* fired, so we can know for sure that it is safe to continue once * fired, so we can know for sure that it is safe to continue once
* the node returns a live node or no node. */ * the node returns a live node or no node. */
static int dlm_pre_master_reco_lockres(struct dlm_ctxt *dlm, static int dlm_pre_master_reco_lockres(struct dlm_ctxt *dlm,
...@@ -2174,7 +2174,7 @@ static int dlm_pre_master_reco_lockres(struct dlm_ctxt *dlm, ...@@ -2174,7 +2174,7 @@ static int dlm_pre_master_reco_lockres(struct dlm_ctxt *dlm,
ret = -EAGAIN; ret = -EAGAIN;
} }
spin_unlock(&dlm->spinlock); spin_unlock(&dlm->spinlock);
mlog(0, "%s: reco lock master is %u\n", dlm->name, mlog(0, "%s: reco lock master is %u\n", dlm->name,
master); master);
break; break;
} }
...@@ -2602,7 +2602,7 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm, ...@@ -2602,7 +2602,7 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
mlog(0, "%s:%.*s: timed out during migration\n", mlog(0, "%s:%.*s: timed out during migration\n",
dlm->name, res->lockname.len, res->lockname.name); dlm->name, res->lockname.len, res->lockname.name);
/* avoid hang during shutdown when migrating lockres /* avoid hang during shutdown when migrating lockres
* to a node which also goes down */ * to a node which also goes down */
if (dlm_is_node_dead(dlm, target)) { if (dlm_is_node_dead(dlm, target)) {
mlog(0, "%s:%.*s: expected migration " mlog(0, "%s:%.*s: expected migration "
...@@ -2738,7 +2738,7 @@ static int dlm_migration_can_proceed(struct dlm_ctxt *dlm, ...@@ -2738,7 +2738,7 @@ static int dlm_migration_can_proceed(struct dlm_ctxt *dlm,
can_proceed = !!(res->state & DLM_LOCK_RES_MIGRATING); can_proceed = !!(res->state & DLM_LOCK_RES_MIGRATING);
spin_unlock(&res->spinlock); spin_unlock(&res->spinlock);
/* target has died, so make the caller break out of the /* target has died, so make the caller break out of the
* wait_event, but caller must recheck the domain_map */ * wait_event, but caller must recheck the domain_map */
spin_lock(&dlm->spinlock); spin_lock(&dlm->spinlock);
if (!test_bit(mig_target, dlm->domain_map)) if (!test_bit(mig_target, dlm->domain_map))
......
This diff is collapsed.
...@@ -190,8 +190,8 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm, ...@@ -190,8 +190,8 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm,
actions &= ~(DLM_UNLOCK_REMOVE_LOCK| actions &= ~(DLM_UNLOCK_REMOVE_LOCK|
DLM_UNLOCK_REGRANT_LOCK| DLM_UNLOCK_REGRANT_LOCK|
DLM_UNLOCK_CLEAR_CONVERT_TYPE); DLM_UNLOCK_CLEAR_CONVERT_TYPE);
} else if (status == DLM_RECOVERING || } else if (status == DLM_RECOVERING ||
status == DLM_MIGRATING || status == DLM_MIGRATING ||
status == DLM_FORWARD) { status == DLM_FORWARD) {
/* must clear the actions because this unlock /* must clear the actions because this unlock
* is about to be retried. cannot free or do * is about to be retried. cannot free or do
...@@ -661,14 +661,14 @@ enum dlm_status dlmunlock(struct dlm_ctxt *dlm, struct dlm_lockstatus *lksb, ...@@ -661,14 +661,14 @@ enum dlm_status dlmunlock(struct dlm_ctxt *dlm, struct dlm_lockstatus *lksb,
if (call_ast) { if (call_ast) {
mlog(0, "calling unlockast(%p, %d)\n", data, status); mlog(0, "calling unlockast(%p, %d)\n", data, status);
if (is_master) { if (is_master) {
/* it is possible that there is one last bast /* it is possible that there is one last bast
* pending. make sure it is flushed, then * pending. make sure it is flushed, then
* call the unlockast. * call the unlockast.
* not an issue if this is a mastered remotely, * not an issue if this is a mastered remotely,
* since this lock has been removed from the * since this lock has been removed from the
* lockres queues and cannot be found. */ * lockres queues and cannot be found. */
dlm_kick_thread(dlm, NULL); dlm_kick_thread(dlm, NULL);
wait_event(dlm->ast_wq, wait_event(dlm->ast_wq,
dlm_lock_basts_flushed(dlm, lock)); dlm_lock_basts_flushed(dlm, lock));
} }
(*unlockast)(data, status); (*unlockast)(data, status);
......
...@@ -875,6 +875,14 @@ static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lo ...@@ -875,6 +875,14 @@ static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lo
lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH); lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);
lockres->l_level = lockres->l_requested; lockres->l_level = lockres->l_requested;
/*
* We set the OCFS2_LOCK_UPCONVERT_FINISHING flag before clearing
* the OCFS2_LOCK_BUSY flag to prevent the dc thread from
* downconverting the lock before the upconvert has fully completed.
*/
lockres_or_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
mlog_exit_void(); mlog_exit_void();
...@@ -907,8 +915,6 @@ static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres, ...@@ -907,8 +915,6 @@ static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres,
assert_spin_locked(&lockres->l_lock); assert_spin_locked(&lockres->l_lock);
lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED);
if (level > lockres->l_blocking) { if (level > lockres->l_blocking) {
/* only schedule a downconvert if we haven't already scheduled /* only schedule a downconvert if we haven't already scheduled
* one that goes low enough to satisfy the level we're * one that goes low enough to satisfy the level we're
...@@ -921,6 +927,9 @@ static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres, ...@@ -921,6 +927,9 @@ static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres,
lockres->l_blocking = level; lockres->l_blocking = level;
} }
if (needs_downconvert)
lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED);
mlog_exit(needs_downconvert); mlog_exit(needs_downconvert);
return needs_downconvert; return needs_downconvert;
} }
...@@ -1133,6 +1142,7 @@ static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, ...@@ -1133,6 +1142,7 @@ static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,
mlog_entry_void(); mlog_entry_void();
spin_lock_irqsave(&lockres->l_lock, flags); spin_lock_irqsave(&lockres->l_lock, flags);
lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
lockres_clear_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
if (convert) if (convert)
lockres->l_action = OCFS2_AST_INVALID; lockres->l_action = OCFS2_AST_INVALID;
else else
...@@ -1323,13 +1333,13 @@ static int __ocfs2_cluster_lock(struct ocfs2_super *osb, ...@@ -1323,13 +1333,13 @@ static int __ocfs2_cluster_lock(struct ocfs2_super *osb,
again: again:
wait = 0; wait = 0;
spin_lock_irqsave(&lockres->l_lock, flags);
if (catch_signals && signal_pending(current)) { if (catch_signals && signal_pending(current)) {
ret = -ERESTARTSYS; ret = -ERESTARTSYS;
goto out; goto unlock;
} }
spin_lock_irqsave(&lockres->l_lock, flags);
mlog_bug_on_msg(lockres->l_flags & OCFS2_LOCK_FREEING, mlog_bug_on_msg(lockres->l_flags & OCFS2_LOCK_FREEING,
"Cluster lock called on freeing lockres %s! flags " "Cluster lock called on freeing lockres %s! flags "
"0x%lx\n", lockres->l_name, lockres->l_flags); "0x%lx\n", lockres->l_name, lockres->l_flags);
...@@ -1346,6 +1356,25 @@ static int __ocfs2_cluster_lock(struct ocfs2_super *osb, ...@@ -1346,6 +1356,25 @@ static int __ocfs2_cluster_lock(struct ocfs2_super *osb,
goto unlock; goto unlock;
} }
if (lockres->l_flags & OCFS2_LOCK_UPCONVERT_FINISHING) {
/*
* We've upconverted. If the lock now has a level we can
* work with, we take it. If, however, the lock is not at the
* required level, we go thru the full cycle. One way this could
* happen is if a process requesting an upconvert to PR is
* closely followed by another requesting upconvert to an EX.
* If the process requesting EX lands here, we want it to
* continue attempting to upconvert and let the process
* requesting PR take the lock.
* If multiple processes request upconvert to PR, the first one
* here will take the lock. The others will have to go thru the
* OCFS2_LOCK_BLOCKED check to ensure that there is no pending
* downconvert request.
*/
if (level <= lockres->l_level)
goto update_holders;
}
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
...@@ -1416,11 +1445,14 @@ static int __ocfs2_cluster_lock(struct ocfs2_super *osb, ...@@ -1416,11 +1445,14 @@ static int __ocfs2_cluster_lock(struct ocfs2_super *osb,
goto again; goto again;
} }
update_holders:
/* Ok, if we get here then we're good to go. */ /* Ok, if we get here then we're good to go. */
ocfs2_inc_holders(lockres, level); ocfs2_inc_holders(lockres, level);
ret = 0; ret = 0;
unlock: unlock:
lockres_clear_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
spin_unlock_irqrestore(&lockres->l_lock, flags); spin_unlock_irqrestore(&lockres->l_lock, flags);
out: out:
/* /*
...@@ -3155,7 +3187,7 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb, ...@@ -3155,7 +3187,7 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb,
/* Mark the lockres as being dropped. It will no longer be /* Mark the lockres as being dropped. It will no longer be
* queued if blocking, but we still may have to wait on it * queued if blocking, but we still may have to wait on it
* being dequeued from the downconvert thread before we can consider * being dequeued from the downconvert thread before we can consider
* it safe to drop. * it safe to drop.
* *
* You can *not* attempt to call cluster_lock on this lockres anymore. */ * You can *not* attempt to call cluster_lock on this lockres anymore. */
void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres) void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres)
...@@ -3352,6 +3384,7 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb, ...@@ -3352,6 +3384,7 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb,
unsigned long flags; unsigned long flags;
int blocking; int blocking;
int new_level; int new_level;
int level;
int ret = 0; int ret = 0;
int set_lvb = 0; int set_lvb = 0;
unsigned int gen; unsigned int gen;
...@@ -3360,9 +3393,17 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb, ...@@ -3360,9 +3393,17 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb,
spin_lock_irqsave(&lockres->l_lock, flags); spin_lock_irqsave(&lockres->l_lock, flags);
BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED));
recheck: recheck:
/*
* Is it still blocking? If not, we have no more work to do.
*/
if (!(lockres->l_flags & OCFS2_LOCK_BLOCKED)) {
BUG_ON(lockres->l_blocking != DLM_LOCK_NL);
spin_unlock_irqrestore(&lockres->l_lock, flags);
ret = 0;
goto leave;
}
if (lockres->l_flags & OCFS2_LOCK_BUSY) { if (lockres->l_flags & OCFS2_LOCK_BUSY) {
/* XXX /* XXX
* This is a *big* race. The OCFS2_LOCK_PENDING flag * This is a *big* race. The OCFS2_LOCK_PENDING flag
...@@ -3401,6 +3442,31 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb, ...@@ -3401,6 +3442,31 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb,
goto leave; goto leave;
} }
/*
* This prevents livelocks. OCFS2_LOCK_UPCONVERT_FINISHING flag is
* set when the ast is received for an upconvert just before the
* OCFS2_LOCK_BUSY flag is cleared. Now if the fs received a bast
* on the heels of the ast, we want to delay the downconvert just
* enough to allow the up requestor to do its task. Because this
* lock is in the blocked queue, the lock will be downconverted
* as soon as the requestor is done with the lock.
*/
if (lockres->l_flags & OCFS2_LOCK_UPCONVERT_FINISHING)
goto leave_requeue;
/*
* How can we block and yet be at NL? We were trying to upconvert
* from NL and got canceled. The code comes back here, and now
* we notice and clear BLOCKING.
*/
if (lockres->l_level == DLM_LOCK_NL) {
BUG_ON(lockres->l_ex_holders || lockres->l_ro_holders);
lockres->l_blocking = DLM_LOCK_NL;
lockres_clear_flags(lockres, OCFS2_LOCK_BLOCKED);
spin_unlock_irqrestore(&lockres->l_lock, flags);
goto leave;
}
/* if we're blocking an exclusive and we have *any* holders, /* if we're blocking an exclusive and we have *any* holders,
* then requeue. */ * then requeue. */
if ((lockres->l_blocking == DLM_LOCK_EX) if ((lockres->l_blocking == DLM_LOCK_EX)
...@@ -3438,6 +3504,7 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb, ...@@ -3438,6 +3504,7 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb,
* may sleep, so we save off a copy of what we're blocking as * may sleep, so we save off a copy of what we're blocking as
* it may change while we're not holding the spin lock. */ * it may change while we're not holding the spin lock. */
blocking = lockres->l_blocking; blocking = lockres->l_blocking;
level = lockres->l_level;
spin_unlock_irqrestore(&lockres->l_lock, flags); spin_unlock_irqrestore(&lockres->l_lock, flags);
ctl->unblock_action = lockres->l_ops->downconvert_worker(lockres, blocking); ctl->unblock_action = lockres->l_ops->downconvert_worker(lockres, blocking);
...@@ -3446,7 +3513,7 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb, ...@@ -3446,7 +3513,7 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb,
goto leave; goto leave;
spin_lock_irqsave(&lockres->l_lock, flags); spin_lock_irqsave(&lockres->l_lock, flags);
if (blocking != lockres->l_blocking) { if ((blocking != lockres->l_blocking) || (level != lockres->l_level)) {
/* If this changed underneath us, then we can't drop /* If this changed underneath us, then we can't drop
* it just yet. */ * it just yet. */
goto recheck; goto recheck;
......
...@@ -239,7 +239,7 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, ...@@ -239,7 +239,7 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len,
mlog(0, "Encoding parent: blkno: %llu, generation: %u\n", mlog(0, "Encoding parent: blkno: %llu, generation: %u\n",
(unsigned long long)blkno, generation); (unsigned long long)blkno, generation);
} }
*max_len = len; *max_len = len;
bail: bail:
......
...@@ -192,7 +192,7 @@ static int ocfs2_try_to_merge_extent_map(struct ocfs2_extent_map_item *emi, ...@@ -192,7 +192,7 @@ static int ocfs2_try_to_merge_extent_map(struct ocfs2_extent_map_item *emi,
emi->ei_clusters += ins->ei_clusters; emi->ei_clusters += ins->ei_clusters;
return 1; return 1;
} else if ((ins->ei_phys + ins->ei_clusters) == emi->ei_phys && } else if ((ins->ei_phys + ins->ei_clusters) == emi->ei_phys &&
(ins->ei_cpos + ins->ei_clusters) == emi->ei_phys && (ins->ei_cpos + ins->ei_clusters) == emi->ei_cpos &&
ins->ei_flags == emi->ei_flags) { ins->ei_flags == emi->ei_flags) {
emi->ei_phys = ins->ei_phys; emi->ei_phys = ins->ei_phys;
emi->ei_cpos = ins->ei_cpos; emi->ei_cpos = ins->ei_cpos;
......
...@@ -749,7 +749,7 @@ static int ocfs2_write_zero_page(struct inode *inode, ...@@ -749,7 +749,7 @@ static int ocfs2_write_zero_page(struct inode *inode,
int ret; int ret;
offset = (size & (PAGE_CACHE_SIZE-1)); /* Within page */ offset = (size & (PAGE_CACHE_SIZE-1)); /* Within page */
/* ugh. in prepare/commit_write, if from==to==start of block, we /* ugh. in prepare/commit_write, if from==to==start of block, we
** skip the prepare. make sure we never send an offset for the start ** skip the prepare. make sure we never send an offset for the start
** of a block ** of a block
*/ */
...@@ -1779,7 +1779,7 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry, ...@@ -1779,7 +1779,7 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
loff_t saved_pos, end; loff_t saved_pos, end;
/* /*
* We start with a read level meta lock and only jump to an ex * We start with a read level meta lock and only jump to an ex
* if we need to make modifications here. * if we need to make modifications here.
*/ */
...@@ -2013,8 +2013,8 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, ...@@ -2013,8 +2013,8 @@ 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_DSYNC && !direct_io) || IS_SYNC(inode) || if (((file->f_flags & O_DSYNC) && !direct_io) || IS_SYNC(inode) ||
(file->f_flags & O_DIRECT && has_refcount)) { ((file->f_flags & O_DIRECT) && has_refcount)) {
ret = filemap_fdatawrite_range(file->f_mapping, pos, ret = filemap_fdatawrite_range(file->f_mapping, pos,
pos + count - 1); pos + count - 1);
if (ret < 0) if (ret < 0)
...@@ -2033,7 +2033,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, ...@@ -2033,7 +2033,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
pos + count - 1); pos + count - 1);
} }
/* /*
* 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
* it can unlock our rw lock. (it's the clustered equivalent of * it can unlock our rw lock. (it's the clustered equivalent of
...@@ -2198,7 +2198,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, ...@@ -2198,7 +2198,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
goto bail; goto bail;
} }
/* /*
* buffered reads protect themselves in ->readpage(). O_DIRECT reads * buffered reads protect themselves in ->readpage(). O_DIRECT reads
* need locks to protect pending reads from racing with truncate. * need locks to protect pending reads from racing with truncate.
*/ */
...@@ -2220,10 +2220,10 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, ...@@ -2220,10 +2220,10 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
* We're fine letting folks race truncates and extending * We're fine letting folks race truncates and extending
* writes with read across the cluster, just like they can * writes with read across the cluster, just like they can
* locally. Hence no rw_lock during read. * locally. Hence no rw_lock during read.
* *
* Take and drop the meta data lock to update inode fields * Take and drop the meta data lock to update inode fields
* like i_size. This allows the checks down below * like i_size. This allows the checks down below
* generic_file_aio_read() a chance of actually working. * generic_file_aio_read() a chance of actually working.
*/ */
ret = ocfs2_inode_lock_atime(inode, filp->f_vfsmnt, &lock_level); ret = ocfs2_inode_lock_atime(inode, filp->f_vfsmnt, &lock_level);
if (ret < 0) { if (ret < 0) {
...@@ -2248,7 +2248,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, ...@@ -2248,7 +2248,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
bail: bail:
if (have_alloc_sem) if (have_alloc_sem)
up_read(&inode->i_alloc_sem); up_read(&inode->i_alloc_sem);
if (rw_level != -1) if (rw_level != -1)
ocfs2_rw_unlock(inode, rw_level); ocfs2_rw_unlock(inode, rw_level);
mlog_exit(ret); mlog_exit(ret);
......
...@@ -475,7 +475,7 @@ static int ocfs2_read_locked_inode(struct inode *inode, ...@@ -475,7 +475,7 @@ static int ocfs2_read_locked_inode(struct inode *inode,
if (args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY) { if (args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY) {
status = ocfs2_try_open_lock(inode, 0); status = ocfs2_try_open_lock(inode, 0);
if (status) { if (status) {
make_bad_inode(inode); make_bad_inode(inode);
return status; return status;
} }
} }
...@@ -684,7 +684,7 @@ static int ocfs2_remove_inode(struct inode *inode, ...@@ -684,7 +684,7 @@ static int ocfs2_remove_inode(struct inode *inode,
return status; return status;
} }
/* /*
* Serialize with orphan dir recovery. If the process doing * Serialize with orphan dir recovery. If the process doing
* recovery on this orphan dir does an iget() with the dir * recovery on this orphan dir does an iget() with the dir
* i_mutex held, we'll deadlock here. Instead we detect this * i_mutex held, we'll deadlock here. Instead we detect this
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/compat.h>
#define MLOG_MASK_PREFIX ML_INODE #define MLOG_MASK_PREFIX ML_INODE
#include <cluster/masklog.h> #include <cluster/masklog.h>
...@@ -181,6 +182,10 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -181,6 +182,10 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{ {
bool preserve;
struct reflink_arguments args;
struct inode *inode = file->f_path.dentry->d_inode;
switch (cmd) { switch (cmd) {
case OCFS2_IOC32_GETFLAGS: case OCFS2_IOC32_GETFLAGS:
cmd = OCFS2_IOC_GETFLAGS; cmd = OCFS2_IOC_GETFLAGS;
...@@ -195,8 +200,15 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) ...@@ -195,8 +200,15 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case OCFS2_IOC_GROUP_EXTEND: case OCFS2_IOC_GROUP_EXTEND:
case OCFS2_IOC_GROUP_ADD: case OCFS2_IOC_GROUP_ADD:
case OCFS2_IOC_GROUP_ADD64: case OCFS2_IOC_GROUP_ADD64:
case OCFS2_IOC_REFLINK:
break; break;
case OCFS2_IOC_REFLINK:
if (copy_from_user(&args, (struct reflink_arguments *)arg,
sizeof(args)))
return -EFAULT;
preserve = (args.preserve != 0);
return ocfs2_reflink_ioctl(inode, compat_ptr(args.old_path),
compat_ptr(args.new_path), preserve);
default: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
......
...@@ -2034,7 +2034,7 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb, ...@@ -2034,7 +2034,7 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb,
status = -ENOENT; status = -ENOENT;
mlog_errno(status); mlog_errno(status);
return status; return status;
} }
mutex_lock(&orphan_dir_inode->i_mutex); mutex_lock(&orphan_dir_inode->i_mutex);
status = ocfs2_inode_lock(orphan_dir_inode, NULL, 0); status = ocfs2_inode_lock(orphan_dir_inode, NULL, 0);
......
...@@ -136,6 +136,10 @@ enum ocfs2_unlock_action { ...@@ -136,6 +136,10 @@ enum ocfs2_unlock_action {
#define OCFS2_LOCK_PENDING (0x00000400) /* This lockres is pending a #define OCFS2_LOCK_PENDING (0x00000400) /* This lockres is pending a
call to dlm_lock. Only call to dlm_lock. Only
exists with BUSY set. */ exists with BUSY set. */
#define OCFS2_LOCK_UPCONVERT_FINISHING (0x00000800) /* blocks the dc thread
* from downconverting
* before the upconvert
* has completed */
struct ocfs2_lock_res_ops; struct ocfs2_lock_res_ops;
......
...@@ -1417,9 +1417,16 @@ static inline int ocfs2_fast_symlink_chars(int blocksize) ...@@ -1417,9 +1417,16 @@ static inline int ocfs2_fast_symlink_chars(int blocksize)
return blocksize - offsetof(struct ocfs2_dinode, id2.i_symlink); return blocksize - offsetof(struct ocfs2_dinode, id2.i_symlink);
} }
static inline int ocfs2_max_inline_data(int blocksize) static inline int ocfs2_max_inline_data_with_xattr(int blocksize,
struct ocfs2_dinode *di)
{ {
return blocksize - offsetof(struct ocfs2_dinode, id2.i_data.id_data); if (di && (di->i_dyn_features & OCFS2_INLINE_XATTR_FL))
return blocksize -
offsetof(struct ocfs2_dinode, id2.i_data.id_data) -
di->i_xattr_inline_size;
else
return blocksize -
offsetof(struct ocfs2_dinode, id2.i_data.id_data);
} }
static inline int ocfs2_extent_recs_per_inode(int blocksize) static inline int ocfs2_extent_recs_per_inode(int blocksize)
......
...@@ -2945,7 +2945,7 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle, ...@@ -2945,7 +2945,7 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle,
while (offset < end) { while (offset < end) {
page_index = offset >> PAGE_CACHE_SHIFT; page_index = offset >> PAGE_CACHE_SHIFT;
map_end = (page_index + 1) << PAGE_CACHE_SHIFT; map_end = ((loff_t)page_index + 1) << PAGE_CACHE_SHIFT;
if (map_end > end) if (map_end > end)
map_end = end; map_end = end;
...@@ -2957,8 +2957,12 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle, ...@@ -2957,8 +2957,12 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle,
page = grab_cache_page(mapping, page_index); page = grab_cache_page(mapping, page_index);
/* This page can't be dirtied before we CoW it out. */ /*
BUG_ON(PageDirty(page)); * In case PAGE_CACHE_SIZE <= CLUSTER_SIZE, This page
* can't be dirtied before we CoW it out.
*/
if (PAGE_CACHE_SIZE <= OCFS2_SB(sb)->s_clustersize)
BUG_ON(PageDirty(page));
if (!PageUptodate(page)) { if (!PageUptodate(page)) {
ret = block_read_full_page(page, ocfs2_get_block); ret = block_read_full_page(page, ocfs2_get_block);
...@@ -3170,7 +3174,7 @@ static int ocfs2_cow_sync_writeback(struct super_block *sb, ...@@ -3170,7 +3174,7 @@ static int ocfs2_cow_sync_writeback(struct super_block *sb,
while (offset < end) { while (offset < end) {
page_index = offset >> PAGE_CACHE_SHIFT; page_index = offset >> PAGE_CACHE_SHIFT;
map_end = (page_index + 1) << PAGE_CACHE_SHIFT; map_end = ((loff_t)page_index + 1) << PAGE_CACHE_SHIFT;
if (map_end > end) if (map_end > end)
map_end = end; map_end = end;
......
...@@ -277,7 +277,7 @@ static int o2cb_cluster_connect(struct ocfs2_cluster_connection *conn) ...@@ -277,7 +277,7 @@ static int o2cb_cluster_connect(struct ocfs2_cluster_connection *conn)
u32 dlm_key; u32 dlm_key;
struct dlm_ctxt *dlm; struct dlm_ctxt *dlm;
struct o2dlm_private *priv; struct o2dlm_private *priv;
struct dlm_protocol_version dlm_version; struct dlm_protocol_version fs_version;
BUG_ON(conn == NULL); BUG_ON(conn == NULL);
BUG_ON(o2cb_stack.sp_proto == NULL); BUG_ON(o2cb_stack.sp_proto == NULL);
...@@ -304,18 +304,18 @@ static int o2cb_cluster_connect(struct ocfs2_cluster_connection *conn) ...@@ -304,18 +304,18 @@ static int o2cb_cluster_connect(struct ocfs2_cluster_connection *conn)
/* used by the dlm code to make message headers unique, each /* used by the dlm code to make message headers unique, each
* node in this domain must agree on this. */ * node in this domain must agree on this. */
dlm_key = crc32_le(0, conn->cc_name, conn->cc_namelen); dlm_key = crc32_le(0, conn->cc_name, conn->cc_namelen);
dlm_version.pv_major = conn->cc_version.pv_major; fs_version.pv_major = conn->cc_version.pv_major;
dlm_version.pv_minor = conn->cc_version.pv_minor; fs_version.pv_minor = conn->cc_version.pv_minor;
dlm = dlm_register_domain(conn->cc_name, dlm_key, &dlm_version); dlm = dlm_register_domain(conn->cc_name, dlm_key, &fs_version);
if (IS_ERR(dlm)) { if (IS_ERR(dlm)) {
rc = PTR_ERR(dlm); rc = PTR_ERR(dlm);
mlog_errno(rc); mlog_errno(rc);
goto out_free; goto out_free;
} }
conn->cc_version.pv_major = dlm_version.pv_major; conn->cc_version.pv_major = fs_version.pv_major;
conn->cc_version.pv_minor = dlm_version.pv_minor; conn->cc_version.pv_minor = fs_version.pv_minor;
conn->cc_lockspace = dlm; conn->cc_lockspace = dlm;
dlm_register_eviction_cb(dlm, &priv->op_eviction_cb); dlm_register_eviction_cb(dlm, &priv->op_eviction_cb);
......
...@@ -1062,7 +1062,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1062,7 +1062,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
"file system, but write access is " "file system, but write access is "
"unavailable.\n"); "unavailable.\n");
else else
mlog_errno(status); mlog_errno(status);
goto read_super_error; goto read_super_error;
} }
......
...@@ -137,20 +137,20 @@ static void *ocfs2_fast_follow_link(struct dentry *dentry, ...@@ -137,20 +137,20 @@ static void *ocfs2_fast_follow_link(struct dentry *dentry,
} }
memcpy(link, target, len); memcpy(link, target, len);
nd_set_link(nd, link);
bail: bail:
nd_set_link(nd, status ? ERR_PTR(status) : link);
brelse(bh); brelse(bh);
mlog_exit(status); mlog_exit(status);
return status ? ERR_PTR(status) : link; return NULL;
} }
static void ocfs2_fast_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) static void ocfs2_fast_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
{ {
char *link = cookie; char *link = nd_get_link(nd);
if (!IS_ERR(link))
kfree(link); kfree(link);
} }
const struct inode_operations ocfs2_symlink_inode_operations = { const struct inode_operations ocfs2_symlink_inode_operations = {
......
...@@ -267,8 +267,8 @@ static int ocfs2_buffer_cached(struct ocfs2_caching_info *ci, ...@@ -267,8 +267,8 @@ static int ocfs2_buffer_cached(struct ocfs2_caching_info *ci,
} }
/* Warning: even if it returns true, this does *not* guarantee that /* Warning: even if it returns true, this does *not* guarantee that
* the block is stored in our inode metadata cache. * the block is stored in our inode metadata cache.
* *
* This can be called under lock_buffer() * This can be called under lock_buffer()
*/ */
int ocfs2_buffer_uptodate(struct ocfs2_caching_info *ci, int ocfs2_buffer_uptodate(struct ocfs2_caching_info *ci,
......
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