mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 23:52:08 +02:00
gfs2 changes
- Partially revert "gfs2: do_xmote fixes" to ignore dlm_lock() errors during withdraw; passing on those errors doesn't help. - Change the LM_FLAG_TRY and LM_FLAG_TRY_1CB logic in add_to_queue() to check if the holder would actually block. - Move some more dlm specific code from glock.c to lock_dlm.c. - Remove the unused dlm alternate locking mode code. - Add proper locking to make sure that dlm lockspaces are never used after being released. - Various other cleanups. -----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEEJZs3krPW0xkhLMTc1b+f6wMTZToFAmjSYYQUHGFncnVlbmJh QHJlZGhhdC5jb20ACgkQ1b+f6wMTZToIxhAAm4fh3AvbkFiLgocIUqXB/iNOaBLk yJ1tIYTjhsC+RRE7HR/7qv6tAOYJvXcFS8qQrYwueRdJ9k43G0bJD7f527fH03fq rH/Qmvj/WMfbNCswBBYcIlGfvwR6XhW4FI0VpFZ0Ewkn3SPxXkS41IVHEjfxpiqS 4CqK6VyiZeSZgusAC4VXnGssc2WXBQgfnxoCO+5ouaGUZm+KNqxKcsVnU11c1UYU Vl6muVqwQCAaosvP7OWxfEGu0cs2MkmTBnjKsKUmAhZFH6RX9+TGZXA9lE+eWz1u rs2geSgJ7/NRwCvQHWTnsOeBPNd/CeBxenDlx0NaYOKbnqOXE1yW09hFKu345kWl CqhCcOqAFjJMA8kEQDOexlrJWljbVaVU0s5buQpm+d/nHMKF/x5+TBuo+aWb0jyL VdUoy0q9rgcF3oR7ifnlKuiSQ9g215uM37SeT1RpJUC23sRfI5NMTccz4Lj2A8to Y3S+jmVZOvDh+/EujxUGRkWjPQrIQNmLXxIhvntEdCGCfZonT7T+TPwMWlW+qIit I7cJN2iS0UVNb/z6TZRp0e3R2NIZQVJ71vQZVFE4McZaG5b7/juiYwWuglaSh/RO Qz1Fjyjh6r6rcMk0+Hm0VOj8XLP7A10MZ2dAVQfRCnvFgVp+ERQ8d+BWk7JM0v+A EoKkLS3YsseLCSs= =U0Vt -----END PGP SIGNATURE----- Merge tag 'gfs2-for-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2 Pull gfs2 updates from Andreas Gruenbacher: - Partially revert "gfs2: do_xmote fixes" to ignore dlm_lock() errors during withdraw; passing on those errors doesn't help - Change the LM_FLAG_TRY and LM_FLAG_TRY_1CB logic in add_to_queue() to check if the holder would actually block - Move some more dlm specific code from glock.c to lock_dlm.c - Remove the unused dlm alternate locking mode code - Add proper locking to make sure that dlm lockspaces are never used after being released - Various other cleanups * tag 'gfs2-for-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: gfs2: Fix unlikely race in gdlm_put_lock gfs2: Add proper lockspace locking gfs2: Minor run_queue fixes gfs2: run_queue cleanup gfs2: Simplify do_promote gfs2: Get rid of GLF_INVALIDATE_IN_PROGRESS gfs2: Fix GLF_INVALIDATE_IN_PROGRESS flag clearing in do_xmote gfs2: Remove duplicate check in do_xmote gfs2: Fix LM_FLAG_TRY* logic in add_to_queue gfs2: Remove DLM_LKF_ALTCW / DLM_LKF_ALTPR code gfs2: Further sanitize lock_dlm.c gfs2: Do not use atomic operations unnecessarily gfs2: Sanitize gfs2_meta_check, gfs2_metatype_check, gfs2_io_error gfs2: Turn gfs2_withdraw into a void function gfs2: Partially revert "gfs2: do_xmote fixes" gfs2: Simplify refcounting in do_xmote gfs2: do_xmote cleanup gfs2: Remove space before newline gfs2: Remove unused sd_withdraw_wait field gfs2: Remove unused GIF_FREE_VFS_INODE flag
This commit is contained in:
commit
a40eb50a95
|
|
@ -1442,6 +1442,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
|
|||
struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
|
||||
struct lm_lockstruct *ls = &sdp->sd_lockstruct;
|
||||
int ret;
|
||||
|
||||
if (!(fl->c.flc_flags & FL_POSIX))
|
||||
return -ENOLCK;
|
||||
|
|
@ -1450,14 +1451,20 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
|
|||
locks_lock_file_wait(file, fl);
|
||||
return -EIO;
|
||||
}
|
||||
if (cmd == F_CANCELLK)
|
||||
return dlm_posix_cancel(ls->ls_dlm, ip->i_no_addr, file, fl);
|
||||
else if (IS_GETLK(cmd))
|
||||
return dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl);
|
||||
else if (lock_is_unlock(fl))
|
||||
return dlm_posix_unlock(ls->ls_dlm, ip->i_no_addr, file, fl);
|
||||
else
|
||||
return dlm_posix_lock(ls->ls_dlm, ip->i_no_addr, file, cmd, fl);
|
||||
down_read(&ls->ls_sem);
|
||||
ret = -ENODEV;
|
||||
if (likely(ls->ls_dlm != NULL)) {
|
||||
if (cmd == F_CANCELLK)
|
||||
ret = dlm_posix_cancel(ls->ls_dlm, ip->i_no_addr, file, fl);
|
||||
else if (IS_GETLK(cmd))
|
||||
ret = dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl);
|
||||
else if (lock_is_unlock(fl))
|
||||
ret = dlm_posix_unlock(ls->ls_dlm, ip->i_no_addr, file, fl);
|
||||
else
|
||||
ret = dlm_posix_lock(ls->ls_dlm, ip->i_no_addr, file, cmd, fl);
|
||||
}
|
||||
up_read(&ls->ls_sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __flock_holder_uninit(struct file *file, struct gfs2_holder *fl_gh)
|
||||
|
|
|
|||
185
fs/gfs2/glock.c
185
fs/gfs2/glock.c
|
|
@ -481,11 +481,9 @@ int gfs2_instantiate(struct gfs2_holder *gh)
|
|||
/**
|
||||
* do_promote - promote as many requests as possible on the current queue
|
||||
* @gl: The glock
|
||||
*
|
||||
* Returns true on success (i.e., progress was made or there are no waiters).
|
||||
*/
|
||||
|
||||
static bool do_promote(struct gfs2_glock *gl)
|
||||
static void do_promote(struct gfs2_glock *gl)
|
||||
{
|
||||
struct gfs2_holder *gh, *current_gh;
|
||||
|
||||
|
|
@ -496,13 +494,10 @@ static bool do_promote(struct gfs2_glock *gl)
|
|||
if (!may_grant(gl, current_gh, gh)) {
|
||||
/*
|
||||
* If we get here, it means we may not grant this
|
||||
* holder for some reason. If this holder is at the
|
||||
* head of the list, it means we have a blocked holder
|
||||
* at the head, so return false.
|
||||
* holder for some reason.
|
||||
*/
|
||||
if (list_is_first(&gh->gh_list, &gl->gl_holders))
|
||||
return false;
|
||||
do_error(gl, 0);
|
||||
if (current_gh)
|
||||
do_error(gl, 0); /* Fail queued try locks */
|
||||
break;
|
||||
}
|
||||
set_bit(HIF_HOLDER, &gh->gh_iflags);
|
||||
|
|
@ -511,7 +506,6 @@ static bool do_promote(struct gfs2_glock *gl)
|
|||
if (!current_gh)
|
||||
current_gh = gh;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -646,8 +640,10 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
|
|||
}
|
||||
|
||||
/* Fast path - we got what we asked for */
|
||||
if (test_and_clear_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags))
|
||||
if (test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags)) {
|
||||
clear_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);
|
||||
gfs2_demote_wake(gl);
|
||||
}
|
||||
if (gl->gl_state != LM_ST_UNLOCKED) {
|
||||
if (glops->go_xmote_bh) {
|
||||
int rv;
|
||||
|
|
@ -693,54 +689,33 @@ __acquires(&gl->gl_lockref.lock)
|
|||
const struct gfs2_glock_operations *glops = gl->gl_ops;
|
||||
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
|
||||
struct lm_lockstruct *ls = &sdp->sd_lockstruct;
|
||||
unsigned int lck_flags = (unsigned int)(gh ? gh->gh_flags : 0);
|
||||
int ret;
|
||||
|
||||
if (target != LM_ST_UNLOCKED && glock_blocked_by_withdraw(gl) &&
|
||||
gh && !(gh->gh_flags & LM_FLAG_NOEXP))
|
||||
goto skip_inval;
|
||||
|
||||
lck_flags &= (LM_FLAG_TRY | LM_FLAG_TRY_1CB | LM_FLAG_NOEXP);
|
||||
GLOCK_BUG_ON(gl, gl->gl_state == target);
|
||||
GLOCK_BUG_ON(gl, gl->gl_state == gl->gl_target);
|
||||
if ((target == LM_ST_UNLOCKED || target == LM_ST_DEFERRED) &&
|
||||
glops->go_inval) {
|
||||
/*
|
||||
* If another process is already doing the invalidate, let that
|
||||
* finish first. The glock state machine will get back to this
|
||||
* holder again later.
|
||||
*/
|
||||
if (test_and_set_bit(GLF_INVALIDATE_IN_PROGRESS,
|
||||
&gl->gl_flags))
|
||||
return;
|
||||
do_error(gl, 0); /* Fail queued try locks */
|
||||
}
|
||||
gl->gl_req = target;
|
||||
set_bit(GLF_BLOCKING, &gl->gl_flags);
|
||||
if ((gl->gl_req == LM_ST_UNLOCKED) ||
|
||||
(gl->gl_state == LM_ST_EXCLUSIVE) ||
|
||||
(lck_flags & (LM_FLAG_TRY|LM_FLAG_TRY_1CB)))
|
||||
clear_bit(GLF_BLOCKING, &gl->gl_flags);
|
||||
if (!glops->go_inval && !glops->go_sync)
|
||||
if (!glops->go_inval || !glops->go_sync)
|
||||
goto skip_inval;
|
||||
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
if (glops->go_sync) {
|
||||
ret = glops->go_sync(gl);
|
||||
/* If we had a problem syncing (due to io errors or whatever,
|
||||
* we should not invalidate the metadata or tell dlm to
|
||||
* release the glock to other nodes.
|
||||
*/
|
||||
if (ret) {
|
||||
if (cmpxchg(&sdp->sd_log_error, 0, ret)) {
|
||||
fs_err(sdp, "Error %d syncing glock \n", ret);
|
||||
gfs2_dump_glock(NULL, gl, true);
|
||||
}
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
goto skip_inval;
|
||||
ret = glops->go_sync(gl);
|
||||
/* If we had a problem syncing (due to io errors or whatever,
|
||||
* we should not invalidate the metadata or tell dlm to
|
||||
* release the glock to other nodes.
|
||||
*/
|
||||
if (ret) {
|
||||
if (cmpxchg(&sdp->sd_log_error, 0, ret)) {
|
||||
fs_err(sdp, "Error %d syncing glock\n", ret);
|
||||
gfs2_dump_glock(NULL, gl, true);
|
||||
}
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
goto skip_inval;
|
||||
}
|
||||
if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags)) {
|
||||
|
||||
if (target == LM_ST_UNLOCKED || target == LM_ST_DEFERRED) {
|
||||
/*
|
||||
* The call to go_sync should have cleared out the ail list.
|
||||
* If there are still items, we have a problem. We ought to
|
||||
|
|
@ -755,12 +730,10 @@ __acquires(&gl->gl_lockref.lock)
|
|||
gfs2_dump_glock(NULL, gl, true);
|
||||
}
|
||||
glops->go_inval(gl, target == LM_ST_DEFERRED ? 0 : DIO_METADATA);
|
||||
clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
|
||||
}
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
|
||||
skip_inval:
|
||||
gl->gl_lockref.count++;
|
||||
/*
|
||||
* Check for an error encountered since we called go_sync and go_inval.
|
||||
* If so, we can't withdraw from the glock code because the withdraw
|
||||
|
|
@ -803,38 +776,41 @@ __acquires(&gl->gl_lockref.lock)
|
|||
if (!test_bit(GLF_CANCELING, &gl->gl_flags))
|
||||
clear_bit(GLF_LOCK, &gl->gl_flags);
|
||||
clear_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);
|
||||
gl->gl_lockref.count++;
|
||||
gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD);
|
||||
return;
|
||||
} else {
|
||||
clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
|
||||
}
|
||||
}
|
||||
|
||||
if (ls->ls_ops->lm_lock) {
|
||||
set_bit(GLF_PENDING_REPLY, &gl->gl_flags);
|
||||
spin_unlock(&gl->gl_lockref.lock);
|
||||
ret = ls->ls_ops->lm_lock(gl, target, lck_flags);
|
||||
ret = ls->ls_ops->lm_lock(gl, target, gh ? gh->gh_flags : 0);
|
||||
spin_lock(&gl->gl_lockref.lock);
|
||||
|
||||
if (ret == -EINVAL && gl->gl_target == LM_ST_UNLOCKED &&
|
||||
target == LM_ST_UNLOCKED &&
|
||||
test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) {
|
||||
if (!ret) {
|
||||
/* The operation will be completed asynchronously. */
|
||||
gl->gl_lockref.count++;
|
||||
return;
|
||||
}
|
||||
clear_bit(GLF_PENDING_REPLY, &gl->gl_flags);
|
||||
|
||||
if (ret == -ENODEV && gl->gl_target == LM_ST_UNLOCKED &&
|
||||
target == LM_ST_UNLOCKED) {
|
||||
/*
|
||||
* The lockspace has been released and the lock has
|
||||
* been unlocked implicitly.
|
||||
*/
|
||||
} else if (ret) {
|
||||
fs_err(sdp, "lm_lock ret %d\n", ret);
|
||||
target = gl->gl_state | LM_OUT_ERROR;
|
||||
} else {
|
||||
/* The operation will be completed asynchronously. */
|
||||
fs_err(sdp, "lm_lock ret %d\n", ret);
|
||||
GLOCK_BUG_ON(gl, !gfs2_withdrawing_or_withdrawn(sdp));
|
||||
return;
|
||||
}
|
||||
clear_bit(GLF_PENDING_REPLY, &gl->gl_flags);
|
||||
}
|
||||
|
||||
/* Complete the operation now. */
|
||||
finish_xmote(gl, target);
|
||||
gl->gl_lockref.count++;
|
||||
gfs2_glock_queue_work(gl, 0);
|
||||
}
|
||||
|
||||
|
|
@ -855,11 +831,20 @@ __acquires(&gl->gl_lockref.lock)
|
|||
return;
|
||||
set_bit(GLF_LOCK, &gl->gl_flags);
|
||||
|
||||
/* While a demote is in progress, the GLF_LOCK flag must be set. */
|
||||
/*
|
||||
* The GLF_DEMOTE_IN_PROGRESS flag is only set intermittently during
|
||||
* locking operations. We have just started a locking operation by
|
||||
* setting the GLF_LOCK flag, so the GLF_DEMOTE_IN_PROGRESS flag must
|
||||
* be cleared.
|
||||
*/
|
||||
GLOCK_BUG_ON(gl, test_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags));
|
||||
|
||||
if (test_bit(GLF_DEMOTE, &gl->gl_flags) &&
|
||||
gl->gl_demote_state != gl->gl_state) {
|
||||
if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
|
||||
if (gl->gl_demote_state == gl->gl_state) {
|
||||
gfs2_demote_wake(gl);
|
||||
goto promote;
|
||||
}
|
||||
|
||||
if (find_first_holder(gl))
|
||||
goto out_unlock;
|
||||
if (nonblock)
|
||||
|
|
@ -869,31 +854,31 @@ __acquires(&gl->gl_lockref.lock)
|
|||
gl->gl_target = gl->gl_demote_state;
|
||||
do_xmote(gl, NULL, gl->gl_target);
|
||||
return;
|
||||
} else {
|
||||
if (test_bit(GLF_DEMOTE, &gl->gl_flags))
|
||||
gfs2_demote_wake(gl);
|
||||
if (do_promote(gl))
|
||||
goto out_unlock;
|
||||
gh = find_first_waiter(gl);
|
||||
if (!gh)
|
||||
goto out_unlock;
|
||||
gl->gl_target = gh->gh_state;
|
||||
if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)))
|
||||
do_error(gl, 0); /* Fail queued try locks */
|
||||
do_xmote(gl, gh, gl->gl_target);
|
||||
return;
|
||||
}
|
||||
|
||||
promote:
|
||||
do_promote(gl);
|
||||
if (find_first_holder(gl))
|
||||
goto out_unlock;
|
||||
gh = find_first_waiter(gl);
|
||||
if (!gh)
|
||||
goto out_unlock;
|
||||
if (nonblock)
|
||||
goto out_sched;
|
||||
gl->gl_target = gh->gh_state;
|
||||
if (!(gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)))
|
||||
do_error(gl, 0); /* Fail queued try locks */
|
||||
do_xmote(gl, gh, gl->gl_target);
|
||||
return;
|
||||
|
||||
out_sched:
|
||||
clear_bit(GLF_LOCK, &gl->gl_flags);
|
||||
smp_mb__after_atomic();
|
||||
gl->gl_lockref.count++;
|
||||
gfs2_glock_queue_work(gl, 0);
|
||||
return;
|
||||
|
||||
out_unlock:
|
||||
clear_bit(GLF_LOCK, &gl->gl_flags);
|
||||
smp_mb__after_atomic();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1462,6 +1447,24 @@ void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...)
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
static bool gfs2_should_queue_trylock(struct gfs2_glock *gl,
|
||||
struct gfs2_holder *gh)
|
||||
{
|
||||
struct gfs2_holder *current_gh, *gh2;
|
||||
|
||||
current_gh = find_first_holder(gl);
|
||||
if (current_gh && !may_grant(gl, current_gh, gh))
|
||||
return false;
|
||||
|
||||
list_for_each_entry(gh2, &gl->gl_holders, gh_list) {
|
||||
if (test_bit(HIF_HOLDER, &gh2->gh_iflags))
|
||||
continue;
|
||||
if (!(gh2->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool pid_is_meaningful(const struct gfs2_holder *gh)
|
||||
{
|
||||
if (!(gh->gh_flags & GL_NOPID))
|
||||
|
|
@ -1480,27 +1483,20 @@ static inline bool pid_is_meaningful(const struct gfs2_holder *gh)
|
|||
*/
|
||||
|
||||
static inline void add_to_queue(struct gfs2_holder *gh)
|
||||
__releases(&gl->gl_lockref.lock)
|
||||
__acquires(&gl->gl_lockref.lock)
|
||||
{
|
||||
struct gfs2_glock *gl = gh->gh_gl;
|
||||
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
|
||||
struct gfs2_holder *gh2;
|
||||
int try_futile = 0;
|
||||
|
||||
GLOCK_BUG_ON(gl, gh->gh_owner_pid == NULL);
|
||||
if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags))
|
||||
GLOCK_BUG_ON(gl, true);
|
||||
|
||||
if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) {
|
||||
if (test_bit(GLF_LOCK, &gl->gl_flags)) {
|
||||
struct gfs2_holder *current_gh;
|
||||
|
||||
current_gh = find_first_holder(gl);
|
||||
try_futile = !may_grant(gl, current_gh, gh);
|
||||
}
|
||||
if (test_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags))
|
||||
goto fail;
|
||||
if ((gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) &&
|
||||
!gfs2_should_queue_trylock(gl, gh)) {
|
||||
gh->gh_error = GLR_TRYFAILED;
|
||||
gfs2_holder_wake(gh);
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each_entry(gh2, &gl->gl_holders, gh_list) {
|
||||
|
|
@ -1512,15 +1508,6 @@ __acquires(&gl->gl_lockref.lock)
|
|||
continue;
|
||||
goto trap_recursive;
|
||||
}
|
||||
list_for_each_entry(gh2, &gl->gl_holders, gh_list) {
|
||||
if (try_futile &&
|
||||
!(gh2->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) {
|
||||
fail:
|
||||
gh->gh_error = GLR_TRYFAILED;
|
||||
gfs2_holder_wake(gh);
|
||||
return;
|
||||
}
|
||||
}
|
||||
trace_gfs2_glock_queue(gh, 1);
|
||||
gfs2_glstats_inc(gl, GFS2_LKS_QCOUNT);
|
||||
gfs2_sbstats_inc(gl, GFS2_LKS_QCOUNT);
|
||||
|
|
@ -2321,8 +2308,6 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
|
|||
*p++ = 'y';
|
||||
if (test_bit(GLF_LFLUSH, gflags))
|
||||
*p++ = 'f';
|
||||
if (test_bit(GLF_INVALIDATE_IN_PROGRESS, gflags))
|
||||
*p++ = 'i';
|
||||
if (test_bit(GLF_PENDING_REPLY, gflags))
|
||||
*p++ = 'R';
|
||||
if (test_bit(GLF_HAVE_REPLY, gflags))
|
||||
|
|
|
|||
|
|
@ -68,6 +68,10 @@ enum {
|
|||
* also be granted in SHARED. The preferred state is whichever is compatible
|
||||
* with other granted locks, or the specified state if no other locks exist.
|
||||
*
|
||||
* In addition, when a lock is already held in EX mode locally, a SHARED or
|
||||
* DEFERRED mode request with the LM_FLAG_ANY flag set will be granted.
|
||||
* (The LM_FLAG_ANY flag is only use for SHARED mode requests currently.)
|
||||
*
|
||||
* LM_FLAG_NODE_SCOPE
|
||||
* This holder agrees to share the lock within this node. In other words,
|
||||
* the glock is held in EX mode according to DLM, but local holders on the
|
||||
|
|
|
|||
|
|
@ -319,7 +319,6 @@ enum {
|
|||
GLF_DEMOTE_IN_PROGRESS = 5,
|
||||
GLF_DIRTY = 6,
|
||||
GLF_LFLUSH = 7,
|
||||
GLF_INVALIDATE_IN_PROGRESS = 8,
|
||||
GLF_HAVE_REPLY = 9,
|
||||
GLF_INITIAL = 10,
|
||||
GLF_HAVE_FROZEN_REPLY = 11,
|
||||
|
|
@ -376,7 +375,6 @@ struct gfs2_glock {
|
|||
enum {
|
||||
GIF_QD_LOCKED = 1,
|
||||
GIF_SW_PAGED = 3,
|
||||
GIF_FREE_VFS_INODE = 5,
|
||||
GIF_GLOP_PENDING = 6,
|
||||
};
|
||||
|
||||
|
|
@ -658,6 +656,8 @@ struct lm_lockstruct {
|
|||
struct completion ls_sync_wait; /* {control,mounted}_{lock,unlock} */
|
||||
char *ls_lvb_bits;
|
||||
|
||||
struct rw_semaphore ls_sem;
|
||||
|
||||
spinlock_t ls_recover_spin; /* protects following fields */
|
||||
unsigned long ls_recover_flags; /* DFL_ */
|
||||
uint32_t ls_recover_mount; /* gen in first recover_done cb */
|
||||
|
|
@ -823,7 +823,6 @@ struct gfs2_sbd {
|
|||
atomic_t sd_log_in_flight;
|
||||
wait_queue_head_t sd_log_flush_wait;
|
||||
int sd_log_error; /* First log error */
|
||||
wait_queue_head_t sd_withdraw_wait;
|
||||
|
||||
unsigned int sd_log_tail;
|
||||
unsigned int sd_log_flush_tail;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ static inline void gfs2_update_stats(struct gfs2_lkstats *s, unsigned index,
|
|||
/**
|
||||
* gfs2_update_reply_times - Update locking statistics
|
||||
* @gl: The glock to update
|
||||
* @blocking: The operation may have been blocking
|
||||
*
|
||||
* This assumes that gl->gl_dstamp has been set earlier.
|
||||
*
|
||||
|
|
@ -72,12 +73,12 @@ static inline void gfs2_update_stats(struct gfs2_lkstats *s, unsigned index,
|
|||
* TRY_1CB flags are set are classified as non-blocking. All
|
||||
* other DLM requests are counted as (potentially) blocking.
|
||||
*/
|
||||
static inline void gfs2_update_reply_times(struct gfs2_glock *gl)
|
||||
static inline void gfs2_update_reply_times(struct gfs2_glock *gl,
|
||||
bool blocking)
|
||||
{
|
||||
struct gfs2_pcpu_lkstats *lks;
|
||||
const unsigned gltype = gl->gl_name.ln_type;
|
||||
unsigned index = test_bit(GLF_BLOCKING, &gl->gl_flags) ?
|
||||
GFS2_LKS_SRTTB : GFS2_LKS_SRTT;
|
||||
unsigned index = blocking ? GFS2_LKS_SRTTB : GFS2_LKS_SRTT;
|
||||
s64 rtt;
|
||||
|
||||
preempt_disable();
|
||||
|
|
@ -119,14 +120,18 @@ static inline void gfs2_update_request_times(struct gfs2_glock *gl)
|
|||
static void gdlm_ast(void *arg)
|
||||
{
|
||||
struct gfs2_glock *gl = arg;
|
||||
bool blocking;
|
||||
unsigned ret;
|
||||
|
||||
blocking = test_bit(GLF_BLOCKING, &gl->gl_flags);
|
||||
gfs2_update_reply_times(gl, blocking);
|
||||
clear_bit(GLF_BLOCKING, &gl->gl_flags);
|
||||
|
||||
/* If the glock is dead, we only react to a dlm_unlock() reply. */
|
||||
if (__lockref_is_dead(&gl->gl_lockref) &&
|
||||
gl->gl_lksb.sb_status != -DLM_EUNLOCK)
|
||||
return;
|
||||
|
||||
gfs2_update_reply_times(gl);
|
||||
BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED);
|
||||
|
||||
if ((gl->gl_lksb.sb_flags & DLM_SBF_VALNOTVALID) && gl->gl_lksb.sb_lvbptr)
|
||||
|
|
@ -157,14 +162,6 @@ static void gdlm_ast(void *arg)
|
|||
}
|
||||
|
||||
ret = gl->gl_req;
|
||||
if (gl->gl_lksb.sb_flags & DLM_SBF_ALTMODE) {
|
||||
if (gl->gl_req == LM_ST_SHARED)
|
||||
ret = LM_ST_DEFERRED;
|
||||
else if (gl->gl_req == LM_ST_DEFERRED)
|
||||
ret = LM_ST_SHARED;
|
||||
else
|
||||
BUG();
|
||||
}
|
||||
|
||||
/*
|
||||
* The GLF_INITIAL flag is initially set for new glocks. Upon the
|
||||
|
|
@ -241,7 +238,7 @@ static bool down_conversion(int cur, int req)
|
|||
}
|
||||
|
||||
static u32 make_flags(struct gfs2_glock *gl, const unsigned int gfs_flags,
|
||||
const int cur, const int req)
|
||||
const int req, bool blocking)
|
||||
{
|
||||
u32 lkf = 0;
|
||||
|
||||
|
|
@ -256,15 +253,6 @@ static u32 make_flags(struct gfs2_glock *gl, const unsigned int gfs_flags,
|
|||
lkf |= DLM_LKF_NOQUEUEBAST;
|
||||
}
|
||||
|
||||
if (gfs_flags & LM_FLAG_ANY) {
|
||||
if (req == DLM_LOCK_PR)
|
||||
lkf |= DLM_LKF_ALTCW;
|
||||
else if (req == DLM_LOCK_CW)
|
||||
lkf |= DLM_LKF_ALTPR;
|
||||
else
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (!test_bit(GLF_INITIAL, &gl->gl_flags)) {
|
||||
lkf |= DLM_LKF_CONVERT;
|
||||
|
||||
|
|
@ -274,7 +262,7 @@ static u32 make_flags(struct gfs2_glock *gl, const unsigned int gfs_flags,
|
|||
* "upward" lock conversions or else DLM will reject the
|
||||
* request as invalid.
|
||||
*/
|
||||
if (!down_conversion(cur, req))
|
||||
if (blocking)
|
||||
lkf |= DLM_LKF_QUECVT;
|
||||
}
|
||||
|
||||
|
|
@ -294,14 +282,20 @@ static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
|
|||
unsigned int flags)
|
||||
{
|
||||
struct lm_lockstruct *ls = &gl->gl_name.ln_sbd->sd_lockstruct;
|
||||
bool blocking;
|
||||
int cur, req;
|
||||
u32 lkf;
|
||||
char strname[GDLM_STRNAME_BYTES] = "";
|
||||
int error;
|
||||
|
||||
gl->gl_req = req_state;
|
||||
cur = make_mode(gl->gl_name.ln_sbd, gl->gl_state);
|
||||
req = make_mode(gl->gl_name.ln_sbd, req_state);
|
||||
lkf = make_flags(gl, flags, cur, req);
|
||||
blocking = !down_conversion(cur, req) &&
|
||||
!(flags & (LM_FLAG_TRY|LM_FLAG_TRY_1CB));
|
||||
lkf = make_flags(gl, flags, req, blocking);
|
||||
if (blocking)
|
||||
set_bit(GLF_BLOCKING, &gl->gl_flags);
|
||||
gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT);
|
||||
gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT);
|
||||
if (test_bit(GLF_INITIAL, &gl->gl_flags)) {
|
||||
|
|
@ -318,8 +312,13 @@ static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
|
|||
*/
|
||||
|
||||
again:
|
||||
error = dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, strname,
|
||||
GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast);
|
||||
down_read(&ls->ls_sem);
|
||||
error = -ENODEV;
|
||||
if (likely(ls->ls_dlm != NULL)) {
|
||||
error = dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, strname,
|
||||
GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast);
|
||||
}
|
||||
up_read(&ls->ls_sem);
|
||||
if (error == -EBUSY) {
|
||||
msleep(20);
|
||||
goto again;
|
||||
|
|
@ -341,17 +340,10 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
|
|||
return;
|
||||
}
|
||||
|
||||
clear_bit(GLF_BLOCKING, &gl->gl_flags);
|
||||
gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT);
|
||||
gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT);
|
||||
gfs2_update_request_times(gl);
|
||||
|
||||
/* don't want to call dlm if we've unmounted the lock protocol */
|
||||
if (test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) {
|
||||
gfs2_glock_free(gl);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* When the lockspace is released, all remaining glocks will be
|
||||
* unlocked automatically. This is more efficient than unlocking them
|
||||
|
|
@ -369,13 +361,23 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
|
|||
flags |= DLM_LKF_VALBLK;
|
||||
|
||||
again:
|
||||
error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, flags,
|
||||
NULL, gl);
|
||||
down_read(&ls->ls_sem);
|
||||
error = -ENODEV;
|
||||
if (likely(ls->ls_dlm != NULL)) {
|
||||
error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, flags,
|
||||
NULL, gl);
|
||||
}
|
||||
up_read(&ls->ls_sem);
|
||||
if (error == -EBUSY) {
|
||||
msleep(20);
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (error == -ENODEV) {
|
||||
gfs2_glock_free(gl);
|
||||
return;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
fs_err(sdp, "gdlm_unlock %x,%llx err=%d\n",
|
||||
gl->gl_name.ln_type,
|
||||
|
|
@ -386,7 +388,12 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
|
|||
static void gdlm_cancel(struct gfs2_glock *gl)
|
||||
{
|
||||
struct lm_lockstruct *ls = &gl->gl_name.ln_sbd->sd_lockstruct;
|
||||
dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_CANCEL, NULL, gl);
|
||||
|
||||
down_read(&ls->ls_sem);
|
||||
if (likely(ls->ls_dlm != NULL)) {
|
||||
dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_CANCEL, NULL, gl);
|
||||
}
|
||||
up_read(&ls->ls_sem);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -567,7 +574,11 @@ static int sync_unlock(struct gfs2_sbd *sdp, struct dlm_lksb *lksb, char *name)
|
|||
struct lm_lockstruct *ls = &sdp->sd_lockstruct;
|
||||
int error;
|
||||
|
||||
error = dlm_unlock(ls->ls_dlm, lksb->sb_lkid, 0, lksb, ls);
|
||||
down_read(&ls->ls_sem);
|
||||
error = -ENODEV;
|
||||
if (likely(ls->ls_dlm != NULL))
|
||||
error = dlm_unlock(ls->ls_dlm, lksb->sb_lkid, 0, lksb, ls);
|
||||
up_read(&ls->ls_sem);
|
||||
if (error) {
|
||||
fs_err(sdp, "%s lkid %x error %d\n",
|
||||
name, lksb->sb_lkid, error);
|
||||
|
|
@ -594,9 +605,14 @@ static int sync_lock(struct gfs2_sbd *sdp, int mode, uint32_t flags,
|
|||
memset(strname, 0, GDLM_STRNAME_BYTES);
|
||||
snprintf(strname, GDLM_STRNAME_BYTES, "%8x%16x", LM_TYPE_NONDISK, num);
|
||||
|
||||
error = dlm_lock(ls->ls_dlm, mode, lksb, flags,
|
||||
strname, GDLM_STRNAME_BYTES - 1,
|
||||
0, sync_wait_cb, ls, NULL);
|
||||
down_read(&ls->ls_sem);
|
||||
error = -ENODEV;
|
||||
if (likely(ls->ls_dlm != NULL)) {
|
||||
error = dlm_lock(ls->ls_dlm, mode, lksb, flags,
|
||||
strname, GDLM_STRNAME_BYTES - 1,
|
||||
0, sync_wait_cb, ls, NULL);
|
||||
}
|
||||
up_read(&ls->ls_sem);
|
||||
if (error) {
|
||||
fs_err(sdp, "%s lkid %x flags %x mode %d error %d\n",
|
||||
name, lksb->sb_lkid, flags, mode, error);
|
||||
|
|
@ -1323,6 +1339,7 @@ static int gdlm_mount(struct gfs2_sbd *sdp, const char *table)
|
|||
*/
|
||||
|
||||
INIT_DELAYED_WORK(&sdp->sd_control_work, gfs2_control_func);
|
||||
ls->ls_dlm = NULL;
|
||||
spin_lock_init(&ls->ls_recover_spin);
|
||||
ls->ls_recover_flags = 0;
|
||||
ls->ls_recover_mount = 0;
|
||||
|
|
@ -1357,6 +1374,7 @@ static int gdlm_mount(struct gfs2_sbd *sdp, const char *table)
|
|||
* create/join lockspace
|
||||
*/
|
||||
|
||||
init_rwsem(&ls->ls_sem);
|
||||
error = dlm_new_lockspace(fsname, cluster, flags, GDLM_LVB_SIZE,
|
||||
&gdlm_lockspace_ops, sdp, &ops_result,
|
||||
&ls->ls_dlm);
|
||||
|
|
@ -1436,10 +1454,12 @@ static void gdlm_unmount(struct gfs2_sbd *sdp)
|
|||
|
||||
/* mounted_lock and control_lock will be purged in dlm recovery */
|
||||
release:
|
||||
down_write(&ls->ls_sem);
|
||||
if (ls->ls_dlm) {
|
||||
dlm_release_lockspace(ls->ls_dlm, 2);
|
||||
ls->ls_dlm = NULL;
|
||||
}
|
||||
up_write(&ls->ls_sem);
|
||||
|
||||
free_recover_size(ls);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@
|
|||
{(1UL << GLF_DEMOTE_IN_PROGRESS), "p" }, \
|
||||
{(1UL << GLF_DIRTY), "y" }, \
|
||||
{(1UL << GLF_LFLUSH), "f" }, \
|
||||
{(1UL << GLF_INVALIDATE_IN_PROGRESS), "i" }, \
|
||||
{(1UL << GLF_PENDING_REPLY), "R" }, \
|
||||
{(1UL << GLF_HAVE_REPLY), "r" }, \
|
||||
{(1UL << GLF_INITIAL), "a" }, \
|
||||
|
|
|
|||
|
|
@ -309,7 +309,7 @@ void gfs2_lm(struct gfs2_sbd *sdp, const char *fmt, ...)
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
int gfs2_withdraw(struct gfs2_sbd *sdp)
|
||||
void gfs2_withdraw(struct gfs2_sbd *sdp)
|
||||
{
|
||||
struct lm_lockstruct *ls = &sdp->sd_lockstruct;
|
||||
const struct lm_lockops *lm = ls->ls_ops;
|
||||
|
|
@ -322,7 +322,7 @@ int gfs2_withdraw(struct gfs2_sbd *sdp)
|
|||
wait_on_bit(&sdp->sd_flags,
|
||||
SDF_WITHDRAW_IN_PROG,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
new = old | BIT(SDF_WITHDRAWN) | BIT(SDF_WITHDRAW_IN_PROG);
|
||||
} while (unlikely(!try_cmpxchg(&sdp->sd_flags, &old, new)));
|
||||
|
|
@ -350,8 +350,6 @@ int gfs2_withdraw(struct gfs2_sbd *sdp)
|
|||
|
||||
if (sdp->sd_args.ar_errors == GFS2_ERRORS_PANIC)
|
||||
panic("GFS2: fsid=%s: panic requested\n", sdp->sd_fsname);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -473,46 +471,36 @@ void gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd,
|
|||
|
||||
/*
|
||||
* gfs2_meta_check_ii - Flag a magic number consistency error and withdraw
|
||||
* Returns: -1 if this call withdrew the machine,
|
||||
* -2 if it was already withdrawn
|
||||
*/
|
||||
|
||||
int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
|
||||
const char *function, char *file,
|
||||
unsigned int line)
|
||||
void gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
|
||||
const char *function, char *file,
|
||||
unsigned int line)
|
||||
{
|
||||
int me;
|
||||
|
||||
gfs2_lm(sdp,
|
||||
"fatal: invalid metadata block - "
|
||||
"bh = %llu (bad magic number), "
|
||||
"function = %s, file = %s, line = %u\n",
|
||||
(unsigned long long)bh->b_blocknr,
|
||||
function, file, line);
|
||||
me = gfs2_withdraw(sdp);
|
||||
return (me) ? -1 : -2;
|
||||
gfs2_withdraw(sdp);
|
||||
}
|
||||
|
||||
/*
|
||||
* gfs2_metatype_check_ii - Flag a metadata type consistency error and withdraw
|
||||
* Returns: -1 if this call withdrew the machine,
|
||||
* -2 if it was already withdrawn
|
||||
*/
|
||||
|
||||
int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
|
||||
u16 type, u16 t, const char *function,
|
||||
char *file, unsigned int line)
|
||||
void gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
|
||||
u16 type, u16 t, const char *function,
|
||||
char *file, unsigned int line)
|
||||
{
|
||||
int me;
|
||||
|
||||
gfs2_lm(sdp,
|
||||
"fatal: invalid metadata block - "
|
||||
"bh = %llu (type: exp=%u, found=%u), "
|
||||
"function = %s, file = %s, line = %u\n",
|
||||
(unsigned long long)bh->b_blocknr, type, t,
|
||||
function, file, line);
|
||||
me = gfs2_withdraw(sdp);
|
||||
return (me) ? -1 : -2;
|
||||
gfs2_withdraw(sdp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -521,14 +509,14 @@ int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
|
|||
* 0 if it was already withdrawn
|
||||
*/
|
||||
|
||||
int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function, char *file,
|
||||
unsigned int line)
|
||||
void gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function, char *file,
|
||||
unsigned int line)
|
||||
{
|
||||
gfs2_lm(sdp,
|
||||
"fatal: I/O error - "
|
||||
"function = %s, file = %s, line = %u\n",
|
||||
function, file, line);
|
||||
return gfs2_withdraw(sdp);
|
||||
gfs2_withdraw(sdp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -91,9 +91,9 @@ void gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd,
|
|||
gfs2_consist_rgrpd_i((rgd), __func__, __FILE__, __LINE__)
|
||||
|
||||
|
||||
int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
|
||||
const char *function,
|
||||
char *file, unsigned int line);
|
||||
void gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
|
||||
const char *function,
|
||||
char *file, unsigned int line);
|
||||
|
||||
static inline int gfs2_meta_check(struct gfs2_sbd *sdp,
|
||||
struct buffer_head *bh)
|
||||
|
|
@ -108,10 +108,10 @@ static inline int gfs2_meta_check(struct gfs2_sbd *sdp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
|
||||
u16 type, u16 t,
|
||||
const char *function,
|
||||
char *file, unsigned int line);
|
||||
void gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
|
||||
u16 type, u16 t,
|
||||
const char *function,
|
||||
char *file, unsigned int line);
|
||||
|
||||
static inline int gfs2_metatype_check_i(struct gfs2_sbd *sdp,
|
||||
struct buffer_head *bh,
|
||||
|
|
@ -122,12 +122,16 @@ static inline int gfs2_metatype_check_i(struct gfs2_sbd *sdp,
|
|||
struct gfs2_meta_header *mh = (struct gfs2_meta_header *)bh->b_data;
|
||||
u32 magic = be32_to_cpu(mh->mh_magic);
|
||||
u16 t = be32_to_cpu(mh->mh_type);
|
||||
if (unlikely(magic != GFS2_MAGIC))
|
||||
return gfs2_meta_check_ii(sdp, bh, function,
|
||||
file, line);
|
||||
if (unlikely(t != type))
|
||||
return gfs2_metatype_check_ii(sdp, bh, type, t, function,
|
||||
file, line);
|
||||
if (unlikely(magic != GFS2_MAGIC)) {
|
||||
gfs2_meta_check_ii(sdp, bh, function,
|
||||
file, line);
|
||||
return -EIO;
|
||||
}
|
||||
if (unlikely(t != type)) {
|
||||
gfs2_metatype_check_ii(sdp, bh, type, t, function,
|
||||
file, line);
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -144,8 +148,8 @@ static inline void gfs2_metatype_set(struct buffer_head *bh, u16 type,
|
|||
}
|
||||
|
||||
|
||||
int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function,
|
||||
char *file, unsigned int line);
|
||||
void gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function,
|
||||
char *file, unsigned int line);
|
||||
|
||||
int check_journal_clean(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
|
||||
bool verbose);
|
||||
|
|
@ -228,6 +232,6 @@ gfs2_tune_get_i(&(sdp)->sd_tune, &(sdp)->sd_tune.field)
|
|||
|
||||
__printf(2, 3)
|
||||
void gfs2_lm(struct gfs2_sbd *sdp, const char *fmt, ...);
|
||||
int gfs2_withdraw(struct gfs2_sbd *sdp);
|
||||
void gfs2_withdraw(struct gfs2_sbd *sdp);
|
||||
|
||||
#endif /* __UTIL_DOT_H__ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user