#include "journal.h"
#include "namei.h"
#include "suballoc.h"
+#include "super.h"
#include "symlink.h"
#include "sysfile.h"
#include "uptodate.h"
goto bail;
}
- mlog(0, "find name %.*s in directory %"MLFu64"\n", dentry->d_name.len,
- dentry->d_name.name, OCFS2_I(dir)->ip_blkno);
+ mlog(0, "find name %.*s in directory %llu\n", dentry->d_name.len,
+ dentry->d_name.name, (unsigned long long)OCFS2_I(dir)->ip_blkno);
status = ocfs2_meta_lock(dir, NULL, NULL, 0);
if (status < 0) {
if (status < 0)
goto bail_add;
- inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno);
+ inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno, 0);
if (IS_ERR(inode)) {
- mlog(ML_ERROR, "Unable to create inode %"MLFu64"\n", blkno);
+ mlog(ML_ERROR, "Unable to create inode %llu\n",
+ (unsigned long long)blkno);
ret = ERR_PTR(-EACCES);
goto bail_unlock;
}
spin_unlock(&oi->ip_lock);
bail_add:
-
dentry->d_op = &ocfs2_dentry_ops;
ret = d_splice_alias(inode, dentry);
+ if (inode) {
+ /*
+ * If d_splice_alias() finds a DCACHE_DISCONNECTED
+ * dentry, it will d_move() it on top of ourse. The
+ * return value will indicate this however, so in
+ * those cases, we switch them around for the locking
+ * code.
+ *
+ * NOTE: This dentry already has ->d_op set from
+ * ocfs2_get_parent() and ocfs2_get_dentry()
+ */
+ if (ret)
+ dentry = ret;
+
+ status = ocfs2_dentry_attach_lock(dentry, inode,
+ OCFS2_I(dir)->ip_blkno);
+ if (status) {
+ mlog_errno(status);
+ ret = ERR_PTR(status);
+ goto bail_unlock;
+ }
+ }
+
bail_unlock:
/* Don't drop the cluster lock until *after* the d_add --
* unlink on another node will message us to remove that
/* get our super block */
osb = OCFS2_SB(dir->i_sb);
- if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) {
- mlog(ML_ERROR, "inode %"MLFu64" has i_nlink of %u\n",
- OCFS2_I(dir)->ip_blkno, dir->i_nlink);
- status = -EMLINK;
- goto leave;
- }
-
handle = ocfs2_alloc_handle(osb);
if (handle == NULL) {
status = -ENOMEM;
goto leave;
}
+ if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) {
+ status = -EMLINK;
+ goto leave;
+ }
+
dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
if (!dirfe->i_links_count) {
/* can't make a file in a deleted directory. */
goto leave;
}
+ status = ocfs2_dentry_attach_lock(dentry, inode,
+ OCFS2_I(dir)->ip_blkno);
+ if (status) {
+ mlog_errno(status);
+ goto leave;
+ }
+
insert_inode_hash(inode);
dentry->d_op = &ocfs2_dentry_ops;
d_instantiate(dentry, inode);
if (ocfs2_populate_inode(inode, fe, 1) < 0) {
mlog(ML_ERROR, "populate inode failed! bh->b_blocknr=%llu, "
- "i_blkno=%"MLFu64", i_ino=%lu\n",
+ "i_blkno=%llu, i_ino=%lu\n",
(unsigned long long) (*new_fe_bh)->b_blocknr,
- fe->i_blkno, inode->i_ino);
+ (unsigned long long)fe->i_blkno, inode->i_ino);
BUG();
}
goto bail;
}
- if (inode->i_nlink >= OCFS2_LINK_MAX) {
- err = -EMLINK;
- goto bail;
- }
-
handle = ocfs2_alloc_handle(osb);
if (handle == NULL) {
err = -ENOMEM;
goto bail;
}
+ if (!dir->i_nlink) {
+ err = -ENOENT;
+ goto bail;
+ }
+
err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name,
dentry->d_name.len);
if (err)
goto bail;
}
+ err = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno);
+ if (err) {
+ mlog_errno(err);
+ goto bail;
+ }
+
atomic_inc(&inode->i_count);
dentry->d_op = &ocfs2_dentry_ops;
d_instantiate(dentry, inode);
return err;
}
+/*
+ * Takes and drops an exclusive lock on the given dentry. This will
+ * force other nodes to drop it.
+ */
+static int ocfs2_remote_dentry_delete(struct dentry *dentry)
+{
+ int ret;
+
+ ret = ocfs2_dentry_lock(dentry, 1);
+ if (ret)
+ mlog_errno(ret);
+ else
+ ocfs2_dentry_unlock(dentry, 1);
+
+ return ret;
+}
+
static int ocfs2_unlink(struct inode *dir,
struct dentry *dentry)
{
BUG_ON(dentry->d_parent->d_inode != dir);
- mlog(0, "ino = %"MLFu64"\n", OCFS2_I(inode)->ip_blkno);
+ mlog(0, "ino = %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno);
if (inode == osb->root_inode) {
mlog(0, "Cannot delete the root directory\n");
if (OCFS2_I(inode)->ip_blkno != blkno) {
status = -ENOENT;
- mlog(0, "ip_blkno (%"MLFu64") != dirent blkno (%"MLFu64") "
- "ip_flags = %x\n", OCFS2_I(inode)->ip_blkno, blkno,
- OCFS2_I(inode)->ip_flags);
+ mlog(0, "ip_blkno %llu != dirent blkno %llu ip_flags = %x\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
+ (unsigned long long)blkno, OCFS2_I(inode)->ip_flags);
goto leave;
}
else
inode->i_nlink--;
- status = ocfs2_request_unlink_vote(inode, dentry,
- (unsigned int) inode->i_nlink);
+ status = ocfs2_remote_dentry_delete(dentry);
if (status < 0) {
/* This vote should succeed under all normal
* circumstances. */
struct buffer_head **tmpbh;
struct inode *tmpinode;
- mlog_entry("(inode1 = %"MLFu64", inode2 = %"MLFu64")\n",
- oi1->ip_blkno, oi2->ip_blkno);
+ mlog_entry("(inode1 = %llu, inode2 = %llu)\n",
+ (unsigned long long)oi1->ip_blkno,
+ (unsigned long long)oi2->ip_blkno);
BUG_ON(!handle);
struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir,
// this is the 1st dirent bh
nlink_t old_dir_nlink = old_dir->i_nlink, new_dir_nlink = new_dir->i_nlink;
- unsigned int links_count;
/* At some point it might be nice to break this function up a
* bit. */
}
}
- if (S_ISDIR(old_inode->i_mode)) {
- /* Directories actually require metadata updates to
- * the directory info so we can't get away with not
- * doing node locking on it. */
- status = ocfs2_meta_lock(old_inode, handle, NULL, 1);
- if (status < 0) {
- if (status != -ENOENT)
- mlog_errno(status);
- goto bail;
- }
-
- status = ocfs2_request_rename_vote(old_inode, old_dentry);
- if (status < 0) {
+ /*
+ * Though we don't require an inode meta data update if
+ * old_inode is not a directory, we lock anyway here to ensure
+ * the vote thread on other nodes won't have to concurrently
+ * downconvert the inode and the dentry locks.
+ */
+ status = ocfs2_meta_lock(old_inode, handle, NULL, 1);
+ if (status < 0) {
+ if (status != -ENOENT)
mlog_errno(status);
- goto bail;
- }
+ goto bail;
+ }
+
+ status = ocfs2_remote_dentry_delete(old_dentry);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ if (S_ISDIR(old_inode->i_mode)) {
status = -EIO;
old_inode_de_bh = ocfs2_bread(old_inode, 0, &status, 0);
if (!old_inode_de_bh)
if (!new_inode && new_dir!=old_dir &&
new_dir->i_nlink >= OCFS2_LINK_MAX)
goto bail;
- } else {
- /* Ah, the simple case - we're a file so just send a
- * message. */
- status = ocfs2_request_rename_vote(old_inode, old_dentry);
- if (status < 0) {
- mlog_errno(status);
- goto bail;
- }
}
status = -ENOENT;
if (OCFS2_I(new_inode)->ip_blkno != newfe_blkno) {
status = -EACCES;
- mlog(0, "Inode blkno (%"MLFu64") and dir (%"MLFu64") "
- "disagree. ip_flags = %x\n",
- OCFS2_I(new_inode)->ip_blkno, newfe_blkno,
+ mlog(0, "Inode %llu and dir %llu disagree. flags = %x\n",
+ (unsigned long long)OCFS2_I(new_inode)->ip_blkno,
+ (unsigned long long)newfe_blkno,
OCFS2_I(new_inode)->ip_flags);
goto bail;
}
goto bail;
}
- if (S_ISDIR(new_inode->i_mode))
- links_count = 0;
- else
- links_count = (unsigned int) (new_inode->i_nlink - 1);
-
- status = ocfs2_request_unlink_vote(new_inode, new_dentry,
- links_count);
+ status = ocfs2_remote_dentry_delete(new_dentry);
if (status < 0) {
mlog_errno(status);
goto bail;
newfe = (struct ocfs2_dinode *) newfe_bh->b_data;
- mlog(0, "aha rename over existing... new_de=%p "
- "new_blkno=%"MLFu64" newfebh=%p bhblocknr=%llu\n",
- new_de, newfe_blkno, newfe_bh, newfe_bh ?
+ mlog(0, "aha rename over existing... new_de=%p new_blkno=%llu "
+ "newfebh=%p bhblocknr=%llu\n", new_de,
+ (unsigned long long)newfe_blkno, newfe_bh, newfe_bh ?
(unsigned long long)newfe_bh->b_blocknr : 0ULL);
if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) {
if (new_dir_nlink != new_dir->i_nlink) {
if (!new_dir_bh) {
mlog(ML_ERROR, "need to change nlink for new "
- "dir %"MLFu64" from %d to %d but bh is "
- "NULL\n", OCFS2_I(new_dir)->ip_blkno,
+ "dir %llu from %d to %d but bh is NULL\n",
+ (unsigned long long)OCFS2_I(new_dir)->ip_blkno,
(int)new_dir_nlink, new_dir->i_nlink);
} else {
struct ocfs2_dinode *fe;
if (old_dir_nlink != old_dir->i_nlink) {
if (!old_dir_bh) {
mlog(ML_ERROR, "need to change nlink for old dir "
- "%"MLFu64" from %d to %d but bh is NULL!\n",
- OCFS2_I(old_dir)->ip_blkno,
- (int)old_dir_nlink,
- old_dir->i_nlink);
+ "%llu from %d to %d but bh is NULL!\n",
+ (unsigned long long)OCFS2_I(old_dir)->ip_blkno,
+ (int)old_dir_nlink, old_dir->i_nlink);
} else {
struct ocfs2_dinode *fe;
status = ocfs2_journal_access(handle, old_dir,
}
}
+ ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir);
status = 0;
bail:
if (rename_lock)
* write i_size + 1 bytes. */
blocks = (bytes_left + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
- mlog_entry("i_blocks = %lu, i_size = %llu, blocks = %d\n",
- inode->i_blocks, i_size_read(inode), blocks);
+ mlog_entry("i_blocks = %llu, i_size = %llu, blocks = %d\n",
+ (unsigned long long)inode->i_blocks,
+ i_size_read(inode), blocks);
/* Sanity check -- make sure we're going to fit. */
if (bytes_left >
NULL);
if (status < 0) {
if (status != -ENOSPC && status != -EINTR) {
- mlog(ML_ERROR, "Failed to extend file to "
- "%"MLFu64"\n",
- newsize);
+ mlog(ML_ERROR,
+ "Failed to extend file to %llu\n",
+ (unsigned long long)newsize);
mlog_errno(status);
status = -ENOSPC;
}
goto bail;
}
+ status = ocfs2_dentry_attach_lock(dentry, inode, OCFS2_I(dir)->ip_blkno);
+ if (status) {
+ mlog_errno(status);
+ goto bail;
+ }
+
insert_inode_hash(inode);
dentry->d_op = &ocfs2_dentry_ops;
d_instantiate(dentry, inode);
error_msg = "directory entry across blocks";
if (error_msg != NULL)
- mlog(ML_ERROR, "bad entry in directory #%"MLFu64": %s - "
- "offset=%lu, inode=%"MLFu64", rec_len=%d, name_len=%d\n",
- OCFS2_I(dir)->ip_blkno, error_msg, offset,
- le64_to_cpu(de->inode), rlen, de->name_len);
+ mlog(ML_ERROR, "bad entry in directory #%llu: %s - "
+ "offset=%lu, inode=%llu, rec_len=%d, name_len=%d\n",
+ (unsigned long long)OCFS2_I(dir)->ip_blkno, error_msg,
+ offset, (unsigned long long)le64_to_cpu(de->inode), rlen,
+ de->name_len);
return error_msg == NULL ? 1 : 0;
}
}
num++;
- /* XXX: questionable readahead stuff here */
bh = ocfs2_bread(dir, b++, &err, 1);
bh_use[ra_max] = bh;
-#if 0 // ???
- if (bh)
- ll_rw_block(READ, 1, &bh);
-#endif
}
}
if ((bh = bh_use[ra_ptr++]) == NULL)
wait_on_buffer(bh);
if (!buffer_uptodate(bh)) {
/* read error, skip block & hope for the best */
+ ocfs2_error(dir->i_sb, "reading directory %llu, "
+ "offset %lu\n",
+ (unsigned long long)OCFS2_I(dir)->ip_blkno,
+ block);
brelse(bh);
goto next;
}
mlog_entry_void();
- namelen = snprintf(name, OCFS2_ORPHAN_NAMELEN + 1, "%016"MLFx64,
- blkno);
+ namelen = snprintf(name, OCFS2_ORPHAN_NAMELEN + 1, "%016llx",
+ (long long)blkno);
if (namelen <= 0) {
if (namelen)
status = namelen;
OCFS2_I(inode)->ip_orphaned_slot = osb->slot_num;
spin_unlock(&OCFS2_I(inode)->ip_lock);
- mlog(0, "Inode %"MLFu64" orphaned in slot %d\n",
- OCFS2_I(inode)->ip_blkno, osb->slot_num);
+ mlog(0, "Inode %llu orphaned in slot %d\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num);
leave:
if (orphan_dir_inode)
goto leave;
}
- mlog(0, "removing '%s' from orphan dir %"MLFu64" (namelen=%d)\n",
- name, OCFS2_I(orphan_dir_inode)->ip_blkno, OCFS2_ORPHAN_NAMELEN);
+ mlog(0, "removing '%s' from orphan dir %llu (namelen=%d)\n",
+ name, (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno,
+ OCFS2_ORPHAN_NAMELEN);
/* find it's spot in the orphan directory */
target_de_bh = ocfs2_find_entry(name, OCFS2_ORPHAN_NAMELEN,