aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_attr.c')
-rw-r--r--fs/xfs/xfs_attr.c230
1 files changed, 113 insertions, 117 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index a41ad3a5e554..5484eeb460c8 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -1,41 +1,26 @@
1/* 1/*
2 * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. 2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
3 * 4 *
4 * This program is free software; you can redistribute it and/or modify it 5 * This program is free software; you can redistribute it and/or
5 * under the terms of version 2 of the GNU General Public License as 6 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
7 * 8 *
8 * This program is distributed in the hope that it would be useful, but 9 * This program is distributed in the hope that it would be useful,
9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
11 * 13 *
12 * Further, this software is distributed without any warranty that it is 14 * You should have received a copy of the GNU General Public License
13 * free of the rightful claim of any third person regarding infringement 15 * along with this program; if not, write the Free Software Foundation,
14 * or the like. Any license provided herein, whether implied or 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */ 17 */
32
33#include "xfs.h" 18#include "xfs.h"
34 19#include "xfs_fs.h"
35#include "xfs_macros.h"
36#include "xfs_types.h" 20#include "xfs_types.h"
37#include "xfs_inum.h" 21#include "xfs_bit.h"
38#include "xfs_log.h" 22#include "xfs_log.h"
23#include "xfs_inum.h"
39#include "xfs_trans.h" 24#include "xfs_trans.h"
40#include "xfs_sb.h" 25#include "xfs_sb.h"
41#include "xfs_ag.h" 26#include "xfs_ag.h"
@@ -43,27 +28,26 @@
43#include "xfs_dir2.h" 28#include "xfs_dir2.h"
44#include "xfs_dmapi.h" 29#include "xfs_dmapi.h"
45#include "xfs_mount.h" 30#include "xfs_mount.h"
46#include "xfs_alloc_btree.h" 31#include "xfs_da_btree.h"
47#include "xfs_bmap_btree.h" 32#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h"
48#include "xfs_ialloc_btree.h" 34#include "xfs_ialloc_btree.h"
49#include "xfs_alloc.h"
50#include "xfs_btree.h"
51#include "xfs_attr_sf.h"
52#include "xfs_dir_sf.h" 35#include "xfs_dir_sf.h"
53#include "xfs_dir2_sf.h" 36#include "xfs_dir2_sf.h"
37#include "xfs_attr_sf.h"
54#include "xfs_dinode.h" 38#include "xfs_dinode.h"
55#include "xfs_inode_item.h"
56#include "xfs_inode.h" 39#include "xfs_inode.h"
40#include "xfs_alloc.h"
41#include "xfs_btree.h"
42#include "xfs_inode_item.h"
57#include "xfs_bmap.h" 43#include "xfs_bmap.h"
58#include "xfs_da_btree.h"
59#include "xfs_attr.h" 44#include "xfs_attr.h"
60#include "xfs_attr_leaf.h" 45#include "xfs_attr_leaf.h"
61#include "xfs_error.h" 46#include "xfs_error.h"
62#include "xfs_bit.h"
63#include "xfs_quota.h" 47#include "xfs_quota.h"
64#include "xfs_rw.h"
65#include "xfs_trans_space.h" 48#include "xfs_trans_space.h"
66#include "xfs_acl.h" 49#include "xfs_acl.h"
50#include "xfs_rw.h"
67 51
68/* 52/*
69 * xfs_attr.c 53 * xfs_attr.c
@@ -122,7 +106,7 @@ ktrace_t *xfs_attr_trace_buf;
122 *========================================================================*/ 106 *========================================================================*/
123 107
124int 108int
125xfs_attr_fetch(xfs_inode_t *ip, char *name, int namelen, 109xfs_attr_fetch(xfs_inode_t *ip, const char *name, int namelen,
126 char *value, int *valuelenp, int flags, struct cred *cred) 110 char *value, int *valuelenp, int flags, struct cred *cred)
127{ 111{
128 xfs_da_args_t args; 112 xfs_da_args_t args;
@@ -177,7 +161,7 @@ xfs_attr_fetch(xfs_inode_t *ip, char *name, int namelen,
177} 161}
178 162
179int 163int
180xfs_attr_get(bhv_desc_t *bdp, char *name, char *value, int *valuelenp, 164xfs_attr_get(bhv_desc_t *bdp, const char *name, char *value, int *valuelenp,
181 int flags, struct cred *cred) 165 int flags, struct cred *cred)
182{ 166{
183 xfs_inode_t *ip = XFS_BHVTOI(bdp); 167 xfs_inode_t *ip = XFS_BHVTOI(bdp);
@@ -200,40 +184,18 @@ xfs_attr_get(bhv_desc_t *bdp, char *name, char *value, int *valuelenp,
200 return(error); 184 return(error);
201} 185}
202 186
203/*ARGSUSED*/ 187STATIC int
204int /* error */ 188xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
205xfs_attr_set(bhv_desc_t *bdp, char *name, char *value, int valuelen, int flags, 189 char *value, int valuelen, int flags)
206 struct cred *cred)
207{ 190{
208 xfs_da_args_t args; 191 xfs_da_args_t args;
209 xfs_inode_t *dp;
210 xfs_fsblock_t firstblock; 192 xfs_fsblock_t firstblock;
211 xfs_bmap_free_t flist; 193 xfs_bmap_free_t flist;
212 int error, err2, committed; 194 int error, err2, committed;
213 int local, size; 195 int local, size;
214 uint nblks; 196 uint nblks;
215 xfs_mount_t *mp; 197 xfs_mount_t *mp = dp->i_mount;
216 int rsvd = (flags & ATTR_ROOT) != 0; 198 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 199
238 /* 200 /*
239 * Attach the dquots to the inode. 201 * Attach the dquots to the inode.
@@ -242,12 +204,18 @@ xfs_attr_set(bhv_desc_t *bdp, char *name, char *value, int valuelen, int flags,
242 return (error); 204 return (error);
243 205
244 /* 206 /*
207 * Determine space new attribute will use, and if it would be
208 * "local" or "remote" (note: local != inline).
209 */
210 size = xfs_attr_leaf_newentsize(namelen, valuelen,
211 mp->m_sb.sb_blocksize, &local);
212
213 /*
245 * If the inode doesn't have an attribute fork, add one. 214 * If the inode doesn't have an attribute fork, add one.
246 * (inode must not be locked when we call this routine) 215 * (inode must not be locked when we call this routine)
247 */ 216 */
248 if (XFS_IFORK_Q(dp) == 0) { 217 if (XFS_IFORK_Q(dp) == 0) {
249 error = xfs_bmap_add_attrfork(dp, rsvd); 218 if ((error = xfs_bmap_add_attrfork(dp, size, rsvd)))
250 if (error)
251 return(error); 219 return(error);
252 } 220 }
253 221
@@ -265,13 +233,9 @@ xfs_attr_set(bhv_desc_t *bdp, char *name, char *value, int valuelen, int flags,
265 args.firstblock = &firstblock; 233 args.firstblock = &firstblock;
266 args.flist = &flist; 234 args.flist = &flist;
267 args.whichfork = XFS_ATTR_FORK; 235 args.whichfork = XFS_ATTR_FORK;
236 args.addname = 1;
268 args.oknoent = 1; 237 args.oknoent = 1;
269 238
270 /* Determine space new attribute will use, and if it will be inline
271 * or out of line.
272 */
273 size = xfs_attr_leaf_newentsize(&args, mp->m_sb.sb_blocksize, &local);
274
275 nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); 239 nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
276 if (local) { 240 if (local) {
277 if (size > (mp->m_sb.sb_blocksize >> 1)) { 241 if (size > (mp->m_sb.sb_blocksize >> 1)) {
@@ -343,7 +307,7 @@ xfs_attr_set(bhv_desc_t *bdp, char *name, char *value, int valuelen, int flags,
343 * Build initial attribute list (if required). 307 * Build initial attribute list (if required).
344 */ 308 */
345 if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) 309 if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
346 (void)xfs_attr_shortform_create(&args); 310 xfs_attr_shortform_create(&args);
347 311
348 /* 312 /*
349 * Try to add the attr to the attribute list in 313 * Try to add the attr to the attribute list in
@@ -456,32 +420,21 @@ out:
456 return(error); 420 return(error);
457} 421}
458 422
459/* 423int
460 * Generic handler routine to remove a name from an attribute list. 424xfs_attr_set(bhv_desc_t *bdp, const char *name, char *value, int valuelen, int flags,
461 * Transitions attribute list from Btree to shortform as necessary. 425 struct cred *cred)
462 */
463/*ARGSUSED*/
464int /* error */
465xfs_attr_remove(bhv_desc_t *bdp, char *name, int flags, struct cred *cred)
466{ 426{
467 xfs_da_args_t args; 427 xfs_inode_t *dp;
468 xfs_inode_t *dp; 428 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 429
475 ASSERT(MAXNAMELEN-1<=0xff); /* length is stored in uint8 */
476 namelen = strlen(name); 430 namelen = strlen(name);
477 if (namelen>=MAXNAMELEN) 431 if (namelen >= MAXNAMELEN)
478 return EFAULT; /* match irix behaviour */ 432 return EFAULT; /* match IRIX behaviour */
479 433
480 XFS_STATS_INC(xs_attr_remove); 434 XFS_STATS_INC(xs_attr_set);
481 435
482 dp = XFS_BHVTOI(bdp); 436 dp = XFS_BHVTOI(bdp);
483 mp = dp->i_mount; 437 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
484 if (XFS_FORCED_SHUTDOWN(mp))
485 return (EIO); 438 return (EIO);
486 439
487 xfs_ilock(dp, XFS_ILOCK_SHARED); 440 xfs_ilock(dp, XFS_ILOCK_SHARED);
@@ -489,14 +442,25 @@ xfs_attr_remove(bhv_desc_t *bdp, char *name, int flags, struct cred *cred)
489 (error = xfs_iaccess(dp, S_IWUSR, cred))) { 442 (error = xfs_iaccess(dp, S_IWUSR, cred))) {
490 xfs_iunlock(dp, XFS_ILOCK_SHARED); 443 xfs_iunlock(dp, XFS_ILOCK_SHARED);
491 return(XFS_ERROR(error)); 444 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 } 445 }
498 xfs_iunlock(dp, XFS_ILOCK_SHARED); 446 xfs_iunlock(dp, XFS_ILOCK_SHARED);
499 447
448 return xfs_attr_set_int(dp, name, namelen, value, valuelen, flags);
449}
450
451/*
452 * Generic handler routine to remove a name from an attribute list.
453 * Transitions attribute list from Btree to shortform as necessary.
454 */
455STATIC int
456xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags)
457{
458 xfs_da_args_t args;
459 xfs_fsblock_t firstblock;
460 xfs_bmap_free_t flist;
461 int error;
462 xfs_mount_t *mp = dp->i_mount;
463
500 /* 464 /*
501 * Fill in the arg structure for this request. 465 * Fill in the arg structure for this request.
502 */ 466 */
@@ -544,7 +508,6 @@ xfs_attr_remove(bhv_desc_t *bdp, char *name, int flags, struct cred *cred)
544 XFS_ATTRRM_LOG_COUNT))) { 508 XFS_ATTRRM_LOG_COUNT))) {
545 xfs_trans_cancel(args.trans, 0); 509 xfs_trans_cancel(args.trans, 0);
546 return(error); 510 return(error);
547
548 } 511 }
549 512
550 xfs_ilock(dp, XFS_ILOCK_EXCL); 513 xfs_ilock(dp, XFS_ILOCK_EXCL);
@@ -612,6 +575,38 @@ out:
612 return(error); 575 return(error);
613} 576}
614 577
578int
579xfs_attr_remove(bhv_desc_t *bdp, const char *name, int flags, struct cred *cred)
580{
581 xfs_inode_t *dp;
582 int namelen, error;
583
584 namelen = strlen(name);
585 if (namelen >= MAXNAMELEN)
586 return EFAULT; /* match IRIX behaviour */
587
588 XFS_STATS_INC(xs_attr_remove);
589
590 dp = XFS_BHVTOI(bdp);
591 if (XFS_FORCED_SHUTDOWN(dp->i_mount))
592 return (EIO);
593
594 xfs_ilock(dp, XFS_ILOCK_SHARED);
595 if (!(flags & ATTR_SECURE) &&
596 (error = xfs_iaccess(dp, S_IWUSR, cred))) {
597 xfs_iunlock(dp, XFS_ILOCK_SHARED);
598 return(XFS_ERROR(error));
599 } else if (XFS_IFORK_Q(dp) == 0 ||
600 (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
601 dp->i_d.di_anextents == 0)) {
602 xfs_iunlock(dp, XFS_ILOCK_SHARED);
603 return(XFS_ERROR(ENOATTR));
604 }
605 xfs_iunlock(dp, XFS_ILOCK_SHARED);
606
607 return xfs_attr_remove_int(dp, name, namelen, flags);
608}
609
615/* 610/*
616 * Generate a list of extended attribute names and optionally 611 * Generate a list of extended attribute names and optionally
617 * also value lengths. Positive return value follows the XFS 612 * also value lengths. Positive return value follows the XFS
@@ -811,7 +806,7 @@ out:
811STATIC int 806STATIC int
812xfs_attr_shortform_addname(xfs_da_args_t *args) 807xfs_attr_shortform_addname(xfs_da_args_t *args)
813{ 808{
814 int newsize, retval; 809 int newsize, forkoff, retval;
815 810
816 retval = xfs_attr_shortform_lookup(args); 811 retval = xfs_attr_shortform_lookup(args);
817 if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) { 812 if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
@@ -823,16 +818,18 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
823 ASSERT(retval == 0); 818 ASSERT(retval == 0);
824 } 819 }
825 820
821 if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
822 args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
823 return(XFS_ERROR(ENOSPC));
824
826 newsize = XFS_ATTR_SF_TOTSIZE(args->dp); 825 newsize = XFS_ATTR_SF_TOTSIZE(args->dp);
827 newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen); 826 newsize += XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen);
828 if ((newsize <= XFS_IFORK_ASIZE(args->dp)) && 827
829 (args->namelen < XFS_ATTR_SF_ENTSIZE_MAX) && 828 forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
830 (args->valuelen < XFS_ATTR_SF_ENTSIZE_MAX)) { 829 if (!forkoff)
831 retval = xfs_attr_shortform_add(args);
832 ASSERT(retval == 0);
833 } else {
834 return(XFS_ERROR(ENOSPC)); 830 return(XFS_ERROR(ENOSPC));
835 } 831
832 xfs_attr_shortform_add(args, forkoff);
836 return(0); 833 return(0);
837} 834}
838 835
@@ -852,7 +849,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
852{ 849{
853 xfs_inode_t *dp; 850 xfs_inode_t *dp;
854 xfs_dabuf_t *bp; 851 xfs_dabuf_t *bp;
855 int retval, error, committed; 852 int retval, error, committed, forkoff;
856 853
857 /* 854 /*
858 * Read the (only) block in the attribute list in. 855 * Read the (only) block in the attribute list in.
@@ -995,9 +992,9 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
995 /* 992 /*
996 * If the result is small enough, shrink it all into the inode. 993 * If the result is small enough, shrink it all into the inode.
997 */ 994 */
998 if (xfs_attr_shortform_allfit(bp, dp)) { 995 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
999 XFS_BMAP_INIT(args->flist, args->firstblock); 996 XFS_BMAP_INIT(args->flist, args->firstblock);
1000 error = xfs_attr_leaf_to_shortform(bp, args); 997 error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1001 /* bp is gone due to xfs_da_shrink_inode */ 998 /* bp is gone due to xfs_da_shrink_inode */
1002 if (!error) { 999 if (!error) {
1003 error = xfs_bmap_finish(&args->trans, 1000 error = xfs_bmap_finish(&args->trans,
@@ -1049,8 +1046,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
1049{ 1046{
1050 xfs_inode_t *dp; 1047 xfs_inode_t *dp;
1051 xfs_dabuf_t *bp; 1048 xfs_dabuf_t *bp;
1052 int committed; 1049 int error, committed, forkoff;
1053 int error;
1054 1050
1055 /* 1051 /*
1056 * Remove the attribute. 1052 * Remove the attribute.
@@ -1075,9 +1071,9 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
1075 /* 1071 /*
1076 * If the result is small enough, shrink it all into the inode. 1072 * If the result is small enough, shrink it all into the inode.
1077 */ 1073 */
1078 if (xfs_attr_shortform_allfit(bp, dp)) { 1074 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1079 XFS_BMAP_INIT(args->flist, args->firstblock); 1075 XFS_BMAP_INIT(args->flist, args->firstblock);
1080 error = xfs_attr_leaf_to_shortform(bp, args); 1076 error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1081 /* bp is gone due to xfs_da_shrink_inode */ 1077 /* bp is gone due to xfs_da_shrink_inode */
1082 if (!error) { 1078 if (!error) {
1083 error = xfs_bmap_finish(&args->trans, args->flist, 1079 error = xfs_bmap_finish(&args->trans, args->flist,
@@ -1448,7 +1444,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
1448 xfs_da_state_blk_t *blk; 1444 xfs_da_state_blk_t *blk;
1449 xfs_inode_t *dp; 1445 xfs_inode_t *dp;
1450 xfs_dabuf_t *bp; 1446 xfs_dabuf_t *bp;
1451 int retval, error, committed; 1447 int retval, error, committed, forkoff;
1452 1448
1453 /* 1449 /*
1454 * Tie a string around our finger to remind us where we are. 1450 * Tie a string around our finger to remind us where we are.
@@ -1569,9 +1565,9 @@ xfs_attr_node_removename(xfs_da_args_t *args)
1569 bp->data)->hdr.info.magic, ARCH_CONVERT) 1565 bp->data)->hdr.info.magic, ARCH_CONVERT)
1570 == XFS_ATTR_LEAF_MAGIC); 1566 == XFS_ATTR_LEAF_MAGIC);
1571 1567
1572 if (xfs_attr_shortform_allfit(bp, dp)) { 1568 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1573 XFS_BMAP_INIT(args->flist, args->firstblock); 1569 XFS_BMAP_INIT(args->flist, args->firstblock);
1574 error = xfs_attr_leaf_to_shortform(bp, args); 1570 error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
1575 /* bp is gone due to xfs_da_shrink_inode */ 1571 /* bp is gone due to xfs_da_shrink_inode */
1576 if (!error) { 1572 if (!error) {
1577 error = xfs_bmap_finish(&args->trans, 1573 error = xfs_bmap_finish(&args->trans,