/*
- * Copyright (C) International Business Machines Corp., 2000-2003
+ * Copyright (C) International Business Machines Corp., 2000-2004
* Portions Copyright (C) Christoph Hellwig, 2001-2002
*
* This program is free software; you can redistribute it and/or modify
*/
#include <linux/fs.h>
+#include <linux/ctype.h>
+#include <linux/quotaops.h>
#include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_inode.h"
*/
struct inode_operations jfs_dir_inode_operations;
struct file_operations jfs_dir_operations;
+struct dentry_operations jfs_ci_dentry_operations;
static s64 commitZeroLink(tid_t, struct inode *);
*/
ino = ip->i_ino;
if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
- jfs_err("jfs_create: dtInsert returned %d", rc);
- if (rc == -EIO)
+ if (rc == -EIO) {
+ jfs_err("jfs_create: dtInsert returned -EIO");
txAbort(tid, 1); /* Marks Filesystem dirty */
- else
+ } else
txAbort(tid, 0); /* Filesystem full */
goto out3;
}
*/
ino = ip->i_ino;
if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
- jfs_err("jfs_mkdir: dtInsert returned %d", rc);
-
- if (rc == -EIO)
+ if (rc == -EIO) {
+ jfs_err("jfs_mkdir: dtInsert returned -EIO");
txAbort(tid, 1); /* Marks Filesystem dirty */
- else
+ } else
txAbort(tid, 0); /* Filesystem full */
goto out3;
}
jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name);
+ /* Init inode for quota operations. */
+ DQUOT_INIT(ip);
+
/* directory must be empty to be removed */
if (!dtEmpty(ip)) {
rc = -ENOTEMPTY;
jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name);
+ /* Init inode for quota operations. */
+ DQUOT_INIT(ip);
+
if ((rc = get_UCSname(&dname, dentry)))
goto out;
pxdlock->flag = mlckFREEPXD;
PXDaddress(&pxdlock->pxd, xaddr);
PXDlength(&pxdlock->pxd, xlen);
- txFreeMap(ip, pxdlock, 0, COMMIT_WMAP);
+ txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP);
}
/*
pxdlock->flag = mlckFREEPXD;
PXDaddress(&pxdlock->pxd, xaddr);
PXDlength(&pxdlock->pxd, xlen);
- txFreeMap(ip, pxdlock, 0, COMMIT_WMAP);
+ txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP);
}
/*
iplist[1] = dir;
rc = txCommit(tid, 2, &iplist[0], 0);
- if (!rc)
+ if (rc) {
+ ip->i_nlink--;
+ iput(ip);
+ } else
d_instantiate(dentry, ip);
free_dname:
mp = get_metapage(ip, xaddr, PSIZE, 1);
if (mp == NULL) {
- dbFree(ip, extent, xlen);
+ xtTruncate(tid, ip, 0, COMMIT_PWMAP);
rc = -EIO;
txAbort(tid, 0);
goto out3;
name += copy_size;
xaddr += JFS_SBI(sb)->nbperpage;
}
- ip->i_blocks = LBLK2PBLK(sb, xlen);
}
/*
}
if (rc) {
if (xlen)
- dbFree(ip, extent, xlen);
+ xtTruncate(tid, ip, 0, COMMIT_PWMAP);
txAbort(tid, 0);
/* discard new inode */
goto out3;
rc = -EMLINK;
goto out3;
}
- } else if (new_ip)
+ } else if (new_ip) {
IWRITE_LOCK(new_ip);
+ /* Init inode for quota operations. */
+ DQUOT_INIT(new_ip);
+ }
/*
* The real work starts here
ino = old_ip->i_ino;
rc = dtInsert(tid, new_dir, &new_dname, &ino, &btstack);
if (rc) {
- jfs_err("jfs_rename: dtInsert failed w/rc = %d",
- rc);
+ if (rc == -EIO)
+ jfs_err("jfs_rename: dtInsert returned -EIO");
goto out4;
}
if (S_ISDIR(old_ip->i_mode))
return ERR_PTR(-EACCES);
}
- return d_splice_alias(ip, dentry);
+ if (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2)
+ dentry->d_op = &jfs_ci_dentry_operations;
+
+ dentry = d_splice_alias(ip, dentry);
+
+ if (dentry && (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2))
+ dentry->d_op = &jfs_ci_dentry_operations;
+
+ return dentry;
}
struct dentry *jfs_get_parent(struct dentry *dentry)
.readdir = jfs_readdir,
.fsync = jfs_fsync,
};
+
+static int jfs_ci_hash(struct dentry *dir, struct qstr *this)
+{
+ unsigned long hash;
+ int i;
+
+ hash = init_name_hash();
+ for (i=0; i < this->len; i++)
+ hash = partial_name_hash(tolower(this->name[i]), hash);
+ this->hash = end_name_hash(hash);
+
+ return 0;
+}
+
+static int jfs_ci_compare(struct dentry *dir, struct qstr *a, struct qstr *b)
+{
+ int i, result = 1;
+
+ if (a->len != b->len)
+ goto out;
+ for (i=0; i < a->len; i++) {
+ if (tolower(a->name[i]) != tolower(b->name[i]))
+ goto out;
+ }
+ result = 0;
+
+ /*
+ * We want creates to preserve case. A negative dentry, a, that
+ * has a different case than b may cause a new entry to be created
+ * with the wrong case. Since we can't tell if a comes from a negative
+ * dentry, we blindly replace it with b. This should be harmless if
+ * a is not a negative dentry.
+ */
+ memcpy((unsigned char *)a->name, b->name, a->len);
+out:
+ return result;
+}
+
+struct dentry_operations jfs_ci_dentry_operations =
+{
+ .d_hash = jfs_ci_hash,
+ .d_compare = jfs_ci_compare,
+};