diff options
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/Kconfig | 85 | ||||
-rw-r--r-- | fs/ocfs2/alloc.c | 33 | ||||
-rw-r--r-- | fs/ocfs2/aops.c | 7 | ||||
-rw-r--r-- | fs/ocfs2/dcache.c | 42 | ||||
-rw-r--r-- | fs/ocfs2/dcache.h | 9 | ||||
-rw-r--r-- | fs/ocfs2/dlm/dlmmaster.c | 12 | ||||
-rw-r--r-- | fs/ocfs2/dlm/dlmthread.c | 3 | ||||
-rw-r--r-- | fs/ocfs2/dlm/dlmunlock.c | 4 | ||||
-rw-r--r-- | fs/ocfs2/dlmglue.c | 15 | ||||
-rw-r--r-- | fs/ocfs2/journal.h | 6 | ||||
-rw-r--r-- | fs/ocfs2/namei.c | 3 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2.h | 9 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2_fs.h | 6 | ||||
-rw-r--r-- | fs/ocfs2/quota_global.c | 173 | ||||
-rw-r--r-- | fs/ocfs2/super.c | 11 | ||||
-rw-r--r-- | fs/ocfs2/xattr.c | 74 |
16 files changed, 269 insertions, 223 deletions
diff --git a/fs/ocfs2/Kconfig b/fs/ocfs2/Kconfig new file mode 100644 index 000000000000..701b7a3a872e --- /dev/null +++ b/fs/ocfs2/Kconfig | |||
@@ -0,0 +1,85 @@ | |||
1 | config OCFS2_FS | ||
2 | tristate "OCFS2 file system support" | ||
3 | depends on NET && SYSFS | ||
4 | select CONFIGFS_FS | ||
5 | select JBD2 | ||
6 | select CRC32 | ||
7 | select QUOTA | ||
8 | select QUOTA_TREE | ||
9 | help | ||
10 | OCFS2 is a general purpose extent based shared disk cluster file | ||
11 | system with many similarities to ext3. It supports 64 bit inode | ||
12 | numbers, and has automatically extending metadata groups which may | ||
13 | also make it attractive for non-clustered use. | ||
14 | |||
15 | You'll want to install the ocfs2-tools package in order to at least | ||
16 | get "mount.ocfs2". | ||
17 | |||
18 | Project web page: http://oss.oracle.com/projects/ocfs2 | ||
19 | Tools web page: http://oss.oracle.com/projects/ocfs2-tools | ||
20 | OCFS2 mailing lists: http://oss.oracle.com/projects/ocfs2/mailman/ | ||
21 | |||
22 | For more information on OCFS2, see the file | ||
23 | <file:Documentation/filesystems/ocfs2.txt>. | ||
24 | |||
25 | config OCFS2_FS_O2CB | ||
26 | tristate "O2CB Kernelspace Clustering" | ||
27 | depends on OCFS2_FS | ||
28 | default y | ||
29 | help | ||
30 | OCFS2 includes a simple kernelspace clustering package, the OCFS2 | ||
31 | Cluster Base. It only requires a very small userspace component | ||
32 | to configure it. This comes with the standard ocfs2-tools package. | ||
33 | O2CB is limited to maintaining a cluster for OCFS2 file systems. | ||
34 | It cannot manage any other cluster applications. | ||
35 | |||
36 | It is always safe to say Y here, as the clustering method is | ||
37 | run-time selectable. | ||
38 | |||
39 | config OCFS2_FS_USERSPACE_CLUSTER | ||
40 | tristate "OCFS2 Userspace Clustering" | ||
41 | depends on OCFS2_FS && DLM | ||
42 | default y | ||
43 | help | ||
44 | This option will allow OCFS2 to use userspace clustering services | ||
45 | in conjunction with the DLM in fs/dlm. If you are using a | ||
46 | userspace cluster manager, say Y here. | ||
47 | |||
48 | It is safe to say Y, as the clustering method is run-time | ||
49 | selectable. | ||
50 | |||
51 | config OCFS2_FS_STATS | ||
52 | bool "OCFS2 statistics" | ||
53 | depends on OCFS2_FS | ||
54 | default y | ||
55 | help | ||
56 | This option allows some fs statistics to be captured. Enabling | ||
57 | this option may increase the memory consumption. | ||
58 | |||
59 | config OCFS2_DEBUG_MASKLOG | ||
60 | bool "OCFS2 logging support" | ||
61 | depends on OCFS2_FS | ||
62 | default y | ||
63 | help | ||
64 | The ocfs2 filesystem has an extensive logging system. The system | ||
65 | allows selection of events to log via files in /sys/o2cb/logmask/. | ||
66 | This option will enlarge your kernel, but it allows debugging of | ||
67 | ocfs2 filesystem issues. | ||
68 | |||
69 | config OCFS2_DEBUG_FS | ||
70 | bool "OCFS2 expensive checks" | ||
71 | depends on OCFS2_FS | ||
72 | default n | ||
73 | help | ||
74 | This option will enable expensive consistency checks. Enable | ||
75 | this option for debugging only as it is likely to decrease | ||
76 | performance of the filesystem. | ||
77 | |||
78 | config OCFS2_FS_POSIX_ACL | ||
79 | bool "OCFS2 POSIX Access Control Lists" | ||
80 | depends on OCFS2_FS | ||
81 | select FS_POSIX_ACL | ||
82 | default n | ||
83 | help | ||
84 | Posix Access Control Lists (ACLs) support permissions for users and | ||
85 | groups beyond the owner/group/world scheme. | ||
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index d861096c9d81..19e3a96aa02c 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -176,7 +176,8 @@ static int ocfs2_dinode_insert_check(struct inode *inode, | |||
176 | 176 | ||
177 | BUG_ON(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL); | 177 | BUG_ON(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL); |
178 | mlog_bug_on_msg(!ocfs2_sparse_alloc(osb) && | 178 | mlog_bug_on_msg(!ocfs2_sparse_alloc(osb) && |
179 | (OCFS2_I(inode)->ip_clusters != rec->e_cpos), | 179 | (OCFS2_I(inode)->ip_clusters != |
180 | le32_to_cpu(rec->e_cpos)), | ||
180 | "Device %s, asking for sparse allocation: inode %llu, " | 181 | "Device %s, asking for sparse allocation: inode %llu, " |
181 | "cpos %u, clusters %u\n", | 182 | "cpos %u, clusters %u\n", |
182 | osb->dev_str, | 183 | osb->dev_str, |
@@ -4796,6 +4797,29 @@ out: | |||
4796 | return ret; | 4797 | return ret; |
4797 | } | 4798 | } |
4798 | 4799 | ||
4800 | static int ocfs2_replace_extent_rec(struct inode *inode, | ||
4801 | handle_t *handle, | ||
4802 | struct ocfs2_path *path, | ||
4803 | struct ocfs2_extent_list *el, | ||
4804 | int split_index, | ||
4805 | struct ocfs2_extent_rec *split_rec) | ||
4806 | { | ||
4807 | int ret; | ||
4808 | |||
4809 | ret = ocfs2_path_bh_journal_access(handle, inode, path, | ||
4810 | path_num_items(path) - 1); | ||
4811 | if (ret) { | ||
4812 | mlog_errno(ret); | ||
4813 | goto out; | ||
4814 | } | ||
4815 | |||
4816 | el->l_recs[split_index] = *split_rec; | ||
4817 | |||
4818 | ocfs2_journal_dirty(handle, path_leaf_bh(path)); | ||
4819 | out: | ||
4820 | return ret; | ||
4821 | } | ||
4822 | |||
4799 | /* | 4823 | /* |
4800 | * Mark part or all of the extent record at split_index in the leaf | 4824 | * Mark part or all of the extent record at split_index in the leaf |
4801 | * pointed to by path as written. This removes the unwritten | 4825 | * pointed to by path as written. This removes the unwritten |
@@ -4885,7 +4909,9 @@ static int __ocfs2_mark_extent_written(struct inode *inode, | |||
4885 | 4909 | ||
4886 | if (ctxt.c_contig_type == CONTIG_NONE) { | 4910 | if (ctxt.c_contig_type == CONTIG_NONE) { |
4887 | if (ctxt.c_split_covers_rec) | 4911 | if (ctxt.c_split_covers_rec) |
4888 | el->l_recs[split_index] = *split_rec; | 4912 | ret = ocfs2_replace_extent_rec(inode, handle, |
4913 | path, el, | ||
4914 | split_index, split_rec); | ||
4889 | else | 4915 | else |
4890 | ret = ocfs2_split_and_insert(inode, handle, path, et, | 4916 | ret = ocfs2_split_and_insert(inode, handle, path, et, |
4891 | &last_eb_bh, split_index, | 4917 | &last_eb_bh, split_index, |
@@ -5390,6 +5416,9 @@ int ocfs2_remove_btree_range(struct inode *inode, | |||
5390 | goto out; | 5416 | goto out; |
5391 | } | 5417 | } |
5392 | 5418 | ||
5419 | vfs_dq_free_space_nodirty(inode, | ||
5420 | ocfs2_clusters_to_bytes(inode->i_sb, len)); | ||
5421 | |||
5393 | ret = ocfs2_remove_extent(inode, et, cpos, len, handle, meta_ac, | 5422 | ret = ocfs2_remove_extent(inode, et, cpos, len, handle, meta_ac, |
5394 | dealloc); | 5423 | dealloc); |
5395 | if (ret) { | 5424 | if (ret) { |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index a067a6cffb01..8e1709a679b7 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -227,7 +227,7 @@ int ocfs2_read_inline_data(struct inode *inode, struct page *page, | |||
227 | size = i_size_read(inode); | 227 | size = i_size_read(inode); |
228 | 228 | ||
229 | if (size > PAGE_CACHE_SIZE || | 229 | if (size > PAGE_CACHE_SIZE || |
230 | size > ocfs2_max_inline_data(inode->i_sb)) { | 230 | size > ocfs2_max_inline_data_with_xattr(inode->i_sb, di)) { |
231 | ocfs2_error(inode->i_sb, | 231 | ocfs2_error(inode->i_sb, |
232 | "Inode %llu has with inline data has bad size: %Lu", | 232 | "Inode %llu has with inline data has bad size: %Lu", |
233 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | 233 | (unsigned long long)OCFS2_I(inode)->ip_blkno, |
@@ -1555,6 +1555,7 @@ static int ocfs2_try_to_write_inline_data(struct address_space *mapping, | |||
1555 | int ret, written = 0; | 1555 | int ret, written = 0; |
1556 | loff_t end = pos + len; | 1556 | loff_t end = pos + len; |
1557 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 1557 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
1558 | struct ocfs2_dinode *di = NULL; | ||
1558 | 1559 | ||
1559 | mlog(0, "Inode %llu, write of %u bytes at off %llu. features: 0x%x\n", | 1560 | mlog(0, "Inode %llu, write of %u bytes at off %llu. features: 0x%x\n", |
1560 | (unsigned long long)oi->ip_blkno, len, (unsigned long long)pos, | 1561 | (unsigned long long)oi->ip_blkno, len, (unsigned long long)pos, |
@@ -1587,7 +1588,9 @@ static int ocfs2_try_to_write_inline_data(struct address_space *mapping, | |||
1587 | /* | 1588 | /* |
1588 | * Check whether the write can fit. | 1589 | * Check whether the write can fit. |
1589 | */ | 1590 | */ |
1590 | if (mmap_page || end > ocfs2_max_inline_data(inode->i_sb)) | 1591 | di = (struct ocfs2_dinode *)wc->w_di_bh->b_data; |
1592 | if (mmap_page || | ||
1593 | end > ocfs2_max_inline_data_with_xattr(inode->i_sb, di)) | ||
1591 | return 0; | 1594 | return 0; |
1592 | 1595 | ||
1593 | do_inline_write: | 1596 | do_inline_write: |
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index b1cc7c381e88..e9d7c2038c0f 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include "dlmglue.h" | 38 | #include "dlmglue.h" |
39 | #include "file.h" | 39 | #include "file.h" |
40 | #include "inode.h" | 40 | #include "inode.h" |
41 | #include "super.h" | ||
41 | 42 | ||
42 | 43 | ||
43 | static int ocfs2_dentry_revalidate(struct dentry *dentry, | 44 | static int ocfs2_dentry_revalidate(struct dentry *dentry, |
@@ -294,6 +295,34 @@ out_attach: | |||
294 | return ret; | 295 | return ret; |
295 | } | 296 | } |
296 | 297 | ||
298 | static DEFINE_SPINLOCK(dentry_list_lock); | ||
299 | |||
300 | /* We limit the number of dentry locks to drop in one go. We have | ||
301 | * this limit so that we don't starve other users of ocfs2_wq. */ | ||
302 | #define DL_INODE_DROP_COUNT 64 | ||
303 | |||
304 | /* Drop inode references from dentry locks */ | ||
305 | void ocfs2_drop_dl_inodes(struct work_struct *work) | ||
306 | { | ||
307 | struct ocfs2_super *osb = container_of(work, struct ocfs2_super, | ||
308 | dentry_lock_work); | ||
309 | struct ocfs2_dentry_lock *dl; | ||
310 | int drop_count = DL_INODE_DROP_COUNT; | ||
311 | |||
312 | spin_lock(&dentry_list_lock); | ||
313 | while (osb->dentry_lock_list && drop_count--) { | ||
314 | dl = osb->dentry_lock_list; | ||
315 | osb->dentry_lock_list = dl->dl_next; | ||
316 | spin_unlock(&dentry_list_lock); | ||
317 | iput(dl->dl_inode); | ||
318 | kfree(dl); | ||
319 | spin_lock(&dentry_list_lock); | ||
320 | } | ||
321 | if (osb->dentry_lock_list) | ||
322 | queue_work(ocfs2_wq, &osb->dentry_lock_work); | ||
323 | spin_unlock(&dentry_list_lock); | ||
324 | } | ||
325 | |||
297 | /* | 326 | /* |
298 | * ocfs2_dentry_iput() and friends. | 327 | * ocfs2_dentry_iput() and friends. |
299 | * | 328 | * |
@@ -318,16 +347,23 @@ out_attach: | |||
318 | static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, | 347 | static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, |
319 | struct ocfs2_dentry_lock *dl) | 348 | struct ocfs2_dentry_lock *dl) |
320 | { | 349 | { |
321 | iput(dl->dl_inode); | ||
322 | ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); | 350 | ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); |
323 | ocfs2_lock_res_free(&dl->dl_lockres); | 351 | ocfs2_lock_res_free(&dl->dl_lockres); |
324 | kfree(dl); | 352 | |
353 | /* We leave dropping of inode reference to ocfs2_wq as that can | ||
354 | * possibly lead to inode deletion which gets tricky */ | ||
355 | spin_lock(&dentry_list_lock); | ||
356 | if (!osb->dentry_lock_list) | ||
357 | queue_work(ocfs2_wq, &osb->dentry_lock_work); | ||
358 | dl->dl_next = osb->dentry_lock_list; | ||
359 | osb->dentry_lock_list = dl; | ||
360 | spin_unlock(&dentry_list_lock); | ||
325 | } | 361 | } |
326 | 362 | ||
327 | void ocfs2_dentry_lock_put(struct ocfs2_super *osb, | 363 | void ocfs2_dentry_lock_put(struct ocfs2_super *osb, |
328 | struct ocfs2_dentry_lock *dl) | 364 | struct ocfs2_dentry_lock *dl) |
329 | { | 365 | { |
330 | int unlock = 0; | 366 | int unlock; |
331 | 367 | ||
332 | BUG_ON(dl->dl_count == 0); | 368 | BUG_ON(dl->dl_count == 0); |
333 | 369 | ||
diff --git a/fs/ocfs2/dcache.h b/fs/ocfs2/dcache.h index c091c34d9883..d06e16c06640 100644 --- a/fs/ocfs2/dcache.h +++ b/fs/ocfs2/dcache.h | |||
@@ -29,8 +29,13 @@ | |||
29 | extern struct dentry_operations ocfs2_dentry_ops; | 29 | extern struct dentry_operations ocfs2_dentry_ops; |
30 | 30 | ||
31 | struct ocfs2_dentry_lock { | 31 | struct ocfs2_dentry_lock { |
32 | /* Use count of dentry lock */ | ||
32 | unsigned int dl_count; | 33 | unsigned int dl_count; |
33 | u64 dl_parent_blkno; | 34 | union { |
35 | /* Linked list of dentry locks to release */ | ||
36 | struct ocfs2_dentry_lock *dl_next; | ||
37 | u64 dl_parent_blkno; | ||
38 | }; | ||
34 | 39 | ||
35 | /* | 40 | /* |
36 | * The ocfs2_dentry_lock keeps an inode reference until | 41 | * The ocfs2_dentry_lock keeps an inode reference until |
@@ -47,6 +52,8 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode, | |||
47 | void ocfs2_dentry_lock_put(struct ocfs2_super *osb, | 52 | void ocfs2_dentry_lock_put(struct ocfs2_super *osb, |
48 | struct ocfs2_dentry_lock *dl); | 53 | struct ocfs2_dentry_lock *dl); |
49 | 54 | ||
55 | void ocfs2_drop_dl_inodes(struct work_struct *work); | ||
56 | |||
50 | struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno, | 57 | struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno, |
51 | int skip_unhashed); | 58 | int skip_unhashed); |
52 | 59 | ||
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 54e182a27caf..0a2813947853 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c | |||
@@ -1849,12 +1849,12 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data, | |||
1849 | if (!mle) { | 1849 | if (!mle) { |
1850 | if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN && | 1850 | if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN && |
1851 | res->owner != assert->node_idx) { | 1851 | res->owner != assert->node_idx) { |
1852 | mlog(ML_ERROR, "assert_master from " | 1852 | mlog(ML_ERROR, "DIE! Mastery assert from %u, " |
1853 | "%u, but current owner is " | 1853 | "but current owner is %u! (%.*s)\n", |
1854 | "%u! (%.*s)\n", | 1854 | assert->node_idx, res->owner, namelen, |
1855 | assert->node_idx, res->owner, | 1855 | name); |
1856 | namelen, name); | 1856 | __dlm_print_one_lock_resource(res); |
1857 | goto kill; | 1857 | BUG(); |
1858 | } | 1858 | } |
1859 | } else if (mle->type != DLM_MLE_MIGRATION) { | 1859 | } else if (mle->type != DLM_MLE_MIGRATION) { |
1860 | if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN) { | 1860 | if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN) { |
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c index d1295203029f..4060bb328bc8 100644 --- a/fs/ocfs2/dlm/dlmthread.c +++ b/fs/ocfs2/dlm/dlmthread.c | |||
@@ -181,8 +181,7 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm, | |||
181 | 181 | ||
182 | spin_lock(&res->spinlock); | 182 | spin_lock(&res->spinlock); |
183 | /* This ensures that clear refmap is sent after the set */ | 183 | /* This ensures that clear refmap is sent after the set */ |
184 | __dlm_wait_on_lockres_flags(res, (DLM_LOCK_RES_SETREF_INPROG | | 184 | __dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG); |
185 | DLM_LOCK_RES_MIGRATING)); | ||
186 | spin_unlock(&res->spinlock); | 185 | spin_unlock(&res->spinlock); |
187 | 186 | ||
188 | /* clear our bit from the master's refmap, ignore errors */ | 187 | /* clear our bit from the master's refmap, ignore errors */ |
diff --git a/fs/ocfs2/dlm/dlmunlock.c b/fs/ocfs2/dlm/dlmunlock.c index 86ca085ef324..fcf879ed6930 100644 --- a/fs/ocfs2/dlm/dlmunlock.c +++ b/fs/ocfs2/dlm/dlmunlock.c | |||
@@ -117,11 +117,11 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm, | |||
117 | else | 117 | else |
118 | BUG_ON(res->owner == dlm->node_num); | 118 | BUG_ON(res->owner == dlm->node_num); |
119 | 119 | ||
120 | spin_lock(&dlm->spinlock); | 120 | spin_lock(&dlm->ast_lock); |
121 | /* We want to be sure that we're not freeing a lock | 121 | /* We want to be sure that we're not freeing a lock |
122 | * that still has AST's pending... */ | 122 | * that still has AST's pending... */ |
123 | in_use = !list_empty(&lock->ast_list); | 123 | in_use = !list_empty(&lock->ast_list); |
124 | spin_unlock(&dlm->spinlock); | 124 | spin_unlock(&dlm->ast_lock); |
125 | if (in_use) { | 125 | if (in_use) { |
126 | mlog(ML_ERROR, "lockres %.*s: Someone is calling dlmunlock " | 126 | mlog(ML_ERROR, "lockres %.*s: Someone is calling dlmunlock " |
127 | "while waiting for an ast!", res->lockname.len, | 127 | "while waiting for an ast!", res->lockname.len, |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index b0c4cadd4c45..7219a86d34cc 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -320,9 +320,14 @@ static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb, | |||
320 | struct ocfs2_lock_res *lockres); | 320 | struct ocfs2_lock_res *lockres); |
321 | static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, | 321 | static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, |
322 | int convert); | 322 | int convert); |
323 | #define ocfs2_log_dlm_error(_func, _err, _lockres) do { \ | 323 | #define ocfs2_log_dlm_error(_func, _err, _lockres) do { \ |
324 | mlog(ML_ERROR, "DLM error %d while calling %s on resource %s\n", \ | 324 | if ((_lockres)->l_type != OCFS2_LOCK_TYPE_DENTRY) \ |
325 | _err, _func, _lockres->l_name); \ | 325 | mlog(ML_ERROR, "DLM error %d while calling %s on resource %s\n", \ |
326 | _err, _func, _lockres->l_name); \ | ||
327 | else \ | ||
328 | mlog(ML_ERROR, "DLM error %d while calling %s on resource %.*s%08x\n", \ | ||
329 | _err, _func, OCFS2_DENTRY_LOCK_INO_START - 1, (_lockres)->l_name, \ | ||
330 | (unsigned int)ocfs2_get_dentry_lock_ino(_lockres)); \ | ||
326 | } while (0) | 331 | } while (0) |
327 | static int ocfs2_downconvert_thread(void *arg); | 332 | static int ocfs2_downconvert_thread(void *arg); |
328 | static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb, | 333 | static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb, |
@@ -2860,6 +2865,10 @@ static void ocfs2_unlock_ast(void *opaque, int error) | |||
2860 | case OCFS2_UNLOCK_CANCEL_CONVERT: | 2865 | case OCFS2_UNLOCK_CANCEL_CONVERT: |
2861 | mlog(0, "Cancel convert success for %s\n", lockres->l_name); | 2866 | mlog(0, "Cancel convert success for %s\n", lockres->l_name); |
2862 | lockres->l_action = OCFS2_AST_INVALID; | 2867 | lockres->l_action = OCFS2_AST_INVALID; |
2868 | /* Downconvert thread may have requeued this lock, we | ||
2869 | * need to wake it. */ | ||
2870 | if (lockres->l_flags & OCFS2_LOCK_BLOCKED) | ||
2871 | ocfs2_wake_downconvert_thread(ocfs2_get_lockres_osb(lockres)); | ||
2863 | break; | 2872 | break; |
2864 | case OCFS2_UNLOCK_DROP_LOCK: | 2873 | case OCFS2_UNLOCK_DROP_LOCK: |
2865 | lockres->l_level = DLM_LOCK_IV; | 2874 | lockres->l_level = DLM_LOCK_IV; |
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 3c3532e1307c..172850a9a12a 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h | |||
@@ -513,8 +513,10 @@ static inline int ocfs2_jbd2_file_inode(handle_t *handle, struct inode *inode) | |||
513 | static inline int ocfs2_begin_ordered_truncate(struct inode *inode, | 513 | static inline int ocfs2_begin_ordered_truncate(struct inode *inode, |
514 | loff_t new_size) | 514 | loff_t new_size) |
515 | { | 515 | { |
516 | return jbd2_journal_begin_ordered_truncate(&OCFS2_I(inode)->ip_jinode, | 516 | return jbd2_journal_begin_ordered_truncate( |
517 | new_size); | 517 | OCFS2_SB(inode->i_sb)->journal->j_journal, |
518 | &OCFS2_I(inode)->ip_jinode, | ||
519 | new_size); | ||
518 | } | 520 | } |
519 | 521 | ||
520 | #endif /* OCFS2_JOURNAL_H */ | 522 | #endif /* OCFS2_JOURNAL_H */ |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 084aba86c3b2..4b11762f249e 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -532,7 +532,8 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, | |||
532 | 532 | ||
533 | fe->i_dyn_features = cpu_to_le16(feat | OCFS2_INLINE_DATA_FL); | 533 | fe->i_dyn_features = cpu_to_le16(feat | OCFS2_INLINE_DATA_FL); |
534 | 534 | ||
535 | fe->id2.i_data.id_count = cpu_to_le16(ocfs2_max_inline_data(osb->sb)); | 535 | fe->id2.i_data.id_count = cpu_to_le16( |
536 | ocfs2_max_inline_data_with_xattr(osb->sb, fe)); | ||
536 | } else { | 537 | } else { |
537 | fel = &fe->id2.i_list; | 538 | fel = &fe->id2.i_list; |
538 | fel->l_tree_depth = 0; | 539 | fel->l_tree_depth = 0; |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index ad5c24a29edd..946d3c34b90b 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -210,6 +210,7 @@ struct ocfs2_journal; | |||
210 | struct ocfs2_slot_info; | 210 | struct ocfs2_slot_info; |
211 | struct ocfs2_recovery_map; | 211 | struct ocfs2_recovery_map; |
212 | struct ocfs2_quota_recovery; | 212 | struct ocfs2_quota_recovery; |
213 | struct ocfs2_dentry_lock; | ||
213 | struct ocfs2_super | 214 | struct ocfs2_super |
214 | { | 215 | { |
215 | struct task_struct *commit_task; | 216 | struct task_struct *commit_task; |
@@ -325,6 +326,11 @@ struct ocfs2_super | |||
325 | struct list_head blocked_lock_list; | 326 | struct list_head blocked_lock_list; |
326 | unsigned long blocked_lock_count; | 327 | unsigned long blocked_lock_count; |
327 | 328 | ||
329 | /* List of dentry locks to release. Anyone can add locks to | ||
330 | * the list, ocfs2_wq processes the list */ | ||
331 | struct ocfs2_dentry_lock *dentry_lock_list; | ||
332 | struct work_struct dentry_lock_work; | ||
333 | |||
328 | wait_queue_head_t osb_mount_event; | 334 | wait_queue_head_t osb_mount_event; |
329 | 335 | ||
330 | /* Truncate log info */ | 336 | /* Truncate log info */ |
@@ -335,6 +341,9 @@ struct ocfs2_super | |||
335 | struct ocfs2_node_map osb_recovering_orphan_dirs; | 341 | struct ocfs2_node_map osb_recovering_orphan_dirs; |
336 | unsigned int *osb_orphan_wipes; | 342 | unsigned int *osb_orphan_wipes; |
337 | wait_queue_head_t osb_wipe_event; | 343 | wait_queue_head_t osb_wipe_event; |
344 | |||
345 | /* used to protect metaecc calculation check of xattr. */ | ||
346 | spinlock_t osb_xattr_lock; | ||
338 | }; | 347 | }; |
339 | 348 | ||
340 | #define OCFS2_SB(sb) ((struct ocfs2_super *)(sb)->s_fs_info) | 349 | #define OCFS2_SB(sb) ((struct ocfs2_super *)(sb)->s_fs_info) |
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index c7ae45aaa36c..2332ef740f4f 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h | |||
@@ -1070,12 +1070,6 @@ static inline int ocfs2_fast_symlink_chars(struct super_block *sb) | |||
1070 | offsetof(struct ocfs2_dinode, id2.i_symlink); | 1070 | offsetof(struct ocfs2_dinode, id2.i_symlink); |
1071 | } | 1071 | } |
1072 | 1072 | ||
1073 | static inline int ocfs2_max_inline_data(struct super_block *sb) | ||
1074 | { | ||
1075 | return sb->s_blocksize - | ||
1076 | offsetof(struct ocfs2_dinode, id2.i_data.id_data); | ||
1077 | } | ||
1078 | |||
1079 | static inline int ocfs2_max_inline_data_with_xattr(struct super_block *sb, | 1073 | static inline int ocfs2_max_inline_data_with_xattr(struct super_block *sb, |
1080 | struct ocfs2_dinode *di) | 1074 | struct ocfs2_dinode *di) |
1081 | { | 1075 | { |
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 6aff8f2d3e49..1ed0f7c86869 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c | |||
@@ -754,7 +754,9 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) | |||
754 | if (dquot->dq_flags & mask) | 754 | if (dquot->dq_flags & mask) |
755 | sync = 1; | 755 | sync = 1; |
756 | spin_unlock(&dq_data_lock); | 756 | spin_unlock(&dq_data_lock); |
757 | if (!sync) { | 757 | /* This is a slight hack but we can't afford getting global quota |
758 | * lock if we already have a transaction started. */ | ||
759 | if (!sync || journal_current_handle()) { | ||
758 | status = ocfs2_write_dquot(dquot); | 760 | status = ocfs2_write_dquot(dquot); |
759 | goto out; | 761 | goto out; |
760 | } | 762 | } |
@@ -810,171 +812,6 @@ out: | |||
810 | return status; | 812 | return status; |
811 | } | 813 | } |
812 | 814 | ||
813 | /* This is difficult. We have to lock quota inode and start transaction | ||
814 | * in this function but we don't want to take the penalty of exlusive | ||
815 | * quota file lock when we are just going to use cached structures. So | ||
816 | * we just take read lock check whether we have dquot cached and if so, | ||
817 | * we don't have to take the write lock... */ | ||
818 | static int ocfs2_dquot_initialize(struct inode *inode, int type) | ||
819 | { | ||
820 | handle_t *handle = NULL; | ||
821 | int status = 0; | ||
822 | struct super_block *sb = inode->i_sb; | ||
823 | struct ocfs2_mem_dqinfo *oinfo; | ||
824 | int exclusive = 0; | ||
825 | int cnt; | ||
826 | qid_t id; | ||
827 | |||
828 | mlog_entry_void(); | ||
829 | |||
830 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | ||
831 | if (type != -1 && cnt != type) | ||
832 | continue; | ||
833 | if (!sb_has_quota_active(sb, cnt)) | ||
834 | continue; | ||
835 | oinfo = sb_dqinfo(sb, cnt)->dqi_priv; | ||
836 | status = ocfs2_lock_global_qf(oinfo, 0); | ||
837 | if (status < 0) | ||
838 | goto out; | ||
839 | /* This is just a performance optimization not a reliable test. | ||
840 | * Since we hold an inode lock, noone can actually release | ||
841 | * the structure until we are finished with initialization. */ | ||
842 | if (inode->i_dquot[cnt] != NODQUOT) { | ||
843 | ocfs2_unlock_global_qf(oinfo, 0); | ||
844 | continue; | ||
845 | } | ||
846 | /* When we have inode lock, we know that no dquot_release() can | ||
847 | * run and thus we can safely check whether we need to | ||
848 | * read+modify global file to get quota information or whether | ||
849 | * our node already has it. */ | ||
850 | if (cnt == USRQUOTA) | ||
851 | id = inode->i_uid; | ||
852 | else if (cnt == GRPQUOTA) | ||
853 | id = inode->i_gid; | ||
854 | else | ||
855 | BUG(); | ||
856 | /* Obtain exclusion from quota off... */ | ||
857 | down_write(&sb_dqopt(sb)->dqptr_sem); | ||
858 | exclusive = !dquot_is_cached(sb, id, cnt); | ||
859 | up_write(&sb_dqopt(sb)->dqptr_sem); | ||
860 | if (exclusive) { | ||
861 | status = ocfs2_lock_global_qf(oinfo, 1); | ||
862 | if (status < 0) { | ||
863 | exclusive = 0; | ||
864 | mlog_errno(status); | ||
865 | goto out_ilock; | ||
866 | } | ||
867 | handle = ocfs2_start_trans(OCFS2_SB(sb), | ||
868 | ocfs2_calc_qinit_credits(sb, cnt)); | ||
869 | if (IS_ERR(handle)) { | ||
870 | status = PTR_ERR(handle); | ||
871 | mlog_errno(status); | ||
872 | goto out_ilock; | ||
873 | } | ||
874 | } | ||
875 | dquot_initialize(inode, cnt); | ||
876 | if (exclusive) { | ||
877 | ocfs2_commit_trans(OCFS2_SB(sb), handle); | ||
878 | ocfs2_unlock_global_qf(oinfo, 1); | ||
879 | } | ||
880 | ocfs2_unlock_global_qf(oinfo, 0); | ||
881 | } | ||
882 | mlog_exit(0); | ||
883 | return 0; | ||
884 | out_ilock: | ||
885 | if (exclusive) | ||
886 | ocfs2_unlock_global_qf(oinfo, 1); | ||
887 | ocfs2_unlock_global_qf(oinfo, 0); | ||
888 | out: | ||
889 | mlog_exit(status); | ||
890 | return status; | ||
891 | } | ||
892 | |||
893 | static int ocfs2_dquot_drop_slow(struct inode *inode) | ||
894 | { | ||
895 | int status = 0; | ||
896 | int cnt; | ||
897 | int got_lock[MAXQUOTAS] = {0, 0}; | ||
898 | handle_t *handle; | ||
899 | struct super_block *sb = inode->i_sb; | ||
900 | struct ocfs2_mem_dqinfo *oinfo; | ||
901 | |||
902 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | ||
903 | if (!sb_has_quota_active(sb, cnt)) | ||
904 | continue; | ||
905 | oinfo = sb_dqinfo(sb, cnt)->dqi_priv; | ||
906 | status = ocfs2_lock_global_qf(oinfo, 1); | ||
907 | if (status < 0) | ||
908 | goto out; | ||
909 | got_lock[cnt] = 1; | ||
910 | } | ||
911 | handle = ocfs2_start_trans(OCFS2_SB(sb), | ||
912 | ocfs2_calc_qinit_credits(sb, USRQUOTA) + | ||
913 | ocfs2_calc_qinit_credits(sb, GRPQUOTA)); | ||
914 | if (IS_ERR(handle)) { | ||
915 | status = PTR_ERR(handle); | ||
916 | mlog_errno(status); | ||
917 | goto out; | ||
918 | } | ||
919 | dquot_drop(inode); | ||
920 | ocfs2_commit_trans(OCFS2_SB(sb), handle); | ||
921 | out: | ||
922 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | ||
923 | if (got_lock[cnt]) { | ||
924 | oinfo = sb_dqinfo(sb, cnt)->dqi_priv; | ||
925 | ocfs2_unlock_global_qf(oinfo, 1); | ||
926 | } | ||
927 | return status; | ||
928 | } | ||
929 | |||
930 | /* See the comment before ocfs2_dquot_initialize. */ | ||
931 | static int ocfs2_dquot_drop(struct inode *inode) | ||
932 | { | ||
933 | int status = 0; | ||
934 | struct super_block *sb = inode->i_sb; | ||
935 | struct ocfs2_mem_dqinfo *oinfo; | ||
936 | int exclusive = 0; | ||
937 | int cnt; | ||
938 | int got_lock[MAXQUOTAS] = {0, 0}; | ||
939 | |||
940 | mlog_entry_void(); | ||
941 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | ||
942 | if (!sb_has_quota_active(sb, cnt)) | ||
943 | continue; | ||
944 | oinfo = sb_dqinfo(sb, cnt)->dqi_priv; | ||
945 | status = ocfs2_lock_global_qf(oinfo, 0); | ||
946 | if (status < 0) | ||
947 | goto out; | ||
948 | got_lock[cnt] = 1; | ||
949 | } | ||
950 | /* Lock against anyone releasing references so that when when we check | ||
951 | * we know we are not going to be last ones to release dquot */ | ||
952 | down_write(&sb_dqopt(sb)->dqptr_sem); | ||
953 | /* Urgh, this is a terrible hack :( */ | ||
954 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | ||
955 | if (inode->i_dquot[cnt] != NODQUOT && | ||
956 | atomic_read(&inode->i_dquot[cnt]->dq_count) > 1) { | ||
957 | exclusive = 1; | ||
958 | break; | ||
959 | } | ||
960 | } | ||
961 | if (!exclusive) | ||
962 | dquot_drop_locked(inode); | ||
963 | up_write(&sb_dqopt(sb)->dqptr_sem); | ||
964 | out: | ||
965 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | ||
966 | if (got_lock[cnt]) { | ||
967 | oinfo = sb_dqinfo(sb, cnt)->dqi_priv; | ||
968 | ocfs2_unlock_global_qf(oinfo, 0); | ||
969 | } | ||
970 | /* In case we bailed out because we had to do expensive locking | ||
971 | * do it now... */ | ||
972 | if (exclusive) | ||
973 | status = ocfs2_dquot_drop_slow(inode); | ||
974 | mlog_exit(status); | ||
975 | return status; | ||
976 | } | ||
977 | |||
978 | static struct dquot *ocfs2_alloc_dquot(struct super_block *sb, int type) | 815 | static struct dquot *ocfs2_alloc_dquot(struct super_block *sb, int type) |
979 | { | 816 | { |
980 | struct ocfs2_dquot *dquot = | 817 | struct ocfs2_dquot *dquot = |
@@ -991,8 +828,8 @@ static void ocfs2_destroy_dquot(struct dquot *dquot) | |||
991 | } | 828 | } |
992 | 829 | ||
993 | struct dquot_operations ocfs2_quota_operations = { | 830 | struct dquot_operations ocfs2_quota_operations = { |
994 | .initialize = ocfs2_dquot_initialize, | 831 | .initialize = dquot_initialize, |
995 | .drop = ocfs2_dquot_drop, | 832 | .drop = dquot_drop, |
996 | .alloc_space = dquot_alloc_space, | 833 | .alloc_space = dquot_alloc_space, |
997 | .alloc_inode = dquot_alloc_inode, | 834 | .alloc_inode = dquot_alloc_inode, |
998 | .free_space = dquot_free_space, | 835 | .free_space = dquot_free_space, |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 43ed11345b59..7ac83a81ee55 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -1537,6 +1537,13 @@ static int ocfs2_get_sector(struct super_block *sb, | |||
1537 | unlock_buffer(*bh); | 1537 | unlock_buffer(*bh); |
1538 | ll_rw_block(READ, 1, bh); | 1538 | ll_rw_block(READ, 1, bh); |
1539 | wait_on_buffer(*bh); | 1539 | wait_on_buffer(*bh); |
1540 | if (!buffer_uptodate(*bh)) { | ||
1541 | mlog_errno(-EIO); | ||
1542 | brelse(*bh); | ||
1543 | *bh = NULL; | ||
1544 | return -EIO; | ||
1545 | } | ||
1546 | |||
1540 | return 0; | 1547 | return 0; |
1541 | } | 1548 | } |
1542 | 1549 | ||
@@ -1747,6 +1754,7 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
1747 | INIT_LIST_HEAD(&osb->blocked_lock_list); | 1754 | INIT_LIST_HEAD(&osb->blocked_lock_list); |
1748 | osb->blocked_lock_count = 0; | 1755 | osb->blocked_lock_count = 0; |
1749 | spin_lock_init(&osb->osb_lock); | 1756 | spin_lock_init(&osb->osb_lock); |
1757 | spin_lock_init(&osb->osb_xattr_lock); | ||
1750 | ocfs2_init_inode_steal_slot(osb); | 1758 | ocfs2_init_inode_steal_slot(osb); |
1751 | 1759 | ||
1752 | atomic_set(&osb->alloc_stats.moves, 0); | 1760 | atomic_set(&osb->alloc_stats.moves, 0); |
@@ -1887,6 +1895,9 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
1887 | INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery); | 1895 | INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery); |
1888 | journal->j_state = OCFS2_JOURNAL_FREE; | 1896 | journal->j_state = OCFS2_JOURNAL_FREE; |
1889 | 1897 | ||
1898 | INIT_WORK(&osb->dentry_lock_work, ocfs2_drop_dl_inodes); | ||
1899 | osb->dentry_lock_list = NULL; | ||
1900 | |||
1890 | /* get some pseudo constants for clustersize bits */ | 1901 | /* get some pseudo constants for clustersize bits */ |
1891 | osb->s_clustersize_bits = | 1902 | osb->s_clustersize_bits = |
1892 | le32_to_cpu(di->id2.i_super.s_clustersize_bits); | 1903 | le32_to_cpu(di->id2.i_super.s_clustersize_bits); |
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index e1d638af6ac3..2563df89fc2a 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -82,13 +82,14 @@ struct ocfs2_xattr_set_ctxt { | |||
82 | 82 | ||
83 | #define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root)) | 83 | #define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root)) |
84 | #define OCFS2_XATTR_INLINE_SIZE 80 | 84 | #define OCFS2_XATTR_INLINE_SIZE 80 |
85 | #define OCFS2_XATTR_HEADER_GAP 4 | ||
85 | #define OCFS2_XATTR_FREE_IN_IBODY (OCFS2_MIN_XATTR_INLINE_SIZE \ | 86 | #define OCFS2_XATTR_FREE_IN_IBODY (OCFS2_MIN_XATTR_INLINE_SIZE \ |
86 | - sizeof(struct ocfs2_xattr_header) \ | 87 | - sizeof(struct ocfs2_xattr_header) \ |
87 | - sizeof(__u32)) | 88 | - OCFS2_XATTR_HEADER_GAP) |
88 | #define OCFS2_XATTR_FREE_IN_BLOCK(ptr) ((ptr)->i_sb->s_blocksize \ | 89 | #define OCFS2_XATTR_FREE_IN_BLOCK(ptr) ((ptr)->i_sb->s_blocksize \ |
89 | - sizeof(struct ocfs2_xattr_block) \ | 90 | - sizeof(struct ocfs2_xattr_block) \ |
90 | - sizeof(struct ocfs2_xattr_header) \ | 91 | - sizeof(struct ocfs2_xattr_header) \ |
91 | - sizeof(__u32)) | 92 | - OCFS2_XATTR_HEADER_GAP) |
92 | 93 | ||
93 | static struct ocfs2_xattr_def_value_root def_xv = { | 94 | static struct ocfs2_xattr_def_value_root def_xv = { |
94 | .xv.xr_list.l_count = cpu_to_le16(1), | 95 | .xv.xr_list.l_count = cpu_to_le16(1), |
@@ -274,10 +275,12 @@ static int ocfs2_read_xattr_bucket(struct ocfs2_xattr_bucket *bucket, | |||
274 | bucket->bu_blocks, bucket->bu_bhs, 0, | 275 | bucket->bu_blocks, bucket->bu_bhs, 0, |
275 | NULL); | 276 | NULL); |
276 | if (!rc) { | 277 | if (!rc) { |
278 | spin_lock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock); | ||
277 | rc = ocfs2_validate_meta_ecc_bhs(bucket->bu_inode->i_sb, | 279 | rc = ocfs2_validate_meta_ecc_bhs(bucket->bu_inode->i_sb, |
278 | bucket->bu_bhs, | 280 | bucket->bu_bhs, |
279 | bucket->bu_blocks, | 281 | bucket->bu_blocks, |
280 | &bucket_xh(bucket)->xh_check); | 282 | &bucket_xh(bucket)->xh_check); |
283 | spin_unlock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock); | ||
281 | if (rc) | 284 | if (rc) |
282 | mlog_errno(rc); | 285 | mlog_errno(rc); |
283 | } | 286 | } |
@@ -310,9 +313,11 @@ static void ocfs2_xattr_bucket_journal_dirty(handle_t *handle, | |||
310 | { | 313 | { |
311 | int i; | 314 | int i; |
312 | 315 | ||
316 | spin_lock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock); | ||
313 | ocfs2_compute_meta_ecc_bhs(bucket->bu_inode->i_sb, | 317 | ocfs2_compute_meta_ecc_bhs(bucket->bu_inode->i_sb, |
314 | bucket->bu_bhs, bucket->bu_blocks, | 318 | bucket->bu_bhs, bucket->bu_blocks, |
315 | &bucket_xh(bucket)->xh_check); | 319 | &bucket_xh(bucket)->xh_check); |
320 | spin_unlock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock); | ||
316 | 321 | ||
317 | for (i = 0; i < bucket->bu_blocks; i++) | 322 | for (i = 0; i < bucket->bu_blocks; i++) |
318 | ocfs2_journal_dirty(handle, bucket->bu_bhs[i]); | 323 | ocfs2_journal_dirty(handle, bucket->bu_bhs[i]); |
@@ -542,8 +547,12 @@ int ocfs2_calc_xattr_init(struct inode *dir, | |||
542 | * when blocksize = 512, may reserve one more cluser for | 547 | * when blocksize = 512, may reserve one more cluser for |
543 | * xattr bucket, otherwise reserve one metadata block | 548 | * xattr bucket, otherwise reserve one metadata block |
544 | * for them is ok. | 549 | * for them is ok. |
550 | * If this is a new directory with inline data, | ||
551 | * we choose to reserve the entire inline area for | ||
552 | * directory contents and force an external xattr block. | ||
545 | */ | 553 | */ |
546 | if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE || | 554 | if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE || |
555 | (S_ISDIR(mode) && ocfs2_supports_inline_data(osb)) || | ||
547 | (s_size + a_size) > OCFS2_XATTR_FREE_IN_IBODY) { | 556 | (s_size + a_size) > OCFS2_XATTR_FREE_IN_IBODY) { |
548 | ret = ocfs2_reserve_new_metadata_blocks(osb, 1, xattr_ac); | 557 | ret = ocfs2_reserve_new_metadata_blocks(osb, 1, xattr_ac); |
549 | if (ret) { | 558 | if (ret) { |
@@ -1507,7 +1516,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
1507 | last += 1; | 1516 | last += 1; |
1508 | } | 1517 | } |
1509 | 1518 | ||
1510 | free = min_offs - ((void *)last - xs->base) - sizeof(__u32); | 1519 | free = min_offs - ((void *)last - xs->base) - OCFS2_XATTR_HEADER_GAP; |
1511 | if (free < 0) | 1520 | if (free < 0) |
1512 | return -EIO; | 1521 | return -EIO; |
1513 | 1522 | ||
@@ -2190,7 +2199,7 @@ static int ocfs2_xattr_can_be_in_inode(struct inode *inode, | |||
2190 | last += 1; | 2199 | last += 1; |
2191 | } | 2200 | } |
2192 | 2201 | ||
2193 | free = min_offs - ((void *)last - xs->base) - sizeof(__u32); | 2202 | free = min_offs - ((void *)last - xs->base) - OCFS2_XATTR_HEADER_GAP; |
2194 | if (free < 0) | 2203 | if (free < 0) |
2195 | return 0; | 2204 | return 0; |
2196 | 2205 | ||
@@ -2592,8 +2601,9 @@ static int __ocfs2_xattr_set_handle(struct inode *inode, | |||
2592 | 2601 | ||
2593 | if (!ret) { | 2602 | if (!ret) { |
2594 | /* Update inode ctime. */ | 2603 | /* Update inode ctime. */ |
2595 | ret = ocfs2_journal_access(ctxt->handle, inode, xis->inode_bh, | 2604 | ret = ocfs2_journal_access_di(ctxt->handle, inode, |
2596 | OCFS2_JOURNAL_ACCESS_WRITE); | 2605 | xis->inode_bh, |
2606 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
2597 | if (ret) { | 2607 | if (ret) { |
2598 | mlog_errno(ret); | 2608 | mlog_errno(ret); |
2599 | goto out; | 2609 | goto out; |
@@ -4729,13 +4739,6 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, | |||
4729 | vb.vb_xv = (struct ocfs2_xattr_value_root *) | 4739 | vb.vb_xv = (struct ocfs2_xattr_value_root *) |
4730 | (vb.vb_bh->b_data + offset % blocksize); | 4740 | (vb.vb_bh->b_data + offset % blocksize); |
4731 | 4741 | ||
4732 | ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket, | ||
4733 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
4734 | if (ret) { | ||
4735 | mlog_errno(ret); | ||
4736 | goto out; | ||
4737 | } | ||
4738 | |||
4739 | /* | 4742 | /* |
4740 | * From here on out we have to dirty the bucket. The generic | 4743 | * From here on out we have to dirty the bucket. The generic |
4741 | * value calls only modify one of the bucket's bhs, but we need | 4744 | * value calls only modify one of the bucket's bhs, but we need |
@@ -4748,12 +4751,18 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, | |||
4748 | ret = ocfs2_xattr_value_truncate(inode, &vb, len, ctxt); | 4751 | ret = ocfs2_xattr_value_truncate(inode, &vb, len, ctxt); |
4749 | if (ret) { | 4752 | if (ret) { |
4750 | mlog_errno(ret); | 4753 | mlog_errno(ret); |
4751 | goto out_dirty; | 4754 | goto out; |
4755 | } | ||
4756 | |||
4757 | ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket, | ||
4758 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
4759 | if (ret) { | ||
4760 | mlog_errno(ret); | ||
4761 | goto out; | ||
4752 | } | 4762 | } |
4753 | 4763 | ||
4754 | xe->xe_value_size = cpu_to_le64(len); | 4764 | xe->xe_value_size = cpu_to_le64(len); |
4755 | 4765 | ||
4756 | out_dirty: | ||
4757 | ocfs2_xattr_bucket_journal_dirty(ctxt->handle, bucket); | 4766 | ocfs2_xattr_bucket_journal_dirty(ctxt->handle, bucket); |
4758 | 4767 | ||
4759 | out: | 4768 | out: |
@@ -4786,19 +4795,33 @@ static int ocfs2_xattr_bucket_set_value_outside(struct inode *inode, | |||
4786 | char *val, | 4795 | char *val, |
4787 | int value_len) | 4796 | int value_len) |
4788 | { | 4797 | { |
4789 | int offset; | 4798 | int ret, offset, block_off; |
4790 | struct ocfs2_xattr_value_root *xv; | 4799 | struct ocfs2_xattr_value_root *xv; |
4791 | struct ocfs2_xattr_entry *xe = xs->here; | 4800 | struct ocfs2_xattr_entry *xe = xs->here; |
4801 | struct ocfs2_xattr_header *xh = bucket_xh(xs->bucket); | ||
4802 | void *base; | ||
4792 | 4803 | ||
4793 | BUG_ON(!xs->base || !xe || ocfs2_xattr_is_local(xe)); | 4804 | BUG_ON(!xs->base || !xe || ocfs2_xattr_is_local(xe)); |
4794 | 4805 | ||
4795 | offset = le16_to_cpu(xe->xe_name_offset) + | 4806 | ret = ocfs2_xattr_bucket_get_name_value(inode, xh, |
4796 | OCFS2_XATTR_SIZE(xe->xe_name_len); | 4807 | xe - xh->xh_entries, |
4808 | &block_off, | ||
4809 | &offset); | ||
4810 | if (ret) { | ||
4811 | mlog_errno(ret); | ||
4812 | goto out; | ||
4813 | } | ||
4797 | 4814 | ||
4798 | xv = (struct ocfs2_xattr_value_root *)(xs->base + offset); | 4815 | base = bucket_block(xs->bucket, block_off); |
4816 | xv = (struct ocfs2_xattr_value_root *)(base + offset + | ||
4817 | OCFS2_XATTR_SIZE(xe->xe_name_len)); | ||
4799 | 4818 | ||
4800 | return __ocfs2_xattr_set_value_outside(inode, handle, | 4819 | ret = __ocfs2_xattr_set_value_outside(inode, handle, |
4801 | xv, val, value_len); | 4820 | xv, val, value_len); |
4821 | if (ret) | ||
4822 | mlog_errno(ret); | ||
4823 | out: | ||
4824 | return ret; | ||
4802 | } | 4825 | } |
4803 | 4826 | ||
4804 | static int ocfs2_rm_xattr_cluster(struct inode *inode, | 4827 | static int ocfs2_rm_xattr_cluster(struct inode *inode, |
@@ -5061,8 +5084,8 @@ try_again: | |||
5061 | xh_free_start = le16_to_cpu(xh->xh_free_start); | 5084 | xh_free_start = le16_to_cpu(xh->xh_free_start); |
5062 | header_size = sizeof(struct ocfs2_xattr_header) + | 5085 | header_size = sizeof(struct ocfs2_xattr_header) + |
5063 | count * sizeof(struct ocfs2_xattr_entry); | 5086 | count * sizeof(struct ocfs2_xattr_entry); |
5064 | max_free = OCFS2_XATTR_BUCKET_SIZE - | 5087 | max_free = OCFS2_XATTR_BUCKET_SIZE - header_size - |
5065 | le16_to_cpu(xh->xh_name_value_len) - header_size; | 5088 | le16_to_cpu(xh->xh_name_value_len) - OCFS2_XATTR_HEADER_GAP; |
5066 | 5089 | ||
5067 | mlog_bug_on_msg(header_size > blocksize, "bucket %llu has header size " | 5090 | mlog_bug_on_msg(header_size > blocksize, "bucket %llu has header size " |
5068 | "of %u which exceed block size\n", | 5091 | "of %u which exceed block size\n", |
@@ -5095,7 +5118,7 @@ try_again: | |||
5095 | need = 0; | 5118 | need = 0; |
5096 | } | 5119 | } |
5097 | 5120 | ||
5098 | free = xh_free_start - header_size; | 5121 | free = xh_free_start - header_size - OCFS2_XATTR_HEADER_GAP; |
5099 | /* | 5122 | /* |
5100 | * We need to make sure the new name/value pair | 5123 | * We need to make sure the new name/value pair |
5101 | * can exist in the same block. | 5124 | * can exist in the same block. |
@@ -5128,7 +5151,8 @@ try_again: | |||
5128 | } | 5151 | } |
5129 | 5152 | ||
5130 | xh_free_start = le16_to_cpu(xh->xh_free_start); | 5153 | xh_free_start = le16_to_cpu(xh->xh_free_start); |
5131 | free = xh_free_start - header_size; | 5154 | free = xh_free_start - header_size |
5155 | - OCFS2_XATTR_HEADER_GAP; | ||
5132 | if (xh_free_start % blocksize < need) | 5156 | if (xh_free_start % blocksize < need) |
5133 | free -= xh_free_start % blocksize; | 5157 | free -= xh_free_start % blocksize; |
5134 | 5158 | ||