diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/Kconfig | 4 | ||||
-rw-r--r-- | fs/configfs/dir.c | 32 | ||||
-rw-r--r-- | fs/ocfs2/Makefile | 1 | ||||
-rw-r--r-- | fs/ocfs2/alloc.c | 28 | ||||
-rw-r--r-- | fs/ocfs2/aops.c | 83 | ||||
-rw-r--r-- | fs/ocfs2/buffer_head_io.c | 95 | ||||
-rw-r--r-- | fs/ocfs2/buffer_head_io.h | 2 | ||||
-rw-r--r-- | fs/ocfs2/cluster/heartbeat.c | 8 | ||||
-rw-r--r-- | fs/ocfs2/dir.c | 28 | ||||
-rw-r--r-- | fs/ocfs2/dlm/dlmast.c | 10 | ||||
-rw-r--r-- | fs/ocfs2/dlmglue.c | 9 | ||||
-rw-r--r-- | fs/ocfs2/dlmglue.h | 5 | ||||
-rw-r--r-- | fs/ocfs2/file.c | 3 | ||||
-rw-r--r-- | fs/ocfs2/inode.c | 32 | ||||
-rw-r--r-- | fs/ocfs2/inode.h | 3 | ||||
-rw-r--r-- | fs/ocfs2/ioctl.c | 136 | ||||
-rw-r--r-- | fs/ocfs2/ioctl.h | 16 | ||||
-rw-r--r-- | fs/ocfs2/namei.c | 32 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2_fs.h | 24 | ||||
-rw-r--r-- | fs/ocfs2/uptodate.c | 21 | ||||
-rw-r--r-- | fs/ocfs2/uptodate.h | 2 |
21 files changed, 440 insertions, 134 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index 3f00a9faabcb..530581628311 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -325,8 +325,8 @@ config FS_POSIX_ACL | |||
325 | source "fs/xfs/Kconfig" | 325 | source "fs/xfs/Kconfig" |
326 | 326 | ||
327 | config OCFS2_FS | 327 | config OCFS2_FS |
328 | tristate "OCFS2 file system support (EXPERIMENTAL)" | 328 | tristate "OCFS2 file system support" |
329 | depends on NET && SYSFS && EXPERIMENTAL | 329 | depends on NET && SYSFS |
330 | select CONFIGFS_FS | 330 | select CONFIGFS_FS |
331 | select JBD | 331 | select JBD |
332 | select CRC32 | 332 | select CRC32 |
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index df025453dd97..816e8ef64560 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -86,6 +86,32 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent * pare | |||
86 | return sd; | 86 | return sd; |
87 | } | 87 | } |
88 | 88 | ||
89 | /* | ||
90 | * | ||
91 | * Return -EEXIST if there is already a configfs element with the same | ||
92 | * name for the same parent. | ||
93 | * | ||
94 | * called with parent inode's i_mutex held | ||
95 | */ | ||
96 | int configfs_dirent_exists(struct configfs_dirent *parent_sd, | ||
97 | const unsigned char *new) | ||
98 | { | ||
99 | struct configfs_dirent * sd; | ||
100 | |||
101 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { | ||
102 | if (sd->s_element) { | ||
103 | const unsigned char *existing = configfs_get_name(sd); | ||
104 | if (strcmp(existing, new)) | ||
105 | continue; | ||
106 | else | ||
107 | return -EEXIST; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | |||
89 | int configfs_make_dirent(struct configfs_dirent * parent_sd, | 115 | int configfs_make_dirent(struct configfs_dirent * parent_sd, |
90 | struct dentry * dentry, void * element, | 116 | struct dentry * dentry, void * element, |
91 | umode_t mode, int type) | 117 | umode_t mode, int type) |
@@ -136,8 +162,10 @@ static int create_dir(struct config_item * k, struct dentry * p, | |||
136 | int error; | 162 | int error; |
137 | umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; | 163 | umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; |
138 | 164 | ||
139 | error = configfs_make_dirent(p->d_fsdata, d, k, mode, | 165 | error = configfs_dirent_exists(p->d_fsdata, d->d_name.name); |
140 | CONFIGFS_DIR); | 166 | if (!error) |
167 | error = configfs_make_dirent(p->d_fsdata, d, k, mode, | ||
168 | CONFIGFS_DIR); | ||
141 | if (!error) { | 169 | if (!error) { |
142 | error = configfs_create(d, mode, init_dir); | 170 | error = configfs_create(d, mode, init_dir); |
143 | if (!error) { | 171 | if (!error) { |
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile index 7d3be845a614..9fb8132f19b0 100644 --- a/fs/ocfs2/Makefile +++ b/fs/ocfs2/Makefile | |||
@@ -16,6 +16,7 @@ ocfs2-objs := \ | |||
16 | file.o \ | 16 | file.o \ |
17 | heartbeat.o \ | 17 | heartbeat.o \ |
18 | inode.o \ | 18 | inode.o \ |
19 | ioctl.o \ | ||
19 | journal.o \ | 20 | journal.o \ |
20 | localalloc.o \ | 21 | localalloc.o \ |
21 | mmap.o \ | 22 | mmap.o \ |
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index edaab05a93e0..f43bc5f18a35 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -1717,17 +1717,29 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb, | |||
1717 | 1717 | ||
1718 | ocfs2_remove_from_cache(inode, eb_bh); | 1718 | ocfs2_remove_from_cache(inode, eb_bh); |
1719 | 1719 | ||
1720 | BUG_ON(eb->h_suballoc_slot); | ||
1721 | BUG_ON(el->l_recs[0].e_clusters); | 1720 | BUG_ON(el->l_recs[0].e_clusters); |
1722 | BUG_ON(el->l_recs[0].e_cpos); | 1721 | BUG_ON(el->l_recs[0].e_cpos); |
1723 | BUG_ON(el->l_recs[0].e_blkno); | 1722 | BUG_ON(el->l_recs[0].e_blkno); |
1724 | status = ocfs2_free_extent_block(handle, | 1723 | if (eb->h_suballoc_slot == 0) { |
1725 | tc->tc_ext_alloc_inode, | 1724 | /* |
1726 | tc->tc_ext_alloc_bh, | 1725 | * This code only understands how to |
1727 | eb); | 1726 | * lock the suballocator in slot 0, |
1728 | if (status < 0) { | 1727 | * which is fine because allocation is |
1729 | mlog_errno(status); | 1728 | * only ever done out of that |
1730 | goto bail; | 1729 | * suballocator too. A future version |
1730 | * might change that however, so avoid | ||
1731 | * a free if we don't know how to | ||
1732 | * handle it. This way an fs incompat | ||
1733 | * bit will not be necessary. | ||
1734 | */ | ||
1735 | status = ocfs2_free_extent_block(handle, | ||
1736 | tc->tc_ext_alloc_inode, | ||
1737 | tc->tc_ext_alloc_bh, | ||
1738 | eb); | ||
1739 | if (status < 0) { | ||
1740 | mlog_errno(status); | ||
1741 | goto bail; | ||
1742 | } | ||
1731 | } | 1743 | } |
1732 | } | 1744 | } |
1733 | brelse(eb_bh); | 1745 | brelse(eb_bh); |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index f1d1c342ce01..3d7c082a8f58 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -391,31 +391,28 @@ out: | |||
391 | static int ocfs2_commit_write(struct file *file, struct page *page, | 391 | static int ocfs2_commit_write(struct file *file, struct page *page, |
392 | unsigned from, unsigned to) | 392 | unsigned from, unsigned to) |
393 | { | 393 | { |
394 | int ret, extending = 0, locklevel = 0; | 394 | int ret; |
395 | loff_t new_i_size; | ||
396 | struct buffer_head *di_bh = NULL; | 395 | struct buffer_head *di_bh = NULL; |
397 | struct inode *inode = page->mapping->host; | 396 | struct inode *inode = page->mapping->host; |
398 | struct ocfs2_journal_handle *handle = NULL; | 397 | struct ocfs2_journal_handle *handle = NULL; |
398 | struct ocfs2_dinode *di; | ||
399 | 399 | ||
400 | mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to); | 400 | mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to); |
401 | 401 | ||
402 | /* NOTE: ocfs2_file_aio_write has ensured that it's safe for | 402 | /* NOTE: ocfs2_file_aio_write has ensured that it's safe for |
403 | * us to sample inode->i_size here without the metadata lock: | 403 | * us to continue here without rechecking the I/O against |
404 | * changed inode values. | ||
404 | * | 405 | * |
405 | * 1) We're currently holding the inode alloc lock, so no | 406 | * 1) We're currently holding the inode alloc lock, so no |
406 | * nodes can change it underneath us. | 407 | * nodes can change it underneath us. |
407 | * | 408 | * |
408 | * 2) We've had to take the metadata lock at least once | 409 | * 2) We've had to take the metadata lock at least once |
409 | * already to check for extending writes, hence insuring | 410 | * already to check for extending writes, suid removal, etc. |
410 | * that our current copy is also up to date. | 411 | * The meta data update code then ensures that we don't get a |
412 | * stale inode allocation image (i_size, i_clusters, etc). | ||
411 | */ | 413 | */ |
412 | new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; | ||
413 | if (new_i_size > i_size_read(inode)) { | ||
414 | extending = 1; | ||
415 | locklevel = 1; | ||
416 | } | ||
417 | 414 | ||
418 | ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, locklevel, page); | 415 | ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, 1, page); |
419 | if (ret != 0) { | 416 | if (ret != 0) { |
420 | mlog_errno(ret); | 417 | mlog_errno(ret); |
421 | goto out; | 418 | goto out; |
@@ -427,23 +424,20 @@ static int ocfs2_commit_write(struct file *file, struct page *page, | |||
427 | goto out_unlock_meta; | 424 | goto out_unlock_meta; |
428 | } | 425 | } |
429 | 426 | ||
430 | if (extending) { | 427 | handle = ocfs2_start_walk_page_trans(inode, page, from, to); |
431 | handle = ocfs2_start_walk_page_trans(inode, page, from, to); | 428 | if (IS_ERR(handle)) { |
432 | if (IS_ERR(handle)) { | 429 | ret = PTR_ERR(handle); |
433 | ret = PTR_ERR(handle); | 430 | goto out_unlock_data; |
434 | handle = NULL; | 431 | } |
435 | goto out_unlock_data; | ||
436 | } | ||
437 | 432 | ||
438 | /* Mark our buffer early. We'd rather catch this error up here | 433 | /* Mark our buffer early. We'd rather catch this error up here |
439 | * as opposed to after a successful commit_write which would | 434 | * as opposed to after a successful commit_write which would |
440 | * require us to set back inode->i_size. */ | 435 | * require us to set back inode->i_size. */ |
441 | ret = ocfs2_journal_access(handle, inode, di_bh, | 436 | ret = ocfs2_journal_access(handle, inode, di_bh, |
442 | OCFS2_JOURNAL_ACCESS_WRITE); | 437 | OCFS2_JOURNAL_ACCESS_WRITE); |
443 | if (ret < 0) { | 438 | if (ret < 0) { |
444 | mlog_errno(ret); | 439 | mlog_errno(ret); |
445 | goto out_commit; | 440 | goto out_commit; |
446 | } | ||
447 | } | 441 | } |
448 | 442 | ||
449 | /* might update i_size */ | 443 | /* might update i_size */ |
@@ -453,37 +447,28 @@ static int ocfs2_commit_write(struct file *file, struct page *page, | |||
453 | goto out_commit; | 447 | goto out_commit; |
454 | } | 448 | } |
455 | 449 | ||
456 | if (extending) { | 450 | di = (struct ocfs2_dinode *)di_bh->b_data; |
457 | loff_t size = (u64) i_size_read(inode); | ||
458 | struct ocfs2_dinode *di = | ||
459 | (struct ocfs2_dinode *)di_bh->b_data; | ||
460 | 451 | ||
461 | /* ocfs2_mark_inode_dirty is too heavy to use here. */ | 452 | /* ocfs2_mark_inode_dirty() is too heavy to use here. */ |
462 | inode->i_blocks = ocfs2_align_bytes_to_sectors(size); | 453 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
463 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; | 454 | di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec); |
455 | di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); | ||
464 | 456 | ||
465 | di->i_size = cpu_to_le64(size); | 457 | inode->i_blocks = ocfs2_align_bytes_to_sectors((u64)(i_size_read(inode))); |
466 | di->i_ctime = di->i_mtime = | 458 | di->i_size = cpu_to_le64((u64)i_size_read(inode)); |
467 | cpu_to_le64(inode->i_mtime.tv_sec); | ||
468 | di->i_ctime_nsec = di->i_mtime_nsec = | ||
469 | cpu_to_le32(inode->i_mtime.tv_nsec); | ||
470 | 459 | ||
471 | ret = ocfs2_journal_dirty(handle, di_bh); | 460 | ret = ocfs2_journal_dirty(handle, di_bh); |
472 | if (ret < 0) { | 461 | if (ret < 0) { |
473 | mlog_errno(ret); | 462 | mlog_errno(ret); |
474 | goto out_commit; | 463 | goto out_commit; |
475 | } | ||
476 | } | 464 | } |
477 | 465 | ||
478 | BUG_ON(extending && (i_size_read(inode) != new_i_size)); | ||
479 | |||
480 | out_commit: | 466 | out_commit: |
481 | if (handle) | 467 | ocfs2_commit_trans(handle); |
482 | ocfs2_commit_trans(handle); | ||
483 | out_unlock_data: | 468 | out_unlock_data: |
484 | ocfs2_data_unlock(inode, 1); | 469 | ocfs2_data_unlock(inode, 1); |
485 | out_unlock_meta: | 470 | out_unlock_meta: |
486 | ocfs2_meta_unlock(inode, locklevel); | 471 | ocfs2_meta_unlock(inode, 1); |
487 | out: | 472 | out: |
488 | if (di_bh) | 473 | if (di_bh) |
489 | brelse(di_bh); | 474 | brelse(di_bh); |
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index 9a24adf9be6e..c9037414f4f6 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c | |||
@@ -100,6 +100,9 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
100 | mlog_entry("(block=(%llu), nr=(%d), flags=%d, inode=%p)\n", | 100 | mlog_entry("(block=(%llu), nr=(%d), flags=%d, inode=%p)\n", |
101 | (unsigned long long)block, nr, flags, inode); | 101 | (unsigned long long)block, nr, flags, inode); |
102 | 102 | ||
103 | BUG_ON((flags & OCFS2_BH_READAHEAD) && | ||
104 | (!inode || !(flags & OCFS2_BH_CACHED))); | ||
105 | |||
103 | if (osb == NULL || osb->sb == NULL || bhs == NULL) { | 106 | if (osb == NULL || osb->sb == NULL || bhs == NULL) { |
104 | status = -EINVAL; | 107 | status = -EINVAL; |
105 | mlog_errno(status); | 108 | mlog_errno(status); |
@@ -140,6 +143,30 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
140 | bh = bhs[i]; | 143 | bh = bhs[i]; |
141 | ignore_cache = 0; | 144 | ignore_cache = 0; |
142 | 145 | ||
146 | /* There are three read-ahead cases here which we need to | ||
147 | * be concerned with. All three assume a buffer has | ||
148 | * previously been submitted with OCFS2_BH_READAHEAD | ||
149 | * and it hasn't yet completed I/O. | ||
150 | * | ||
151 | * 1) The current request is sync to disk. This rarely | ||
152 | * happens these days, and never when performance | ||
153 | * matters - the code can just wait on the buffer | ||
154 | * lock and re-submit. | ||
155 | * | ||
156 | * 2) The current request is cached, but not | ||
157 | * readahead. ocfs2_buffer_uptodate() will return | ||
158 | * false anyway, so we'll wind up waiting on the | ||
159 | * buffer lock to do I/O. We re-check the request | ||
160 | * with after getting the lock to avoid a re-submit. | ||
161 | * | ||
162 | * 3) The current request is readahead (and so must | ||
163 | * also be a caching one). We short circuit if the | ||
164 | * buffer is locked (under I/O) and if it's in the | ||
165 | * uptodate cache. The re-check from #2 catches the | ||
166 | * case that the previous read-ahead completes just | ||
167 | * before our is-it-in-flight check. | ||
168 | */ | ||
169 | |||
143 | if (flags & OCFS2_BH_CACHED && | 170 | if (flags & OCFS2_BH_CACHED && |
144 | !ocfs2_buffer_uptodate(inode, bh)) { | 171 | !ocfs2_buffer_uptodate(inode, bh)) { |
145 | mlog(ML_UPTODATE, | 172 | mlog(ML_UPTODATE, |
@@ -169,6 +196,14 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
169 | continue; | 196 | continue; |
170 | } | 197 | } |
171 | 198 | ||
199 | /* A read-ahead request was made - if the | ||
200 | * buffer is already under read-ahead from a | ||
201 | * previously submitted request than we are | ||
202 | * done here. */ | ||
203 | if ((flags & OCFS2_BH_READAHEAD) | ||
204 | && ocfs2_buffer_read_ahead(inode, bh)) | ||
205 | continue; | ||
206 | |||
172 | lock_buffer(bh); | 207 | lock_buffer(bh); |
173 | if (buffer_jbd(bh)) { | 208 | if (buffer_jbd(bh)) { |
174 | #ifdef CATCH_BH_JBD_RACES | 209 | #ifdef CATCH_BH_JBD_RACES |
@@ -181,13 +216,22 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
181 | continue; | 216 | continue; |
182 | #endif | 217 | #endif |
183 | } | 218 | } |
219 | |||
220 | /* Re-check ocfs2_buffer_uptodate() as a | ||
221 | * previously read-ahead buffer may have | ||
222 | * completed I/O while we were waiting for the | ||
223 | * buffer lock. */ | ||
224 | if ((flags & OCFS2_BH_CACHED) | ||
225 | && !(flags & OCFS2_BH_READAHEAD) | ||
226 | && ocfs2_buffer_uptodate(inode, bh)) { | ||
227 | unlock_buffer(bh); | ||
228 | continue; | ||
229 | } | ||
230 | |||
184 | clear_buffer_uptodate(bh); | 231 | clear_buffer_uptodate(bh); |
185 | get_bh(bh); /* for end_buffer_read_sync() */ | 232 | get_bh(bh); /* for end_buffer_read_sync() */ |
186 | bh->b_end_io = end_buffer_read_sync; | 233 | bh->b_end_io = end_buffer_read_sync; |
187 | if (flags & OCFS2_BH_READAHEAD) | 234 | submit_bh(READ, bh); |
188 | submit_bh(READA, bh); | ||
189 | else | ||
190 | submit_bh(READ, bh); | ||
191 | continue; | 235 | continue; |
192 | } | 236 | } |
193 | } | 237 | } |
@@ -197,34 +241,39 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, | |||
197 | for (i = (nr - 1); i >= 0; i--) { | 241 | for (i = (nr - 1); i >= 0; i--) { |
198 | bh = bhs[i]; | 242 | bh = bhs[i]; |
199 | 243 | ||
200 | /* We know this can't have changed as we hold the | 244 | if (!(flags & OCFS2_BH_READAHEAD)) { |
201 | * inode sem. Avoid doing any work on the bh if the | 245 | /* We know this can't have changed as we hold the |
202 | * journal has it. */ | 246 | * inode sem. Avoid doing any work on the bh if the |
203 | if (!buffer_jbd(bh)) | 247 | * journal has it. */ |
204 | wait_on_buffer(bh); | 248 | if (!buffer_jbd(bh)) |
205 | 249 | wait_on_buffer(bh); | |
206 | if (!buffer_uptodate(bh)) { | 250 | |
207 | /* Status won't be cleared from here on out, | 251 | if (!buffer_uptodate(bh)) { |
208 | * so we can safely record this and loop back | 252 | /* Status won't be cleared from here on out, |
209 | * to cleanup the other buffers. Don't need to | 253 | * so we can safely record this and loop back |
210 | * remove the clustered uptodate information | 254 | * to cleanup the other buffers. Don't need to |
211 | * for this bh as it's not marked locally | 255 | * remove the clustered uptodate information |
212 | * uptodate. */ | 256 | * for this bh as it's not marked locally |
213 | status = -EIO; | 257 | * uptodate. */ |
214 | brelse(bh); | 258 | status = -EIO; |
215 | bhs[i] = NULL; | 259 | brelse(bh); |
216 | continue; | 260 | bhs[i] = NULL; |
261 | continue; | ||
262 | } | ||
217 | } | 263 | } |
218 | 264 | ||
265 | /* Always set the buffer in the cache, even if it was | ||
266 | * a forced read, or read-ahead which hasn't yet | ||
267 | * completed. */ | ||
219 | if (inode) | 268 | if (inode) |
220 | ocfs2_set_buffer_uptodate(inode, bh); | 269 | ocfs2_set_buffer_uptodate(inode, bh); |
221 | } | 270 | } |
222 | if (inode) | 271 | if (inode) |
223 | mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); | 272 | mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); |
224 | 273 | ||
225 | mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s\n", | 274 | mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n", |
226 | (unsigned long long)block, nr, | 275 | (unsigned long long)block, nr, |
227 | (!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes"); | 276 | (!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes", flags); |
228 | 277 | ||
229 | bail: | 278 | bail: |
230 | 279 | ||
diff --git a/fs/ocfs2/buffer_head_io.h b/fs/ocfs2/buffer_head_io.h index 6ecb90937b68..6cc20930fac3 100644 --- a/fs/ocfs2/buffer_head_io.h +++ b/fs/ocfs2/buffer_head_io.h | |||
@@ -49,7 +49,7 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, | |||
49 | 49 | ||
50 | 50 | ||
51 | #define OCFS2_BH_CACHED 1 | 51 | #define OCFS2_BH_CACHED 1 |
52 | #define OCFS2_BH_READAHEAD 8 /* use this to pass READA down to submit_bh */ | 52 | #define OCFS2_BH_READAHEAD 8 |
53 | 53 | ||
54 | static inline int ocfs2_read_block(struct ocfs2_super * osb, u64 off, | 54 | static inline int ocfs2_read_block(struct ocfs2_super * osb, u64 off, |
55 | struct buffer_head **bh, int flags, | 55 | struct buffer_head **bh, int flags, |
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 504595d6cf65..305cba3681fe 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
@@ -320,8 +320,12 @@ static int compute_max_sectors(struct block_device *bdev) | |||
320 | max_pages = q->max_hw_segments; | 320 | max_pages = q->max_hw_segments; |
321 | max_pages--; /* Handle I/Os that straddle a page */ | 321 | max_pages--; /* Handle I/Os that straddle a page */ |
322 | 322 | ||
323 | max_sectors = max_pages << (PAGE_SHIFT - 9); | 323 | if (max_pages) { |
324 | 324 | max_sectors = max_pages << (PAGE_SHIFT - 9); | |
325 | } else { | ||
326 | /* If BIO contains 1 or less than 1 page. */ | ||
327 | max_sectors = q->max_sectors; | ||
328 | } | ||
325 | /* Why is fls() 1-based???? */ | 329 | /* Why is fls() 1-based???? */ |
326 | pow_two_sectors = 1 << (fls(max_sectors) - 1); | 330 | pow_two_sectors = 1 << (fls(max_sectors) - 1); |
327 | 331 | ||
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 3d494d1a5f36..04e01915b86e 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -74,14 +74,14 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, | |||
74 | int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | 74 | int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) |
75 | { | 75 | { |
76 | int error = 0; | 76 | int error = 0; |
77 | unsigned long offset, blk; | 77 | unsigned long offset, blk, last_ra_blk = 0; |
78 | int i, num, stored; | 78 | int i, stored; |
79 | struct buffer_head * bh, * tmp; | 79 | struct buffer_head * bh, * tmp; |
80 | struct ocfs2_dir_entry * de; | 80 | struct ocfs2_dir_entry * de; |
81 | int err; | 81 | int err; |
82 | struct inode *inode = filp->f_dentry->d_inode; | 82 | struct inode *inode = filp->f_dentry->d_inode; |
83 | struct super_block * sb = inode->i_sb; | 83 | struct super_block * sb = inode->i_sb; |
84 | int have_disk_lock = 0; | 84 | unsigned int ra_sectors = 16; |
85 | 85 | ||
86 | mlog_entry("dirino=%llu\n", | 86 | mlog_entry("dirino=%llu\n", |
87 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | 87 | (unsigned long long)OCFS2_I(inode)->ip_blkno); |
@@ -95,9 +95,8 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
95 | mlog_errno(error); | 95 | mlog_errno(error); |
96 | /* we haven't got any yet, so propagate the error. */ | 96 | /* we haven't got any yet, so propagate the error. */ |
97 | stored = error; | 97 | stored = error; |
98 | goto bail; | 98 | goto bail_nolock; |
99 | } | 99 | } |
100 | have_disk_lock = 1; | ||
101 | 100 | ||
102 | offset = filp->f_pos & (sb->s_blocksize - 1); | 101 | offset = filp->f_pos & (sb->s_blocksize - 1); |
103 | 102 | ||
@@ -113,16 +112,21 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
113 | continue; | 112 | continue; |
114 | } | 113 | } |
115 | 114 | ||
116 | /* | 115 | /* The idea here is to begin with 8k read-ahead and to stay |
117 | * Do the readahead (8k) | 116 | * 4k ahead of our current position. |
118 | */ | 117 | * |
119 | if (!offset) { | 118 | * TODO: Use the pagecache for this. We just need to |
120 | for (i = 16 >> (sb->s_blocksize_bits - 9), num = 0; | 119 | * make sure it's cluster-safe... */ |
120 | if (!last_ra_blk | ||
121 | || (((last_ra_blk - blk) << 9) <= (ra_sectors / 2))) { | ||
122 | for (i = ra_sectors >> (sb->s_blocksize_bits - 9); | ||
121 | i > 0; i--) { | 123 | i > 0; i--) { |
122 | tmp = ocfs2_bread(inode, ++blk, &err, 1); | 124 | tmp = ocfs2_bread(inode, ++blk, &err, 1); |
123 | if (tmp) | 125 | if (tmp) |
124 | brelse(tmp); | 126 | brelse(tmp); |
125 | } | 127 | } |
128 | last_ra_blk = blk; | ||
129 | ra_sectors = 8; | ||
126 | } | 130 | } |
127 | 131 | ||
128 | revalidate: | 132 | revalidate: |
@@ -194,9 +198,9 @@ revalidate: | |||
194 | 198 | ||
195 | stored = 0; | 199 | stored = 0; |
196 | bail: | 200 | bail: |
197 | if (have_disk_lock) | 201 | ocfs2_meta_unlock(inode, 0); |
198 | ocfs2_meta_unlock(inode, 0); | ||
199 | 202 | ||
203 | bail_nolock: | ||
200 | mlog_exit(stored); | 204 | mlog_exit(stored); |
201 | 205 | ||
202 | return stored; | 206 | return stored; |
diff --git a/fs/ocfs2/dlm/dlmast.c b/fs/ocfs2/dlm/dlmast.c index 42775e2bbe2c..f13a4bac41f0 100644 --- a/fs/ocfs2/dlm/dlmast.c +++ b/fs/ocfs2/dlm/dlmast.c | |||
@@ -367,12 +367,10 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data) | |||
367 | goto do_ast; | 367 | goto do_ast; |
368 | } | 368 | } |
369 | 369 | ||
370 | mlog(ML_ERROR, "got %sast for unknown lock! cookie=%u:%llu, " | 370 | mlog(0, "got %sast for unknown lock! cookie=%u:%llu, " |
371 | "name=%.*s, namelen=%u\n", | 371 | "name=%.*s, namelen=%u\n", past->type == DLM_AST ? "" : "b", |
372 | past->type == DLM_AST ? "" : "b", | 372 | dlm_get_lock_cookie_node(cookie), dlm_get_lock_cookie_seq(cookie), |
373 | dlm_get_lock_cookie_node(cookie), | 373 | locklen, name, locklen); |
374 | dlm_get_lock_cookie_seq(cookie), | ||
375 | locklen, name, locklen); | ||
376 | 374 | ||
377 | ret = DLM_NORMAL; | 375 | ret = DLM_NORMAL; |
378 | unlock_out: | 376 | unlock_out: |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 762eb1fbb34d..151b41781eab 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -1330,6 +1330,7 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) | |||
1330 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_ctime)); | 1330 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_ctime)); |
1331 | lvb->lvb_imtime_packed = | 1331 | lvb->lvb_imtime_packed = |
1332 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime)); | 1332 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime)); |
1333 | lvb->lvb_iattr = cpu_to_be32(oi->ip_attr); | ||
1333 | 1334 | ||
1334 | mlog_meta_lvb(0, lockres); | 1335 | mlog_meta_lvb(0, lockres); |
1335 | 1336 | ||
@@ -1360,6 +1361,9 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode) | |||
1360 | oi->ip_clusters = be32_to_cpu(lvb->lvb_iclusters); | 1361 | oi->ip_clusters = be32_to_cpu(lvb->lvb_iclusters); |
1361 | i_size_write(inode, be64_to_cpu(lvb->lvb_isize)); | 1362 | i_size_write(inode, be64_to_cpu(lvb->lvb_isize)); |
1362 | 1363 | ||
1364 | oi->ip_attr = be32_to_cpu(lvb->lvb_iattr); | ||
1365 | ocfs2_set_inode_flags(inode); | ||
1366 | |||
1363 | /* fast-symlinks are a special case */ | 1367 | /* fast-symlinks are a special case */ |
1364 | if (S_ISLNK(inode->i_mode) && !oi->ip_clusters) | 1368 | if (S_ISLNK(inode->i_mode) && !oi->ip_clusters) |
1365 | inode->i_blocks = 0; | 1369 | inode->i_blocks = 0; |
@@ -2899,8 +2903,9 @@ void ocfs2_dump_meta_lvb_info(u64 level, | |||
2899 | be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid), | 2903 | be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid), |
2900 | be16_to_cpu(lvb->lvb_imode)); | 2904 | be16_to_cpu(lvb->lvb_imode)); |
2901 | mlog(level, "nlink %u, atime_packed 0x%llx, ctime_packed 0x%llx, " | 2905 | mlog(level, "nlink %u, atime_packed 0x%llx, ctime_packed 0x%llx, " |
2902 | "mtime_packed 0x%llx\n", be16_to_cpu(lvb->lvb_inlink), | 2906 | "mtime_packed 0x%llx iattr 0x%x\n", be16_to_cpu(lvb->lvb_inlink), |
2903 | (long long)be64_to_cpu(lvb->lvb_iatime_packed), | 2907 | (long long)be64_to_cpu(lvb->lvb_iatime_packed), |
2904 | (long long)be64_to_cpu(lvb->lvb_ictime_packed), | 2908 | (long long)be64_to_cpu(lvb->lvb_ictime_packed), |
2905 | (long long)be64_to_cpu(lvb->lvb_imtime_packed)); | 2909 | (long long)be64_to_cpu(lvb->lvb_imtime_packed), |
2910 | be32_to_cpu(lvb->lvb_iattr)); | ||
2906 | } | 2911 | } |
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h index 8f2d1db2d9ea..243ae862ece5 100644 --- a/fs/ocfs2/dlmglue.h +++ b/fs/ocfs2/dlmglue.h | |||
@@ -27,7 +27,7 @@ | |||
27 | #ifndef DLMGLUE_H | 27 | #ifndef DLMGLUE_H |
28 | #define DLMGLUE_H | 28 | #define DLMGLUE_H |
29 | 29 | ||
30 | #define OCFS2_LVB_VERSION 2 | 30 | #define OCFS2_LVB_VERSION 3 |
31 | 31 | ||
32 | struct ocfs2_meta_lvb { | 32 | struct ocfs2_meta_lvb { |
33 | __be32 lvb_version; | 33 | __be32 lvb_version; |
@@ -40,7 +40,8 @@ struct ocfs2_meta_lvb { | |||
40 | __be64 lvb_isize; | 40 | __be64 lvb_isize; |
41 | __be16 lvb_imode; | 41 | __be16 lvb_imode; |
42 | __be16 lvb_inlink; | 42 | __be16 lvb_inlink; |
43 | __be32 lvb_reserved[3]; | 43 | __be32 lvb_iattr; |
44 | __be32 lvb_reserved[2]; | ||
44 | }; | 45 | }; |
45 | 46 | ||
46 | /* ocfs2_meta_lock_full() and ocfs2_data_lock_full() 'arg_flags' flags */ | 47 | /* ocfs2_meta_lock_full() and ocfs2_data_lock_full() 'arg_flags' flags */ |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index a9559c874530..2bbfa17090cf 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include "file.h" | 44 | #include "file.h" |
45 | #include "sysfile.h" | 45 | #include "sysfile.h" |
46 | #include "inode.h" | 46 | #include "inode.h" |
47 | #include "ioctl.h" | ||
47 | #include "journal.h" | 48 | #include "journal.h" |
48 | #include "mmap.h" | 49 | #include "mmap.h" |
49 | #include "suballoc.h" | 50 | #include "suballoc.h" |
@@ -1227,10 +1228,12 @@ const struct file_operations ocfs2_fops = { | |||
1227 | .open = ocfs2_file_open, | 1228 | .open = ocfs2_file_open, |
1228 | .aio_read = ocfs2_file_aio_read, | 1229 | .aio_read = ocfs2_file_aio_read, |
1229 | .aio_write = ocfs2_file_aio_write, | 1230 | .aio_write = ocfs2_file_aio_write, |
1231 | .ioctl = ocfs2_ioctl, | ||
1230 | }; | 1232 | }; |
1231 | 1233 | ||
1232 | const struct file_operations ocfs2_dops = { | 1234 | const struct file_operations ocfs2_dops = { |
1233 | .read = generic_read_dir, | 1235 | .read = generic_read_dir, |
1234 | .readdir = ocfs2_readdir, | 1236 | .readdir = ocfs2_readdir, |
1235 | .fsync = ocfs2_sync_file, | 1237 | .fsync = ocfs2_sync_file, |
1238 | .ioctl = ocfs2_ioctl, | ||
1236 | }; | 1239 | }; |
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 327a5b7b86ed..7bcf69154592 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -71,6 +71,26 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, | |||
71 | struct inode *inode, | 71 | struct inode *inode, |
72 | struct buffer_head *fe_bh); | 72 | struct buffer_head *fe_bh); |
73 | 73 | ||
74 | void ocfs2_set_inode_flags(struct inode *inode) | ||
75 | { | ||
76 | unsigned int flags = OCFS2_I(inode)->ip_attr; | ||
77 | |||
78 | inode->i_flags &= ~(S_IMMUTABLE | | ||
79 | S_SYNC | S_APPEND | S_NOATIME | S_DIRSYNC); | ||
80 | |||
81 | if (flags & OCFS2_IMMUTABLE_FL) | ||
82 | inode->i_flags |= S_IMMUTABLE; | ||
83 | |||
84 | if (flags & OCFS2_SYNC_FL) | ||
85 | inode->i_flags |= S_SYNC; | ||
86 | if (flags & OCFS2_APPEND_FL) | ||
87 | inode->i_flags |= S_APPEND; | ||
88 | if (flags & OCFS2_NOATIME_FL) | ||
89 | inode->i_flags |= S_NOATIME; | ||
90 | if (flags & OCFS2_DIRSYNC_FL) | ||
91 | inode->i_flags |= S_DIRSYNC; | ||
92 | } | ||
93 | |||
74 | struct inode *ocfs2_ilookup_for_vote(struct ocfs2_super *osb, | 94 | struct inode *ocfs2_ilookup_for_vote(struct ocfs2_super *osb, |
75 | u64 blkno, | 95 | u64 blkno, |
76 | int delete_vote) | 96 | int delete_vote) |
@@ -260,7 +280,6 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
260 | inode->i_blocks = | 280 | inode->i_blocks = |
261 | ocfs2_align_bytes_to_sectors(le64_to_cpu(fe->i_size)); | 281 | ocfs2_align_bytes_to_sectors(le64_to_cpu(fe->i_size)); |
262 | inode->i_mapping->a_ops = &ocfs2_aops; | 282 | inode->i_mapping->a_ops = &ocfs2_aops; |
263 | inode->i_flags |= S_NOATIME; | ||
264 | inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime); | 283 | inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime); |
265 | inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec); | 284 | inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec); |
266 | inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime); | 285 | inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime); |
@@ -276,6 +295,7 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
276 | 295 | ||
277 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); | 296 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); |
278 | OCFS2_I(inode)->ip_orphaned_slot = OCFS2_INVALID_SLOT; | 297 | OCFS2_I(inode)->ip_orphaned_slot = OCFS2_INVALID_SLOT; |
298 | OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr); | ||
279 | 299 | ||
280 | if (create_ino) | 300 | if (create_ino) |
281 | inode->i_ino = ino_from_blkno(inode->i_sb, | 301 | inode->i_ino = ino_from_blkno(inode->i_sb, |
@@ -330,6 +350,9 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
330 | ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_data_lockres, | 350 | ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_data_lockres, |
331 | OCFS2_LOCK_TYPE_DATA, inode); | 351 | OCFS2_LOCK_TYPE_DATA, inode); |
332 | 352 | ||
353 | ocfs2_set_inode_flags(inode); | ||
354 | inode->i_flags |= S_NOATIME; | ||
355 | |||
333 | status = 0; | 356 | status = 0; |
334 | bail: | 357 | bail: |
335 | mlog_exit(status); | 358 | mlog_exit(status); |
@@ -1027,12 +1050,8 @@ struct buffer_head *ocfs2_bread(struct inode *inode, | |||
1027 | u64 p_blkno; | 1050 | u64 p_blkno; |
1028 | int readflags = OCFS2_BH_CACHED; | 1051 | int readflags = OCFS2_BH_CACHED; |
1029 | 1052 | ||
1030 | #if 0 | ||
1031 | /* only turn this on if we know we can deal with read_block | ||
1032 | * returning nothing */ | ||
1033 | if (reada) | 1053 | if (reada) |
1034 | readflags |= OCFS2_BH_READAHEAD; | 1054 | readflags |= OCFS2_BH_READAHEAD; |
1035 | #endif | ||
1036 | 1055 | ||
1037 | if (((u64)block << inode->i_sb->s_blocksize_bits) >= | 1056 | if (((u64)block << inode->i_sb->s_blocksize_bits) >= |
1038 | i_size_read(inode)) { | 1057 | i_size_read(inode)) { |
@@ -1131,6 +1150,7 @@ int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle, | |||
1131 | 1150 | ||
1132 | spin_lock(&OCFS2_I(inode)->ip_lock); | 1151 | spin_lock(&OCFS2_I(inode)->ip_lock); |
1133 | fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters); | 1152 | fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters); |
1153 | fe->i_attr = cpu_to_le32(OCFS2_I(inode)->ip_attr); | ||
1134 | spin_unlock(&OCFS2_I(inode)->ip_lock); | 1154 | spin_unlock(&OCFS2_I(inode)->ip_lock); |
1135 | 1155 | ||
1136 | fe->i_size = cpu_to_le64(i_size_read(inode)); | 1156 | fe->i_size = cpu_to_le64(i_size_read(inode)); |
@@ -1169,6 +1189,8 @@ void ocfs2_refresh_inode(struct inode *inode, | |||
1169 | spin_lock(&OCFS2_I(inode)->ip_lock); | 1189 | spin_lock(&OCFS2_I(inode)->ip_lock); |
1170 | 1190 | ||
1171 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); | 1191 | OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); |
1192 | OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr); | ||
1193 | ocfs2_set_inode_flags(inode); | ||
1172 | i_size_write(inode, le64_to_cpu(fe->i_size)); | 1194 | i_size_write(inode, le64_to_cpu(fe->i_size)); |
1173 | inode->i_nlink = le16_to_cpu(fe->i_links_count); | 1195 | inode->i_nlink = le16_to_cpu(fe->i_links_count); |
1174 | inode->i_uid = le32_to_cpu(fe->i_uid); | 1196 | inode->i_uid = le32_to_cpu(fe->i_uid); |
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h index 35140f6cf840..4d1e53992566 100644 --- a/fs/ocfs2/inode.h +++ b/fs/ocfs2/inode.h | |||
@@ -56,6 +56,7 @@ struct ocfs2_inode_info | |||
56 | struct ocfs2_journal_handle *ip_handle; | 56 | struct ocfs2_journal_handle *ip_handle; |
57 | 57 | ||
58 | u32 ip_flags; /* see below */ | 58 | u32 ip_flags; /* see below */ |
59 | u32 ip_attr; /* inode attributes */ | ||
59 | 60 | ||
60 | /* protected by recovery_lock. */ | 61 | /* protected by recovery_lock. */ |
61 | struct inode *ip_next_orphan; | 62 | struct inode *ip_next_orphan; |
@@ -142,4 +143,6 @@ int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle, | |||
142 | int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb); | 143 | int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb); |
143 | int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb); | 144 | int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb); |
144 | 145 | ||
146 | void ocfs2_set_inode_flags(struct inode *inode); | ||
147 | |||
145 | #endif /* OCFS2_INODE_H */ | 148 | #endif /* OCFS2_INODE_H */ |
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c new file mode 100644 index 000000000000..3663cef80689 --- /dev/null +++ b/fs/ocfs2/ioctl.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * linux/fs/ocfs2/ioctl.c | ||
3 | * | ||
4 | * Copyright (C) 2006 Herbert Poetzl | ||
5 | * adapted from Remy Card's ext2/ioctl.c | ||
6 | */ | ||
7 | |||
8 | #include <linux/fs.h> | ||
9 | #include <linux/mount.h> | ||
10 | |||
11 | #define MLOG_MASK_PREFIX ML_INODE | ||
12 | #include <cluster/masklog.h> | ||
13 | |||
14 | #include "ocfs2.h" | ||
15 | #include "alloc.h" | ||
16 | #include "dlmglue.h" | ||
17 | #include "inode.h" | ||
18 | #include "journal.h" | ||
19 | |||
20 | #include "ocfs2_fs.h" | ||
21 | #include "ioctl.h" | ||
22 | |||
23 | #include <linux/ext2_fs.h> | ||
24 | |||
25 | static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) | ||
26 | { | ||
27 | int status; | ||
28 | |||
29 | status = ocfs2_meta_lock(inode, NULL, NULL, 0); | ||
30 | if (status < 0) { | ||
31 | mlog_errno(status); | ||
32 | return status; | ||
33 | } | ||
34 | *flags = OCFS2_I(inode)->ip_attr; | ||
35 | ocfs2_meta_unlock(inode, 0); | ||
36 | |||
37 | mlog_exit(status); | ||
38 | return status; | ||
39 | } | ||
40 | |||
41 | static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, | ||
42 | unsigned mask) | ||
43 | { | ||
44 | struct ocfs2_inode_info *ocfs2_inode = OCFS2_I(inode); | ||
45 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
46 | struct ocfs2_journal_handle *handle = NULL; | ||
47 | struct buffer_head *bh = NULL; | ||
48 | unsigned oldflags; | ||
49 | int status; | ||
50 | |||
51 | mutex_lock(&inode->i_mutex); | ||
52 | |||
53 | status = ocfs2_meta_lock(inode, NULL, &bh, 1); | ||
54 | if (status < 0) { | ||
55 | mlog_errno(status); | ||
56 | goto bail; | ||
57 | } | ||
58 | |||
59 | status = -EROFS; | ||
60 | if (IS_RDONLY(inode)) | ||
61 | goto bail_unlock; | ||
62 | |||
63 | status = -EACCES; | ||
64 | if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) | ||
65 | goto bail_unlock; | ||
66 | |||
67 | if (!S_ISDIR(inode->i_mode)) | ||
68 | flags &= ~OCFS2_DIRSYNC_FL; | ||
69 | |||
70 | handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS); | ||
71 | if (IS_ERR(handle)) { | ||
72 | status = PTR_ERR(handle); | ||
73 | mlog_errno(status); | ||
74 | goto bail_unlock; | ||
75 | } | ||
76 | |||
77 | oldflags = ocfs2_inode->ip_attr; | ||
78 | flags = flags & mask; | ||
79 | flags |= oldflags & ~mask; | ||
80 | |||
81 | /* | ||
82 | * The IMMUTABLE and APPEND_ONLY flags can only be changed by | ||
83 | * the relevant capability. | ||
84 | */ | ||
85 | status = -EPERM; | ||
86 | if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) & | ||
87 | (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) { | ||
88 | if (!capable(CAP_LINUX_IMMUTABLE)) | ||
89 | goto bail_unlock; | ||
90 | } | ||
91 | |||
92 | ocfs2_inode->ip_attr = flags; | ||
93 | ocfs2_set_inode_flags(inode); | ||
94 | |||
95 | status = ocfs2_mark_inode_dirty(handle, inode, bh); | ||
96 | if (status < 0) | ||
97 | mlog_errno(status); | ||
98 | |||
99 | ocfs2_commit_trans(handle); | ||
100 | bail_unlock: | ||
101 | ocfs2_meta_unlock(inode, 1); | ||
102 | bail: | ||
103 | mutex_unlock(&inode->i_mutex); | ||
104 | |||
105 | if (bh) | ||
106 | brelse(bh); | ||
107 | |||
108 | mlog_exit(status); | ||
109 | return status; | ||
110 | } | ||
111 | |||
112 | int ocfs2_ioctl(struct inode * inode, struct file * filp, | ||
113 | unsigned int cmd, unsigned long arg) | ||
114 | { | ||
115 | unsigned int flags; | ||
116 | int status; | ||
117 | |||
118 | switch (cmd) { | ||
119 | case OCFS2_IOC_GETFLAGS: | ||
120 | status = ocfs2_get_inode_attr(inode, &flags); | ||
121 | if (status < 0) | ||
122 | return status; | ||
123 | |||
124 | flags &= OCFS2_FL_VISIBLE; | ||
125 | return put_user(flags, (int __user *) arg); | ||
126 | case OCFS2_IOC_SETFLAGS: | ||
127 | if (get_user(flags, (int __user *) arg)) | ||
128 | return -EFAULT; | ||
129 | |||
130 | return ocfs2_set_inode_attr(inode, flags, | ||
131 | OCFS2_FL_MODIFIABLE); | ||
132 | default: | ||
133 | return -ENOTTY; | ||
134 | } | ||
135 | } | ||
136 | |||
diff --git a/fs/ocfs2/ioctl.h b/fs/ocfs2/ioctl.h new file mode 100644 index 000000000000..4a7c82931dba --- /dev/null +++ b/fs/ocfs2/ioctl.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * ioctl.h | ||
3 | * | ||
4 | * Function prototypes | ||
5 | * | ||
6 | * Copyright (C) 2006 Herbert Poetzl | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #ifndef OCFS2_IOCTL_H | ||
11 | #define OCFS2_IOCTL_H | ||
12 | |||
13 | int ocfs2_ioctl(struct inode * inode, struct file * filp, | ||
14 | unsigned int cmd, unsigned long arg); | ||
15 | |||
16 | #endif /* OCFS2_IOCTL_H */ | ||
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 0673862c8bdd..0d3e939b1f56 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include "journal.h" | 56 | #include "journal.h" |
57 | #include "namei.h" | 57 | #include "namei.h" |
58 | #include "suballoc.h" | 58 | #include "suballoc.h" |
59 | #include "super.h" | ||
59 | #include "symlink.h" | 60 | #include "symlink.h" |
60 | #include "sysfile.h" | 61 | #include "sysfile.h" |
61 | #include "uptodate.h" | 62 | #include "uptodate.h" |
@@ -310,13 +311,6 @@ static int ocfs2_mknod(struct inode *dir, | |||
310 | /* get our super block */ | 311 | /* get our super block */ |
311 | osb = OCFS2_SB(dir->i_sb); | 312 | osb = OCFS2_SB(dir->i_sb); |
312 | 313 | ||
313 | if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) { | ||
314 | mlog(ML_ERROR, "inode %llu has i_nlink of %u\n", | ||
315 | (unsigned long long)OCFS2_I(dir)->ip_blkno, dir->i_nlink); | ||
316 | status = -EMLINK; | ||
317 | goto leave; | ||
318 | } | ||
319 | |||
320 | handle = ocfs2_alloc_handle(osb); | 314 | handle = ocfs2_alloc_handle(osb); |
321 | if (handle == NULL) { | 315 | if (handle == NULL) { |
322 | status = -ENOMEM; | 316 | status = -ENOMEM; |
@@ -331,6 +325,11 @@ static int ocfs2_mknod(struct inode *dir, | |||
331 | goto leave; | 325 | goto leave; |
332 | } | 326 | } |
333 | 327 | ||
328 | if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) { | ||
329 | status = -EMLINK; | ||
330 | goto leave; | ||
331 | } | ||
332 | |||
334 | dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; | 333 | dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; |
335 | if (!dirfe->i_links_count) { | 334 | if (!dirfe->i_links_count) { |
336 | /* can't make a file in a deleted directory. */ | 335 | /* can't make a file in a deleted directory. */ |
@@ -643,11 +642,6 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
643 | goto bail; | 642 | goto bail; |
644 | } | 643 | } |
645 | 644 | ||
646 | if (inode->i_nlink >= OCFS2_LINK_MAX) { | ||
647 | err = -EMLINK; | ||
648 | goto bail; | ||
649 | } | ||
650 | |||
651 | handle = ocfs2_alloc_handle(osb); | 645 | handle = ocfs2_alloc_handle(osb); |
652 | if (handle == NULL) { | 646 | if (handle == NULL) { |
653 | err = -ENOMEM; | 647 | err = -ENOMEM; |
@@ -661,6 +655,11 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
661 | goto bail; | 655 | goto bail; |
662 | } | 656 | } |
663 | 657 | ||
658 | if (!dir->i_nlink) { | ||
659 | err = -ENOENT; | ||
660 | goto bail; | ||
661 | } | ||
662 | |||
664 | err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, | 663 | err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, |
665 | dentry->d_name.len); | 664 | dentry->d_name.len); |
666 | if (err) | 665 | if (err) |
@@ -1964,13 +1963,8 @@ restart: | |||
1964 | } | 1963 | } |
1965 | num++; | 1964 | num++; |
1966 | 1965 | ||
1967 | /* XXX: questionable readahead stuff here */ | ||
1968 | bh = ocfs2_bread(dir, b++, &err, 1); | 1966 | bh = ocfs2_bread(dir, b++, &err, 1); |
1969 | bh_use[ra_max] = bh; | 1967 | bh_use[ra_max] = bh; |
1970 | #if 0 // ??? | ||
1971 | if (bh) | ||
1972 | ll_rw_block(READ, 1, &bh); | ||
1973 | #endif | ||
1974 | } | 1968 | } |
1975 | } | 1969 | } |
1976 | if ((bh = bh_use[ra_ptr++]) == NULL) | 1970 | if ((bh = bh_use[ra_ptr++]) == NULL) |
@@ -1978,6 +1972,10 @@ restart: | |||
1978 | wait_on_buffer(bh); | 1972 | wait_on_buffer(bh); |
1979 | if (!buffer_uptodate(bh)) { | 1973 | if (!buffer_uptodate(bh)) { |
1980 | /* read error, skip block & hope for the best */ | 1974 | /* read error, skip block & hope for the best */ |
1975 | ocfs2_error(dir->i_sb, "reading directory %llu, " | ||
1976 | "offset %lu\n", | ||
1977 | (unsigned long long)OCFS2_I(dir)->ip_blkno, | ||
1978 | block); | ||
1981 | brelse(bh); | 1979 | brelse(bh); |
1982 | goto next; | 1980 | goto next; |
1983 | } | 1981 | } |
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index c5b1ac547c15..3330a5dc6be2 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h | |||
@@ -114,6 +114,26 @@ | |||
114 | #define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */ | 114 | #define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */ |
115 | #define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */ | 115 | #define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */ |
116 | 116 | ||
117 | /* Inode attributes, keep in sync with EXT2 */ | ||
118 | #define OCFS2_SECRM_FL (0x00000001) /* Secure deletion */ | ||
119 | #define OCFS2_UNRM_FL (0x00000002) /* Undelete */ | ||
120 | #define OCFS2_COMPR_FL (0x00000004) /* Compress file */ | ||
121 | #define OCFS2_SYNC_FL (0x00000008) /* Synchronous updates */ | ||
122 | #define OCFS2_IMMUTABLE_FL (0x00000010) /* Immutable file */ | ||
123 | #define OCFS2_APPEND_FL (0x00000020) /* writes to file may only append */ | ||
124 | #define OCFS2_NODUMP_FL (0x00000040) /* do not dump file */ | ||
125 | #define OCFS2_NOATIME_FL (0x00000080) /* do not update atime */ | ||
126 | #define OCFS2_DIRSYNC_FL (0x00010000) /* dirsync behaviour (directories only) */ | ||
127 | |||
128 | #define OCFS2_FL_VISIBLE (0x000100FF) /* User visible flags */ | ||
129 | #define OCFS2_FL_MODIFIABLE (0x000100FF) /* User modifiable flags */ | ||
130 | |||
131 | /* | ||
132 | * ioctl commands | ||
133 | */ | ||
134 | #define OCFS2_IOC_GETFLAGS _IOR('f', 1, long) | ||
135 | #define OCFS2_IOC_SETFLAGS _IOW('f', 2, long) | ||
136 | |||
117 | /* | 137 | /* |
118 | * Journal Flags (ocfs2_dinode.id1.journal1.i_flags) | 138 | * Journal Flags (ocfs2_dinode.id1.journal1.i_flags) |
119 | */ | 139 | */ |
@@ -399,7 +419,9 @@ struct ocfs2_dinode { | |||
399 | __le32 i_atime_nsec; | 419 | __le32 i_atime_nsec; |
400 | __le32 i_ctime_nsec; | 420 | __le32 i_ctime_nsec; |
401 | __le32 i_mtime_nsec; | 421 | __le32 i_mtime_nsec; |
402 | /*70*/ __le64 i_reserved1[9]; | 422 | __le32 i_attr; |
423 | __le32 i_reserved1; | ||
424 | /*70*/ __le64 i_reserved2[8]; | ||
403 | /*B8*/ union { | 425 | /*B8*/ union { |
404 | __le64 i_pad1; /* Generic way to refer to this | 426 | __le64 i_pad1; /* Generic way to refer to this |
405 | 64bit union */ | 427 | 64bit union */ |
diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c index b8a00a793326..9707ed7a3206 100644 --- a/fs/ocfs2/uptodate.c +++ b/fs/ocfs2/uptodate.c | |||
@@ -206,7 +206,10 @@ static int ocfs2_buffer_cached(struct ocfs2_inode_info *oi, | |||
206 | } | 206 | } |
207 | 207 | ||
208 | /* Warning: even if it returns true, this does *not* guarantee that | 208 | /* Warning: even if it returns true, this does *not* guarantee that |
209 | * the block is stored in our inode metadata cache. */ | 209 | * the block is stored in our inode metadata cache. |
210 | * | ||
211 | * This can be called under lock_buffer() | ||
212 | */ | ||
210 | int ocfs2_buffer_uptodate(struct inode *inode, | 213 | int ocfs2_buffer_uptodate(struct inode *inode, |
211 | struct buffer_head *bh) | 214 | struct buffer_head *bh) |
212 | { | 215 | { |
@@ -226,6 +229,16 @@ int ocfs2_buffer_uptodate(struct inode *inode, | |||
226 | return ocfs2_buffer_cached(OCFS2_I(inode), bh); | 229 | return ocfs2_buffer_cached(OCFS2_I(inode), bh); |
227 | } | 230 | } |
228 | 231 | ||
232 | /* | ||
233 | * Determine whether a buffer is currently out on a read-ahead request. | ||
234 | * ip_io_sem should be held to serialize submitters with the logic here. | ||
235 | */ | ||
236 | int ocfs2_buffer_read_ahead(struct inode *inode, | ||
237 | struct buffer_head *bh) | ||
238 | { | ||
239 | return buffer_locked(bh) && ocfs2_buffer_cached(OCFS2_I(inode), bh); | ||
240 | } | ||
241 | |||
229 | /* Requires ip_lock */ | 242 | /* Requires ip_lock */ |
230 | static void ocfs2_append_cache_array(struct ocfs2_caching_info *ci, | 243 | static void ocfs2_append_cache_array(struct ocfs2_caching_info *ci, |
231 | sector_t block) | 244 | sector_t block) |
@@ -403,7 +416,11 @@ out_free: | |||
403 | * | 416 | * |
404 | * Note that this function may actually fail to insert the block if | 417 | * Note that this function may actually fail to insert the block if |
405 | * memory cannot be allocated. This is not fatal however (but may | 418 | * memory cannot be allocated. This is not fatal however (but may |
406 | * result in a performance penalty) */ | 419 | * result in a performance penalty) |
420 | * | ||
421 | * Readahead buffers can be passed in here before the I/O request is | ||
422 | * completed. | ||
423 | */ | ||
407 | void ocfs2_set_buffer_uptodate(struct inode *inode, | 424 | void ocfs2_set_buffer_uptodate(struct inode *inode, |
408 | struct buffer_head *bh) | 425 | struct buffer_head *bh) |
409 | { | 426 | { |
diff --git a/fs/ocfs2/uptodate.h b/fs/ocfs2/uptodate.h index 01cd32d26b06..2e73206059a8 100644 --- a/fs/ocfs2/uptodate.h +++ b/fs/ocfs2/uptodate.h | |||
@@ -40,5 +40,7 @@ void ocfs2_set_new_buffer_uptodate(struct inode *inode, | |||
40 | struct buffer_head *bh); | 40 | struct buffer_head *bh); |
41 | void ocfs2_remove_from_cache(struct inode *inode, | 41 | void ocfs2_remove_from_cache(struct inode *inode, |
42 | struct buffer_head *bh); | 42 | struct buffer_head *bh); |
43 | int ocfs2_buffer_read_ahead(struct inode *inode, | ||
44 | struct buffer_head *bh); | ||
43 | 45 | ||
44 | #endif /* OCFS2_UPTODATE_H */ | 46 | #endif /* OCFS2_UPTODATE_H */ |