diff options
Diffstat (limited to 'fs/xfs/xfs_attr.c')
-rw-r--r-- | fs/xfs/xfs_attr.c | 117 |
1 files changed, 64 insertions, 53 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index a41ad3a5e554..ce9f673f2b4c 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of version 2 of the GNU General Public License as | 5 | * under the terms of version 2 of the GNU General Public License as |
@@ -200,40 +200,18 @@ xfs_attr_get(bhv_desc_t *bdp, char *name, char *value, int *valuelenp, | |||
200 | return(error); | 200 | return(error); |
201 | } | 201 | } |
202 | 202 | ||
203 | /*ARGSUSED*/ | 203 | int |
204 | int /* error */ | 204 | xfs_attr_set_int(xfs_inode_t *dp, char *name, int namelen, |
205 | xfs_attr_set(bhv_desc_t *bdp, char *name, char *value, int valuelen, int flags, | 205 | char *value, int valuelen, int flags) |
206 | struct cred *cred) | ||
207 | { | 206 | { |
208 | xfs_da_args_t args; | 207 | xfs_da_args_t args; |
209 | xfs_inode_t *dp; | ||
210 | xfs_fsblock_t firstblock; | 208 | xfs_fsblock_t firstblock; |
211 | xfs_bmap_free_t flist; | 209 | xfs_bmap_free_t flist; |
212 | int error, err2, committed; | 210 | int error, err2, committed; |
213 | int local, size; | 211 | int local, size; |
214 | uint nblks; | 212 | uint nblks; |
215 | xfs_mount_t *mp; | 213 | xfs_mount_t *mp = dp->i_mount; |
216 | int rsvd = (flags & ATTR_ROOT) != 0; | 214 | int rsvd = (flags & ATTR_ROOT) != 0; |
217 | int namelen; | ||
218 | |||
219 | namelen = strlen(name); | ||
220 | if (namelen >= MAXNAMELEN) | ||
221 | return EFAULT; /* match IRIX behaviour */ | ||
222 | |||
223 | XFS_STATS_INC(xs_attr_set); | ||
224 | |||
225 | dp = XFS_BHVTOI(bdp); | ||
226 | mp = dp->i_mount; | ||
227 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
228 | return (EIO); | ||
229 | |||
230 | xfs_ilock(dp, XFS_ILOCK_SHARED); | ||
231 | if (!(flags & ATTR_SECURE) && | ||
232 | (error = xfs_iaccess(dp, S_IWUSR, cred))) { | ||
233 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | ||
234 | return(XFS_ERROR(error)); | ||
235 | } | ||
236 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | ||
237 | 215 | ||
238 | /* | 216 | /* |
239 | * Attach the dquots to the inode. | 217 | * Attach the dquots to the inode. |
@@ -270,7 +248,8 @@ xfs_attr_set(bhv_desc_t *bdp, char *name, char *value, int valuelen, int flags, | |||
270 | /* Determine space new attribute will use, and if it will be inline | 248 | /* Determine space new attribute will use, and if it will be inline |
271 | * or out of line. | 249 | * or out of line. |
272 | */ | 250 | */ |
273 | size = xfs_attr_leaf_newentsize(&args, mp->m_sb.sb_blocksize, &local); | 251 | size = xfs_attr_leaf_newentsize(namelen, valuelen, |
252 | mp->m_sb.sb_blocksize, &local); | ||
274 | 253 | ||
275 | nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); | 254 | nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); |
276 | if (local) { | 255 | if (local) { |
@@ -456,32 +435,21 @@ out: | |||
456 | return(error); | 435 | return(error); |
457 | } | 436 | } |
458 | 437 | ||
459 | /* | 438 | int |
460 | * Generic handler routine to remove a name from an attribute list. | 439 | xfs_attr_set(bhv_desc_t *bdp, char *name, char *value, int valuelen, int flags, |
461 | * Transitions attribute list from Btree to shortform as necessary. | 440 | struct cred *cred) |
462 | */ | ||
463 | /*ARGSUSED*/ | ||
464 | int /* error */ | ||
465 | xfs_attr_remove(bhv_desc_t *bdp, char *name, int flags, struct cred *cred) | ||
466 | { | 441 | { |
467 | xfs_da_args_t args; | 442 | xfs_inode_t *dp; |
468 | xfs_inode_t *dp; | 443 | int namelen, error; |
469 | xfs_fsblock_t firstblock; | ||
470 | xfs_bmap_free_t flist; | ||
471 | int error; | ||
472 | xfs_mount_t *mp; | ||
473 | int namelen; | ||
474 | 444 | ||
475 | ASSERT(MAXNAMELEN-1<=0xff); /* length is stored in uint8 */ | ||
476 | namelen = strlen(name); | 445 | namelen = strlen(name); |
477 | if (namelen>=MAXNAMELEN) | 446 | if (namelen >= MAXNAMELEN) |
478 | return EFAULT; /* match irix behaviour */ | 447 | return EFAULT; /* match IRIX behaviour */ |
479 | 448 | ||
480 | XFS_STATS_INC(xs_attr_remove); | 449 | XFS_STATS_INC(xs_attr_set); |
481 | 450 | ||
482 | dp = XFS_BHVTOI(bdp); | 451 | dp = XFS_BHVTOI(bdp); |
483 | mp = dp->i_mount; | 452 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) |
484 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
485 | return (EIO); | 453 | return (EIO); |
486 | 454 | ||
487 | xfs_ilock(dp, XFS_ILOCK_SHARED); | 455 | xfs_ilock(dp, XFS_ILOCK_SHARED); |
@@ -489,14 +457,25 @@ xfs_attr_remove(bhv_desc_t *bdp, char *name, int flags, struct cred *cred) | |||
489 | (error = xfs_iaccess(dp, S_IWUSR, cred))) { | 457 | (error = xfs_iaccess(dp, S_IWUSR, cred))) { |
490 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | 458 | xfs_iunlock(dp, XFS_ILOCK_SHARED); |
491 | return(XFS_ERROR(error)); | 459 | return(XFS_ERROR(error)); |
492 | } else if (XFS_IFORK_Q(dp) == 0 || | ||
493 | (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && | ||
494 | dp->i_d.di_anextents == 0)) { | ||
495 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | ||
496 | return(XFS_ERROR(ENOATTR)); | ||
497 | } | 460 | } |
498 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | 461 | xfs_iunlock(dp, XFS_ILOCK_SHARED); |
499 | 462 | ||
463 | return xfs_attr_set_int(dp, name, namelen, value, valuelen, flags); | ||
464 | } | ||
465 | |||
466 | /* | ||
467 | * Generic handler routine to remove a name from an attribute list. | ||
468 | * Transitions attribute list from Btree to shortform as necessary. | ||
469 | */ | ||
470 | int | ||
471 | xfs_attr_remove_int(xfs_inode_t *dp, char *name, int namelen, int flags) | ||
472 | { | ||
473 | xfs_da_args_t args; | ||
474 | xfs_fsblock_t firstblock; | ||
475 | xfs_bmap_free_t flist; | ||
476 | int error; | ||
477 | xfs_mount_t *mp = dp->i_mount; | ||
478 | |||
500 | /* | 479 | /* |
501 | * Fill in the arg structure for this request. | 480 | * Fill in the arg structure for this request. |
502 | */ | 481 | */ |
@@ -612,6 +591,38 @@ out: | |||
612 | return(error); | 591 | return(error); |
613 | } | 592 | } |
614 | 593 | ||
594 | int | ||
595 | xfs_attr_remove(bhv_desc_t *bdp, char *name, int flags, struct cred *cred) | ||
596 | { | ||
597 | xfs_inode_t *dp; | ||
598 | int namelen, error; | ||
599 | |||
600 | namelen = strlen(name); | ||
601 | if (namelen >= MAXNAMELEN) | ||
602 | return EFAULT; /* match IRIX behaviour */ | ||
603 | |||
604 | XFS_STATS_INC(xs_attr_remove); | ||
605 | |||
606 | dp = XFS_BHVTOI(bdp); | ||
607 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | ||
608 | return (EIO); | ||
609 | |||
610 | xfs_ilock(dp, XFS_ILOCK_SHARED); | ||
611 | if (!(flags & ATTR_SECURE) && | ||
612 | (error = xfs_iaccess(dp, S_IWUSR, cred))) { | ||
613 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | ||
614 | return(XFS_ERROR(error)); | ||
615 | } else if (XFS_IFORK_Q(dp) == 0 || | ||
616 | (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && | ||
617 | dp->i_d.di_anextents == 0)) { | ||
618 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | ||
619 | return(XFS_ERROR(ENOATTR)); | ||
620 | } | ||
621 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | ||
622 | |||
623 | return xfs_attr_remove_int(dp, name, namelen, flags); | ||
624 | } | ||
625 | |||
615 | /* | 626 | /* |
616 | * Generate a list of extended attribute names and optionally | 627 | * Generate a list of extended attribute names and optionally |
617 | * also value lengths. Positive return value follows the XFS | 628 | * also value lengths. Positive return value follows the XFS |