diff options
Diffstat (limited to 'fs/jfs/namei.c')
-rw-r--r-- | fs/jfs/namei.c | 82 |
1 files changed, 52 insertions, 30 deletions
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index a9cf8e8675be..eaaf2b511e89 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
21 | #include <linux/namei.h> | ||
21 | #include <linux/ctype.h> | 22 | #include <linux/ctype.h> |
22 | #include <linux/quotaops.h> | 23 | #include <linux/quotaops.h> |
23 | #include <linux/exportfs.h> | 24 | #include <linux/exportfs.h> |
@@ -114,7 +115,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, | |||
114 | if (rc) | 115 | if (rc) |
115 | goto out3; | 116 | goto out3; |
116 | 117 | ||
117 | rc = jfs_init_security(tid, ip, dip); | 118 | rc = jfs_init_security(tid, ip, dip, &dentry->d_name); |
118 | if (rc) { | 119 | if (rc) { |
119 | txAbort(tid, 0); | 120 | txAbort(tid, 0); |
120 | goto out3; | 121 | goto out3; |
@@ -252,7 +253,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) | |||
252 | if (rc) | 253 | if (rc) |
253 | goto out3; | 254 | goto out3; |
254 | 255 | ||
255 | rc = jfs_init_security(tid, ip, dip); | 256 | rc = jfs_init_security(tid, ip, dip, &dentry->d_name); |
256 | if (rc) { | 257 | if (rc) { |
257 | txAbort(tid, 0); | 258 | txAbort(tid, 0); |
258 | goto out3; | 259 | goto out3; |
@@ -808,9 +809,6 @@ static int jfs_link(struct dentry *old_dentry, | |||
808 | if (ip->i_nlink == JFS_LINK_MAX) | 809 | if (ip->i_nlink == JFS_LINK_MAX) |
809 | return -EMLINK; | 810 | return -EMLINK; |
810 | 811 | ||
811 | if (ip->i_nlink == 0) | ||
812 | return -ENOENT; | ||
813 | |||
814 | dquot_initialize(dir); | 812 | dquot_initialize(dir); |
815 | 813 | ||
816 | tid = txBegin(ip->i_sb, 0); | 814 | tid = txBegin(ip->i_sb, 0); |
@@ -839,7 +837,7 @@ static int jfs_link(struct dentry *old_dentry, | |||
839 | ip->i_ctime = CURRENT_TIME; | 837 | ip->i_ctime = CURRENT_TIME; |
840 | dir->i_ctime = dir->i_mtime = CURRENT_TIME; | 838 | dir->i_ctime = dir->i_mtime = CURRENT_TIME; |
841 | mark_inode_dirty(dir); | 839 | mark_inode_dirty(dir); |
842 | atomic_inc(&ip->i_count); | 840 | ihold(ip); |
843 | 841 | ||
844 | iplist[0] = ip; | 842 | iplist[0] = ip; |
845 | iplist[1] = dir; | 843 | iplist[1] = dir; |
@@ -931,7 +929,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, | |||
931 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); | 929 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); |
932 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); | 930 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); |
933 | 931 | ||
934 | rc = jfs_init_security(tid, ip, dip); | 932 | rc = jfs_init_security(tid, ip, dip, &dentry->d_name); |
935 | if (rc) | 933 | if (rc) |
936 | goto out3; | 934 | goto out3; |
937 | 935 | ||
@@ -1394,7 +1392,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, | |||
1394 | if (rc) | 1392 | if (rc) |
1395 | goto out3; | 1393 | goto out3; |
1396 | 1394 | ||
1397 | rc = jfs_init_security(tid, ip, dir); | 1395 | rc = jfs_init_security(tid, ip, dir, &dentry->d_name); |
1398 | if (rc) { | 1396 | if (rc) { |
1399 | txAbort(tid, 0); | 1397 | txAbort(tid, 0); |
1400 | goto out3; | 1398 | goto out3; |
@@ -1464,9 +1462,6 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc | |||
1464 | 1462 | ||
1465 | jfs_info("jfs_lookup: name = %s", name); | 1463 | jfs_info("jfs_lookup: name = %s", name); |
1466 | 1464 | ||
1467 | if (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2) | ||
1468 | dentry->d_op = &jfs_ci_dentry_operations; | ||
1469 | |||
1470 | if ((name[0] == '.') && (len == 1)) | 1465 | if ((name[0] == '.') && (len == 1)) |
1471 | inum = dip->i_ino; | 1466 | inum = dip->i_ino; |
1472 | else if (strcmp(name, "..") == 0) | 1467 | else if (strcmp(name, "..") == 0) |
@@ -1491,12 +1486,7 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc | |||
1491 | return ERR_CAST(ip); | 1486 | return ERR_CAST(ip); |
1492 | } | 1487 | } |
1493 | 1488 | ||
1494 | dentry = d_splice_alias(ip, dentry); | 1489 | return d_splice_alias(ip, dentry); |
1495 | |||
1496 | if (dentry && (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2)) | ||
1497 | dentry->d_op = &jfs_ci_dentry_operations; | ||
1498 | |||
1499 | return dentry; | ||
1500 | } | 1490 | } |
1501 | 1491 | ||
1502 | static struct inode *jfs_nfs_get_inode(struct super_block *sb, | 1492 | static struct inode *jfs_nfs_get_inode(struct super_block *sb, |
@@ -1573,7 +1563,8 @@ const struct file_operations jfs_dir_operations = { | |||
1573 | .llseek = generic_file_llseek, | 1563 | .llseek = generic_file_llseek, |
1574 | }; | 1564 | }; |
1575 | 1565 | ||
1576 | static int jfs_ci_hash(struct dentry *dir, struct qstr *this) | 1566 | static int jfs_ci_hash(const struct dentry *dir, const struct inode *inode, |
1567 | struct qstr *this) | ||
1577 | { | 1568 | { |
1578 | unsigned long hash; | 1569 | unsigned long hash; |
1579 | int i; | 1570 | int i; |
@@ -1586,32 +1577,63 @@ static int jfs_ci_hash(struct dentry *dir, struct qstr *this) | |||
1586 | return 0; | 1577 | return 0; |
1587 | } | 1578 | } |
1588 | 1579 | ||
1589 | static int jfs_ci_compare(struct dentry *dir, struct qstr *a, struct qstr *b) | 1580 | static int jfs_ci_compare(const struct dentry *parent, |
1581 | const struct inode *pinode, | ||
1582 | const struct dentry *dentry, const struct inode *inode, | ||
1583 | unsigned int len, const char *str, const struct qstr *name) | ||
1590 | { | 1584 | { |
1591 | int i, result = 1; | 1585 | int i, result = 1; |
1592 | 1586 | ||
1593 | if (a->len != b->len) | 1587 | if (len != name->len) |
1594 | goto out; | 1588 | goto out; |
1595 | for (i=0; i < a->len; i++) { | 1589 | for (i=0; i < len; i++) { |
1596 | if (tolower(a->name[i]) != tolower(b->name[i])) | 1590 | if (tolower(str[i]) != tolower(name->name[i])) |
1597 | goto out; | 1591 | goto out; |
1598 | } | 1592 | } |
1599 | result = 0; | 1593 | result = 0; |
1594 | out: | ||
1595 | return result; | ||
1596 | } | ||
1600 | 1597 | ||
1598 | static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd) | ||
1599 | { | ||
1600 | if (nd && nd->flags & LOOKUP_RCU) | ||
1601 | return -ECHILD; | ||
1601 | /* | 1602 | /* |
1602 | * We want creates to preserve case. A negative dentry, a, that | 1603 | * This is not negative dentry. Always valid. |
1603 | * has a different case than b may cause a new entry to be created | 1604 | * |
1604 | * with the wrong case. Since we can't tell if a comes from a negative | 1605 | * Note, rename() to existing directory entry will have ->d_inode, |
1605 | * dentry, we blindly replace it with b. This should be harmless if | 1606 | * and will use existing name which isn't specified name by user. |
1606 | * a is not a negative dentry. | 1607 | * |
1608 | * We may be able to drop this positive dentry here. But dropping | ||
1609 | * positive dentry isn't good idea. So it's unsupported like | ||
1610 | * rename("filename", "FILENAME") for now. | ||
1607 | */ | 1611 | */ |
1608 | memcpy((unsigned char *)a->name, b->name, a->len); | 1612 | if (dentry->d_inode) |
1609 | out: | 1613 | return 1; |
1610 | return result; | 1614 | |
1615 | /* | ||
1616 | * This may be nfsd (or something), anyway, we can't see the | ||
1617 | * intent of this. So, since this can be for creation, drop it. | ||
1618 | */ | ||
1619 | if (!nd) | ||
1620 | return 0; | ||
1621 | |||
1622 | /* | ||
1623 | * Drop the negative dentry, in order to make sure to use the | ||
1624 | * case sensitive name which is specified by user if this is | ||
1625 | * for creation. | ||
1626 | */ | ||
1627 | if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) { | ||
1628 | if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) | ||
1629 | return 0; | ||
1630 | } | ||
1631 | return 1; | ||
1611 | } | 1632 | } |
1612 | 1633 | ||
1613 | const struct dentry_operations jfs_ci_dentry_operations = | 1634 | const struct dentry_operations jfs_ci_dentry_operations = |
1614 | { | 1635 | { |
1615 | .d_hash = jfs_ci_hash, | 1636 | .d_hash = jfs_ci_hash, |
1616 | .d_compare = jfs_ci_compare, | 1637 | .d_compare = jfs_ci_compare, |
1638 | .d_revalidate = jfs_ci_revalidate, | ||
1617 | }; | 1639 | }; |