Commit b08b2721 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: Don't flush delete workqueue when releasing the transaction lock
  GFS2: fsck.gfs2 reported statfs error after gfs2_grow
  GFS2: Merge glock state fields into a bitfield
  GFS2: Fix uninitialised error value in previous patch
  GFS2: fix recursive locking during rindex truncates
  GFS2: reread rindex when necessary to grow rindex
  GFS2: Remove duplicate #defines from glock.h
  GFS2: Clean up of gdlm_lock function
  GFS2: Allow gfs2 to update quota usage values through the quotactl interface
  GFS2: fs/gfs2/glock.h: Add __attribute__((format(printf,2,3)) to gfs2_print_dbg
  GFS2: fs/gfs2/glock.c: Use printf extension %pV
  GFS2: Clean up duplicated setattr code
  GFS2: Remove unreachable calls to vmtruncate
  GFS2: fs/gfs2/glock.c: Convert sprintf_symbol to %pS
  GFS2: Change two WQ_RESCUERs into WQ_MEM_RECLAIM
parents 8484baaa 846f4045
...@@ -763,7 +763,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, ...@@ -763,7 +763,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
int metadata; int metadata;
unsigned int revokes = 0; unsigned int revokes = 0;
int x; int x;
int error; int error = 0;
if (!*top) if (!*top)
sm->sm_first = 0; sm->sm_first = 0;
...@@ -780,7 +780,11 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, ...@@ -780,7 +780,11 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
if (metadata) if (metadata)
revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs; revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs;
if (ip != GFS2_I(sdp->sd_rindex))
error = gfs2_rindex_hold(sdp, &ip->i_alloc->al_ri_gh); error = gfs2_rindex_hold(sdp, &ip->i_alloc->al_ri_gh);
else if (!sdp->sd_rgrps)
error = gfs2_ri_update(ip);
if (error) if (error)
return error; return error;
...@@ -879,6 +883,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, ...@@ -879,6 +883,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
out_rlist: out_rlist:
gfs2_rlist_free(&rlist); gfs2_rlist_free(&rlist);
out: out:
if (ip != GFS2_I(sdp->sd_rindex))
gfs2_glock_dq_uninit(&ip->i_alloc->al_ri_gh); gfs2_glock_dq_uninit(&ip->i_alloc->al_ri_gh);
return error; return error;
} }
......
...@@ -541,21 +541,6 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret) ...@@ -541,21 +541,6 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
} }
static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock,
unsigned int req_state,
unsigned int flags)
{
int ret = LM_OUT_ERROR;
if (!sdp->sd_lockstruct.ls_ops->lm_lock)
return req_state == LM_ST_UNLOCKED ? 0 : req_state;
if (likely(!test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
ret = sdp->sd_lockstruct.ls_ops->lm_lock(lock,
req_state, flags);
return ret;
}
/** /**
* do_xmote - Calls the DLM to change the state of a lock * do_xmote - Calls the DLM to change the state of a lock
* @gl: The lock state * @gl: The lock state
...@@ -575,13 +560,14 @@ __acquires(&gl->gl_spin) ...@@ -575,13 +560,14 @@ __acquires(&gl->gl_spin)
lck_flags &= (LM_FLAG_TRY | LM_FLAG_TRY_1CB | LM_FLAG_NOEXP | lck_flags &= (LM_FLAG_TRY | LM_FLAG_TRY_1CB | LM_FLAG_NOEXP |
LM_FLAG_PRIORITY); LM_FLAG_PRIORITY);
BUG_ON(gl->gl_state == target); GLOCK_BUG_ON(gl, gl->gl_state == target);
BUG_ON(gl->gl_state == gl->gl_target); GLOCK_BUG_ON(gl, gl->gl_state == gl->gl_target);
if ((target == LM_ST_UNLOCKED || target == LM_ST_DEFERRED) && if ((target == LM_ST_UNLOCKED || target == LM_ST_DEFERRED) &&
glops->go_inval) { glops->go_inval) {
set_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags); set_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
do_error(gl, 0); /* Fail queued try locks */ do_error(gl, 0); /* Fail queued try locks */
} }
gl->gl_req = target;
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
if (glops->go_xmote_th) if (glops->go_xmote_th)
glops->go_xmote_th(gl); glops->go_xmote_th(gl);
...@@ -594,15 +580,17 @@ __acquires(&gl->gl_spin) ...@@ -594,15 +580,17 @@ __acquires(&gl->gl_spin)
gl->gl_state == LM_ST_DEFERRED) && gl->gl_state == LM_ST_DEFERRED) &&
!(lck_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) !(lck_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)))
lck_flags |= LM_FLAG_TRY_1CB; lck_flags |= LM_FLAG_TRY_1CB;
ret = gfs2_lm_lock(sdp, gl, target, lck_flags);
if (!(ret & LM_OUT_ASYNC)) { if (sdp->sd_lockstruct.ls_ops->lm_lock) {
finish_xmote(gl, ret); /* lock_dlm */
ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags);
GLOCK_BUG_ON(gl, ret);
} else { /* lock_nolock */
finish_xmote(gl, target);
if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
gfs2_glock_put(gl); gfs2_glock_put(gl);
} else {
GLOCK_BUG_ON(gl, ret != LM_OUT_ASYNC);
} }
spin_lock(&gl->gl_spin); spin_lock(&gl->gl_spin);
} }
...@@ -951,17 +939,22 @@ int gfs2_glock_wait(struct gfs2_holder *gh) ...@@ -951,17 +939,22 @@ int gfs2_glock_wait(struct gfs2_holder *gh)
void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...) void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...)
{ {
struct va_format vaf;
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
if (seq) { if (seq) {
struct gfs2_glock_iter *gi = seq->private; struct gfs2_glock_iter *gi = seq->private;
vsprintf(gi->string, fmt, args); vsprintf(gi->string, fmt, args);
seq_printf(seq, gi->string); seq_printf(seq, gi->string);
} else { } else {
printk(KERN_ERR " "); vaf.fmt = fmt;
vprintk(fmt, args); vaf.va = &args;
printk(KERN_ERR " %pV", &vaf);
} }
va_end(args); va_end(args);
} }
...@@ -1361,24 +1354,28 @@ static int gfs2_should_freeze(const struct gfs2_glock *gl) ...@@ -1361,24 +1354,28 @@ static int gfs2_should_freeze(const struct gfs2_glock *gl)
* @gl: Pointer to the glock * @gl: Pointer to the glock
* @ret: The return value from the dlm * @ret: The return value from the dlm
* *
* The gl_reply field is under the gl_spin lock so that it is ok
* to use a bitfield shared with other glock state fields.
*/ */
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;
spin_lock(&gl->gl_spin);
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))) {
spin_lock(&gl->gl_spin);
if (gfs2_should_freeze(gl)) { if (gfs2_should_freeze(gl)) {
set_bit(GLF_FROZEN, &gl->gl_flags); set_bit(GLF_FROZEN, &gl->gl_flags);
spin_unlock(&gl->gl_spin); spin_unlock(&gl->gl_spin);
return; return;
} }
spin_unlock(&gl->gl_spin);
} }
spin_unlock(&gl->gl_spin);
set_bit(GLF_REPLY_PENDING, &gl->gl_flags); set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
smp_wmb();
gfs2_glock_hold(gl); gfs2_glock_hold(gl);
if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
gfs2_glock_put(gl); gfs2_glock_put(gl);
...@@ -1626,18 +1623,17 @@ static const char *hflags2str(char *buf, unsigned flags, unsigned long iflags) ...@@ -1626,18 +1623,17 @@ static const char *hflags2str(char *buf, unsigned flags, unsigned long iflags)
static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh) static int dump_holder(struct seq_file *seq, const struct gfs2_holder *gh)
{ {
struct task_struct *gh_owner = NULL; struct task_struct *gh_owner = NULL;
char buffer[KSYM_SYMBOL_LEN];
char flags_buf[32]; char flags_buf[32];
sprint_symbol(buffer, gh->gh_ip);
if (gh->gh_owner_pid) if (gh->gh_owner_pid)
gh_owner = pid_task(gh->gh_owner_pid, PIDTYPE_PID); gh_owner = pid_task(gh->gh_owner_pid, PIDTYPE_PID);
gfs2_print_dbg(seq, " H: s:%s f:%s e:%d p:%ld [%s] %s\n", gfs2_print_dbg(seq, " H: s:%s f:%s e:%d p:%ld [%s] %pS\n",
state2str(gh->gh_state), state2str(gh->gh_state),
hflags2str(flags_buf, gh->gh_flags, gh->gh_iflags), hflags2str(flags_buf, gh->gh_flags, gh->gh_iflags),
gh->gh_error, gh->gh_error,
gh->gh_owner_pid ? (long)pid_nr(gh->gh_owner_pid) : -1, gh->gh_owner_pid ? (long)pid_nr(gh->gh_owner_pid) : -1,
gh_owner ? gh_owner->comm : "(ended)", buffer); gh_owner ? gh_owner->comm : "(ended)",
(void *)gh->gh_ip);
return 0; return 0;
} }
...@@ -1782,12 +1778,13 @@ int __init gfs2_glock_init(void) ...@@ -1782,12 +1778,13 @@ int __init gfs2_glock_init(void)
} }
#endif #endif
glock_workqueue = alloc_workqueue("glock_workqueue", WQ_RESCUER | glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM |
WQ_HIGHPRI | WQ_FREEZEABLE, 0); WQ_HIGHPRI | WQ_FREEZEABLE, 0);
if (IS_ERR(glock_workqueue)) if (IS_ERR(glock_workqueue))
return PTR_ERR(glock_workqueue); return PTR_ERR(glock_workqueue);
gfs2_delete_workqueue = alloc_workqueue("delete_workqueue", WQ_RESCUER | gfs2_delete_workqueue = alloc_workqueue("delete_workqueue",
WQ_FREEZEABLE, 0); WQ_MEM_RECLAIM | WQ_FREEZEABLE,
0);
if (IS_ERR(gfs2_delete_workqueue)) { if (IS_ERR(gfs2_delete_workqueue)) {
destroy_workqueue(glock_workqueue); destroy_workqueue(glock_workqueue);
return PTR_ERR(gfs2_delete_workqueue); return PTR_ERR(gfs2_delete_workqueue);
......
...@@ -87,11 +87,10 @@ enum { ...@@ -87,11 +87,10 @@ enum {
#define GL_ASYNC 0x00000040 #define GL_ASYNC 0x00000040
#define GL_EXACT 0x00000080 #define GL_EXACT 0x00000080
#define GL_SKIP 0x00000100 #define GL_SKIP 0x00000100
#define GL_ATIME 0x00000200
#define GL_NOCACHE 0x00000400 #define GL_NOCACHE 0x00000400
/* /*
* lm_lock() and lm_async_cb return flags * lm_async_cb return flags
* *
* LM_OUT_ST_MASK * LM_OUT_ST_MASK
* Masks the lower two bits of lock state in the returned value. * Masks the lower two bits of lock state in the returned value.
...@@ -99,15 +98,11 @@ enum { ...@@ -99,15 +98,11 @@ enum {
* LM_OUT_CANCELED * LM_OUT_CANCELED
* The lock request was canceled. * The lock request was canceled.
* *
* LM_OUT_ASYNC
* The result of the request will be returned in an LM_CB_ASYNC callback.
*
*/ */
#define LM_OUT_ST_MASK 0x00000003 #define LM_OUT_ST_MASK 0x00000003
#define LM_OUT_CANCELED 0x00000008 #define LM_OUT_CANCELED 0x00000008
#define LM_OUT_ASYNC 0x00000080 #define LM_OUT_ERROR 0x00000004
#define LM_OUT_ERROR 0x00000100
/* /*
* lm_recovery_done() messages * lm_recovery_done() messages
...@@ -124,25 +119,12 @@ struct lm_lockops { ...@@ -124,25 +119,12 @@ struct lm_lockops {
void (*lm_unmount) (struct gfs2_sbd *sdp); void (*lm_unmount) (struct gfs2_sbd *sdp);
void (*lm_withdraw) (struct gfs2_sbd *sdp); void (*lm_withdraw) (struct gfs2_sbd *sdp);
void (*lm_put_lock) (struct kmem_cache *cachep, struct gfs2_glock *gl); void (*lm_put_lock) (struct kmem_cache *cachep, struct gfs2_glock *gl);
unsigned int (*lm_lock) (struct gfs2_glock *gl, int (*lm_lock) (struct gfs2_glock *gl, unsigned int req_state,
unsigned int req_state, unsigned int flags); unsigned int flags);
void (*lm_cancel) (struct gfs2_glock *gl); void (*lm_cancel) (struct gfs2_glock *gl);
const match_table_t *lm_tokens; const match_table_t *lm_tokens;
}; };
#define LM_FLAG_TRY 0x00000001
#define LM_FLAG_TRY_1CB 0x00000002
#define LM_FLAG_NOEXP 0x00000004
#define LM_FLAG_ANY 0x00000008
#define LM_FLAG_PRIORITY 0x00000010
#define GL_ASYNC 0x00000040
#define GL_EXACT 0x00000080
#define GL_SKIP 0x00000100
#define GL_NOCACHE 0x00000400
#define GLR_TRYFAILED 13
extern struct workqueue_struct *gfs2_delete_workqueue; extern struct workqueue_struct *gfs2_delete_workqueue;
static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl) static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl)
{ {
...@@ -212,6 +194,8 @@ int gfs2_glock_nq_num(struct gfs2_sbd *sdp, ...@@ -212,6 +194,8 @@ int gfs2_glock_nq_num(struct gfs2_sbd *sdp,
int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs); int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs);
void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs); void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs);
void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs); void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs);
__attribute__ ((format(printf, 2, 3)))
void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...); void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...);
/** /**
......
...@@ -325,7 +325,6 @@ static void trans_go_sync(struct gfs2_glock *gl) ...@@ -325,7 +325,6 @@ static void trans_go_sync(struct gfs2_glock *gl)
if (gl->gl_state != LM_ST_UNLOCKED && if (gl->gl_state != LM_ST_UNLOCKED &&
test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
flush_workqueue(gfs2_delete_workqueue);
gfs2_meta_syncfs(sdp); gfs2_meta_syncfs(sdp);
gfs2_log_shutdown(sdp); gfs2_log_shutdown(sdp);
} }
......
...@@ -207,12 +207,14 @@ struct gfs2_glock { ...@@ -207,12 +207,14 @@ struct gfs2_glock {
spinlock_t gl_spin; spinlock_t gl_spin;
unsigned int gl_state; /* State fields protected by gl_spin */
unsigned int gl_target; unsigned int gl_state:2, /* Current state */
unsigned int gl_reply; gl_target:2, /* Target state */
gl_demote_state:2, /* State requested by remote node */
gl_req:2, /* State in last dlm request */
gl_reply:8; /* Last reply from the dlm */
unsigned int gl_hash; unsigned int gl_hash;
unsigned int gl_req;
unsigned int gl_demote_state; /* state requested by remote node */
unsigned long gl_demote_time; /* time of first demote request */ unsigned long gl_demote_time; /* time of first demote request */
struct list_head gl_holders; struct list_head gl_holders;
......
...@@ -916,17 +916,8 @@ static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) ...@@ -916,17 +916,8 @@ static int __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr)
if (error) if (error)
return error; return error;
if ((attr->ia_valid & ATTR_SIZE) &&
attr->ia_size != i_size_read(inode)) {
error = vmtruncate(inode, attr->ia_size);
if (error)
return error;
}
setattr_copy(inode, attr); setattr_copy(inode, attr);
mark_inode_dirty(inode); mark_inode_dirty(inode);
gfs2_assert_warn(GFS2_SB(inode), !error);
gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data); gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh); brelse(dibh);
......
...@@ -146,15 +146,13 @@ static u32 make_flags(const u32 lkid, const unsigned int gfs_flags, ...@@ -146,15 +146,13 @@ static u32 make_flags(const u32 lkid, const unsigned int gfs_flags,
return lkf; return lkf;
} }
static unsigned int gdlm_lock(struct gfs2_glock *gl, static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
unsigned int req_state, unsigned int flags) unsigned int flags)
{ {
struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
int error;
int req; int req;
u32 lkf; u32 lkf;
gl->gl_req = req_state;
req = make_mode(req_state); req = make_mode(req_state);
lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req); lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req);
...@@ -162,13 +160,8 @@ static unsigned int gdlm_lock(struct gfs2_glock *gl, ...@@ -162,13 +160,8 @@ static unsigned int gdlm_lock(struct gfs2_glock *gl,
* Submit the actual lock request. * Submit the actual lock request.
*/ */
error = dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, gl->gl_strname, return dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, gl->gl_strname,
GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast); GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast);
if (error == -EAGAIN)
return 0;
if (error)
return LM_OUT_ERROR;
return LM_OUT_ASYNC;
} }
static void gdlm_put_lock(struct kmem_cache *cachep, struct gfs2_glock *gl) static void gdlm_put_lock(struct kmem_cache *cachep, struct gfs2_glock *gl)
......
...@@ -1069,7 +1069,6 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) ...@@ -1069,7 +1069,6 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
{ {
struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_sbd *sdp = GFS2_SB(inode);
struct buffer_head *dibh;
u32 ouid, ogid, nuid, ngid; u32 ouid, ogid, nuid, ngid;
int error; int error;
...@@ -1100,25 +1099,10 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) ...@@ -1100,25 +1099,10 @@ static int setattr_chown(struct inode *inode, struct iattr *attr)
if (error) if (error)
goto out_gunlock_q; goto out_gunlock_q;
error = gfs2_meta_inode_buffer(ip, &dibh); error = gfs2_setattr_simple(ip, attr);
if (error) if (error)
goto out_end_trans; goto out_end_trans;
if ((attr->ia_valid & ATTR_SIZE) &&
attr->ia_size != i_size_read(inode)) {
int error;
error = vmtruncate(inode, attr->ia_size);
gfs2_assert_warn(sdp, !error);
}
setattr_copy(inode, attr);
mark_inode_dirty(inode);
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
u64 blocks = gfs2_get_inode_blocks(&ip->i_inode); u64 blocks = gfs2_get_inode_blocks(&ip->i_inode);
gfs2_quota_change(ip, -blocks, ouid, ogid); gfs2_quota_change(ip, -blocks, ouid, ogid);
......
...@@ -666,6 +666,10 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, ...@@ -666,6 +666,10 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
qp->qu_limit = cpu_to_be64(fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift); qp->qu_limit = cpu_to_be64(fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift);
qd->qd_qb.qb_limit = qp->qu_limit; qd->qd_qb.qb_limit = qp->qu_limit;
} }
if (fdq->d_fieldmask & FS_DQ_BCOUNT) {
qp->qu_value = cpu_to_be64(fdq->d_bcount >> sdp->sd_fsb2bb_shift);
qd->qd_qb.qb_value = qp->qu_value;
}
} }
/* Write the quota into the quota file on disk */ /* Write the quota into the quota file on disk */
...@@ -1509,7 +1513,7 @@ static int gfs2_get_dqblk(struct super_block *sb, int type, qid_t id, ...@@ -1509,7 +1513,7 @@ static int gfs2_get_dqblk(struct super_block *sb, int type, qid_t id,
} }
/* GFS2 only supports a subset of the XFS fields */ /* GFS2 only supports a subset of the XFS fields */
#define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD) #define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD|FS_DQ_BCOUNT)
static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id, static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
struct fs_disk_quota *fdq) struct fs_disk_quota *fdq)
...@@ -1569,9 +1573,15 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id, ...@@ -1569,9 +1573,15 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
if ((fdq->d_fieldmask & FS_DQ_BSOFT) && if ((fdq->d_fieldmask & FS_DQ_BSOFT) &&
((fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_warn))) ((fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_warn)))
fdq->d_fieldmask ^= FS_DQ_BSOFT; fdq->d_fieldmask ^= FS_DQ_BSOFT;
if ((fdq->d_fieldmask & FS_DQ_BHARD) && if ((fdq->d_fieldmask & FS_DQ_BHARD) &&
((fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_limit))) ((fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_limit)))
fdq->d_fieldmask ^= FS_DQ_BHARD; fdq->d_fieldmask ^= FS_DQ_BHARD;
if ((fdq->d_fieldmask & FS_DQ_BCOUNT) &&
((fdq->d_bcount >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_value)))
fdq->d_fieldmask ^= FS_DQ_BCOUNT;
if (fdq->d_fieldmask == 0) if (fdq->d_fieldmask == 0)
goto out_i; goto out_i;
...@@ -1620,4 +1630,3 @@ const struct quotactl_ops gfs2_quotactl_ops = { ...@@ -1620,4 +1630,3 @@ const struct quotactl_ops gfs2_quotactl_ops = {
.get_dqblk = gfs2_get_dqblk, .get_dqblk = gfs2_get_dqblk,
.set_dqblk = gfs2_set_dqblk, .set_dqblk = gfs2_set_dqblk,
}; };
...@@ -500,7 +500,7 @@ u64 gfs2_ri_total(struct gfs2_sbd *sdp) ...@@ -500,7 +500,7 @@ u64 gfs2_ri_total(struct gfs2_sbd *sdp)
for (rgrps = 0;; rgrps++) { for (rgrps = 0;; rgrps++) {
loff_t pos = rgrps * sizeof(struct gfs2_rindex); loff_t pos = rgrps * sizeof(struct gfs2_rindex);
if (pos + sizeof(struct gfs2_rindex) >= i_size_read(inode)) if (pos + sizeof(struct gfs2_rindex) > i_size_read(inode))
break; break;
error = gfs2_internal_read(ip, &ra_state, buf, &pos, error = gfs2_internal_read(ip, &ra_state, buf, &pos,
sizeof(struct gfs2_rindex)); sizeof(struct gfs2_rindex));
...@@ -583,7 +583,7 @@ static int read_rindex_entry(struct gfs2_inode *ip, ...@@ -583,7 +583,7 @@ static int read_rindex_entry(struct gfs2_inode *ip,
* Returns: 0 on successful update, error code otherwise * Returns: 0 on successful update, error code otherwise
*/ */
static int gfs2_ri_update(struct gfs2_inode *ip) int gfs2_ri_update(struct gfs2_inode *ip)
{ {
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct inode *inode = &ip->i_inode; struct inode *inode = &ip->i_inode;
...@@ -613,46 +613,6 @@ static int gfs2_ri_update(struct gfs2_inode *ip) ...@@ -613,46 +613,6 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
return 0; return 0;
} }
/**
* gfs2_ri_update_special - Pull in a new resource index from the disk
*
* This is a special version that's safe to call from gfs2_inplace_reserve_i.
* In this case we know that we don't have any resource groups in memory yet.
*
* @ip: pointer to the rindex inode
*
* Returns: 0 on successful update, error code otherwise
*/
static int gfs2_ri_update_special(struct gfs2_inode *ip)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct inode *inode = &ip->i_inode;
struct file_ra_state ra_state;
struct gfs2_rgrpd *rgd;
unsigned int max_data = 0;
int error;
file_ra_state_init(&ra_state, inode->i_mapping);
for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
/* Ignore partials */
if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) >
i_size_read(inode))
break;
error = read_rindex_entry(ip, &ra_state);
if (error) {
clear_rgrpdi(sdp);
return error;
}
}
list_for_each_entry(rgd, &sdp->sd_rindex_list, rd_list)
if (rgd->rd_data > max_data)
max_data = rgd->rd_data;
sdp->sd_max_rg_data = max_data;
sdp->sd_rindex_uptodate = 1;
return 0;
}
/** /**
* gfs2_rindex_hold - Grab a lock on the rindex * gfs2_rindex_hold - Grab a lock on the rindex
* @sdp: The GFS2 superblock * @sdp: The GFS2 superblock
...@@ -1226,16 +1186,25 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex, ...@@ -1226,16 +1186,25 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex,
error = gfs2_rindex_hold(sdp, &al->al_ri_gh); error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
else if (!sdp->sd_rgrps) /* We may not have the rindex read else if (!sdp->sd_rgrps) /* We may not have the rindex read
in, so: */ in, so: */
error = gfs2_ri_update_special(ip); error = gfs2_ri_update(ip);
if (error) if (error)
return error; return error;
} }
try_again:
do { do {
error = get_local_rgrp(ip, &last_unlinked); error = get_local_rgrp(ip, &last_unlinked);
/* If there is no space, flushing the log may release some */ /* If there is no space, flushing the log may release some */
if (error) {
if (ip == GFS2_I(sdp->sd_rindex) &&
!sdp->sd_rindex_uptodate) {
error = gfs2_ri_update(ip);
if (error) if (error)
return error;
goto try_again;
}
gfs2_log_flush(sdp, NULL); gfs2_log_flush(sdp, NULL);
}
} while (error && tries++ < 3); } while (error && tries++ < 3);
if (error) { if (error) {
......
...@@ -48,6 +48,7 @@ extern int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex, ...@@ -48,6 +48,7 @@ extern int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex,
extern void gfs2_inplace_release(struct gfs2_inode *ip); extern void gfs2_inplace_release(struct gfs2_inode *ip);
extern int gfs2_ri_update(struct gfs2_inode *ip);
extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n); extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n);
extern int gfs2_alloc_di(struct gfs2_inode *ip, u64 *bn, u64 *generation); extern int gfs2_alloc_di(struct gfs2_inode *ip, u64 *bn, u64 *generation);
......
...@@ -1296,10 +1296,8 @@ static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip, ...@@ -1296,10 +1296,8 @@ static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
{ {
struct inode *inode = &ip->i_inode;
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_ea_location el; struct gfs2_ea_location el;
struct buffer_head *dibh;
int error; int error;
error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, GFS2_POSIX_ACL_ACCESS, &el); error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, GFS2_POSIX_ACL_ACCESS, &el);
...@@ -1321,26 +1319,7 @@ int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) ...@@ -1321,26 +1319,7 @@ int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
if (error) if (error)
return error; return error;
error = gfs2_meta_inode_buffer(ip, &dibh); error = gfs2_setattr_simple(ip, attr);
if (error)
goto out_trans_end;
if ((attr->ia_valid & ATTR_SIZE) &&
attr->ia_size != i_size_read(inode)) {
int error;
error = vmtruncate(inode, attr->ia_size);
gfs2_assert_warn(GFS2_SB(inode), !error);
}
setattr_copy(inode, attr);
mark_inode_dirty(inode);
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
out_trans_end:
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
return error; return error;
} }
......
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