Message ID | 20240912064720.898600-1-gautham.ananthakrishna@oracle.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [RFC,V4,1/1] ocfs2: reserve space for inline xattr before attaching reflink tree | expand |
On Thu, 12 Sep 2024 06:47:20 +0000 Gautham Ananthakrishna <gautham.ananthakrishna@oracle.com> wrote: > One of our customers reported a crash and a corrupted ocfs2 filesystem. > +++ b/fs/ocfs2/refcounttree.c > @@ -25,6 +25,7 @@ > #include "namei.h" > #include "ocfs2_trace.h" > #include "file.h" > +#include "symlink.h" > > #include <linux/bio.h> > #include <linux/blkdev.h> > @@ -4155,8 +4156,9 @@ static int __ocfs2_reflink(struct dentry *old_dentry, > int ret; > struct inode *inode = d_inode(old_dentry); > struct buffer_head *new_bh = NULL; > + struct ocfs2_inode_info *oi = OCFS2_I(inode); > > - if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE) { > + if (oi->ip_flags & OCFS2_INODE_SYSTEM_FILE) { > ret = -EINVAL; > mlog_errno(ret); > goto out; > @@ -4182,6 +4184,26 @@ static int __ocfs2_reflink(struct dentry *old_dentry, > goto out_unlock; > } > > + if ((oi->ip_dyn_features & OCFS2_HAS_XATTR_FL) && > + (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)) { > + /* > + * Adjust extent record count to reserve space for extended attribute. > + * Inline data count had been adjusted in ocfs2_duplicate_inline_data(). > + */ > + struct ocfs2_inode_info *new_oi = OCFS2_I(new_inode); > + > + if (!(new_oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) && > + !(ocfs2_inode_is_fast_symlink(new_inode))) { > + struct ocfs2_dinode *new_di = new_bh->b_data; > + struct ocfs2_dinode *old_di = old_bh->b_data; fs/ocfs2/refcounttree.c: In function '__ocfs2_reflink': fs/ocfs2/refcounttree.c:4190:55: error: initialization of 'struct ocfs2_dinode *' from incompatible pointer type 'char *' [-Werror=incompatible-pointer-types] 4190 | struct ocfs2_dinode *new_di = new_bh->b_data; | ^~~~~~ fs/ocfs2/refcounttree.c:4191:55: error: initialization of 'struct ocfs2_dinode *' from incompatible pointer type 'char *' [-Werror=incompatible-pointer-types] 4191 | struct ocfs2_dinode *old_di = old_bh->b_data; | ^~~~~~ cc1: all warnings being treated as errors I could just add the typecasts, but that doesn't give me a tested patch :(
On 9/17/24 12:16 AM, Andrew Morton wrote: > On Thu, 12 Sep 2024 06:47:20 +0000 Gautham Ananthakrishna <gautham.ananthakrishna@oracle.com> wrote: > >> One of our customers reported a crash and a corrupted ocfs2 filesystem. >> +++ b/fs/ocfs2/refcounttree.c >> @@ -25,6 +25,7 @@ >> #include "namei.h" >> #include "ocfs2_trace.h" >> #include "file.h" >> +#include "symlink.h" >> >> #include <linux/bio.h> >> #include <linux/blkdev.h> >> @@ -4155,8 +4156,9 @@ static int __ocfs2_reflink(struct dentry *old_dentry, >> int ret; >> struct inode *inode = d_inode(old_dentry); >> struct buffer_head *new_bh = NULL; >> + struct ocfs2_inode_info *oi = OCFS2_I(inode); >> >> - if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE) { >> + if (oi->ip_flags & OCFS2_INODE_SYSTEM_FILE) { >> ret = -EINVAL; >> mlog_errno(ret); >> goto out; >> @@ -4182,6 +4184,26 @@ static int __ocfs2_reflink(struct dentry *old_dentry, >> goto out_unlock; >> } >> >> + if ((oi->ip_dyn_features & OCFS2_HAS_XATTR_FL) && >> + (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)) { >> + /* >> + * Adjust extent record count to reserve space for extended attribute. >> + * Inline data count had been adjusted in ocfs2_duplicate_inline_data(). >> + */ >> + struct ocfs2_inode_info *new_oi = OCFS2_I(new_inode); >> + >> + if (!(new_oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) && >> + !(ocfs2_inode_is_fast_symlink(new_inode))) { >> + struct ocfs2_dinode *new_di = new_bh->b_data; >> + struct ocfs2_dinode *old_di = old_bh->b_data; > > fs/ocfs2/refcounttree.c: In function '__ocfs2_reflink': > fs/ocfs2/refcounttree.c:4190:55: error: initialization of 'struct ocfs2_dinode *' from incompatible pointer type 'char *' [-Werror=incompatible-pointer-types] > 4190 | struct ocfs2_dinode *new_di = new_bh->b_data; > | ^~~~~~ > fs/ocfs2/refcounttree.c:4191:55: error: initialization of 'struct ocfs2_dinode *' from incompatible pointer type 'char *' [-Werror=incompatible-pointer-types] > 4191 | struct ocfs2_dinode *old_di = old_bh->b_data; > | ^~~~~~ > cc1: all warnings being treated as errors > > I could just add the typecasts, but that doesn't give me a tested patch :( > Oops, sorry for missing this when reviewing. Hi Gautham, could you please add the missing typecasts and confirm it? Thanks, Joseph
I have sent a V5 version addressing the warnings. I believe this requires a new RB as the code has changed (even though trivial). Could you please review this. Thanks, Gautham. -----Original Message----- From: Joseph Qi <joseph.qi@linux.alibaba.com> Sent: Wednesday, September 18, 2024 7:27 AM To: Andrew Morton <akpm@linux-foundation.org>; Gautham Ananthakrishna <gautham.ananthakrishna@oracle.com> Cc: Junxiao Bi <junxiao.bi@oracle.com>; Rajesh Sivaramasubramaniom <rajesh.sivaramasubramaniom@oracle.com>; ocfs2-devel@lists.linux.dev; linux-kernel@vger.kernel.org Subject: Re: [PATCH RFC V4 1/1] ocfs2: reserve space for inline xattr before attaching reflink tree On 9/17/24 12:16 AM, Andrew Morton wrote: > On Thu, 12 Sep 2024 06:47:20 +0000 Gautham Ananthakrishna <gautham.ananthakrishna@oracle.com> wrote: > >> One of our customers reported a crash and a corrupted ocfs2 filesystem. >> +++ b/fs/ocfs2/refcounttree.c >> @@ -25,6 +25,7 @@ >> #include "namei.h" >> #include "ocfs2_trace.h" >> #include "file.h" >> +#include "symlink.h" >> >> #include <linux/bio.h> >> #include <linux/blkdev.h> >> @@ -4155,8 +4156,9 @@ static int __ocfs2_reflink(struct dentry *old_dentry, >> int ret; >> struct inode *inode = d_inode(old_dentry); >> struct buffer_head *new_bh = NULL; >> + struct ocfs2_inode_info *oi = OCFS2_I(inode); >> >> - if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE) { >> + if (oi->ip_flags & OCFS2_INODE_SYSTEM_FILE) { >> ret = -EINVAL; >> mlog_errno(ret); >> goto out; >> @@ -4182,6 +4184,26 @@ static int __ocfs2_reflink(struct dentry *old_dentry, >> goto out_unlock; >> } >> >> + if ((oi->ip_dyn_features & OCFS2_HAS_XATTR_FL) && >> + (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)) { >> + /* >> + * Adjust extent record count to reserve space for extended attribute. >> + * Inline data count had been adjusted in ocfs2_duplicate_inline_data(). >> + */ >> + struct ocfs2_inode_info *new_oi = OCFS2_I(new_inode); >> + >> + if (!(new_oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) && >> + !(ocfs2_inode_is_fast_symlink(new_inode))) { >> + struct ocfs2_dinode *new_di = new_bh->b_data; >> + struct ocfs2_dinode *old_di = old_bh->b_data; > > fs/ocfs2/refcounttree.c: In function '__ocfs2_reflink': > fs/ocfs2/refcounttree.c:4190:55: error: initialization of 'struct ocfs2_dinode *' from incompatible pointer type 'char *' [-Werror=incompatible-pointer-types] > 4190 | struct ocfs2_dinode *new_di = new_bh->b_data; > | ^~~~~~ > fs/ocfs2/refcounttree.c:4191:55: error: initialization of 'struct ocfs2_dinode *' from incompatible pointer type 'char *' [-Werror=incompatible-pointer-types] > 4191 | struct ocfs2_dinode *old_di = old_bh->b_data; > | ^~~~~~ > cc1: all warnings being treated as errors > > I could just add the typecasts, but that doesn't give me a tested patch :( > Oops, sorry for missing this when reviewing. Hi Gautham, could you please add the missing typecasts and confirm it? Thanks, Joseph
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 3f80a56d0d60..05105d271fc8 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -25,6 +25,7 @@ #include "namei.h" #include "ocfs2_trace.h" #include "file.h" +#include "symlink.h" #include <linux/bio.h> #include <linux/blkdev.h> @@ -4155,8 +4156,9 @@ static int __ocfs2_reflink(struct dentry *old_dentry, int ret; struct inode *inode = d_inode(old_dentry); struct buffer_head *new_bh = NULL; + struct ocfs2_inode_info *oi = OCFS2_I(inode); - if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE) { + if (oi->ip_flags & OCFS2_INODE_SYSTEM_FILE) { ret = -EINVAL; mlog_errno(ret); goto out; @@ -4182,6 +4184,26 @@ static int __ocfs2_reflink(struct dentry *old_dentry, goto out_unlock; } + if ((oi->ip_dyn_features & OCFS2_HAS_XATTR_FL) && + (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)) { + /* + * Adjust extent record count to reserve space for extended attribute. + * Inline data count had been adjusted in ocfs2_duplicate_inline_data(). + */ + struct ocfs2_inode_info *new_oi = OCFS2_I(new_inode); + + if (!(new_oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) && + !(ocfs2_inode_is_fast_symlink(new_inode))) { + struct ocfs2_dinode *new_di = new_bh->b_data; + struct ocfs2_dinode *old_di = old_bh->b_data; + struct ocfs2_extent_list *el = &new_di->id2.i_list; + int inline_size = le16_to_cpu(old_di->i_xattr_inline_size); + + le16_add_cpu(&el->l_count, -(inline_size / + sizeof(struct ocfs2_extent_rec))); + } + } + ret = ocfs2_create_reflink_node(inode, old_bh, new_inode, new_bh, preserve); if (ret) { @@ -4189,7 +4211,7 @@ static int __ocfs2_reflink(struct dentry *old_dentry, goto inode_unlock; } - if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_XATTR_FL) { + if (oi->ip_dyn_features & OCFS2_HAS_XATTR_FL) { ret = ocfs2_reflink_xattrs(inode, old_bh, new_inode, new_bh, preserve); diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 3b81213ed7b8..a9f716ec89e2 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -6511,16 +6511,7 @@ static int ocfs2_reflink_xattr_inline(struct ocfs2_xattr_reflink *args) } new_oi = OCFS2_I(args->new_inode); - /* - * Adjust extent record count to reserve space for extended attribute. - * Inline data count had been adjusted in ocfs2_duplicate_inline_data(). - */ - if (!(new_oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) && - !(ocfs2_inode_is_fast_symlink(args->new_inode))) { - struct ocfs2_extent_list *el = &new_di->id2.i_list; - le16_add_cpu(&el->l_count, -(inline_size / - sizeof(struct ocfs2_extent_rec))); - } + spin_lock(&new_oi->ip_lock); new_oi->ip_dyn_features |= OCFS2_HAS_XATTR_FL | OCFS2_INLINE_XATTR_FL; new_di->i_dyn_features = cpu_to_le16(new_oi->ip_dyn_features);