|
Lines 43-54
Link Here
|
| 43 |
* |
43 |
* |
| 44 |
* Locking strategy |
44 |
* Locking strategy |
| 45 |
* ---------------- |
45 |
* ---------------- |
| 46 |
* EXT3_I(inode)->i_file_acl is protected by EXT3_I(inode)->xattr_sem. |
46 |
* As a minimal fix of a race with the mbcache, we are using a global |
| 47 |
* EA blocks are only changed if they are exclusive to an inode, so |
47 |
* readers/writer semaphore (http://linux.bkbits.net:8080/linux-2.6/ |
| 48 |
* holding xattr_sem also means that nothing but the EA block's reference |
48 |
* cset@41e9a8dde680BhQtidQ5PNNkGXHKMQ?nav=index.html|ChangeSet@-8w |
| 49 |
* count will change. Multiple writers to an EA block are synchronized |
49 |
* explains the problem). |
| 50 |
* by the bh lock. No more than a single bh lock is held at any time, |
|
|
| 51 |
* which avoids deadlocks. |
| 52 |
*/ |
50 |
*/ |
| 53 |
|
51 |
|
| 54 |
#include <linux/fs.h> |
52 |
#include <linux/fs.h> |
|
Lines 84-89
Link Here
|
| 84 |
# define ea_bdebug(f...) |
82 |
# define ea_bdebug(f...) |
| 85 |
#endif |
83 |
#endif |
| 86 |
|
84 |
|
|
|
85 |
static DECLARE_RWSEM(ext3_xattr_sem); |
| 86 |
|
| 87 |
static int ext3_xattr_set_handle2(handle_t *, struct inode *, |
87 |
static int ext3_xattr_set_handle2(handle_t *, struct inode *, |
| 88 |
struct buffer_head *, |
88 |
struct buffer_head *, |
| 89 |
struct ext3_xattr_header *); |
89 |
struct ext3_xattr_header *); |
|
Lines 280-286
ext3_xattr_get(struct inode *inode, int
Link Here
|
| 280 |
|
280 |
|
| 281 |
if (name == NULL) |
281 |
if (name == NULL) |
| 282 |
return -EINVAL; |
282 |
return -EINVAL; |
| 283 |
down_read(&EXT3_I(inode)->xattr_sem); |
283 |
down_read(&ext3_xattr_sem); |
| 284 |
error = -ENODATA; |
284 |
error = -ENODATA; |
| 285 |
if (!EXT3_I(inode)->i_file_acl) |
285 |
if (!EXT3_I(inode)->i_file_acl) |
| 286 |
goto cleanup; |
286 |
goto cleanup; |
|
Lines 353-359
found:
Link Here
|
| 353 |
|
353 |
|
| 354 |
cleanup: |
354 |
cleanup: |
| 355 |
brelse(bh); |
355 |
brelse(bh); |
| 356 |
up_read(&EXT3_I(inode)->xattr_sem); |
356 |
up_read(&ext3_xattr_sem); |
| 357 |
|
357 |
|
| 358 |
return error; |
358 |
return error; |
| 359 |
} |
359 |
} |
|
Lines 380-386
ext3_xattr_list(struct inode *inode, cha
Link Here
|
| 380 |
ea_idebug(inode, "buffer=%p, buffer_size=%ld", |
380 |
ea_idebug(inode, "buffer=%p, buffer_size=%ld", |
| 381 |
buffer, (long)buffer_size); |
381 |
buffer, (long)buffer_size); |
| 382 |
|
382 |
|
| 383 |
down_read(&EXT3_I(inode)->xattr_sem); |
383 |
down_read(&ext3_xattr_sem); |
| 384 |
error = 0; |
384 |
error = 0; |
| 385 |
if (!EXT3_I(inode)->i_file_acl) |
385 |
if (!EXT3_I(inode)->i_file_acl) |
| 386 |
goto cleanup; |
386 |
goto cleanup; |
|
Lines 441-447
bad_block: ext3_error(inode->i_sb, "ext3
Link Here
|
| 441 |
|
441 |
|
| 442 |
cleanup: |
442 |
cleanup: |
| 443 |
brelse(bh); |
443 |
brelse(bh); |
| 444 |
up_read(&EXT3_I(inode)->xattr_sem); |
444 |
up_read(&ext3_xattr_sem); |
| 445 |
|
445 |
|
| 446 |
return error; |
446 |
return error; |
| 447 |
} |
447 |
} |
|
Lines 517-523
ext3_xattr_set_handle(handle_t *handle,
Link Here
|
| 517 |
name_len = strlen(name); |
517 |
name_len = strlen(name); |
| 518 |
if (name_len > 255 || value_len > sb->s_blocksize) |
518 |
if (name_len > 255 || value_len > sb->s_blocksize) |
| 519 |
return -ERANGE; |
519 |
return -ERANGE; |
| 520 |
down_write(&EXT3_I(inode)->xattr_sem); |
520 |
down_write(&ext3_xattr_sem); |
| 521 |
if (EXT3_I(inode)->i_file_acl) { |
521 |
if (EXT3_I(inode)->i_file_acl) { |
| 522 |
/* The inode already has an extended attribute block. */ |
522 |
/* The inode already has an extended attribute block. */ |
| 523 |
bh = sb_bread(sb, EXT3_I(inode)->i_file_acl); |
523 |
bh = sb_bread(sb, EXT3_I(inode)->i_file_acl); |
|
Lines 740-746
cleanup:
Link Here
|
| 740 |
brelse(bh); |
740 |
brelse(bh); |
| 741 |
if (!(bh && header == HDR(bh))) |
741 |
if (!(bh && header == HDR(bh))) |
| 742 |
kfree(header); |
742 |
kfree(header); |
| 743 |
up_write(&EXT3_I(inode)->xattr_sem); |
743 |
up_write(&ext3_xattr_sem); |
| 744 |
|
744 |
|
| 745 |
return error; |
745 |
return error; |
| 746 |
} |
746 |
} |
|
Lines 911-917
ext3_xattr_delete_inode(handle_t *handle
Link Here
|
| 911 |
{ |
911 |
{ |
| 912 |
struct buffer_head *bh = NULL; |
912 |
struct buffer_head *bh = NULL; |
| 913 |
|
913 |
|
| 914 |
down_write(&EXT3_I(inode)->xattr_sem); |
914 |
down_write(&ext3_xattr_sem); |
| 915 |
if (!EXT3_I(inode)->i_file_acl) |
915 |
if (!EXT3_I(inode)->i_file_acl) |
| 916 |
goto cleanup; |
916 |
goto cleanup; |
| 917 |
bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl); |
917 |
bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl); |
|
Lines 954-960
ext3_xattr_delete_inode(handle_t *handle
Link Here
|
| 954 |
|
954 |
|
| 955 |
cleanup: |
955 |
cleanup: |
| 956 |
brelse(bh); |
956 |
brelse(bh); |
| 957 |
up_write(&EXT3_I(inode)->xattr_sem); |
957 |
up_write(&ext3_xattr_sem); |
| 958 |
} |
958 |
} |
| 959 |
|
959 |
|
| 960 |
/* |
960 |
/* |