Commit 3a09b1be authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw

* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw:
  GFS2: Fix recovery stuck bug (try #2)
  GFS2: Fix typo in stuffed file data copy handling
  Revert "GFS2: recovery stuck on transaction lock"
  GFS2: Make "try" lock not try quite so hard
  GFS2: remove dependency on __GFP_NOFAIL
  GFS2: Simplify gfs2_write_alloc_required
  GFS2: Wait for journal id on mount if not specified on mount command line
  GFS2: Use nobh_writepage
parents 7046e668 0809f6ec
...@@ -136,10 +136,7 @@ static int gfs2_writeback_writepage(struct page *page, ...@@ -136,10 +136,7 @@ static int gfs2_writeback_writepage(struct page *page,
if (ret <= 0) if (ret <= 0)
return ret; return ret;
ret = mpage_writepage(page, gfs2_get_block_noalloc, wbc); return nobh_writepage(page, gfs2_get_block_noalloc, wbc);
if (ret == -EAGAIN)
ret = block_write_full_page(page, gfs2_get_block_noalloc, wbc);
return ret;
} }
/** /**
...@@ -637,9 +634,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, ...@@ -637,9 +634,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
} }
} }
error = gfs2_write_alloc_required(ip, pos, len, &alloc_required); alloc_required = gfs2_write_alloc_required(ip, pos, len);
if (error)
goto out_unlock;
if (alloc_required || gfs2_is_jdata(ip)) if (alloc_required || gfs2_is_jdata(ip))
gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks); gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks);
......
...@@ -1040,7 +1040,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size) ...@@ -1040,7 +1040,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
goto out; goto out;
if (gfs2_is_stuffed(ip)) { if (gfs2_is_stuffed(ip)) {
u64 dsize = size + sizeof(struct gfs2_inode); u64 dsize = size + sizeof(struct gfs2_dinode);
ip->i_disksize = size; ip->i_disksize = size;
ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_trans_add_bh(ip->i_gl, dibh, 1);
...@@ -1244,13 +1244,12 @@ int gfs2_file_dealloc(struct gfs2_inode *ip) ...@@ -1244,13 +1244,12 @@ int gfs2_file_dealloc(struct gfs2_inode *ip)
* @ip: the file being written to * @ip: the file being written to
* @offset: the offset to write to * @offset: the offset to write to
* @len: the number of bytes being written * @len: the number of bytes being written
* @alloc_required: set to 1 if an alloc is required, 0 otherwise
* *
* Returns: errno * Returns: 1 if an alloc is required, 0 otherwise
*/ */
int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
unsigned int len, int *alloc_required) unsigned int len)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct buffer_head bh; struct buffer_head bh;
...@@ -1258,26 +1257,23 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, ...@@ -1258,26 +1257,23 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
u64 lblock, lblock_stop, size; u64 lblock, lblock_stop, size;
u64 end_of_file; u64 end_of_file;
*alloc_required = 0;
if (!len) if (!len)
return 0; return 0;
if (gfs2_is_stuffed(ip)) { if (gfs2_is_stuffed(ip)) {
if (offset + len > if (offset + len >
sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode))
*alloc_required = 1; return 1;
return 0; return 0;
} }
*alloc_required = 1;
shift = sdp->sd_sb.sb_bsize_shift; shift = sdp->sd_sb.sb_bsize_shift;
BUG_ON(gfs2_is_dir(ip)); BUG_ON(gfs2_is_dir(ip));
end_of_file = (ip->i_disksize + sdp->sd_sb.sb_bsize - 1) >> shift; end_of_file = (ip->i_disksize + sdp->sd_sb.sb_bsize - 1) >> shift;
lblock = offset >> shift; lblock = offset >> shift;
lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift;
if (lblock_stop > end_of_file) if (lblock_stop > end_of_file)
return 0; return 1;
size = (lblock_stop - lblock) << shift; size = (lblock_stop - lblock) << shift;
do { do {
...@@ -1285,12 +1281,11 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, ...@@ -1285,12 +1281,11 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
bh.b_size = size; bh.b_size = size;
gfs2_block_map(&ip->i_inode, lblock, &bh, 0); gfs2_block_map(&ip->i_inode, lblock, &bh, 0);
if (!buffer_mapped(&bh)) if (!buffer_mapped(&bh))
return 0; return 1;
size -= bh.b_size; size -= bh.b_size;
lblock += (bh.b_size >> ip->i_inode.i_blkbits); lblock += (bh.b_size >> ip->i_inode.i_blkbits);
} while(size > 0); } while(size > 0);
*alloc_required = 0;
return 0; return 0;
} }
...@@ -52,6 +52,6 @@ int gfs2_truncatei(struct gfs2_inode *ip, u64 size); ...@@ -52,6 +52,6 @@ int gfs2_truncatei(struct gfs2_inode *ip, u64 size);
int gfs2_truncatei_resume(struct gfs2_inode *ip); int gfs2_truncatei_resume(struct gfs2_inode *ip);
int gfs2_file_dealloc(struct gfs2_inode *ip); int gfs2_file_dealloc(struct gfs2_inode *ip);
int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
unsigned int len, int *alloc_required); unsigned int len);
#endif /* __BMAP_DOT_H__ */ #endif /* __BMAP_DOT_H__ */
...@@ -955,7 +955,12 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) ...@@ -955,7 +955,12 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
/* Change the pointers. /* Change the pointers.
Don't bother distinguishing stuffed from non-stuffed. Don't bother distinguishing stuffed from non-stuffed.
This code is complicated enough already. */ This code is complicated enough already. */
lp = kmalloc(half_len * sizeof(__be64), GFP_NOFS | __GFP_NOFAIL); lp = kmalloc(half_len * sizeof(__be64), GFP_NOFS);
if (!lp) {
error = -ENOMEM;
goto fail_brelse;
}
/* Change the pointers */ /* Change the pointers */
for (x = 0; x < half_len; x++) for (x = 0; x < half_len; x++)
lp[x] = cpu_to_be64(bn); lp[x] = cpu_to_be64(bn);
...@@ -1063,7 +1068,9 @@ static int dir_double_exhash(struct gfs2_inode *dip) ...@@ -1063,7 +1068,9 @@ static int dir_double_exhash(struct gfs2_inode *dip)
/* Allocate both the "from" and "to" buffers in one big chunk */ /* Allocate both the "from" and "to" buffers in one big chunk */
buf = kcalloc(3, sdp->sd_hash_bsize, GFP_NOFS | __GFP_NOFAIL); buf = kcalloc(3, sdp->sd_hash_bsize, GFP_NOFS);
if (!buf)
return -ENOMEM;
for (block = dip->i_disksize >> sdp->sd_hash_bsize_shift; block--;) { for (block = dip->i_disksize >> sdp->sd_hash_bsize_shift; block--;) {
error = gfs2_dir_read_data(dip, (char *)buf, error = gfs2_dir_read_data(dip, (char *)buf,
......
...@@ -351,7 +351,6 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -351,7 +351,6 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
unsigned long last_index; unsigned long last_index;
u64 pos = page->index << PAGE_CACHE_SHIFT; u64 pos = page->index << PAGE_CACHE_SHIFT;
unsigned int data_blocks, ind_blocks, rblocks; unsigned int data_blocks, ind_blocks, rblocks;
int alloc_required = 0;
struct gfs2_holder gh; struct gfs2_holder gh;
struct gfs2_alloc *al; struct gfs2_alloc *al;
int ret; int ret;
...@@ -364,8 +363,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -364,8 +363,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
set_bit(GIF_SW_PAGED, &ip->i_flags); set_bit(GIF_SW_PAGED, &ip->i_flags);
ret = gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE, &alloc_required); if (!gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE))
if (ret || !alloc_required)
goto out_unlock; goto out_unlock;
ret = -ENOMEM; ret = -ENOMEM;
al = gfs2_alloc_get(ip); al = gfs2_alloc_get(ip);
......
...@@ -327,6 +327,30 @@ static void gfs2_holder_wake(struct gfs2_holder *gh) ...@@ -327,6 +327,30 @@ static void gfs2_holder_wake(struct gfs2_holder *gh)
wake_up_bit(&gh->gh_iflags, HIF_WAIT); wake_up_bit(&gh->gh_iflags, HIF_WAIT);
} }
/**
* do_error - Something unexpected has happened during a lock request
*
*/
static inline void do_error(struct gfs2_glock *gl, const int ret)
{
struct gfs2_holder *gh, *tmp;
list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) {
if (test_bit(HIF_HOLDER, &gh->gh_iflags))
continue;
if (ret & LM_OUT_ERROR)
gh->gh_error = -EIO;
else if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))
gh->gh_error = GLR_TRYFAILED;
else
continue;
list_del_init(&gh->gh_list);
trace_gfs2_glock_queue(gh, 0);
gfs2_holder_wake(gh);
}
}
/** /**
* do_promote - promote as many requests as possible on the current queue * do_promote - promote as many requests as possible on the current queue
* @gl: The glock * @gl: The glock
...@@ -375,35 +399,12 @@ __acquires(&gl->gl_spin) ...@@ -375,35 +399,12 @@ __acquires(&gl->gl_spin)
} }
if (gh->gh_list.prev == &gl->gl_holders) if (gh->gh_list.prev == &gl->gl_holders)
return 1; return 1;
do_error(gl, 0);
break; break;
} }
return 0; return 0;
} }
/**
* do_error - Something unexpected has happened during a lock request
*
*/
static inline void do_error(struct gfs2_glock *gl, const int ret)
{
struct gfs2_holder *gh, *tmp;
list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) {
if (test_bit(HIF_HOLDER, &gh->gh_iflags))
continue;
if (ret & LM_OUT_ERROR)
gh->gh_error = -EIO;
else if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))
gh->gh_error = GLR_TRYFAILED;
else
continue;
list_del_init(&gh->gh_list);
trace_gfs2_glock_queue(gh, 0);
gfs2_holder_wake(gh);
}
}
/** /**
* find_first_waiter - find the first gh that's waiting for the glock * find_first_waiter - find the first gh that's waiting for the glock
* @gl: the glock * @gl: the glock
...@@ -706,18 +707,8 @@ static void glock_work_func(struct work_struct *work) ...@@ -706,18 +707,8 @@ static void glock_work_func(struct work_struct *work)
{ {
unsigned long delay = 0; unsigned long delay = 0;
struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_work.work); struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_work.work);
struct gfs2_holder *gh;
int drop_ref = 0; int drop_ref = 0;
if (unlikely(test_bit(GLF_FROZEN, &gl->gl_flags))) {
spin_lock(&gl->gl_spin);
gh = find_first_waiter(gl);
if (gh && (gh->gh_flags & LM_FLAG_NOEXP) &&
test_and_clear_bit(GLF_FROZEN, &gl->gl_flags))
set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
spin_unlock(&gl->gl_spin);
}
if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags)) { if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags)) {
finish_xmote(gl, gl->gl_reply); finish_xmote(gl, gl->gl_reply);
drop_ref = 1; drop_ref = 1;
...@@ -1072,6 +1063,9 @@ int gfs2_glock_nq(struct gfs2_holder *gh) ...@@ -1072,6 +1063,9 @@ int gfs2_glock_nq(struct gfs2_holder *gh)
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
add_to_queue(gh); add_to_queue(gh);
if ((LM_FLAG_NOEXP & gh->gh_flags) &&
test_and_clear_bit(GLF_FROZEN, &gl->gl_flags))
set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
run_queue(gl, 1); run_queue(gl, 1);
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
...@@ -1328,6 +1322,36 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state) ...@@ -1328,6 +1322,36 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
gfs2_glock_put(gl); gfs2_glock_put(gl);
} }
/**
* gfs2_should_freeze - Figure out if glock should be frozen
* @gl: The glock in question
*
* Glocks are not frozen if (a) the result of the dlm operation is
* an error, (b) the locking operation was an unlock operation or
* (c) if there is a "noexp" flagged request anywhere in the queue
*
* Returns: 1 if freezing should occur, 0 otherwise
*/
static int gfs2_should_freeze(const struct gfs2_glock *gl)
{
const struct gfs2_holder *gh;
if (gl->gl_reply & ~LM_OUT_ST_MASK)
return 0;
if (gl->gl_target == LM_ST_UNLOCKED)
return 0;
list_for_each_entry(gh, &gl->gl_holders, gh_list) {
if (test_bit(HIF_HOLDER, &gh->gh_iflags))
continue;
if (LM_FLAG_NOEXP & gh->gh_flags)
return 0;
}
return 1;
}
/** /**
* gfs2_glock_complete - Callback used by locking * gfs2_glock_complete - Callback used by locking
* @gl: Pointer to the glock * @gl: Pointer to the glock
...@@ -1338,18 +1362,17 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state) ...@@ -1338,18 +1362,17 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
void gfs2_glock_complete(struct gfs2_glock *gl, int ret) void gfs2_glock_complete(struct gfs2_glock *gl, int ret)
{ {
struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
gl->gl_reply = ret; gl->gl_reply = ret;
if (unlikely(test_bit(DFL_BLOCK_LOCKS, &ls->ls_flags))) { if (unlikely(test_bit(DFL_BLOCK_LOCKS, &ls->ls_flags))) {
struct gfs2_holder *gh;
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
gh = find_first_waiter(gl); if (gfs2_should_freeze(gl)) {
if ((!(gh && (gh->gh_flags & LM_FLAG_NOEXP)) &&
(gl->gl_target != LM_ST_UNLOCKED)) ||
((ret & ~LM_OUT_ST_MASK) != 0))
set_bit(GLF_FROZEN, &gl->gl_flags); set_bit(GLF_FROZEN, &gl->gl_flags);
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
if (test_bit(GLF_FROZEN, &gl->gl_flags))
return; return;
}
spin_unlock(&gl->gl_spin);
} }
set_bit(GLF_REPLY_PENDING, &gl->gl_flags); set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
gfs2_glock_hold(gl); gfs2_glock_hold(gl);
......
...@@ -460,6 +460,7 @@ enum { ...@@ -460,6 +460,7 @@ enum {
SDF_NOBARRIERS = 3, SDF_NOBARRIERS = 3,
SDF_NORECOVERY = 4, SDF_NORECOVERY = 4,
SDF_DEMOTE = 5, SDF_DEMOTE = 5,
SDF_NOJOURNALID = 6,
}; };
#define GFS2_FSNAME_LEN 256 #define GFS2_FSNAME_LEN 256
......
...@@ -76,7 +76,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) ...@@ -76,7 +76,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
sb->s_fs_info = sdp; sb->s_fs_info = sdp;
sdp->sd_vfs = sb; sdp->sd_vfs = sb;
set_bit(SDF_NOJOURNALID, &sdp->sd_flags);
gfs2_tune_init(&sdp->sd_tune); gfs2_tune_init(&sdp->sd_tune);
init_waitqueue_head(&sdp->sd_glock_wait); init_waitqueue_head(&sdp->sd_glock_wait);
...@@ -1050,7 +1050,8 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent) ...@@ -1050,7 +1050,8 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent)
ret = match_int(&tmp[0], &option); ret = match_int(&tmp[0], &option);
if (ret || option < 0) if (ret || option < 0)
goto hostdata_error; goto hostdata_error;
ls->ls_jid = option; if (test_and_clear_bit(SDF_NOJOURNALID, &sdp->sd_flags))
ls->ls_jid = option;
break; break;
case Opt_id: case Opt_id:
/* Obsolete, but left for backward compat purposes */ /* Obsolete, but left for backward compat purposes */
...@@ -1102,6 +1103,24 @@ void gfs2_lm_unmount(struct gfs2_sbd *sdp) ...@@ -1102,6 +1103,24 @@ void gfs2_lm_unmount(struct gfs2_sbd *sdp)
lm->lm_unmount(sdp); lm->lm_unmount(sdp);
} }
static int gfs2_journalid_wait(void *word)
{
if (signal_pending(current))
return -EINTR;
schedule();
return 0;
}
static int wait_on_journal(struct gfs2_sbd *sdp)
{
if (sdp->sd_args.ar_spectator)
return 0;
if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
return 0;
return wait_on_bit(&sdp->sd_flags, SDF_NOJOURNALID, gfs2_journalid_wait, TASK_INTERRUPTIBLE);
}
void gfs2_online_uevent(struct gfs2_sbd *sdp) void gfs2_online_uevent(struct gfs2_sbd *sdp)
{ {
struct super_block *sb = sdp->sd_vfs; struct super_block *sb = sdp->sd_vfs;
...@@ -1194,6 +1213,10 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent ...@@ -1194,6 +1213,10 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent
if (error) if (error)
goto fail_locking; goto fail_locking;
error = wait_on_journal(sdp);
if (error)
goto fail_sb;
error = init_inodes(sdp, DO); error = init_inodes(sdp, DO);
if (error) if (error)
goto fail_sb; goto fail_sb;
......
...@@ -787,15 +787,9 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) ...@@ -787,15 +787,9 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
goto out; goto out;
for (x = 0; x < num_qd; x++) { for (x = 0; x < num_qd; x++) {
int alloc_required;
offset = qd2offset(qda[x]); offset = qd2offset(qda[x]);
error = gfs2_write_alloc_required(ip, offset, if (gfs2_write_alloc_required(ip, offset,
sizeof(struct gfs2_quota), sizeof(struct gfs2_quota)))
&alloc_required);
if (error)
goto out_gunlock;
if (alloc_required)
nalloc++; nalloc++;
} }
...@@ -1584,10 +1578,7 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id, ...@@ -1584,10 +1578,7 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
goto out_i; goto out_i;
offset = qd2offset(qd); offset = qd2offset(qd);
error = gfs2_write_alloc_required(ip, offset, sizeof(struct gfs2_quota), alloc_required = gfs2_write_alloc_required(ip, offset, sizeof(struct gfs2_quota));
&alloc_required);
if (error)
goto out_i;
if (alloc_required) { if (alloc_required) {
al = gfs2_alloc_get(ip); al = gfs2_alloc_get(ip);
if (al == NULL) if (al == NULL)
......
...@@ -342,8 +342,6 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd) ...@@ -342,8 +342,6 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd)
{ {
struct gfs2_inode *ip = GFS2_I(jd->jd_inode); struct gfs2_inode *ip = GFS2_I(jd->jd_inode);
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
int ar;
int error;
if (ip->i_disksize < (8 << 20) || ip->i_disksize > (1 << 30) || if (ip->i_disksize < (8 << 20) || ip->i_disksize > (1 << 30) ||
(ip->i_disksize & (sdp->sd_sb.sb_bsize - 1))) { (ip->i_disksize & (sdp->sd_sb.sb_bsize - 1))) {
...@@ -352,13 +350,12 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd) ...@@ -352,13 +350,12 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd)
} }
jd->jd_blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift; jd->jd_blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift;
error = gfs2_write_alloc_required(ip, 0, ip->i_disksize, &ar); if (gfs2_write_alloc_required(ip, 0, ip->i_disksize)) {
if (!error && ar) {
gfs2_consist_inode(ip); gfs2_consist_inode(ip);
error = -EIO; return -EIO;
} }
return error; return 0;
} }
/** /**
......
...@@ -325,6 +325,30 @@ static ssize_t lkfirst_show(struct gfs2_sbd *sdp, char *buf) ...@@ -325,6 +325,30 @@ static ssize_t lkfirst_show(struct gfs2_sbd *sdp, char *buf)
return sprintf(buf, "%d\n", ls->ls_first); return sprintf(buf, "%d\n", ls->ls_first);
} }
static ssize_t lkfirst_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
{
unsigned first;
int rv;
rv = sscanf(buf, "%u", &first);
if (rv != 1 || first > 1)
return -EINVAL;
spin_lock(&sdp->sd_jindex_spin);
rv = -EBUSY;
if (test_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0)
goto out;
rv = -EINVAL;
if (sdp->sd_args.ar_spectator)
goto out;
if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
goto out;
sdp->sd_lockstruct.ls_first = first;
rv = 0;
out:
spin_unlock(&sdp->sd_jindex_spin);
return rv ? rv : len;
}
static ssize_t first_done_show(struct gfs2_sbd *sdp, char *buf) static ssize_t first_done_show(struct gfs2_sbd *sdp, char *buf)
{ {
struct lm_lockstruct *ls = &sdp->sd_lockstruct; struct lm_lockstruct *ls = &sdp->sd_lockstruct;
...@@ -377,14 +401,41 @@ static ssize_t jid_show(struct gfs2_sbd *sdp, char *buf) ...@@ -377,14 +401,41 @@ static ssize_t jid_show(struct gfs2_sbd *sdp, char *buf)
return sprintf(buf, "%u\n", sdp->sd_lockstruct.ls_jid); return sprintf(buf, "%u\n", sdp->sd_lockstruct.ls_jid);
} }
static ssize_t jid_store(struct gfs2_sbd *sdp, const char *buf, size_t len)
{
unsigned jid;
int rv;
rv = sscanf(buf, "%u", &jid);
if (rv != 1)
return -EINVAL;
spin_lock(&sdp->sd_jindex_spin);
rv = -EINVAL;
if (sdp->sd_args.ar_spectator)
goto out;
if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL)
goto out;
rv = -EBUSY;
if (test_and_clear_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0)
goto out;
sdp->sd_lockstruct.ls_jid = jid;
smp_mb__after_clear_bit();
wake_up_bit(&sdp->sd_flags, SDF_NOJOURNALID);
rv = 0;
out:
spin_unlock(&sdp->sd_jindex_spin);
return rv ? rv : len;
}
#define GDLM_ATTR(_name,_mode,_show,_store) \ #define GDLM_ATTR(_name,_mode,_show,_store) \
static struct gfs2_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store) static struct gfs2_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store)
GDLM_ATTR(proto_name, 0444, proto_name_show, NULL); GDLM_ATTR(proto_name, 0444, proto_name_show, NULL);
GDLM_ATTR(block, 0644, block_show, block_store); GDLM_ATTR(block, 0644, block_show, block_store);
GDLM_ATTR(withdraw, 0644, withdraw_show, withdraw_store); GDLM_ATTR(withdraw, 0644, withdraw_show, withdraw_store);
GDLM_ATTR(jid, 0444, jid_show, NULL); GDLM_ATTR(jid, 0644, jid_show, jid_store);
GDLM_ATTR(first, 0444, lkfirst_show, NULL); GDLM_ATTR(first, 0644, lkfirst_show, lkfirst_store);
GDLM_ATTR(first_done, 0444, first_done_show, NULL); GDLM_ATTR(first_done, 0444, first_done_show, NULL);
GDLM_ATTR(recover, 0600, NULL, recover_store); GDLM_ATTR(recover, 0600, NULL, recover_store);
GDLM_ATTR(recover_done, 0444, recover_done_show, NULL); GDLM_ATTR(recover_done, 0444, recover_done_show, NULL);
...@@ -564,7 +615,7 @@ static int gfs2_uevent(struct kset *kset, struct kobject *kobj, ...@@ -564,7 +615,7 @@ static int gfs2_uevent(struct kset *kset, struct kobject *kobj,
add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name); add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name);
add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name); add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name);
if (!sdp->sd_args.ar_spectator) if (!test_bit(SDF_NOJOURNALID, &sdp->sd_flags))
add_uevent_var(env, "JOURNALID=%u", sdp->sd_lockstruct.ls_jid); add_uevent_var(env, "JOURNALID=%u", sdp->sd_lockstruct.ls_jid);
if (gfs2_uuid_valid(uuid)) if (gfs2_uuid_valid(uuid))
add_uevent_var(env, "UUID=%pUB", uuid); add_uevent_var(env, "UUID=%pUB", uuid);
......
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