|
@@ -33,6 +33,8 @@
|
|
#include "xfs_trace.h"
|
|
#include "xfs_trace.h"
|
|
#include "xfs_attr_sf.h"
|
|
#include "xfs_attr_sf.h"
|
|
#include "xfs_da_format.h"
|
|
#include "xfs_da_format.h"
|
|
|
|
+#include "xfs_da_btree.h"
|
|
|
|
+#include "xfs_dir2_priv.h"
|
|
|
|
|
|
kmem_zone_t *xfs_ifork_zone;
|
|
kmem_zone_t *xfs_ifork_zone;
|
|
|
|
|
|
@@ -320,6 +322,7 @@ xfs_iformat_local(
|
|
int whichfork,
|
|
int whichfork,
|
|
int size)
|
|
int size)
|
|
{
|
|
{
|
|
|
|
+ int error;
|
|
|
|
|
|
/*
|
|
/*
|
|
* If the size is unreasonable, then something
|
|
* If the size is unreasonable, then something
|
|
@@ -336,6 +339,14 @@ xfs_iformat_local(
|
|
return -EFSCORRUPTED;
|
|
return -EFSCORRUPTED;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (S_ISDIR(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK) {
|
|
|
|
+ error = xfs_dir2_sf_verify(ip->i_mount,
|
|
|
|
+ (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip),
|
|
|
|
+ size);
|
|
|
|
+ if (error)
|
|
|
|
+ return error;
|
|
|
|
+ }
|
|
|
|
+
|
|
xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);
|
|
xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -856,7 +867,7 @@ xfs_iextents_copy(
|
|
* In these cases, the format always takes precedence, because the
|
|
* In these cases, the format always takes precedence, because the
|
|
* format indicates the current state of the fork.
|
|
* format indicates the current state of the fork.
|
|
*/
|
|
*/
|
|
-void
|
|
|
|
|
|
+int
|
|
xfs_iflush_fork(
|
|
xfs_iflush_fork(
|
|
xfs_inode_t *ip,
|
|
xfs_inode_t *ip,
|
|
xfs_dinode_t *dip,
|
|
xfs_dinode_t *dip,
|
|
@@ -866,6 +877,7 @@ xfs_iflush_fork(
|
|
char *cp;
|
|
char *cp;
|
|
xfs_ifork_t *ifp;
|
|
xfs_ifork_t *ifp;
|
|
xfs_mount_t *mp;
|
|
xfs_mount_t *mp;
|
|
|
|
+ int error;
|
|
static const short brootflag[2] =
|
|
static const short brootflag[2] =
|
|
{ XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
|
|
{ XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
|
|
static const short dataflag[2] =
|
|
static const short dataflag[2] =
|
|
@@ -874,7 +886,7 @@ xfs_iflush_fork(
|
|
{ XFS_ILOG_DEXT, XFS_ILOG_AEXT };
|
|
{ XFS_ILOG_DEXT, XFS_ILOG_AEXT };
|
|
|
|
|
|
if (!iip)
|
|
if (!iip)
|
|
- return;
|
|
|
|
|
|
+ return 0;
|
|
ifp = XFS_IFORK_PTR(ip, whichfork);
|
|
ifp = XFS_IFORK_PTR(ip, whichfork);
|
|
/*
|
|
/*
|
|
* This can happen if we gave up in iformat in an error path,
|
|
* This can happen if we gave up in iformat in an error path,
|
|
@@ -882,12 +894,19 @@ xfs_iflush_fork(
|
|
*/
|
|
*/
|
|
if (!ifp) {
|
|
if (!ifp) {
|
|
ASSERT(whichfork == XFS_ATTR_FORK);
|
|
ASSERT(whichfork == XFS_ATTR_FORK);
|
|
- return;
|
|
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
cp = XFS_DFORK_PTR(dip, whichfork);
|
|
cp = XFS_DFORK_PTR(dip, whichfork);
|
|
mp = ip->i_mount;
|
|
mp = ip->i_mount;
|
|
switch (XFS_IFORK_FORMAT(ip, whichfork)) {
|
|
switch (XFS_IFORK_FORMAT(ip, whichfork)) {
|
|
case XFS_DINODE_FMT_LOCAL:
|
|
case XFS_DINODE_FMT_LOCAL:
|
|
|
|
+ if (S_ISDIR(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK) {
|
|
|
|
+ error = xfs_dir2_sf_verify(mp,
|
|
|
|
+ (struct xfs_dir2_sf_hdr *)ifp->if_u1.if_data,
|
|
|
|
+ ifp->if_bytes);
|
|
|
|
+ if (error)
|
|
|
|
+ return error;
|
|
|
|
+ }
|
|
if ((iip->ili_fields & dataflag[whichfork]) &&
|
|
if ((iip->ili_fields & dataflag[whichfork]) &&
|
|
(ifp->if_bytes > 0)) {
|
|
(ifp->if_bytes > 0)) {
|
|
ASSERT(ifp->if_u1.if_data != NULL);
|
|
ASSERT(ifp->if_u1.if_data != NULL);
|
|
@@ -940,6 +959,7 @@ xfs_iflush_fork(
|
|
ASSERT(0);
|
|
ASSERT(0);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|