diff options
| -rw-r--r-- | fs/xfs/xfs_attr.c | 328 |
1 files changed, 117 insertions, 211 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index abda1124a70f..1fc1f06277da 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
| @@ -77,17 +77,26 @@ STATIC int xfs_attr_refillstate(xfs_da_state_t *state); | |||
| 77 | 77 | ||
| 78 | 78 | ||
| 79 | STATIC int | 79 | STATIC int |
| 80 | xfs_attr_name_to_xname( | 80 | xfs_attr_args_init( |
| 81 | struct xfs_name *xname, | 81 | struct xfs_da_args *args, |
| 82 | const unsigned char *aname) | 82 | struct xfs_inode *dp, |
| 83 | const unsigned char *name, | ||
| 84 | int flags) | ||
| 83 | { | 85 | { |
| 84 | if (!aname) | 86 | |
| 87 | if (!name) | ||
| 85 | return EINVAL; | 88 | return EINVAL; |
| 86 | xname->name = aname; | 89 | |
| 87 | xname->len = strlen((char *)aname); | 90 | memset(args, 0, sizeof(*args)); |
| 88 | if (xname->len >= MAXNAMELEN) | 91 | args->whichfork = XFS_ATTR_FORK; |
| 92 | args->dp = dp; | ||
| 93 | args->flags = flags; | ||
| 94 | args->name = name; | ||
| 95 | args->namelen = strlen((const char *)name); | ||
| 96 | if (args->namelen >= MAXNAMELEN) | ||
| 89 | return EFAULT; /* match IRIX behaviour */ | 97 | return EFAULT; /* match IRIX behaviour */ |
| 90 | 98 | ||
| 99 | args->hashval = xfs_da_hashname(args->name, args->namelen); | ||
| 91 | return 0; | 100 | return 0; |
| 92 | } | 101 | } |
| 93 | 102 | ||
| @@ -106,79 +115,46 @@ xfs_inode_hasattr( | |||
| 106 | * Overall external interface routines. | 115 | * Overall external interface routines. |
| 107 | *========================================================================*/ | 116 | *========================================================================*/ |
| 108 | 117 | ||
| 109 | STATIC int | 118 | int |
| 110 | xfs_attr_get_int( | 119 | xfs_attr_get( |
| 111 | struct xfs_inode *ip, | 120 | struct xfs_inode *ip, |
| 112 | struct xfs_name *name, | 121 | const unsigned char *name, |
| 113 | unsigned char *value, | 122 | unsigned char *value, |
| 114 | int *valuelenp, | 123 | int *valuelenp, |
| 115 | int flags) | 124 | int flags) |
| 116 | { | 125 | { |
| 117 | xfs_da_args_t args; | 126 | struct xfs_da_args args; |
| 118 | int error; | 127 | uint lock_mode; |
| 128 | int error; | ||
| 129 | |||
| 130 | XFS_STATS_INC(xs_attr_get); | ||
| 131 | |||
| 132 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
| 133 | return EIO; | ||
| 119 | 134 | ||
| 120 | if (!xfs_inode_hasattr(ip)) | 135 | if (!xfs_inode_hasattr(ip)) |
| 121 | return ENOATTR; | 136 | return ENOATTR; |
| 122 | 137 | ||
| 123 | /* | 138 | error = xfs_attr_args_init(&args, ip, name, flags); |
| 124 | * Fill in the arg structure for this request. | 139 | if (error) |
| 125 | */ | 140 | return error; |
| 126 | memset((char *)&args, 0, sizeof(args)); | 141 | |
| 127 | args.name = name->name; | ||
| 128 | args.namelen = name->len; | ||
| 129 | args.value = value; | 142 | args.value = value; |
| 130 | args.valuelen = *valuelenp; | 143 | args.valuelen = *valuelenp; |
| 131 | args.flags = flags; | ||
| 132 | args.hashval = xfs_da_hashname(args.name, args.namelen); | ||
| 133 | args.dp = ip; | ||
| 134 | args.whichfork = XFS_ATTR_FORK; | ||
| 135 | 144 | ||
| 136 | /* | 145 | lock_mode = xfs_ilock_attr_map_shared(ip); |
| 137 | * Decide on what work routines to call based on the inode size. | 146 | if (!xfs_inode_hasattr(ip)) |
| 138 | */ | 147 | error = ENOATTR; |
| 139 | if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { | 148 | else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) |
| 140 | error = xfs_attr_shortform_getvalue(&args); | 149 | error = xfs_attr_shortform_getvalue(&args); |
| 141 | } else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) { | 150 | else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) |
| 142 | error = xfs_attr_leaf_get(&args); | 151 | error = xfs_attr_leaf_get(&args); |
| 143 | } else { | 152 | else |
| 144 | error = xfs_attr_node_get(&args); | 153 | error = xfs_attr_node_get(&args); |
| 145 | } | 154 | xfs_iunlock(ip, lock_mode); |
| 146 | 155 | ||
| 147 | /* | ||
| 148 | * Return the number of bytes in the value to the caller. | ||
| 149 | */ | ||
| 150 | *valuelenp = args.valuelen; | 156 | *valuelenp = args.valuelen; |
| 151 | 157 | return error == EEXIST ? 0 : error; | |
| 152 | if (error == EEXIST) | ||
| 153 | error = 0; | ||
| 154 | return(error); | ||
| 155 | } | ||
| 156 | |||
| 157 | int | ||
| 158 | xfs_attr_get( | ||
| 159 | xfs_inode_t *ip, | ||
| 160 | const unsigned char *name, | ||
| 161 | unsigned char *value, | ||
| 162 | int *valuelenp, | ||
| 163 | int flags) | ||
| 164 | { | ||
| 165 | int error; | ||
| 166 | struct xfs_name xname; | ||
| 167 | uint lock_mode; | ||
| 168 | |||
| 169 | XFS_STATS_INC(xs_attr_get); | ||
| 170 | |||
| 171 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
| 172 | return(EIO); | ||
| 173 | |||
| 174 | error = xfs_attr_name_to_xname(&xname, name); | ||
| 175 | if (error) | ||
| 176 | return error; | ||
| 177 | |||
| 178 | lock_mode = xfs_ilock_attr_map_shared(ip); | ||
| 179 | error = xfs_attr_get_int(ip, &xname, value, valuelenp, flags); | ||
| 180 | xfs_iunlock(ip, lock_mode); | ||
| 181 | return(error); | ||
| 182 | } | 158 | } |
| 183 | 159 | ||
| 184 | /* | 160 | /* |
| @@ -186,12 +162,10 @@ xfs_attr_get( | |||
| 186 | */ | 162 | */ |
| 187 | STATIC int | 163 | STATIC int |
| 188 | xfs_attr_calc_size( | 164 | xfs_attr_calc_size( |
| 189 | struct xfs_inode *ip, | 165 | struct xfs_da_args *args, |
| 190 | int namelen, | ||
| 191 | int valuelen, | ||
| 192 | int *local) | 166 | int *local) |
| 193 | { | 167 | { |
| 194 | struct xfs_mount *mp = ip->i_mount; | 168 | struct xfs_mount *mp = args->dp->i_mount; |
| 195 | int size; | 169 | int size; |
| 196 | int nblks; | 170 | int nblks; |
| 197 | 171 | ||
| @@ -199,7 +173,7 @@ xfs_attr_calc_size( | |||
| 199 | * Determine space new attribute will use, and if it would be | 173 | * Determine space new attribute will use, and if it would be |
| 200 | * "local" or "remote" (note: local != inline). | 174 | * "local" or "remote" (note: local != inline). |
| 201 | */ | 175 | */ |
| 202 | size = xfs_attr_leaf_newentsize(namelen, valuelen, | 176 | size = xfs_attr_leaf_newentsize(args->namelen, args->valuelen, |
| 203 | mp->m_sb.sb_blocksize, local); | 177 | mp->m_sb.sb_blocksize, local); |
| 204 | 178 | ||
| 205 | nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); | 179 | nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); |
| @@ -213,7 +187,7 @@ xfs_attr_calc_size( | |||
| 213 | * Out of line attribute, cannot double split, but | 187 | * Out of line attribute, cannot double split, but |
| 214 | * make room for the attribute value itself. | 188 | * make room for the attribute value itself. |
| 215 | */ | 189 | */ |
| 216 | uint dblocks = xfs_attr3_rmt_blocks(mp, valuelen); | 190 | uint dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen); |
| 217 | nblks += dblocks; | 191 | nblks += dblocks; |
| 218 | nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); | 192 | nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); |
| 219 | } | 193 | } |
| @@ -221,26 +195,38 @@ xfs_attr_calc_size( | |||
| 221 | return nblks; | 195 | return nblks; |
| 222 | } | 196 | } |
| 223 | 197 | ||
| 224 | STATIC int | 198 | int |
| 225 | xfs_attr_set_int( | 199 | xfs_attr_set( |
| 226 | struct xfs_inode *dp, | 200 | struct xfs_inode *dp, |
| 227 | struct xfs_name *name, | 201 | const unsigned char *name, |
| 228 | unsigned char *value, | 202 | unsigned char *value, |
| 229 | int valuelen, | 203 | int valuelen, |
| 230 | int flags) | 204 | int flags) |
| 231 | { | 205 | { |
| 232 | xfs_da_args_t args; | ||
| 233 | xfs_fsblock_t firstblock; | ||
| 234 | xfs_bmap_free_t flist; | ||
| 235 | int error, err2, committed; | ||
| 236 | struct xfs_mount *mp = dp->i_mount; | 206 | struct xfs_mount *mp = dp->i_mount; |
| 207 | struct xfs_da_args args; | ||
| 208 | struct xfs_bmap_free flist; | ||
| 237 | struct xfs_trans_res tres; | 209 | struct xfs_trans_res tres; |
| 210 | xfs_fsblock_t firstblock; | ||
| 238 | int rsvd = (flags & ATTR_ROOT) != 0; | 211 | int rsvd = (flags & ATTR_ROOT) != 0; |
| 239 | int local; | 212 | int error, err2, committed, local; |
| 213 | |||
| 214 | XFS_STATS_INC(xs_attr_set); | ||
| 215 | |||
| 216 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | ||
| 217 | return EIO; | ||
| 218 | |||
| 219 | error = xfs_attr_args_init(&args, dp, name, flags); | ||
| 220 | if (error) | ||
| 221 | return error; | ||
| 222 | |||
| 223 | args.value = value; | ||
| 224 | args.valuelen = valuelen; | ||
| 225 | args.firstblock = &firstblock; | ||
| 226 | args.flist = &flist; | ||
| 227 | args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; | ||
| 228 | args.total = xfs_attr_calc_size(&args, &local); | ||
| 240 | 229 | ||
| 241 | /* | ||
| 242 | * Attach the dquots to the inode. | ||
| 243 | */ | ||
| 244 | error = xfs_qm_dqattach(dp, 0); | 230 | error = xfs_qm_dqattach(dp, 0); |
| 245 | if (error) | 231 | if (error) |
| 246 | return error; | 232 | return error; |
| @@ -251,32 +237,14 @@ xfs_attr_set_int( | |||
| 251 | */ | 237 | */ |
| 252 | if (XFS_IFORK_Q(dp) == 0) { | 238 | if (XFS_IFORK_Q(dp) == 0) { |
| 253 | int sf_size = sizeof(xfs_attr_sf_hdr_t) + | 239 | int sf_size = sizeof(xfs_attr_sf_hdr_t) + |
| 254 | XFS_ATTR_SF_ENTSIZE_BYNAME(name->len, valuelen); | 240 | XFS_ATTR_SF_ENTSIZE_BYNAME(args.namelen, valuelen); |
| 255 | 241 | ||
| 256 | if ((error = xfs_bmap_add_attrfork(dp, sf_size, rsvd))) | 242 | error = xfs_bmap_add_attrfork(dp, sf_size, rsvd); |
| 257 | return(error); | 243 | if (error) |
| 244 | return error; | ||
| 258 | } | 245 | } |
| 259 | 246 | ||
| 260 | /* | 247 | /* |
| 261 | * Fill in the arg structure for this request. | ||
| 262 | */ | ||
| 263 | memset((char *)&args, 0, sizeof(args)); | ||
| 264 | args.name = name->name; | ||
| 265 | args.namelen = name->len; | ||
| 266 | args.value = value; | ||
| 267 | args.valuelen = valuelen; | ||
| 268 | args.flags = flags; | ||
| 269 | args.hashval = xfs_da_hashname(args.name, args.namelen); | ||
| 270 | args.dp = dp; | ||
| 271 | args.firstblock = &firstblock; | ||
| 272 | args.flist = &flist; | ||
| 273 | args.whichfork = XFS_ATTR_FORK; | ||
| 274 | args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; | ||
| 275 | |||
| 276 | /* Size is now blocks for attribute data */ | ||
| 277 | args.total = xfs_attr_calc_size(dp, name->len, valuelen, &local); | ||
| 278 | |||
| 279 | /* | ||
| 280 | * Start our first transaction of the day. | 248 | * Start our first transaction of the day. |
| 281 | * | 249 | * |
| 282 | * All future transactions during this code must be "chained" off | 250 | * All future transactions during this code must be "chained" off |
| @@ -303,7 +271,7 @@ xfs_attr_set_int( | |||
| 303 | error = xfs_trans_reserve(args.trans, &tres, args.total, 0); | 271 | error = xfs_trans_reserve(args.trans, &tres, args.total, 0); |
| 304 | if (error) { | 272 | if (error) { |
| 305 | xfs_trans_cancel(args.trans, 0); | 273 | xfs_trans_cancel(args.trans, 0); |
| 306 | return(error); | 274 | return error; |
| 307 | } | 275 | } |
| 308 | xfs_ilock(dp, XFS_ILOCK_EXCL); | 276 | xfs_ilock(dp, XFS_ILOCK_EXCL); |
| 309 | 277 | ||
| @@ -313,7 +281,7 @@ xfs_attr_set_int( | |||
| 313 | if (error) { | 281 | if (error) { |
| 314 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 282 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
| 315 | xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES); | 283 | xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES); |
| 316 | return (error); | 284 | return error; |
| 317 | } | 285 | } |
| 318 | 286 | ||
| 319 | xfs_trans_ijoin(args.trans, dp, 0); | 287 | xfs_trans_ijoin(args.trans, dp, 0); |
| @@ -322,9 +290,9 @@ xfs_attr_set_int( | |||
| 322 | * If the attribute list is non-existent or a shortform list, | 290 | * If the attribute list is non-existent or a shortform list, |
| 323 | * upgrade it to a single-leaf-block attribute list. | 291 | * upgrade it to a single-leaf-block attribute list. |
| 324 | */ | 292 | */ |
| 325 | if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || | 293 | if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL || |
| 326 | ((dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) && | 294 | (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && |
| 327 | (dp->i_d.di_anextents == 0))) { | 295 | dp->i_d.di_anextents == 0)) { |
| 328 | 296 | ||
| 329 | /* | 297 | /* |
| 330 | * Build initial attribute list (if required). | 298 | * Build initial attribute list (if required). |
| @@ -349,9 +317,8 @@ xfs_attr_set_int( | |||
| 349 | * the transaction goes to disk before returning | 317 | * the transaction goes to disk before returning |
| 350 | * to the user. | 318 | * to the user. |
| 351 | */ | 319 | */ |
| 352 | if (mp->m_flags & XFS_MOUNT_WSYNC) { | 320 | if (mp->m_flags & XFS_MOUNT_WSYNC) |
| 353 | xfs_trans_set_sync(args.trans); | 321 | xfs_trans_set_sync(args.trans); |
| 354 | } | ||
| 355 | 322 | ||
| 356 | if (!error && (flags & ATTR_KERNOTIME) == 0) { | 323 | if (!error && (flags & ATTR_KERNOTIME) == 0) { |
| 357 | xfs_trans_ichgtime(args.trans, dp, | 324 | xfs_trans_ichgtime(args.trans, dp, |
| @@ -361,7 +328,7 @@ xfs_attr_set_int( | |||
| 361 | XFS_TRANS_RELEASE_LOG_RES); | 328 | XFS_TRANS_RELEASE_LOG_RES); |
| 362 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 329 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
| 363 | 330 | ||
| 364 | return(error == 0 ? err2 : error); | 331 | return error ? error : err2; |
| 365 | } | 332 | } |
| 366 | 333 | ||
| 367 | /* | 334 | /* |
| @@ -399,22 +366,19 @@ xfs_attr_set_int( | |||
| 399 | 366 | ||
| 400 | } | 367 | } |
| 401 | 368 | ||
| 402 | if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { | 369 | if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) |
| 403 | error = xfs_attr_leaf_addname(&args); | 370 | error = xfs_attr_leaf_addname(&args); |
| 404 | } else { | 371 | else |
| 405 | error = xfs_attr_node_addname(&args); | 372 | error = xfs_attr_node_addname(&args); |
| 406 | } | 373 | if (error) |
| 407 | if (error) { | ||
| 408 | goto out; | 374 | goto out; |
| 409 | } | ||
| 410 | 375 | ||
| 411 | /* | 376 | /* |
| 412 | * If this is a synchronous mount, make sure that the | 377 | * If this is a synchronous mount, make sure that the |
| 413 | * transaction goes to disk before returning to the user. | 378 | * transaction goes to disk before returning to the user. |
| 414 | */ | 379 | */ |
| 415 | if (mp->m_flags & XFS_MOUNT_WSYNC) { | 380 | if (mp->m_flags & XFS_MOUNT_WSYNC) |
| 416 | xfs_trans_set_sync(args.trans); | 381 | xfs_trans_set_sync(args.trans); |
| 417 | } | ||
| 418 | 382 | ||
| 419 | if ((flags & ATTR_KERNOTIME) == 0) | 383 | if ((flags & ATTR_KERNOTIME) == 0) |
| 420 | xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); | 384 | xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); |
| @@ -426,65 +390,47 @@ xfs_attr_set_int( | |||
| 426 | error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES); | 390 | error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES); |
| 427 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 391 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
| 428 | 392 | ||
| 429 | return(error); | 393 | return error; |
| 430 | 394 | ||
| 431 | out: | 395 | out: |
| 432 | if (args.trans) | 396 | if (args.trans) { |
| 433 | xfs_trans_cancel(args.trans, | 397 | xfs_trans_cancel(args.trans, |
| 434 | XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); | 398 | XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); |
| 399 | } | ||
| 435 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 400 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
| 436 | return(error); | 401 | return error; |
| 437 | } | 402 | } |
| 438 | 403 | ||
| 404 | /* | ||
| 405 | * Generic handler routine to remove a name from an attribute list. | ||
| 406 | * Transitions attribute list from Btree to shortform as necessary. | ||
| 407 | */ | ||
| 439 | int | 408 | int |
| 440 | xfs_attr_set( | 409 | xfs_attr_remove( |
| 441 | xfs_inode_t *dp, | 410 | struct xfs_inode *dp, |
| 442 | const unsigned char *name, | 411 | const unsigned char *name, |
| 443 | unsigned char *value, | 412 | int flags) |
| 444 | int valuelen, | ||
| 445 | int flags) | ||
| 446 | { | 413 | { |
| 447 | int error; | 414 | struct xfs_mount *mp = dp->i_mount; |
| 448 | struct xfs_name xname; | 415 | struct xfs_da_args args; |
| 416 | struct xfs_bmap_free flist; | ||
| 417 | xfs_fsblock_t firstblock; | ||
| 418 | int error; | ||
| 449 | 419 | ||
| 450 | XFS_STATS_INC(xs_attr_set); | 420 | XFS_STATS_INC(xs_attr_remove); |
| 451 | 421 | ||
| 452 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | 422 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) |
| 453 | return (EIO); | 423 | return EIO; |
| 454 | 424 | ||
| 455 | error = xfs_attr_name_to_xname(&xname, name); | 425 | if (!xfs_inode_hasattr(dp)) |
| 426 | return ENOATTR; | ||
| 427 | |||
| 428 | error = xfs_attr_args_init(&args, dp, name, flags); | ||
| 456 | if (error) | 429 | if (error) |
| 457 | return error; | 430 | return error; |
| 458 | 431 | ||
| 459 | return xfs_attr_set_int(dp, &xname, value, valuelen, flags); | ||
| 460 | } | ||
| 461 | |||
| 462 | /* | ||
| 463 | * Generic handler routine to remove a name from an attribute list. | ||
| 464 | * Transitions attribute list from Btree to shortform as necessary. | ||
| 465 | */ | ||
| 466 | STATIC int | ||
| 467 | xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | ||
| 468 | { | ||
| 469 | xfs_da_args_t args; | ||
| 470 | xfs_fsblock_t firstblock; | ||
| 471 | xfs_bmap_free_t flist; | ||
| 472 | int error; | ||
| 473 | xfs_mount_t *mp = dp->i_mount; | ||
| 474 | |||
| 475 | /* | ||
| 476 | * Fill in the arg structure for this request. | ||
| 477 | */ | ||
| 478 | memset((char *)&args, 0, sizeof(args)); | ||
| 479 | args.name = name->name; | ||
| 480 | args.namelen = name->len; | ||
| 481 | args.flags = flags; | ||
| 482 | args.hashval = xfs_da_hashname(args.name, args.namelen); | ||
| 483 | args.dp = dp; | ||
| 484 | args.firstblock = &firstblock; | 432 | args.firstblock = &firstblock; |
| 485 | args.flist = &flist; | 433 | args.flist = &flist; |
| 486 | args.total = 0; | ||
| 487 | args.whichfork = XFS_ATTR_FORK; | ||
| 488 | 434 | ||
| 489 | /* | 435 | /* |
| 490 | * we have no control over the attribute names that userspace passes us | 436 | * we have no control over the attribute names that userspace passes us |
| @@ -493,9 +439,6 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | |||
| 493 | */ | 439 | */ |
| 494 | args.op_flags = XFS_DA_OP_OKNOENT; | 440 | args.op_flags = XFS_DA_OP_OKNOENT; |
| 495 | 441 | ||
| 496 | /* | ||
| 497 | * Attach the dquots to the inode. | ||
| 498 | */ | ||
| 499 | error = xfs_qm_dqattach(dp, 0); | 442 | error = xfs_qm_dqattach(dp, 0); |
| 500 | if (error) | 443 | if (error) |
| 501 | return error; | 444 | return error; |
| @@ -524,7 +467,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | |||
| 524 | XFS_ATTRRM_SPACE_RES(mp), 0); | 467 | XFS_ATTRRM_SPACE_RES(mp), 0); |
| 525 | if (error) { | 468 | if (error) { |
| 526 | xfs_trans_cancel(args.trans, 0); | 469 | xfs_trans_cancel(args.trans, 0); |
| 527 | return(error); | 470 | return error; |
| 528 | } | 471 | } |
| 529 | 472 | ||
| 530 | xfs_ilock(dp, XFS_ILOCK_EXCL); | 473 | xfs_ilock(dp, XFS_ILOCK_EXCL); |
| @@ -534,35 +477,26 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | |||
| 534 | */ | 477 | */ |
| 535 | xfs_trans_ijoin(args.trans, dp, 0); | 478 | xfs_trans_ijoin(args.trans, dp, 0); |
| 536 | 479 | ||
| 537 | /* | ||
| 538 | * Decide on what work routines to call based on the inode size. | ||
| 539 | */ | ||
| 540 | if (!xfs_inode_hasattr(dp)) { | 480 | if (!xfs_inode_hasattr(dp)) { |
| 541 | error = XFS_ERROR(ENOATTR); | 481 | error = XFS_ERROR(ENOATTR); |
| 542 | goto out; | 482 | } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { |
| 543 | } | ||
| 544 | if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { | ||
| 545 | ASSERT(dp->i_afp->if_flags & XFS_IFINLINE); | 483 | ASSERT(dp->i_afp->if_flags & XFS_IFINLINE); |
| 546 | error = xfs_attr_shortform_remove(&args); | 484 | error = xfs_attr_shortform_remove(&args); |
| 547 | if (error) { | ||
| 548 | goto out; | ||
| 549 | } | ||
| 550 | } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { | 485 | } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { |
| 551 | error = xfs_attr_leaf_removename(&args); | 486 | error = xfs_attr_leaf_removename(&args); |
| 552 | } else { | 487 | } else { |
| 553 | error = xfs_attr_node_removename(&args); | 488 | error = xfs_attr_node_removename(&args); |
| 554 | } | 489 | } |
| 555 | if (error) { | 490 | |
| 491 | if (error) | ||
| 556 | goto out; | 492 | goto out; |
| 557 | } | ||
| 558 | 493 | ||
| 559 | /* | 494 | /* |
| 560 | * If this is a synchronous mount, make sure that the | 495 | * If this is a synchronous mount, make sure that the |
| 561 | * transaction goes to disk before returning to the user. | 496 | * transaction goes to disk before returning to the user. |
| 562 | */ | 497 | */ |
| 563 | if (mp->m_flags & XFS_MOUNT_WSYNC) { | 498 | if (mp->m_flags & XFS_MOUNT_WSYNC) |
| 564 | xfs_trans_set_sync(args.trans); | 499 | xfs_trans_set_sync(args.trans); |
| 565 | } | ||
| 566 | 500 | ||
| 567 | if ((flags & ATTR_KERNOTIME) == 0) | 501 | if ((flags & ATTR_KERNOTIME) == 0) |
| 568 | xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); | 502 | xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); |
| @@ -574,45 +508,17 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | |||
| 574 | error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES); | 508 | error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES); |
| 575 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 509 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
| 576 | 510 | ||
| 577 | return(error); | 511 | return error; |
| 578 | 512 | ||
| 579 | out: | 513 | out: |
| 580 | if (args.trans) | 514 | if (args.trans) { |
| 581 | xfs_trans_cancel(args.trans, | 515 | xfs_trans_cancel(args.trans, |
| 582 | XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); | 516 | XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); |
| 583 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | ||
| 584 | return(error); | ||
| 585 | } | ||
| 586 | |||
| 587 | int | ||
| 588 | xfs_attr_remove( | ||
| 589 | xfs_inode_t *dp, | ||
| 590 | const unsigned char *name, | ||
| 591 | int flags) | ||
| 592 | { | ||
| 593 | int error; | ||
| 594 | struct xfs_name xname; | ||
| 595 | |||
| 596 | XFS_STATS_INC(xs_attr_remove); | ||
| 597 | |||
| 598 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | ||
| 599 | return (EIO); | ||
| 600 | |||
| 601 | error = xfs_attr_name_to_xname(&xname, name); | ||
| 602 | if (error) | ||
| 603 | return error; | ||
| 604 | |||
| 605 | xfs_ilock(dp, XFS_ILOCK_SHARED); | ||
| 606 | if (!xfs_inode_hasattr(dp)) { | ||
| 607 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | ||
| 608 | return XFS_ERROR(ENOATTR); | ||
| 609 | } | 517 | } |
| 610 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | 518 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
| 611 | 519 | return error; | |
| 612 | return xfs_attr_remove_int(dp, &xname, flags); | ||
| 613 | } | 520 | } |
| 614 | 521 | ||
| 615 | |||
| 616 | /*======================================================================== | 522 | /*======================================================================== |
| 617 | * External routines when attribute list is inside the inode | 523 | * External routines when attribute list is inside the inode |
| 618 | *========================================================================*/ | 524 | *========================================================================*/ |
