aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/gfs2/ops_file.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index c2dbc300a50c..cf724800e0e9 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -611,8 +611,10 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
611 611
612 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); 612 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
613 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); 613 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
614 if (error) 614 if (error) {
615 gfs2_holder_uninit(&gh);
615 return error; 616 return error;
617 }
616 618
617 flags = ip->i_di.di_flags; 619 flags = ip->i_di.di_flags;
618 new_flags = (flags & ~mask) | (reqflags & mask); 620 new_flags = (flags & ~mask) | (reqflags & mask);
@@ -635,9 +637,14 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
635 goto out; 637 goto out;
636 if (IS_APPEND(inode) && (new_flags & GFS2_DIF_APPENDONLY)) 638 if (IS_APPEND(inode) && (new_flags & GFS2_DIF_APPENDONLY))
637 goto out; 639 goto out;
638 error = gfs2_repermission(inode, MAY_WRITE, NULL); 640 if (((new_flags ^ flags) & GFS2_DIF_IMMUTABLE) &&
639 if (error) 641 !capable(CAP_LINUX_IMMUTABLE))
640 goto out; 642 goto out;
643 if (!IS_IMMUTABLE(inode)) {
644 error = gfs2_repermission(inode, MAY_WRITE, NULL);
645 if (error)
646 goto out;
647 }
641 648
642 error = gfs2_trans_begin(sdp, RES_DINODE, 0); 649 error = gfs2_trans_begin(sdp, RES_DINODE, 0);
643 if (error) 650 if (error)