diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-08-14 06:19:59 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-08-14 06:19:59 -0400 |
| commit | 8d7ccaa545490cdffdfaff0842436a8dd85cf47b (patch) | |
| tree | 8129b5907161bc6ae26deb3645ce1e280c5e1f51 /fs/xfs/xfs_dir2.c | |
| parent | b2139aa0eec330c711c5a279db361e5ef1178e78 (diff) | |
| parent | 30a2f3c60a84092c8084dfe788b710f8d0768cd4 (diff) | |
Merge commit 'v2.6.27-rc3' into x86/prototypes
Conflicts:
include/asm-x86/dma-mapping.h
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs/xfs/xfs_dir2.c')
| -rw-r--r-- | fs/xfs/xfs_dir2.c | 125 |
1 files changed, 107 insertions, 18 deletions
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 7cb26529766b..80e0dc51361c 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
| @@ -46,6 +46,54 @@ | |||
| 46 | 46 | ||
| 47 | struct xfs_name xfs_name_dotdot = {"..", 2}; | 47 | struct xfs_name xfs_name_dotdot = {"..", 2}; |
| 48 | 48 | ||
| 49 | extern const struct xfs_nameops xfs_default_nameops; | ||
| 50 | |||
| 51 | /* | ||
| 52 | * ASCII case-insensitive (ie. A-Z) support for directories that was | ||
| 53 | * used in IRIX. | ||
| 54 | */ | ||
| 55 | STATIC xfs_dahash_t | ||
| 56 | xfs_ascii_ci_hashname( | ||
| 57 | struct xfs_name *name) | ||
| 58 | { | ||
| 59 | xfs_dahash_t hash; | ||
| 60 | int i; | ||
| 61 | |||
| 62 | for (i = 0, hash = 0; i < name->len; i++) | ||
| 63 | hash = tolower(name->name[i]) ^ rol32(hash, 7); | ||
| 64 | |||
| 65 | return hash; | ||
| 66 | } | ||
| 67 | |||
| 68 | STATIC enum xfs_dacmp | ||
| 69 | xfs_ascii_ci_compname( | ||
| 70 | struct xfs_da_args *args, | ||
| 71 | const char *name, | ||
| 72 | int len) | ||
| 73 | { | ||
| 74 | enum xfs_dacmp result; | ||
| 75 | int i; | ||
| 76 | |||
| 77 | if (args->namelen != len) | ||
| 78 | return XFS_CMP_DIFFERENT; | ||
| 79 | |||
| 80 | result = XFS_CMP_EXACT; | ||
| 81 | for (i = 0; i < len; i++) { | ||
| 82 | if (args->name[i] == name[i]) | ||
| 83 | continue; | ||
| 84 | if (tolower(args->name[i]) != tolower(name[i])) | ||
| 85 | return XFS_CMP_DIFFERENT; | ||
| 86 | result = XFS_CMP_CASE; | ||
| 87 | } | ||
| 88 | |||
| 89 | return result; | ||
| 90 | } | ||
| 91 | |||
| 92 | static struct xfs_nameops xfs_ascii_ci_nameops = { | ||
| 93 | .hashname = xfs_ascii_ci_hashname, | ||
| 94 | .compname = xfs_ascii_ci_compname, | ||
| 95 | }; | ||
| 96 | |||
| 49 | void | 97 | void |
| 50 | xfs_dir_mount( | 98 | xfs_dir_mount( |
| 51 | xfs_mount_t *mp) | 99 | xfs_mount_t *mp) |
| @@ -65,6 +113,10 @@ xfs_dir_mount( | |||
| 65 | (mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) / | 113 | (mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) / |
| 66 | (uint)sizeof(xfs_da_node_entry_t); | 114 | (uint)sizeof(xfs_da_node_entry_t); |
| 67 | mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100; | 115 | mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100; |
| 116 | if (xfs_sb_version_hasasciici(&mp->m_sb)) | ||
| 117 | mp->m_dirnameops = &xfs_ascii_ci_nameops; | ||
| 118 | else | ||
| 119 | mp->m_dirnameops = &xfs_default_nameops; | ||
| 68 | } | 120 | } |
| 69 | 121 | ||
| 70 | /* | 122 | /* |
| @@ -162,9 +214,10 @@ xfs_dir_createname( | |||
| 162 | return rval; | 214 | return rval; |
| 163 | XFS_STATS_INC(xs_dir_create); | 215 | XFS_STATS_INC(xs_dir_create); |
| 164 | 216 | ||
| 217 | memset(&args, 0, sizeof(xfs_da_args_t)); | ||
| 165 | args.name = name->name; | 218 | args.name = name->name; |
| 166 | args.namelen = name->len; | 219 | args.namelen = name->len; |
| 167 | args.hashval = xfs_da_hashname(name->name, name->len); | 220 | args.hashval = dp->i_mount->m_dirnameops->hashname(name); |
| 168 | args.inumber = inum; | 221 | args.inumber = inum; |
| 169 | args.dp = dp; | 222 | args.dp = dp; |
| 170 | args.firstblock = first; | 223 | args.firstblock = first; |
| @@ -172,8 +225,7 @@ xfs_dir_createname( | |||
| 172 | args.total = total; | 225 | args.total = total; |
| 173 | args.whichfork = XFS_DATA_FORK; | 226 | args.whichfork = XFS_DATA_FORK; |
| 174 | args.trans = tp; | 227 | args.trans = tp; |
| 175 | args.justcheck = 0; | 228 | args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; |
| 176 | args.addname = args.oknoent = 1; | ||
| 177 | 229 | ||
| 178 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 230 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
| 179 | rval = xfs_dir2_sf_addname(&args); | 231 | rval = xfs_dir2_sf_addname(&args); |
| @@ -191,14 +243,43 @@ xfs_dir_createname( | |||
| 191 | } | 243 | } |
| 192 | 244 | ||
| 193 | /* | 245 | /* |
| 246 | * If doing a CI lookup and case-insensitive match, dup actual name into | ||
| 247 | * args.value. Return EEXIST for success (ie. name found) or an error. | ||
| 248 | */ | ||
| 249 | int | ||
| 250 | xfs_dir_cilookup_result( | ||
| 251 | struct xfs_da_args *args, | ||
| 252 | const char *name, | ||
| 253 | int len) | ||
| 254 | { | ||
| 255 | if (args->cmpresult == XFS_CMP_DIFFERENT) | ||
| 256 | return ENOENT; | ||
| 257 | if (args->cmpresult != XFS_CMP_CASE || | ||
| 258 | !(args->op_flags & XFS_DA_OP_CILOOKUP)) | ||
| 259 | return EEXIST; | ||
| 260 | |||
| 261 | args->value = kmem_alloc(len, KM_MAYFAIL); | ||
| 262 | if (!args->value) | ||
| 263 | return ENOMEM; | ||
| 264 | |||
| 265 | memcpy(args->value, name, len); | ||
| 266 | args->valuelen = len; | ||
| 267 | return EEXIST; | ||
| 268 | } | ||
| 269 | |||
| 270 | /* | ||
| 194 | * Lookup a name in a directory, give back the inode number. | 271 | * Lookup a name in a directory, give back the inode number. |
| 272 | * If ci_name is not NULL, returns the actual name in ci_name if it differs | ||
| 273 | * to name, or ci_name->name is set to NULL for an exact match. | ||
| 195 | */ | 274 | */ |
| 275 | |||
| 196 | int | 276 | int |
| 197 | xfs_dir_lookup( | 277 | xfs_dir_lookup( |
| 198 | xfs_trans_t *tp, | 278 | xfs_trans_t *tp, |
| 199 | xfs_inode_t *dp, | 279 | xfs_inode_t *dp, |
| 200 | struct xfs_name *name, | 280 | struct xfs_name *name, |
| 201 | xfs_ino_t *inum) /* out: inode number */ | 281 | xfs_ino_t *inum, /* out: inode number */ |
| 282 | struct xfs_name *ci_name) /* out: actual name if CI match */ | ||
| 202 | { | 283 | { |
| 203 | xfs_da_args_t args; | 284 | xfs_da_args_t args; |
| 204 | int rval; | 285 | int rval; |
| @@ -206,15 +287,17 @@ xfs_dir_lookup( | |||
| 206 | 287 | ||
| 207 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | 288 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); |
| 208 | XFS_STATS_INC(xs_dir_lookup); | 289 | XFS_STATS_INC(xs_dir_lookup); |
| 209 | memset(&args, 0, sizeof(xfs_da_args_t)); | ||
| 210 | 290 | ||
| 291 | memset(&args, 0, sizeof(xfs_da_args_t)); | ||
| 211 | args.name = name->name; | 292 | args.name = name->name; |
| 212 | args.namelen = name->len; | 293 | args.namelen = name->len; |
| 213 | args.hashval = xfs_da_hashname(name->name, name->len); | 294 | args.hashval = dp->i_mount->m_dirnameops->hashname(name); |
| 214 | args.dp = dp; | 295 | args.dp = dp; |
| 215 | args.whichfork = XFS_DATA_FORK; | 296 | args.whichfork = XFS_DATA_FORK; |
| 216 | args.trans = tp; | 297 | args.trans = tp; |
| 217 | args.oknoent = 1; | 298 | args.op_flags = XFS_DA_OP_OKNOENT; |
| 299 | if (ci_name) | ||
| 300 | args.op_flags |= XFS_DA_OP_CILOOKUP; | ||
| 218 | 301 | ||
| 219 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 302 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
| 220 | rval = xfs_dir2_sf_lookup(&args); | 303 | rval = xfs_dir2_sf_lookup(&args); |
| @@ -230,8 +313,13 @@ xfs_dir_lookup( | |||
| 230 | rval = xfs_dir2_node_lookup(&args); | 313 | rval = xfs_dir2_node_lookup(&args); |
| 231 | if (rval == EEXIST) | 314 | if (rval == EEXIST) |
| 232 | rval = 0; | 315 | rval = 0; |
| 233 | if (rval == 0) | 316 | if (!rval) { |
| 234 | *inum = args.inumber; | 317 | *inum = args.inumber; |
| 318 | if (ci_name) { | ||
| 319 | ci_name->name = args.value; | ||
| 320 | ci_name->len = args.valuelen; | ||
| 321 | } | ||
| 322 | } | ||
| 235 | return rval; | 323 | return rval; |
| 236 | } | 324 | } |
| 237 | 325 | ||
| @@ -255,9 +343,10 @@ xfs_dir_removename( | |||
| 255 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | 343 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); |
| 256 | XFS_STATS_INC(xs_dir_remove); | 344 | XFS_STATS_INC(xs_dir_remove); |
| 257 | 345 | ||
| 346 | memset(&args, 0, sizeof(xfs_da_args_t)); | ||
| 258 | args.name = name->name; | 347 | args.name = name->name; |
| 259 | args.namelen = name->len; | 348 | args.namelen = name->len; |
| 260 | args.hashval = xfs_da_hashname(name->name, name->len); | 349 | args.hashval = dp->i_mount->m_dirnameops->hashname(name); |
| 261 | args.inumber = ino; | 350 | args.inumber = ino; |
| 262 | args.dp = dp; | 351 | args.dp = dp; |
| 263 | args.firstblock = first; | 352 | args.firstblock = first; |
| @@ -265,7 +354,6 @@ xfs_dir_removename( | |||
| 265 | args.total = total; | 354 | args.total = total; |
| 266 | args.whichfork = XFS_DATA_FORK; | 355 | args.whichfork = XFS_DATA_FORK; |
| 267 | args.trans = tp; | 356 | args.trans = tp; |
| 268 | args.justcheck = args.addname = args.oknoent = 0; | ||
| 269 | 357 | ||
| 270 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 358 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
| 271 | rval = xfs_dir2_sf_removename(&args); | 359 | rval = xfs_dir2_sf_removename(&args); |
| @@ -338,9 +426,10 @@ xfs_dir_replace( | |||
| 338 | if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) | 426 | if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) |
| 339 | return rval; | 427 | return rval; |
| 340 | 428 | ||
| 429 | memset(&args, 0, sizeof(xfs_da_args_t)); | ||
| 341 | args.name = name->name; | 430 | args.name = name->name; |
| 342 | args.namelen = name->len; | 431 | args.namelen = name->len; |
| 343 | args.hashval = xfs_da_hashname(name->name, name->len); | 432 | args.hashval = dp->i_mount->m_dirnameops->hashname(name); |
| 344 | args.inumber = inum; | 433 | args.inumber = inum; |
| 345 | args.dp = dp; | 434 | args.dp = dp; |
| 346 | args.firstblock = first; | 435 | args.firstblock = first; |
| @@ -348,7 +437,6 @@ xfs_dir_replace( | |||
| 348 | args.total = total; | 437 | args.total = total; |
| 349 | args.whichfork = XFS_DATA_FORK; | 438 | args.whichfork = XFS_DATA_FORK; |
| 350 | args.trans = tp; | 439 | args.trans = tp; |
| 351 | args.justcheck = args.addname = args.oknoent = 0; | ||
| 352 | 440 | ||
| 353 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 441 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
| 354 | rval = xfs_dir2_sf_replace(&args); | 442 | rval = xfs_dir2_sf_replace(&args); |
| @@ -384,15 +472,16 @@ xfs_dir_canenter( | |||
| 384 | return 0; | 472 | return 0; |
| 385 | 473 | ||
| 386 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | 474 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); |
| 387 | memset(&args, 0, sizeof(xfs_da_args_t)); | ||
| 388 | 475 | ||
| 476 | memset(&args, 0, sizeof(xfs_da_args_t)); | ||
| 389 | args.name = name->name; | 477 | args.name = name->name; |
| 390 | args.namelen = name->len; | 478 | args.namelen = name->len; |
| 391 | args.hashval = xfs_da_hashname(name->name, name->len); | 479 | args.hashval = dp->i_mount->m_dirnameops->hashname(name); |
| 392 | args.dp = dp; | 480 | args.dp = dp; |
| 393 | args.whichfork = XFS_DATA_FORK; | 481 | args.whichfork = XFS_DATA_FORK; |
| 394 | args.trans = tp; | 482 | args.trans = tp; |
| 395 | args.justcheck = args.addname = args.oknoent = 1; | 483 | args.op_flags = XFS_DA_OP_JUSTCHECK | XFS_DA_OP_ADDNAME | |
| 484 | XFS_DA_OP_OKNOENT; | ||
| 396 | 485 | ||
| 397 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 486 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
| 398 | rval = xfs_dir2_sf_addname(&args); | 487 | rval = xfs_dir2_sf_addname(&args); |
| @@ -493,7 +582,7 @@ xfs_dir2_grow_inode( | |||
| 493 | args->firstblock, args->total, | 582 | args->firstblock, args->total, |
| 494 | &mapp[mapi], &nmap, args->flist, | 583 | &mapp[mapi], &nmap, args->flist, |
| 495 | NULL))) { | 584 | NULL))) { |
| 496 | kmem_free(mapp, sizeof(*mapp) * count); | 585 | kmem_free(mapp); |
| 497 | return error; | 586 | return error; |
| 498 | } | 587 | } |
| 499 | if (nmap < 1) | 588 | if (nmap < 1) |
| @@ -525,14 +614,14 @@ xfs_dir2_grow_inode( | |||
| 525 | mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount != | 614 | mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount != |
| 526 | bno + count) { | 615 | bno + count) { |
| 527 | if (mapp != &map) | 616 | if (mapp != &map) |
| 528 | kmem_free(mapp, sizeof(*mapp) * count); | 617 | kmem_free(mapp); |
| 529 | return XFS_ERROR(ENOSPC); | 618 | return XFS_ERROR(ENOSPC); |
| 530 | } | 619 | } |
| 531 | /* | 620 | /* |
| 532 | * Done with the temporary mapping table. | 621 | * Done with the temporary mapping table. |
| 533 | */ | 622 | */ |
| 534 | if (mapp != &map) | 623 | if (mapp != &map) |
| 535 | kmem_free(mapp, sizeof(*mapp) * count); | 624 | kmem_free(mapp); |
| 536 | *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno); | 625 | *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno); |
| 537 | /* | 626 | /* |
| 538 | * Update file's size if this is the data space and it grew. | 627 | * Update file's size if this is the data space and it grew. |
