Skip to content

Commit

Permalink
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/mfasheh/ocfs2

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2:
  ocfs2: Remove overzealous BUG_ON()
  ocfs2: Don't print on unknown remote blocking call
  ocfs2: Remove EXPERIMENTAL dependency
  ocfs2: implement directory read-ahead
  ocfs2: properly update i_mtime on buffered write
  ocfs2: Fix directory link count checks in ocfs2_link()
  ocfs2: move nlink check in ocfs2_mknod()
  ocfs2: Fix heartbeat sector calculation
  [PATCH] fs/ocfs2/ioctl.c should #include "ioctl.h"
  ocfs2: add ext2 attributes
  configfs: Prevent duplicate subsystem names.
  • Loading branch information
Linus Torvalds committed Sep 22, 2006
2 parents 6bbd9b6 + eb35746 commit 3e59ddf
Show file tree
Hide file tree
Showing 21 changed files with 440 additions and 134 deletions.
4 changes: 2 additions & 2 deletions fs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,8 @@ config FS_POSIX_ACL
source "fs/xfs/Kconfig"

config OCFS2_FS
tristate "OCFS2 file system support (EXPERIMENTAL)"
depends on NET && SYSFS && EXPERIMENTAL
tristate "OCFS2 file system support"
depends on NET && SYSFS
select CONFIGFS_FS
select JBD
select CRC32
Expand Down
32 changes: 30 additions & 2 deletions fs/configfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,32 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent * pare
return sd;
}

/*
*
* Return -EEXIST if there is already a configfs element with the same
* name for the same parent.
*
* called with parent inode's i_mutex held
*/
int configfs_dirent_exists(struct configfs_dirent *parent_sd,
const unsigned char *new)
{
struct configfs_dirent * sd;

list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
if (sd->s_element) {
const unsigned char *existing = configfs_get_name(sd);
if (strcmp(existing, new))
continue;
else
return -EEXIST;
}
}

return 0;
}


int configfs_make_dirent(struct configfs_dirent * parent_sd,
struct dentry * dentry, void * element,
umode_t mode, int type)
Expand Down Expand Up @@ -136,8 +162,10 @@ static int create_dir(struct config_item * k, struct dentry * p,
int error;
umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;

error = configfs_make_dirent(p->d_fsdata, d, k, mode,
CONFIGFS_DIR);
error = configfs_dirent_exists(p->d_fsdata, d->d_name.name);
if (!error)
error = configfs_make_dirent(p->d_fsdata, d, k, mode,
CONFIGFS_DIR);
if (!error) {
error = configfs_create(d, mode, init_dir);
if (!error) {
Expand Down
1 change: 1 addition & 0 deletions fs/ocfs2/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ ocfs2-objs := \
file.o \
heartbeat.o \
inode.o \
ioctl.o \
journal.o \
localalloc.o \
mmap.o \
Expand Down
28 changes: 20 additions & 8 deletions fs/ocfs2/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1717,17 +1717,29 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,

ocfs2_remove_from_cache(inode, eb_bh);

BUG_ON(eb->h_suballoc_slot);
BUG_ON(el->l_recs[0].e_clusters);
BUG_ON(el->l_recs[0].e_cpos);
BUG_ON(el->l_recs[0].e_blkno);
status = ocfs2_free_extent_block(handle,
tc->tc_ext_alloc_inode,
tc->tc_ext_alloc_bh,
eb);
if (status < 0) {
mlog_errno(status);
goto bail;
if (eb->h_suballoc_slot == 0) {
/*
* This code only understands how to
* lock the suballocator in slot 0,
* which is fine because allocation is
* only ever done out of that
* suballocator too. A future version
* might change that however, so avoid
* a free if we don't know how to
* handle it. This way an fs incompat
* bit will not be necessary.
*/
status = ocfs2_free_extent_block(handle,
tc->tc_ext_alloc_inode,
tc->tc_ext_alloc_bh,
eb);
if (status < 0) {
mlog_errno(status);
goto bail;
}
}
}
brelse(eb_bh);
Expand Down
83 changes: 34 additions & 49 deletions fs/ocfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,31 +391,28 @@ struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode,
static int ocfs2_commit_write(struct file *file, struct page *page,
unsigned from, unsigned to)
{
int ret, extending = 0, locklevel = 0;
loff_t new_i_size;
int ret;
struct buffer_head *di_bh = NULL;
struct inode *inode = page->mapping->host;
struct ocfs2_journal_handle *handle = NULL;
struct ocfs2_dinode *di;

mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to);

/* NOTE: ocfs2_file_aio_write has ensured that it's safe for
* us to sample inode->i_size here without the metadata lock:
* us to continue here without rechecking the I/O against
* changed inode values.
*
* 1) We're currently holding the inode alloc lock, so no
* nodes can change it underneath us.
*
* 2) We've had to take the metadata lock at least once
* already to check for extending writes, hence insuring
* that our current copy is also up to date.
* already to check for extending writes, suid removal, etc.
* The meta data update code then ensures that we don't get a
* stale inode allocation image (i_size, i_clusters, etc).
*/
new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
if (new_i_size > i_size_read(inode)) {
extending = 1;
locklevel = 1;
}

ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, locklevel, page);
ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, 1, page);
if (ret != 0) {
mlog_errno(ret);
goto out;
Expand All @@ -427,23 +424,20 @@ static int ocfs2_commit_write(struct file *file, struct page *page,
goto out_unlock_meta;
}

if (extending) {
handle = ocfs2_start_walk_page_trans(inode, page, from, to);
if (IS_ERR(handle)) {
ret = PTR_ERR(handle);
handle = NULL;
goto out_unlock_data;
}
handle = ocfs2_start_walk_page_trans(inode, page, from, to);
if (IS_ERR(handle)) {
ret = PTR_ERR(handle);
goto out_unlock_data;
}

/* Mark our buffer early. We'd rather catch this error up here
* as opposed to after a successful commit_write which would
* require us to set back inode->i_size. */
ret = ocfs2_journal_access(handle, inode, di_bh,
OCFS2_JOURNAL_ACCESS_WRITE);
if (ret < 0) {
mlog_errno(ret);
goto out_commit;
}
/* Mark our buffer early. We'd rather catch this error up here
* as opposed to after a successful commit_write which would
* require us to set back inode->i_size. */
ret = ocfs2_journal_access(handle, inode, di_bh,
OCFS2_JOURNAL_ACCESS_WRITE);
if (ret < 0) {
mlog_errno(ret);
goto out_commit;
}

/* might update i_size */
Expand All @@ -453,37 +447,28 @@ static int ocfs2_commit_write(struct file *file, struct page *page,
goto out_commit;
}

if (extending) {
loff_t size = (u64) i_size_read(inode);
struct ocfs2_dinode *di =
(struct ocfs2_dinode *)di_bh->b_data;
di = (struct ocfs2_dinode *)di_bh->b_data;

/* ocfs2_mark_inode_dirty is too heavy to use here. */
inode->i_blocks = ocfs2_align_bytes_to_sectors(size);
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
/* ocfs2_mark_inode_dirty() is too heavy to use here. */
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec);
di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);

di->i_size = cpu_to_le64(size);
di->i_ctime = di->i_mtime =
cpu_to_le64(inode->i_mtime.tv_sec);
di->i_ctime_nsec = di->i_mtime_nsec =
cpu_to_le32(inode->i_mtime.tv_nsec);
inode->i_blocks = ocfs2_align_bytes_to_sectors((u64)(i_size_read(inode)));
di->i_size = cpu_to_le64((u64)i_size_read(inode));

ret = ocfs2_journal_dirty(handle, di_bh);
if (ret < 0) {
mlog_errno(ret);
goto out_commit;
}
ret = ocfs2_journal_dirty(handle, di_bh);
if (ret < 0) {
mlog_errno(ret);
goto out_commit;
}

BUG_ON(extending && (i_size_read(inode) != new_i_size));

out_commit:
if (handle)
ocfs2_commit_trans(handle);
ocfs2_commit_trans(handle);
out_unlock_data:
ocfs2_data_unlock(inode, 1);
out_unlock_meta:
ocfs2_meta_unlock(inode, locklevel);
ocfs2_meta_unlock(inode, 1);
out:
if (di_bh)
brelse(di_bh);
Expand Down
95 changes: 72 additions & 23 deletions fs/ocfs2/buffer_head_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
mlog_entry("(block=(%llu), nr=(%d), flags=%d, inode=%p)\n",
(unsigned long long)block, nr, flags, inode);

BUG_ON((flags & OCFS2_BH_READAHEAD) &&
(!inode || !(flags & OCFS2_BH_CACHED)));

if (osb == NULL || osb->sb == NULL || bhs == NULL) {
status = -EINVAL;
mlog_errno(status);
Expand Down Expand Up @@ -140,6 +143,30 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
bh = bhs[i];
ignore_cache = 0;

/* There are three read-ahead cases here which we need to
* be concerned with. All three assume a buffer has
* previously been submitted with OCFS2_BH_READAHEAD
* and it hasn't yet completed I/O.
*
* 1) The current request is sync to disk. This rarely
* happens these days, and never when performance
* matters - the code can just wait on the buffer
* lock and re-submit.
*
* 2) The current request is cached, but not
* readahead. ocfs2_buffer_uptodate() will return
* false anyway, so we'll wind up waiting on the
* buffer lock to do I/O. We re-check the request
* with after getting the lock to avoid a re-submit.
*
* 3) The current request is readahead (and so must
* also be a caching one). We short circuit if the
* buffer is locked (under I/O) and if it's in the
* uptodate cache. The re-check from #2 catches the
* case that the previous read-ahead completes just
* before our is-it-in-flight check.
*/

if (flags & OCFS2_BH_CACHED &&
!ocfs2_buffer_uptodate(inode, bh)) {
mlog(ML_UPTODATE,
Expand Down Expand Up @@ -169,6 +196,14 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
continue;
}

/* A read-ahead request was made - if the
* buffer is already under read-ahead from a
* previously submitted request than we are
* done here. */
if ((flags & OCFS2_BH_READAHEAD)
&& ocfs2_buffer_read_ahead(inode, bh))
continue;

lock_buffer(bh);
if (buffer_jbd(bh)) {
#ifdef CATCH_BH_JBD_RACES
Expand All @@ -181,13 +216,22 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
continue;
#endif
}

/* Re-check ocfs2_buffer_uptodate() as a
* previously read-ahead buffer may have
* completed I/O while we were waiting for the
* buffer lock. */
if ((flags & OCFS2_BH_CACHED)
&& !(flags & OCFS2_BH_READAHEAD)
&& ocfs2_buffer_uptodate(inode, bh)) {
unlock_buffer(bh);
continue;
}

clear_buffer_uptodate(bh);
get_bh(bh); /* for end_buffer_read_sync() */
bh->b_end_io = end_buffer_read_sync;
if (flags & OCFS2_BH_READAHEAD)
submit_bh(READA, bh);
else
submit_bh(READ, bh);
submit_bh(READ, bh);
continue;
}
}
Expand All @@ -197,34 +241,39 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
for (i = (nr - 1); i >= 0; i--) {
bh = bhs[i];

/* We know this can't have changed as we hold the
* inode sem. Avoid doing any work on the bh if the
* journal has it. */
if (!buffer_jbd(bh))
wait_on_buffer(bh);

if (!buffer_uptodate(bh)) {
/* Status won't be cleared from here on out,
* so we can safely record this and loop back
* to cleanup the other buffers. Don't need to
* remove the clustered uptodate information
* for this bh as it's not marked locally
* uptodate. */
status = -EIO;
brelse(bh);
bhs[i] = NULL;
continue;
if (!(flags & OCFS2_BH_READAHEAD)) {
/* We know this can't have changed as we hold the
* inode sem. Avoid doing any work on the bh if the
* journal has it. */
if (!buffer_jbd(bh))
wait_on_buffer(bh);

if (!buffer_uptodate(bh)) {
/* Status won't be cleared from here on out,
* so we can safely record this and loop back
* to cleanup the other buffers. Don't need to
* remove the clustered uptodate information
* for this bh as it's not marked locally
* uptodate. */
status = -EIO;
brelse(bh);
bhs[i] = NULL;
continue;
}
}

/* Always set the buffer in the cache, even if it was
* a forced read, or read-ahead which hasn't yet
* completed. */
if (inode)
ocfs2_set_buffer_uptodate(inode, bh);
}
if (inode)
mutex_unlock(&OCFS2_I(inode)->ip_io_mutex);

mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s\n",
mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n",
(unsigned long long)block, nr,
(!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes");
(!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes", flags);

bail:

Expand Down
2 changes: 1 addition & 1 deletion fs/ocfs2/buffer_head_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ int ocfs2_read_blocks(struct ocfs2_super *osb,


#define OCFS2_BH_CACHED 1
#define OCFS2_BH_READAHEAD 8 /* use this to pass READA down to submit_bh */
#define OCFS2_BH_READAHEAD 8

static inline int ocfs2_read_block(struct ocfs2_super * osb, u64 off,
struct buffer_head **bh, int flags,
Expand Down
8 changes: 6 additions & 2 deletions fs/ocfs2/cluster/heartbeat.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,8 +320,12 @@ static int compute_max_sectors(struct block_device *bdev)
max_pages = q->max_hw_segments;
max_pages--; /* Handle I/Os that straddle a page */

max_sectors = max_pages << (PAGE_SHIFT - 9);

if (max_pages) {
max_sectors = max_pages << (PAGE_SHIFT - 9);
} else {
/* If BIO contains 1 or less than 1 page. */
max_sectors = q->max_sectors;
}
/* Why is fls() 1-based???? */
pow_two_sectors = 1 << (fls(max_sectors) - 1);

Expand Down
Loading

0 comments on commit 3e59ddf

Please sign in to comment.