Commit f16a5e34 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 110b9384 7df0e039
...@@ -236,10 +236,14 @@ static int gfs2_xattr_system_get(struct dentry *dentry, const char *name, ...@@ -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) ...@@ -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) ...@@ -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 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, ...@@ -242,34 +242,38 @@ struct inode *gfs2_inode_lookup(struct super_block *sb,
} }
/** /**
* 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, ...@@ -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, ...@@ -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 @@ int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr, ...@@ -321,7 +324,8 @@ int gfs2_unlinked_inode_lookup(struct super_block *sb, u64 no_addr,
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, ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) ...@@ -1210,22 +1209,27 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
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;
......
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