diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /fs/udf/namei.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'fs/udf/namei.c')
-rw-r--r-- | fs/udf/namei.c | 60 |
1 files changed, 40 insertions, 20 deletions
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 95fee278ab9..f1dce848ef9 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include <linux/crc-itu-t.h> | 32 | #include <linux/crc-itu-t.h> |
33 | #include <linux/exportfs.h> | 33 | #include <linux/exportfs.h> |
34 | 34 | ||
35 | enum { UDF_MAX_LINKS = 0xffff }; | ||
36 | |||
35 | static inline int udf_match(int len1, const unsigned char *name1, int len2, | 37 | static inline int udf_match(int len1, const unsigned char *name1, int len2, |
36 | const unsigned char *name2) | 38 | const unsigned char *name2) |
37 | { | 39 | { |
@@ -251,7 +253,7 @@ out_ok: | |||
251 | } | 253 | } |
252 | 254 | ||
253 | static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, | 255 | static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, |
254 | unsigned int flags) | 256 | struct nameidata *nd) |
255 | { | 257 | { |
256 | struct inode *inode = NULL; | 258 | struct inode *inode = NULL; |
257 | struct fileIdentDesc cfi; | 259 | struct fileIdentDesc cfi; |
@@ -550,8 +552,8 @@ static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi, | |||
550 | return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL); | 552 | return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL); |
551 | } | 553 | } |
552 | 554 | ||
553 | static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 555 | static int udf_create(struct inode *dir, struct dentry *dentry, int mode, |
554 | bool excl) | 556 | struct nameidata *nd) |
555 | { | 557 | { |
556 | struct udf_fileident_bh fibh; | 558 | struct udf_fileident_bh fibh; |
557 | struct inode *inode; | 559 | struct inode *inode; |
@@ -575,7 +577,8 @@ static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
575 | 577 | ||
576 | fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); | 578 | fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); |
577 | if (!fi) { | 579 | if (!fi) { |
578 | inode_dec_link_count(inode); | 580 | inode->i_nlink--; |
581 | mark_inode_dirty(inode); | ||
579 | iput(inode); | 582 | iput(inode); |
580 | return err; | 583 | return err; |
581 | } | 584 | } |
@@ -594,7 +597,7 @@ static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
594 | return 0; | 597 | return 0; |
595 | } | 598 | } |
596 | 599 | ||
597 | static int udf_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, | 600 | static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode, |
598 | dev_t rdev) | 601 | dev_t rdev) |
599 | { | 602 | { |
600 | struct inode *inode; | 603 | struct inode *inode; |
@@ -615,7 +618,8 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
615 | init_special_inode(inode, mode, rdev); | 618 | init_special_inode(inode, mode, rdev); |
616 | fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); | 619 | fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); |
617 | if (!fi) { | 620 | if (!fi) { |
618 | inode_dec_link_count(inode); | 621 | inode->i_nlink--; |
622 | mark_inode_dirty(inode); | ||
619 | iput(inode); | 623 | iput(inode); |
620 | return err; | 624 | return err; |
621 | } | 625 | } |
@@ -638,7 +642,7 @@ out: | |||
638 | return err; | 642 | return err; |
639 | } | 643 | } |
640 | 644 | ||
641 | static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | 645 | static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode) |
642 | { | 646 | { |
643 | struct inode *inode; | 647 | struct inode *inode; |
644 | struct udf_fileident_bh fibh; | 648 | struct udf_fileident_bh fibh; |
@@ -647,6 +651,10 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
647 | struct udf_inode_info *dinfo = UDF_I(dir); | 651 | struct udf_inode_info *dinfo = UDF_I(dir); |
648 | struct udf_inode_info *iinfo; | 652 | struct udf_inode_info *iinfo; |
649 | 653 | ||
654 | err = -EMLINK; | ||
655 | if (dir->i_nlink >= UDF_MAX_LINKS) | ||
656 | goto out; | ||
657 | |||
650 | err = -EIO; | 658 | err = -EIO; |
651 | inode = udf_new_inode(dir, S_IFDIR | mode, &err); | 659 | inode = udf_new_inode(dir, S_IFDIR | mode, &err); |
652 | if (!inode) | 660 | if (!inode) |
@@ -657,11 +665,12 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
657 | inode->i_fop = &udf_dir_operations; | 665 | inode->i_fop = &udf_dir_operations; |
658 | fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err); | 666 | fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err); |
659 | if (!fi) { | 667 | if (!fi) { |
660 | inode_dec_link_count(inode); | 668 | inode->i_nlink--; |
669 | mark_inode_dirty(inode); | ||
661 | iput(inode); | 670 | iput(inode); |
662 | goto out; | 671 | goto out; |
663 | } | 672 | } |
664 | set_nlink(inode, 2); | 673 | inode->i_nlink = 2; |
665 | cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); | 674 | cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); |
666 | cfi.icb.extLocation = cpu_to_lelb(dinfo->i_location); | 675 | cfi.icb.extLocation = cpu_to_lelb(dinfo->i_location); |
667 | *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = | 676 | *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = |
@@ -674,7 +683,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
674 | 683 | ||
675 | fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); | 684 | fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); |
676 | if (!fi) { | 685 | if (!fi) { |
677 | clear_nlink(inode); | 686 | inode->i_nlink = 0; |
678 | mark_inode_dirty(inode); | 687 | mark_inode_dirty(inode); |
679 | iput(inode); | 688 | iput(inode); |
680 | goto out; | 689 | goto out; |
@@ -790,8 +799,9 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry) | |||
790 | if (retval) | 799 | if (retval) |
791 | goto end_rmdir; | 800 | goto end_rmdir; |
792 | if (inode->i_nlink != 2) | 801 | if (inode->i_nlink != 2) |
793 | udf_warn(inode->i_sb, "empty directory has nlink != 2 (%d)\n", | 802 | udf_warning(inode->i_sb, "udf_rmdir", |
794 | inode->i_nlink); | 803 | "empty directory has nlink != 2 (%d)", |
804 | inode->i_nlink); | ||
795 | clear_nlink(inode); | 805 | clear_nlink(inode); |
796 | inode->i_size = 0; | 806 | inode->i_size = 0; |
797 | inode_dec_link_count(dir); | 807 | inode_dec_link_count(dir); |
@@ -830,7 +840,7 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry) | |||
830 | if (!inode->i_nlink) { | 840 | if (!inode->i_nlink) { |
831 | udf_debug("Deleting nonexistent file (%lu), %d\n", | 841 | udf_debug("Deleting nonexistent file (%lu), %d\n", |
832 | inode->i_ino, inode->i_nlink); | 842 | inode->i_ino, inode->i_nlink); |
833 | set_nlink(inode, 1); | 843 | inode->i_nlink = 1; |
834 | } | 844 | } |
835 | retval = udf_delete_entry(dir, fi, &fibh, &cfi); | 845 | retval = udf_delete_entry(dir, fi, &fibh, &cfi); |
836 | if (retval) | 846 | if (retval) |
@@ -1026,6 +1036,9 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir, | |||
1026 | struct fileIdentDesc cfi, *fi; | 1036 | struct fileIdentDesc cfi, *fi; |
1027 | int err; | 1037 | int err; |
1028 | 1038 | ||
1039 | if (inode->i_nlink >= UDF_MAX_LINKS) | ||
1040 | return -EMLINK; | ||
1041 | |||
1029 | fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); | 1042 | fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); |
1030 | if (!fi) { | 1043 | if (!fi) { |
1031 | return err; | 1044 | return err; |
@@ -1117,6 +1130,10 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1117 | if (udf_get_lb_pblock(old_inode->i_sb, &tloc, 0) != | 1130 | if (udf_get_lb_pblock(old_inode->i_sb, &tloc, 0) != |
1118 | old_dir->i_ino) | 1131 | old_dir->i_ino) |
1119 | goto end_rename; | 1132 | goto end_rename; |
1133 | |||
1134 | retval = -EMLINK; | ||
1135 | if (!new_inode && new_dir->i_nlink >= UDF_MAX_LINKS) | ||
1136 | goto end_rename; | ||
1120 | } | 1137 | } |
1121 | if (!nfi) { | 1138 | if (!nfi) { |
1122 | nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi, | 1139 | nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi, |
@@ -1193,7 +1210,7 @@ static struct dentry *udf_get_parent(struct dentry *child) | |||
1193 | { | 1210 | { |
1194 | struct kernel_lb_addr tloc; | 1211 | struct kernel_lb_addr tloc; |
1195 | struct inode *inode = NULL; | 1212 | struct inode *inode = NULL; |
1196 | struct qstr dotdot = QSTR_INIT("..", 2); | 1213 | struct qstr dotdot = {.name = "..", .len = 2}; |
1197 | struct fileIdentDesc cfi; | 1214 | struct fileIdentDesc cfi; |
1198 | struct udf_fileident_bh fibh; | 1215 | struct udf_fileident_bh fibh; |
1199 | 1216 | ||
@@ -1260,15 +1277,16 @@ static struct dentry *udf_fh_to_parent(struct super_block *sb, | |||
1260 | fid->udf.parent_partref, | 1277 | fid->udf.parent_partref, |
1261 | fid->udf.parent_generation); | 1278 | fid->udf.parent_generation); |
1262 | } | 1279 | } |
1263 | static int udf_encode_fh(struct inode *inode, __u32 *fh, int *lenp, | 1280 | static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp, |
1264 | struct inode *parent) | 1281 | int connectable) |
1265 | { | 1282 | { |
1266 | int len = *lenp; | 1283 | int len = *lenp; |
1284 | struct inode *inode = de->d_inode; | ||
1267 | struct kernel_lb_addr location = UDF_I(inode)->i_location; | 1285 | struct kernel_lb_addr location = UDF_I(inode)->i_location; |
1268 | struct fid *fid = (struct fid *)fh; | 1286 | struct fid *fid = (struct fid *)fh; |
1269 | int type = FILEID_UDF_WITHOUT_PARENT; | 1287 | int type = FILEID_UDF_WITHOUT_PARENT; |
1270 | 1288 | ||
1271 | if (parent && (len < 5)) { | 1289 | if (connectable && (len < 5)) { |
1272 | *lenp = 5; | 1290 | *lenp = 5; |
1273 | return 255; | 1291 | return 255; |
1274 | } else if (len < 3) { | 1292 | } else if (len < 3) { |
@@ -1279,14 +1297,16 @@ static int udf_encode_fh(struct inode *inode, __u32 *fh, int *lenp, | |||
1279 | *lenp = 3; | 1297 | *lenp = 3; |
1280 | fid->udf.block = location.logicalBlockNum; | 1298 | fid->udf.block = location.logicalBlockNum; |
1281 | fid->udf.partref = location.partitionReferenceNum; | 1299 | fid->udf.partref = location.partitionReferenceNum; |
1282 | fid->udf.parent_partref = 0; | ||
1283 | fid->udf.generation = inode->i_generation; | 1300 | fid->udf.generation = inode->i_generation; |
1284 | 1301 | ||
1285 | if (parent) { | 1302 | if (connectable && !S_ISDIR(inode->i_mode)) { |
1286 | location = UDF_I(parent)->i_location; | 1303 | spin_lock(&de->d_lock); |
1304 | inode = de->d_parent->d_inode; | ||
1305 | location = UDF_I(inode)->i_location; | ||
1287 | fid->udf.parent_block = location.logicalBlockNum; | 1306 | fid->udf.parent_block = location.logicalBlockNum; |
1288 | fid->udf.parent_partref = location.partitionReferenceNum; | 1307 | fid->udf.parent_partref = location.partitionReferenceNum; |
1289 | fid->udf.parent_generation = inode->i_generation; | 1308 | fid->udf.parent_generation = inode->i_generation; |
1309 | spin_unlock(&de->d_lock); | ||
1290 | *lenp = 5; | 1310 | *lenp = 5; |
1291 | type = FILEID_UDF_WITH_PARENT; | 1311 | type = FILEID_UDF_WITH_PARENT; |
1292 | } | 1312 | } |