Commit 220b5284 authored by Nathan Scott's avatar Nathan Scott

[XFS] Dynamically allocate vattr in places it makes sense to do so, to

reduce stack use.  Also re-use vattr in some places so that multiple
copies are not held on-stack.

SGI-PV: 947312
SGI-Modid: xfs-linux-melb:xfs-kern:25369a
Signed-off-by: default avatarNathan Scott <nathans@sgi.com>
parent 9b94c2ed
...@@ -420,7 +420,7 @@ linvfs_file_mmap( ...@@ -420,7 +420,7 @@ linvfs_file_mmap(
{ {
struct inode *ip = filp->f_dentry->d_inode; struct inode *ip = filp->f_dentry->d_inode;
vnode_t *vp = LINVFS_GET_VP(ip); vnode_t *vp = LINVFS_GET_VP(ip);
vattr_t va = { .va_mask = XFS_AT_UPDATIME }; vattr_t *vattr;
int error; int error;
vma->vm_ops = &linvfs_file_vm_ops; vma->vm_ops = &linvfs_file_vm_ops;
...@@ -431,9 +431,14 @@ linvfs_file_mmap( ...@@ -431,9 +431,14 @@ linvfs_file_mmap(
} }
#endif /* CONFIG_XFS_DMAPI */ #endif /* CONFIG_XFS_DMAPI */
VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error); vattr = kmalloc(sizeof(*vattr), GFP_KERNEL);
if (!error) if (unlikely(!vattr))
vn_revalidate(vp); /* update Linux inode flags */ return -ENOMEM;
vattr->va_mask = XFS_AT_UPDATIME;
VOP_SETATTR(vp, vattr, XFS_AT_UPDATIME, NULL, error);
if (likely(!error))
__vn_revalidate(vp, vattr); /* update flags */
kfree(vattr);
return 0; return 0;
} }
......
...@@ -1160,105 +1160,129 @@ xfs_ioc_xattr( ...@@ -1160,105 +1160,129 @@ xfs_ioc_xattr(
void __user *arg) void __user *arg)
{ {
struct fsxattr fa; struct fsxattr fa;
vattr_t va; struct vattr *vattr;
int error; int error = 0;
int attr_flags; int attr_flags;
unsigned int flags; unsigned int flags;
vattr = kmalloc(sizeof(*vattr), GFP_KERNEL);
if (unlikely(!vattr))
return -ENOMEM;
switch (cmd) { switch (cmd) {
case XFS_IOC_FSGETXATTR: { case XFS_IOC_FSGETXATTR: {
va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
XFS_AT_NEXTENTS | XFS_AT_PROJID; XFS_AT_NEXTENTS | XFS_AT_PROJID;
VOP_GETATTR(vp, &va, 0, NULL, error); VOP_GETATTR(vp, vattr, 0, NULL, error);
if (error) if (unlikely(error)) {
return -error; error = -error;
break;
}
fa.fsx_xflags = va.va_xflags; fa.fsx_xflags = vattr->va_xflags;
fa.fsx_extsize = va.va_extsize; fa.fsx_extsize = vattr->va_extsize;
fa.fsx_nextents = va.va_nextents; fa.fsx_nextents = vattr->va_nextents;
fa.fsx_projid = va.va_projid; fa.fsx_projid = vattr->va_projid;
if (copy_to_user(arg, &fa, sizeof(fa))) if (copy_to_user(arg, &fa, sizeof(fa))) {
return -XFS_ERROR(EFAULT); error = -EFAULT;
return 0; break;
}
break;
} }
case XFS_IOC_FSSETXATTR: { case XFS_IOC_FSSETXATTR: {
if (copy_from_user(&fa, arg, sizeof(fa))) if (copy_from_user(&fa, arg, sizeof(fa))) {
return -XFS_ERROR(EFAULT); error = -EFAULT;
break;
}
attr_flags = 0; attr_flags = 0;
if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
attr_flags |= ATTR_NONBLOCK; attr_flags |= ATTR_NONBLOCK;
va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID; vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID;
va.va_xflags = fa.fsx_xflags; vattr->va_xflags = fa.fsx_xflags;
va.va_extsize = fa.fsx_extsize; vattr->va_extsize = fa.fsx_extsize;
va.va_projid = fa.fsx_projid; vattr->va_projid = fa.fsx_projid;
VOP_SETATTR(vp, &va, attr_flags, NULL, error); VOP_SETATTR(vp, vattr, attr_flags, NULL, error);
if (!error) if (likely(!error))
vn_revalidate(vp); /* update Linux inode flags */ __vn_revalidate(vp, vattr); /* update flags */
return -error; error = -error;
break;
} }
case XFS_IOC_FSGETXATTRA: { case XFS_IOC_FSGETXATTRA: {
va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
XFS_AT_ANEXTENTS | XFS_AT_PROJID; XFS_AT_ANEXTENTS | XFS_AT_PROJID;
VOP_GETATTR(vp, &va, 0, NULL, error); VOP_GETATTR(vp, vattr, 0, NULL, error);
if (error) if (unlikely(error)) {
return -error; error = -error;
break;
}
fa.fsx_xflags = va.va_xflags; fa.fsx_xflags = vattr->va_xflags;
fa.fsx_extsize = va.va_extsize; fa.fsx_extsize = vattr->va_extsize;
fa.fsx_nextents = va.va_anextents; fa.fsx_nextents = vattr->va_anextents;
fa.fsx_projid = va.va_projid; fa.fsx_projid = vattr->va_projid;
if (copy_to_user(arg, &fa, sizeof(fa))) if (copy_to_user(arg, &fa, sizeof(fa))) {
return -XFS_ERROR(EFAULT); error = -EFAULT;
return 0; break;
}
break;
} }
case XFS_IOC_GETXFLAGS: { case XFS_IOC_GETXFLAGS: {
flags = xfs_di2lxflags(ip->i_d.di_flags); flags = xfs_di2lxflags(ip->i_d.di_flags);
if (copy_to_user(arg, &flags, sizeof(flags))) if (copy_to_user(arg, &flags, sizeof(flags)))
return -XFS_ERROR(EFAULT); error = -EFAULT;
return 0; break;
} }
case XFS_IOC_SETXFLAGS: { case XFS_IOC_SETXFLAGS: {
if (copy_from_user(&flags, arg, sizeof(flags))) if (copy_from_user(&flags, arg, sizeof(flags))) {
return -XFS_ERROR(EFAULT); error = -EFAULT;
break;
}
if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \ if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \
LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \ LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \
LINUX_XFLAG_SYNC)) LINUX_XFLAG_SYNC)) {
return -XFS_ERROR(EOPNOTSUPP); error = -EOPNOTSUPP;
break;
}
attr_flags = 0; attr_flags = 0;
if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
attr_flags |= ATTR_NONBLOCK; attr_flags |= ATTR_NONBLOCK;
va.va_mask = XFS_AT_XFLAGS; vattr->va_mask = XFS_AT_XFLAGS;
va.va_xflags = xfs_merge_ioc_xflags(flags, vattr->va_xflags = xfs_merge_ioc_xflags(flags,
xfs_ip2xflags(ip)); xfs_ip2xflags(ip));
VOP_SETATTR(vp, &va, attr_flags, NULL, error); VOP_SETATTR(vp, vattr, attr_flags, NULL, error);
if (!error) if (likely(!error))
vn_revalidate(vp); /* update Linux inode flags */ __vn_revalidate(vp, vattr); /* update flags */
return -error; error = -error;
break;
} }
case XFS_IOC_GETVERSION: { case XFS_IOC_GETVERSION: {
flags = LINVFS_GET_IP(vp)->i_generation; flags = LINVFS_GET_IP(vp)->i_generation;
if (copy_to_user(arg, &flags, sizeof(flags))) if (copy_to_user(arg, &flags, sizeof(flags)))
return -XFS_ERROR(EFAULT); error = -EFAULT;
return 0; break;
} }
default: default:
return -ENOTTY; error = -ENOTTY;
break;
} }
kfree(vattr);
return error;
} }
STATIC int STATIC int
......
...@@ -198,22 +198,22 @@ xfs_ichgtime_fast( ...@@ -198,22 +198,22 @@ xfs_ichgtime_fast(
* Pull the link count and size up from the xfs inode to the linux inode * Pull the link count and size up from the xfs inode to the linux inode
*/ */
STATIC void STATIC void
validate_fields( __linvfs_validate_fields(
struct inode *ip) struct inode *ip,
struct vattr *vattr)
{ {
vnode_t *vp = LINVFS_GET_VP(ip); vnode_t *vp = LINVFS_GET_VP(ip);
vattr_t va;
int error; int error;
va.va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS; vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS;
VOP_GETATTR(vp, &va, ATTR_LAZY, NULL, error); VOP_GETATTR(vp, vattr, ATTR_LAZY, NULL, error);
if (likely(!error)) { if (likely(!error)) {
ip->i_nlink = va.va_nlink; ip->i_nlink = vattr->va_nlink;
ip->i_blocks = va.va_nblocks; ip->i_blocks = vattr->va_nblocks;
/* we're under i_mutex so i_size can't change under us */ /* we're under i_sem so i_size can't change under us */
if (i_size_read(ip) != va.va_size) if (i_size_read(ip) != vattr->va_size)
i_size_write(ip, va.va_size); i_size_write(ip, vattr->va_size);
} }
} }
...@@ -224,7 +224,7 @@ validate_fields( ...@@ -224,7 +224,7 @@ validate_fields(
* inode, of course, such that log replay can't cause these to be lost). * inode, of course, such that log replay can't cause these to be lost).
*/ */
STATIC int STATIC int
linvfs_init_security( __linvfs_init_security(
struct vnode *vp, struct vnode *vp,
struct inode *dir) struct inode *dir)
{ {
...@@ -257,23 +257,23 @@ linvfs_init_security( ...@@ -257,23 +257,23 @@ linvfs_init_security(
* XXX(hch): nfsd is broken, better fix it instead. * XXX(hch): nfsd is broken, better fix it instead.
*/ */
STATIC inline int STATIC inline int
has_fs_struct(struct task_struct *task) __linvfs_has_fs_struct(struct task_struct *task)
{ {
return (task->fs != init_task.fs); return (task->fs != init_task.fs);
} }
STATIC inline void STATIC inline void
cleanup_inode( __linvfs_cleanup_inode(
vnode_t *dvp, vnode_t *dvp,
vnode_t *vp, vnode_t *vp,
struct dentry *dentry, struct dentry *dentry,
int mode) int mode)
{ {
struct dentry teardown = {}; struct dentry teardown = {};
int err2; int error;
/* Oh, the horror. /* Oh, the horror.
* If we can't add the ACL or we fail in * If we can't add the ACL or we fail in
* linvfs_init_security we must back out. * linvfs_init_security we must back out.
* ENOSPC can hit here, among other things. * ENOSPC can hit here, among other things.
*/ */
...@@ -281,9 +281,9 @@ cleanup_inode( ...@@ -281,9 +281,9 @@ cleanup_inode(
teardown.d_name = dentry->d_name; teardown.d_name = dentry->d_name;
if (S_ISDIR(mode)) if (S_ISDIR(mode))
VOP_RMDIR(dvp, &teardown, NULL, err2); VOP_RMDIR(dvp, &teardown, NULL, error);
else else
VOP_REMOVE(dvp, &teardown, NULL, err2); VOP_REMOVE(dvp, &teardown, NULL, error);
VN_RELE(vp); VN_RELE(vp);
} }
...@@ -295,7 +295,7 @@ linvfs_mknod( ...@@ -295,7 +295,7 @@ linvfs_mknod(
dev_t rdev) dev_t rdev)
{ {
struct inode *ip; struct inode *ip;
vattr_t va; vattr_t *vattr;
vnode_t *vp = NULL, *dvp = LINVFS_GET_VP(dir); vnode_t *vp = NULL, *dvp = LINVFS_GET_VP(dir);
xfs_acl_t *default_acl = NULL; xfs_acl_t *default_acl = NULL;
attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS;
...@@ -305,70 +305,76 @@ linvfs_mknod( ...@@ -305,70 +305,76 @@ linvfs_mknod(
* Irix uses Missed'em'V split, but doesn't want to see * Irix uses Missed'em'V split, but doesn't want to see
* the upper 5 bits of (14bit) major. * the upper 5 bits of (14bit) major.
*/ */
if (!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff) if (unlikely(!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff))
return -EINVAL; return -EINVAL;
if (test_default_acl && test_default_acl(dvp)) { vattr = kmalloc(sizeof(*vattr), GFP_KERNEL);
if (!_ACL_ALLOC(default_acl)) if (unlikely(!vattr))
return -ENOMEM;
if (unlikely(test_default_acl && test_default_acl(dvp))) {
if (!_ACL_ALLOC(default_acl)) {
kfree(vattr);
return -ENOMEM; return -ENOMEM;
}
if (!_ACL_GET_DEFAULT(dvp, default_acl)) { if (!_ACL_GET_DEFAULT(dvp, default_acl)) {
_ACL_FREE(default_acl); _ACL_FREE(default_acl);
default_acl = NULL; default_acl = NULL;
} }
} }
if (IS_POSIXACL(dir) && !default_acl && has_fs_struct(current)) if (IS_POSIXACL(dir) && !default_acl && __linvfs_has_fs_struct(current))
mode &= ~current->fs->umask; mode &= ~current->fs->umask;
memset(&va, 0, sizeof(va)); memset(vattr, 0, sizeof(*vattr));
va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; vattr->va_mask = XFS_AT_TYPE|XFS_AT_MODE;
va.va_mode = mode; vattr->va_mode = mode;
switch (mode & S_IFMT) { switch (mode & S_IFMT) {
case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
va.va_rdev = sysv_encode_dev(rdev); vattr->va_rdev = sysv_encode_dev(rdev);
va.va_mask |= XFS_AT_RDEV; vattr->va_mask |= XFS_AT_RDEV;
/*FALLTHROUGH*/ /*FALLTHROUGH*/
case S_IFREG: case S_IFREG:
VOP_CREATE(dvp, dentry, &va, &vp, NULL, error); VOP_CREATE(dvp, dentry, vattr, &vp, NULL, error);
break; break;
case S_IFDIR: case S_IFDIR:
VOP_MKDIR(dvp, dentry, &va, &vp, NULL, error); VOP_MKDIR(dvp, dentry, vattr, &vp, NULL, error);
break; break;
default: default:
error = EINVAL; error = EINVAL;
break; break;
} }
if (!error) if (unlikely(!error)) {
{ error = __linvfs_init_security(vp, dir);
error = linvfs_init_security(vp, dir);
if (error) if (error)
cleanup_inode(dvp, vp, dentry, mode); __linvfs_cleanup_inode(dvp, vp, dentry, mode);
} }
if (default_acl) { if (unlikely(default_acl)) {
if (!error) { if (!error) {
error = _ACL_INHERIT(vp, &va, default_acl); error = _ACL_INHERIT(vp, vattr, default_acl);
if (!error) if (!error)
VMODIFY(vp); VMODIFY(vp);
else else
cleanup_inode(dvp, vp, dentry, mode); __linvfs_cleanup_inode(dvp, vp, dentry, mode);
} }
_ACL_FREE(default_acl); _ACL_FREE(default_acl);
} }
if (!error) { if (likely(!error)) {
ASSERT(vp); ASSERT(vp);
ip = LINVFS_GET_IP(vp); ip = LINVFS_GET_IP(vp);
if (S_ISCHR(mode) || S_ISBLK(mode)) if (S_ISCHR(mode) || S_ISBLK(mode))
ip->i_rdev = rdev; ip->i_rdev = rdev;
else if (S_ISDIR(mode)) else if (S_ISDIR(mode))
validate_fields(ip); __linvfs_validate_fields(ip, vattr);
d_instantiate(dentry, ip); d_instantiate(dentry, ip);
validate_fields(dir); __linvfs_validate_fields(dir, vattr);
} }
kfree(vattr);
return -error; return -error;
} }
...@@ -423,22 +429,28 @@ linvfs_link( ...@@ -423,22 +429,28 @@ linvfs_link(
struct inode *ip; /* inode of guy being linked to */ struct inode *ip; /* inode of guy being linked to */
vnode_t *tdvp; /* target directory for new name/link */ vnode_t *tdvp; /* target directory for new name/link */
vnode_t *vp; /* vp of name being linked */ vnode_t *vp; /* vp of name being linked */
vattr_t *vattr;
int error; int error;
ip = old_dentry->d_inode; /* inode being linked to */ ip = old_dentry->d_inode; /* inode being linked to */
if (S_ISDIR(ip->i_mode)) if (S_ISDIR(ip->i_mode))
return -EPERM; return -EPERM;
vattr = kmalloc(sizeof(*vattr), GFP_KERNEL);
if (unlikely(!vattr))
return -ENOMEM;
tdvp = LINVFS_GET_VP(dir); tdvp = LINVFS_GET_VP(dir);
vp = LINVFS_GET_VP(ip); vp = LINVFS_GET_VP(ip);
VOP_LINK(tdvp, vp, dentry, NULL, error); VOP_LINK(tdvp, vp, dentry, NULL, error);
if (!error) { if (likely(!error)) {
VMODIFY(tdvp); VMODIFY(tdvp);
VN_HOLD(vp); VN_HOLD(vp);
validate_fields(ip); __linvfs_validate_fields(ip, vattr);
d_instantiate(dentry, ip); d_instantiate(dentry, ip);
} }
kfree(vattr);
return -error; return -error;
} }
...@@ -449,17 +461,22 @@ linvfs_unlink( ...@@ -449,17 +461,22 @@ linvfs_unlink(
{ {
struct inode *inode; struct inode *inode;
vnode_t *dvp; /* directory containing name to remove */ vnode_t *dvp; /* directory containing name to remove */
vattr_t *vattr;
int error; int error;
vattr = kmalloc(sizeof(*vattr), GFP_KERNEL);
if (unlikely(!vattr))
return -ENOMEM;
inode = dentry->d_inode; inode = dentry->d_inode;
dvp = LINVFS_GET_VP(dir); dvp = LINVFS_GET_VP(dir);
VOP_REMOVE(dvp, dentry, NULL, error); VOP_REMOVE(dvp, dentry, NULL, error);
if (!error) { if (likely(!error)) {
validate_fields(dir); /* For size only */ __linvfs_validate_fields(dir, vattr); /* size needs update */
validate_fields(inode); __linvfs_validate_fields(inode, vattr);
} }
kfree(vattr);
return -error; return -error;
} }
...@@ -470,7 +487,7 @@ linvfs_symlink( ...@@ -470,7 +487,7 @@ linvfs_symlink(
const char *symname) const char *symname)
{ {
struct inode *ip; struct inode *ip;
vattr_t va; vattr_t *vattr;
vnode_t *dvp; /* directory containing name of symlink */ vnode_t *dvp; /* directory containing name of symlink */
vnode_t *cvp; /* used to lookup symlink to put in dentry */ vnode_t *cvp; /* used to lookup symlink to put in dentry */
int error; int error;
...@@ -478,22 +495,27 @@ linvfs_symlink( ...@@ -478,22 +495,27 @@ linvfs_symlink(
dvp = LINVFS_GET_VP(dir); dvp = LINVFS_GET_VP(dir);
cvp = NULL; cvp = NULL;
memset(&va, 0, sizeof(va)); vattr = kmalloc(sizeof(*vattr), GFP_KERNEL);
va.va_mode = S_IFLNK | if (unlikely(!vattr))
return -ENOMEM;
memset(vattr, 0, sizeof(*vattr));
vattr->va_mode = S_IFLNK |
(irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO); (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO);
va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; vattr->va_mask = XFS_AT_TYPE|XFS_AT_MODE;
error = 0; error = 0;
VOP_SYMLINK(dvp, dentry, &va, (char *)symname, &cvp, NULL, error); VOP_SYMLINK(dvp, dentry, vattr, (char *)symname, &cvp, NULL, error);
if (likely(!error && cvp)) { if (likely(!error && cvp)) {
error = linvfs_init_security(cvp, dir); error = __linvfs_init_security(cvp, dir);
if (likely(!error)) { if (likely(!error)) {
ip = LINVFS_GET_IP(cvp); ip = LINVFS_GET_IP(cvp);
d_instantiate(dentry, ip); d_instantiate(dentry, ip);
validate_fields(dir); __linvfs_validate_fields(dir, vattr);
validate_fields(ip); __linvfs_validate_fields(ip, vattr);
} }
} }
kfree(vattr);
return -error; return -error;
} }
...@@ -504,13 +526,19 @@ linvfs_rmdir( ...@@ -504,13 +526,19 @@ linvfs_rmdir(
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
vnode_t *dvp = LINVFS_GET_VP(dir); vnode_t *dvp = LINVFS_GET_VP(dir);
vattr_t *vattr;
int error; int error;
vattr = kmalloc(sizeof(*vattr), GFP_KERNEL);
if (unlikely(!vattr))
return -ENOMEM;
VOP_RMDIR(dvp, dentry, NULL, error); VOP_RMDIR(dvp, dentry, NULL, error);
if (!error) { if (likely(!error)) {
validate_fields(inode); __linvfs_validate_fields(inode, vattr);
validate_fields(dir); __linvfs_validate_fields(dir, vattr);
} }
kfree(vattr);
return -error; return -error;
} }
...@@ -524,22 +552,26 @@ linvfs_rename( ...@@ -524,22 +552,26 @@ linvfs_rename(
struct inode *new_inode = ndentry->d_inode; struct inode *new_inode = ndentry->d_inode;
vnode_t *fvp; /* from directory */ vnode_t *fvp; /* from directory */
vnode_t *tvp; /* target directory */ vnode_t *tvp; /* target directory */
vattr_t *vattr;
int error; int error;
vattr = kmalloc(sizeof(*vattr), GFP_KERNEL);
if (unlikely(!vattr))
return -ENOMEM;
fvp = LINVFS_GET_VP(odir); fvp = LINVFS_GET_VP(odir);
tvp = LINVFS_GET_VP(ndir); tvp = LINVFS_GET_VP(ndir);
VOP_RENAME(fvp, odentry, tvp, ndentry, NULL, error); VOP_RENAME(fvp, odentry, tvp, ndentry, NULL, error);
if (error) if (likely(!error)) {
return -error; if (new_inode)
__linvfs_validate_fields(new_inode, vattr);
if (new_inode) __linvfs_validate_fields(odir, vattr);
validate_fields(new_inode); if (ndir != odir)
__linvfs_validate_fields(ndir, vattr);
validate_fields(odir); }
if (ndir != odir) kfree(vattr);
validate_fields(ndir); return -error;
return 0;
} }
/* /*
...@@ -653,11 +685,10 @@ linvfs_setattr( ...@@ -653,11 +685,10 @@ linvfs_setattr(
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
unsigned int ia_valid = attr->ia_valid; unsigned int ia_valid = attr->ia_valid;
vnode_t *vp = LINVFS_GET_VP(inode); vnode_t *vp = LINVFS_GET_VP(inode);
vattr_t vattr; vattr_t vattr = { 0 };
int flags = 0; int flags = 0;
int error; int error;
memset(&vattr, 0, sizeof(vattr_t));
if (ia_valid & ATTR_UID) { if (ia_valid & ATTR_UID) {
vattr.va_mask |= XFS_AT_UID; vattr.va_mask |= XFS_AT_UID;
vattr.va_uid = attr->ia_uid; vattr.va_uid = attr->ia_uid;
...@@ -699,10 +730,9 @@ linvfs_setattr( ...@@ -699,10 +730,9 @@ linvfs_setattr(
#endif #endif
VOP_SETATTR(vp, &vattr, flags, NULL, error); VOP_SETATTR(vp, &vattr, flags, NULL, error);
if (error) if (likely(!error))
return -error; __vn_revalidate(vp, &vattr);
vn_revalidate(vp); return -error;
return error;
} }
STATIC void STATIC void
......
...@@ -83,7 +83,7 @@ vn_initialize( ...@@ -83,7 +83,7 @@ vn_initialize(
vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP); vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
#endif /* XFS_VNODE_TRACE */ #endif /* XFS_VNODE_TRACE */
vn_trace_exit(vp, "vn_initialize", (inst_t *)__return_address); vn_trace_exit(vp, __FUNCTION__, (inst_t *)__return_address);
return vp; return vp;
} }
...@@ -129,24 +129,31 @@ vn_revalidate_core( ...@@ -129,24 +129,31 @@ vn_revalidate_core(
* Revalidate the Linux inode from the vnode. * Revalidate the Linux inode from the vnode.
*/ */
int int
vn_revalidate( __vn_revalidate(
struct vnode *vp) struct vnode *vp,
struct vattr *vattr)
{ {
vattr_t va;
int error; int error;
vn_trace_entry(vp, "vn_revalidate", (inst_t *)__return_address); vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
ASSERT(vp->v_fbhv != NULL); vattr->va_mask = XFS_AT_STAT | XFS_AT_XFLAGS;
VOP_GETATTR(vp, vattr, 0, NULL, error);
va.va_mask = XFS_AT_STAT|XFS_AT_XFLAGS; if (likely(!error)) {
VOP_GETATTR(vp, &va, 0, NULL, error); vn_revalidate_core(vp, vattr);
if (!error) {
vn_revalidate_core(vp, &va);
VUNMODIFY(vp); VUNMODIFY(vp);
} }
return -error; return -error;
} }
int
vn_revalidate(
struct vnode *vp)
{
vattr_t vattr;
return __vn_revalidate(vp, &vattr);
}
/* /*
* Add a reference to a referenced vnode. * Add a reference to a referenced vnode.
*/ */
......
...@@ -490,6 +490,7 @@ typedef struct vnode_map { ...@@ -490,6 +490,7 @@ typedef struct vnode_map {
(vmap).v_ino = (vp)->v_inode.i_ino; } (vmap).v_ino = (vp)->v_inode.i_ino; }
extern int vn_revalidate(struct vnode *); extern int vn_revalidate(struct vnode *);
extern int __vn_revalidate(struct vnode *, vattr_t *);
extern void vn_revalidate_core(struct vnode *, vattr_t *); extern void vn_revalidate_core(struct vnode *, vattr_t *);
extern void vn_iowait(struct vnode *vp); extern void vn_iowait(struct vnode *vp);
......
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