Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes: GFS2: Fix permissions checking for setflags ioctl() GFS2: Don't "get" xattrs for ACLs when ACLs are turned off GFS2: Rework reclaiming unlinked dinodes
This commit is contained in:
commit
f16a5e3478
|
@ -236,10 +236,14 @@ static int gfs2_xattr_system_get(struct dentry *dentry, const char *name,
|
||||||
void *buffer, size_t size, int xtype)
|
void *buffer, size_t size, int xtype)
|
||||||
{
|
{
|
||||||
struct inode *inode = dentry->d_inode;
|
struct inode *inode = dentry->d_inode;
|
||||||
|
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||||
struct posix_acl *acl;
|
struct posix_acl *acl;
|
||||||
int type;
|
int type;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
if (!sdp->sd_args.ar_posix_acl)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
type = gfs2_acl_type(name);
|
type = gfs2_acl_type(name);
|
||||||
if (type < 0)
|
if (type < 0)
|
||||||
return type;
|
return type;
|
||||||
|
|
|
@ -218,6 +218,11 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
|
||||||
if (error)
|
if (error)
|
||||||
goto out_drop_write;
|
goto out_drop_write;
|
||||||
|
|
||||||
|
error = -EACCES;
|
||||||
|
if (!is_owner_or_cap(inode))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
error = 0;
|
||||||
flags = ip->i_diskflags;
|
flags = ip->i_diskflags;
|
||||||
new_flags = (flags & ~mask) | (reqflags & mask);
|
new_flags = (flags & ~mask) | (reqflags & mask);
|
||||||
if ((new_flags ^ flags) == 0)
|
if ((new_flags ^ flags) == 0)
|
||||||
|
@ -275,8 +280,10 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
|
||||||
{
|
{
|
||||||
struct inode *inode = filp->f_path.dentry->d_inode;
|
struct inode *inode = filp->f_path.dentry->d_inode;
|
||||||
u32 fsflags, gfsflags;
|
u32 fsflags, gfsflags;
|
||||||
|
|
||||||
if (get_user(fsflags, ptr))
|
if (get_user(fsflags, ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
gfsflags = fsflags_cvt(fsflags_to_gfs2, fsflags);
|
gfsflags = fsflags_cvt(fsflags_to_gfs2, fsflags);
|
||||||
if (!S_ISDIR(inode->i_mode)) {
|
if (!S_ISDIR(inode->i_mode)) {
|
||||||
if (gfsflags & GFS2_DIF_INHERIT_JDATA)
|
if (gfsflags & GFS2_DIF_INHERIT_JDATA)
|
||||||
|
|
|
@ -242,34 +242,38 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gfs2_unlinked_inode_lookup - Lookup an unlinked inode for reclamation
|
* gfs2_process_unlinked_inode - Lookup an unlinked inode for reclamation
|
||||||
|
* and try to reclaim it by doing iput.
|
||||||
|
*
|
||||||
|
* This function assumes no rgrp locks are currently held.
|
||||||
|
*
|
||||||
* @sb: The super block
|
* @sb: The super block
|
||||||
* no_addr: The inode number
|
* no_addr: The inode number
|
||||||
* @@inode: A pointer to the inode found, if any
|
|
||||||
*
|
*
|
||||||
* Returns: 0 and *inode if no errors occurred. If an error occurs,
|
|
||||||
* the resulting *inode may or may not be NULL.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr,
|
void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr)
|
||||||
struct inode **inode)
|
|
||||||
{
|
{
|
||||||
struct gfs2_sbd *sdp;
|
struct gfs2_sbd *sdp;
|
||||||
struct gfs2_inode *ip;
|
struct gfs2_inode *ip;
|
||||||
struct gfs2_glock *io_gl;
|
struct gfs2_glock *io_gl;
|
||||||
int error;
|
int error;
|
||||||
struct gfs2_holder gh;
|
struct gfs2_holder gh;
|
||||||
|
struct inode *inode;
|
||||||
|
|
||||||
*inode = gfs2_iget_skip(sb, no_addr);
|
inode = gfs2_iget_skip(sb, no_addr);
|
||||||
|
|
||||||
if (!(*inode))
|
if (!inode)
|
||||||
return -ENOBUFS;
|
return;
|
||||||
|
|
||||||
if (!((*inode)->i_state & I_NEW))
|
/* If it's not a new inode, someone's using it, so leave it alone. */
|
||||||
return -ENOBUFS;
|
if (!(inode->i_state & I_NEW)) {
|
||||||
|
iput(inode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ip = GFS2_I(*inode);
|
ip = GFS2_I(inode);
|
||||||
sdp = GFS2_SB(*inode);
|
sdp = GFS2_SB(inode);
|
||||||
ip->i_no_formal_ino = -1;
|
ip->i_no_formal_ino = -1;
|
||||||
|
|
||||||
error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
|
error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
|
||||||
|
@ -284,15 +288,13 @@ int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr,
|
||||||
set_bit(GIF_INVALID, &ip->i_flags);
|
set_bit(GIF_INVALID, &ip->i_flags);
|
||||||
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, LM_FLAG_TRY | GL_EXACT,
|
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, LM_FLAG_TRY | GL_EXACT,
|
||||||
&ip->i_iopen_gh);
|
&ip->i_iopen_gh);
|
||||||
if (unlikely(error)) {
|
if (unlikely(error))
|
||||||
if (error == GLR_TRYFAILED)
|
|
||||||
error = 0;
|
|
||||||
goto fail_iopen;
|
goto fail_iopen;
|
||||||
}
|
|
||||||
ip->i_iopen_gh.gh_gl->gl_object = ip;
|
ip->i_iopen_gh.gh_gl->gl_object = ip;
|
||||||
gfs2_glock_put(io_gl);
|
gfs2_glock_put(io_gl);
|
||||||
|
|
||||||
(*inode)->i_mode = DT2IF(DT_UNKNOWN);
|
inode->i_mode = DT2IF(DT_UNKNOWN);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We must read the inode in order to work out its type in
|
* We must read the inode in order to work out its type in
|
||||||
|
@ -303,16 +305,17 @@ int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr,
|
||||||
*/
|
*/
|
||||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY,
|
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY,
|
||||||
&gh);
|
&gh);
|
||||||
if (unlikely(error)) {
|
if (unlikely(error))
|
||||||
if (error == GLR_TRYFAILED)
|
|
||||||
error = 0;
|
|
||||||
goto fail_glock;
|
goto fail_glock;
|
||||||
}
|
|
||||||
/* Inode is now uptodate */
|
/* Inode is now uptodate */
|
||||||
gfs2_glock_dq_uninit(&gh);
|
gfs2_glock_dq_uninit(&gh);
|
||||||
gfs2_set_iop(*inode);
|
gfs2_set_iop(inode);
|
||||||
|
|
||||||
|
/* The iput will cause it to be deleted. */
|
||||||
|
iput(inode);
|
||||||
|
return;
|
||||||
|
|
||||||
return 0;
|
|
||||||
fail_glock:
|
fail_glock:
|
||||||
gfs2_glock_dq(&ip->i_iopen_gh);
|
gfs2_glock_dq(&ip->i_iopen_gh);
|
||||||
fail_iopen:
|
fail_iopen:
|
||||||
|
@ -321,7 +324,8 @@ fail_put:
|
||||||
ip->i_gl->gl_object = NULL;
|
ip->i_gl->gl_object = NULL;
|
||||||
gfs2_glock_put(ip->i_gl);
|
gfs2_glock_put(ip->i_gl);
|
||||||
fail:
|
fail:
|
||||||
return error;
|
iget_failed(inode);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
|
static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
|
||||||
|
|
|
@ -84,8 +84,7 @@ static inline void gfs2_inum_out(const struct gfs2_inode *ip,
|
||||||
extern void gfs2_set_iop(struct inode *inode);
|
extern void gfs2_set_iop(struct inode *inode);
|
||||||
extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type,
|
extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type,
|
||||||
u64 no_addr, u64 no_formal_ino);
|
u64 no_addr, u64 no_formal_ino);
|
||||||
extern int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr,
|
extern void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr);
|
||||||
struct inode **inode);
|
|
||||||
extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr);
|
extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr);
|
||||||
|
|
||||||
extern int gfs2_inode_refresh(struct gfs2_inode *ip);
|
extern int gfs2_inode_refresh(struct gfs2_inode *ip);
|
||||||
|
|
|
@ -696,7 +696,7 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
|
void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
|
||||||
{
|
{
|
||||||
struct gfs2_ail *ai;
|
struct gfs2_ail *ai;
|
||||||
|
|
||||||
|
|
|
@ -47,28 +47,21 @@ static inline void gfs2_log_pointers_init(struct gfs2_sbd *sdp,
|
||||||
sdp->sd_log_head = sdp->sd_log_tail = value;
|
sdp->sd_log_head = sdp->sd_log_tail = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
|
extern unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
|
||||||
unsigned int ssize);
|
unsigned int ssize);
|
||||||
|
|
||||||
int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks);
|
extern int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks);
|
||||||
void gfs2_log_incr_head(struct gfs2_sbd *sdp);
|
extern void gfs2_log_incr_head(struct gfs2_sbd *sdp);
|
||||||
|
|
||||||
struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp);
|
extern struct buffer_head *gfs2_log_get_buf(struct gfs2_sbd *sdp);
|
||||||
struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
|
extern struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
|
||||||
struct buffer_head *real);
|
struct buffer_head *real);
|
||||||
void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl);
|
extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl);
|
||||||
|
extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
|
||||||
|
extern void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
|
||||||
|
|
||||||
static inline void gfs2_log_flush(struct gfs2_sbd *sbd, struct gfs2_glock *gl)
|
extern void gfs2_log_shutdown(struct gfs2_sbd *sdp);
|
||||||
{
|
extern void gfs2_meta_syncfs(struct gfs2_sbd *sdp);
|
||||||
if (!gl || test_bit(GLF_LFLUSH, &gl->gl_flags))
|
extern int gfs2_logd(void *data);
|
||||||
__gfs2_log_flush(sbd, gl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
|
|
||||||
void gfs2_remove_from_ail(struct gfs2_bufdata *bd);
|
|
||||||
|
|
||||||
void gfs2_log_shutdown(struct gfs2_sbd *sdp);
|
|
||||||
void gfs2_meta_syncfs(struct gfs2_sbd *sdp);
|
|
||||||
int gfs2_logd(void *data);
|
|
||||||
|
|
||||||
#endif /* __LOG_DOT_H__ */
|
#endif /* __LOG_DOT_H__ */
|
||||||
|
|
|
@ -1192,7 +1192,6 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
|
||||||
{
|
{
|
||||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||||
struct gfs2_alloc *al = ip->i_alloc;
|
struct gfs2_alloc *al = ip->i_alloc;
|
||||||
struct inode *inode;
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
u64 last_unlinked = NO_BLOCK, unlinked;
|
u64 last_unlinked = NO_BLOCK, unlinked;
|
||||||
|
|
||||||
|
@ -1210,22 +1209,27 @@ try_again:
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
/* Find an rgrp suitable for allocation. If it encounters any unlinked
|
||||||
|
dinodes along the way, error will equal -EAGAIN and unlinked will
|
||||||
|
contains it block address. We then need to look up that inode and
|
||||||
|
try to free it, and try the allocation again. */
|
||||||
error = get_local_rgrp(ip, &unlinked, &last_unlinked);
|
error = get_local_rgrp(ip, &unlinked, &last_unlinked);
|
||||||
if (error) {
|
if (error) {
|
||||||
if (ip != GFS2_I(sdp->sd_rindex))
|
if (ip != GFS2_I(sdp->sd_rindex))
|
||||||
gfs2_glock_dq_uninit(&al->al_ri_gh);
|
gfs2_glock_dq_uninit(&al->al_ri_gh);
|
||||||
if (error != -EAGAIN)
|
if (error != -EAGAIN)
|
||||||
return error;
|
return error;
|
||||||
error = gfs2_unlinked_inode_lookup(ip->i_inode.i_sb,
|
|
||||||
unlinked, &inode);
|
gfs2_process_unlinked_inode(ip->i_inode.i_sb, unlinked);
|
||||||
if (inode)
|
/* regardless of whether or not gfs2_process_unlinked_inode
|
||||||
iput(inode);
|
was successful, we don't want to repeat it again. */
|
||||||
|
last_unlinked = unlinked;
|
||||||
gfs2_log_flush(sdp, NULL);
|
gfs2_log_flush(sdp, NULL);
|
||||||
if (error == GLR_TRYFAILED)
|
error = 0;
|
||||||
error = 0;
|
|
||||||
goto try_again;
|
goto try_again;
|
||||||
}
|
}
|
||||||
|
/* no error, so we have the rgrp set in the inode's allocation. */
|
||||||
al->al_file = file;
|
al->al_file = file;
|
||||||
al->al_line = line;
|
al->al_line = line;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue