diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/backref.c | 13 | ||||
-rw-r--r-- | fs/btrfs/delayed-inode.c | 8 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 12 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 4 | ||||
-rw-r--r-- | fs/btrfs/scrub.c | 2 | ||||
-rw-r--r-- | fs/ceph/addr.c | 2 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 6 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 12 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 10 | ||||
-rw-r--r-- | fs/cifs/smb2misc.c | 12 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 3 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 2 | ||||
-rw-r--r-- | fs/cifs/smb2transport.c | 2 | ||||
-rw-r--r-- | fs/ext4/extents.c | 4 | ||||
-rw-r--r-- | fs/ext4/file.c | 220 | ||||
-rw-r--r-- | fs/ext4/resize.c | 24 | ||||
-rw-r--r-- | fs/ext4/super.c | 2 | ||||
-rw-r--r-- | fs/fcntl.c | 5 | ||||
-rw-r--r-- | fs/isofs/rock.c | 3 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 2 | ||||
-rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 10 | ||||
-rw-r--r-- | fs/ocfs2/dlm/dlmrecovery.c | 5 | ||||
-rw-r--r-- | fs/ocfs2/namei.c | 43 | ||||
-rw-r--r-- | fs/udf/dir.c | 31 | ||||
-rw-r--r-- | fs/udf/inode.c | 14 | ||||
-rw-r--r-- | fs/udf/namei.c | 17 | ||||
-rw-r--r-- | fs/udf/symlink.c | 57 | ||||
-rw-r--r-- | fs/udf/udfdecl.h | 3 | ||||
-rw-r--r-- | fs/udf/unicode.c | 28 |
29 files changed, 337 insertions, 219 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 2d3e32ebfd15..8729cf68d2fe 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -1552,7 +1552,6 @@ int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb, | |||
1552 | { | 1552 | { |
1553 | int ret; | 1553 | int ret; |
1554 | int type; | 1554 | int type; |
1555 | struct btrfs_tree_block_info *info; | ||
1556 | struct btrfs_extent_inline_ref *eiref; | 1555 | struct btrfs_extent_inline_ref *eiref; |
1557 | 1556 | ||
1558 | if (*ptr == (unsigned long)-1) | 1557 | if (*ptr == (unsigned long)-1) |
@@ -1573,9 +1572,17 @@ int tree_backref_for_extent(unsigned long *ptr, struct extent_buffer *eb, | |||
1573 | } | 1572 | } |
1574 | 1573 | ||
1575 | /* we can treat both ref types equally here */ | 1574 | /* we can treat both ref types equally here */ |
1576 | info = (struct btrfs_tree_block_info *)(ei + 1); | ||
1577 | *out_root = btrfs_extent_inline_ref_offset(eb, eiref); | 1575 | *out_root = btrfs_extent_inline_ref_offset(eb, eiref); |
1578 | *out_level = btrfs_tree_block_level(eb, info); | 1576 | |
1577 | if (key->type == BTRFS_EXTENT_ITEM_KEY) { | ||
1578 | struct btrfs_tree_block_info *info; | ||
1579 | |||
1580 | info = (struct btrfs_tree_block_info *)(ei + 1); | ||
1581 | *out_level = btrfs_tree_block_level(eb, info); | ||
1582 | } else { | ||
1583 | ASSERT(key->type == BTRFS_METADATA_ITEM_KEY); | ||
1584 | *out_level = (u8)key->offset; | ||
1585 | } | ||
1579 | 1586 | ||
1580 | if (ret == 1) | 1587 | if (ret == 1) |
1581 | *ptr = (unsigned long)-1; | 1588 | *ptr = (unsigned long)-1; |
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 054577bddaf2..de4e70fb3cbb 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c | |||
@@ -1857,6 +1857,14 @@ int btrfs_delayed_delete_inode_ref(struct inode *inode) | |||
1857 | { | 1857 | { |
1858 | struct btrfs_delayed_node *delayed_node; | 1858 | struct btrfs_delayed_node *delayed_node; |
1859 | 1859 | ||
1860 | /* | ||
1861 | * we don't do delayed inode updates during log recovery because it | ||
1862 | * leads to enospc problems. This means we also can't do | ||
1863 | * delayed inode refs | ||
1864 | */ | ||
1865 | if (BTRFS_I(inode)->root->fs_info->log_root_recovering) | ||
1866 | return -EAGAIN; | ||
1867 | |||
1860 | delayed_node = btrfs_get_or_create_delayed_node(inode); | 1868 | delayed_node = btrfs_get_or_create_delayed_node(inode); |
1861 | if (IS_ERR(delayed_node)) | 1869 | if (IS_ERR(delayed_node)) |
1862 | return PTR_ERR(delayed_node); | 1870 | return PTR_ERR(delayed_node); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a80b97100d90..15116585e714 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -3139,9 +3139,11 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans, | |||
3139 | struct extent_buffer *leaf; | 3139 | struct extent_buffer *leaf; |
3140 | 3140 | ||
3141 | ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1); | 3141 | ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1); |
3142 | if (ret < 0) | 3142 | if (ret) { |
3143 | if (ret > 0) | ||
3144 | ret = -ENOENT; | ||
3143 | goto fail; | 3145 | goto fail; |
3144 | BUG_ON(ret); /* Corruption */ | 3146 | } |
3145 | 3147 | ||
3146 | leaf = path->nodes[0]; | 3148 | leaf = path->nodes[0]; |
3147 | bi = btrfs_item_ptr_offset(leaf, path->slots[0]); | 3149 | bi = btrfs_item_ptr_offset(leaf, path->slots[0]); |
@@ -3149,11 +3151,9 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans, | |||
3149 | btrfs_mark_buffer_dirty(leaf); | 3151 | btrfs_mark_buffer_dirty(leaf); |
3150 | btrfs_release_path(path); | 3152 | btrfs_release_path(path); |
3151 | fail: | 3153 | fail: |
3152 | if (ret) { | 3154 | if (ret) |
3153 | btrfs_abort_transaction(trans, root, ret); | 3155 | btrfs_abort_transaction(trans, root, ret); |
3154 | return ret; | 3156 | return ret; |
3155 | } | ||
3156 | return 0; | ||
3157 | 3157 | ||
3158 | } | 3158 | } |
3159 | 3159 | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index e687bb0dc73a..8bf326affb94 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -6255,8 +6255,10 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
6255 | 6255 | ||
6256 | out_fail: | 6256 | out_fail: |
6257 | btrfs_end_transaction(trans, root); | 6257 | btrfs_end_transaction(trans, root); |
6258 | if (drop_on_err) | 6258 | if (drop_on_err) { |
6259 | inode_dec_link_count(inode); | ||
6259 | iput(inode); | 6260 | iput(inode); |
6261 | } | ||
6260 | btrfs_balance_delayed_items(root); | 6262 | btrfs_balance_delayed_items(root); |
6261 | btrfs_btree_balance_dirty(root); | 6263 | btrfs_btree_balance_dirty(root); |
6262 | return err; | 6264 | return err; |
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index f2bb13a23f86..9e1569ffbf6e 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -2607,9 +2607,9 @@ static int scrub_extent_for_parity(struct scrub_parity *sparity, | |||
2607 | ret = scrub_pages_for_parity(sparity, logical, l, physical, dev, | 2607 | ret = scrub_pages_for_parity(sparity, logical, l, physical, dev, |
2608 | flags, gen, mirror_num, | 2608 | flags, gen, mirror_num, |
2609 | have_csum ? csum : NULL); | 2609 | have_csum ? csum : NULL); |
2610 | skip: | ||
2611 | if (ret) | 2610 | if (ret) |
2612 | return ret; | 2611 | return ret; |
2612 | skip: | ||
2613 | len -= l; | 2613 | len -= l; |
2614 | logical += l; | 2614 | logical += l; |
2615 | physical += l; | 2615 | physical += l; |
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index f5013d92a7e6..c81c0e004588 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c | |||
@@ -1416,7 +1416,7 @@ void ceph_fill_inline_data(struct inode *inode, struct page *locked_page, | |||
1416 | } | 1416 | } |
1417 | } | 1417 | } |
1418 | 1418 | ||
1419 | dout("fill_inline_data %p %llx.%llx len %lu locked_page %p\n", | 1419 | dout("fill_inline_data %p %llx.%llx len %zu locked_page %p\n", |
1420 | inode, ceph_vinop(inode), len, locked_page); | 1420 | inode, ceph_vinop(inode), len, locked_page); |
1421 | 1421 | ||
1422 | if (len > 0) { | 1422 | if (len > 0) { |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 6e139111fdb2..22b289a3b1c4 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -661,16 +661,16 @@ set_credits(struct TCP_Server_Info *server, const int val) | |||
661 | server->ops->set_credits(server, val); | 661 | server->ops->set_credits(server, val); |
662 | } | 662 | } |
663 | 663 | ||
664 | static inline __u64 | 664 | static inline __le64 |
665 | get_next_mid64(struct TCP_Server_Info *server) | 665 | get_next_mid64(struct TCP_Server_Info *server) |
666 | { | 666 | { |
667 | return server->ops->get_next_mid(server); | 667 | return cpu_to_le64(server->ops->get_next_mid(server)); |
668 | } | 668 | } |
669 | 669 | ||
670 | static inline __le16 | 670 | static inline __le16 |
671 | get_next_mid(struct TCP_Server_Info *server) | 671 | get_next_mid(struct TCP_Server_Info *server) |
672 | { | 672 | { |
673 | __u16 mid = get_next_mid64(server); | 673 | __u16 mid = server->ops->get_next_mid(server); |
674 | /* | 674 | /* |
675 | * The value in the SMB header should be little endian for easy | 675 | * The value in the SMB header should be little endian for easy |
676 | * on-the-wire decoding. | 676 | * on-the-wire decoding. |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index b333ff60781d..abae6dd2c6b9 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -926,6 +926,7 @@ cifs_NTtimeToUnix(__le64 ntutc) | |||
926 | 926 | ||
927 | /* Subtract the NTFS time offset, then convert to 1s intervals. */ | 927 | /* Subtract the NTFS time offset, then convert to 1s intervals. */ |
928 | s64 t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET; | 928 | s64 t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET; |
929 | u64 abs_t; | ||
929 | 930 | ||
930 | /* | 931 | /* |
931 | * Unfortunately can not use normal 64 bit division on 32 bit arch, but | 932 | * Unfortunately can not use normal 64 bit division on 32 bit arch, but |
@@ -933,13 +934,14 @@ cifs_NTtimeToUnix(__le64 ntutc) | |||
933 | * to special case them | 934 | * to special case them |
934 | */ | 935 | */ |
935 | if (t < 0) { | 936 | if (t < 0) { |
936 | t = -t; | 937 | abs_t = -t; |
937 | ts.tv_nsec = (long)(do_div(t, 10000000) * 100); | 938 | ts.tv_nsec = (long)(do_div(abs_t, 10000000) * 100); |
938 | ts.tv_nsec = -ts.tv_nsec; | 939 | ts.tv_nsec = -ts.tv_nsec; |
939 | ts.tv_sec = -t; | 940 | ts.tv_sec = -abs_t; |
940 | } else { | 941 | } else { |
941 | ts.tv_nsec = (long)do_div(t, 10000000) * 100; | 942 | abs_t = t; |
942 | ts.tv_sec = t; | 943 | ts.tv_nsec = (long)do_div(abs_t, 10000000) * 100; |
944 | ts.tv_sec = abs_t; | ||
943 | } | 945 | } |
944 | 946 | ||
945 | return ts; | 947 | return ts; |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 8eaf20a80649..c295338e0a98 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -69,7 +69,8 @@ static inline void dump_cifs_file_struct(struct file *file, char *label) | |||
69 | * Attempt to preload the dcache with the results from the FIND_FIRST/NEXT | 69 | * Attempt to preload the dcache with the results from the FIND_FIRST/NEXT |
70 | * | 70 | * |
71 | * Find the dentry that matches "name". If there isn't one, create one. If it's | 71 | * Find the dentry that matches "name". If there isn't one, create one. If it's |
72 | * a negative dentry or the uniqueid changed, then drop it and recreate it. | 72 | * a negative dentry or the uniqueid or filetype(mode) changed, |
73 | * then drop it and recreate it. | ||
73 | */ | 74 | */ |
74 | static void | 75 | static void |
75 | cifs_prime_dcache(struct dentry *parent, struct qstr *name, | 76 | cifs_prime_dcache(struct dentry *parent, struct qstr *name, |
@@ -97,8 +98,11 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name, | |||
97 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) | 98 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) |
98 | fattr->cf_uniqueid = CIFS_I(inode)->uniqueid; | 99 | fattr->cf_uniqueid = CIFS_I(inode)->uniqueid; |
99 | 100 | ||
100 | /* update inode in place if i_ino didn't change */ | 101 | /* update inode in place |
101 | if (CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) { | 102 | * if both i_ino and i_mode didn't change */ |
103 | if (CIFS_I(inode)->uniqueid == fattr->cf_uniqueid && | ||
104 | (inode->i_mode & S_IFMT) == | ||
105 | (fattr->cf_mode & S_IFMT)) { | ||
102 | cifs_fattr_to_inode(inode, fattr); | 106 | cifs_fattr_to_inode(inode, fattr); |
103 | goto out; | 107 | goto out; |
104 | } | 108 | } |
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index f1cefc9763ed..689f035915cf 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c | |||
@@ -32,12 +32,14 @@ | |||
32 | static int | 32 | static int |
33 | check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid) | 33 | check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid) |
34 | { | 34 | { |
35 | __u64 wire_mid = le64_to_cpu(hdr->MessageId); | ||
36 | |||
35 | /* | 37 | /* |
36 | * Make sure that this really is an SMB, that it is a response, | 38 | * Make sure that this really is an SMB, that it is a response, |
37 | * and that the message ids match. | 39 | * and that the message ids match. |
38 | */ | 40 | */ |
39 | if ((*(__le32 *)hdr->ProtocolId == SMB2_PROTO_NUMBER) && | 41 | if ((*(__le32 *)hdr->ProtocolId == SMB2_PROTO_NUMBER) && |
40 | (mid == hdr->MessageId)) { | 42 | (mid == wire_mid)) { |
41 | if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) | 43 | if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) |
42 | return 0; | 44 | return 0; |
43 | else { | 45 | else { |
@@ -51,11 +53,11 @@ check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid) | |||
51 | if (*(__le32 *)hdr->ProtocolId != SMB2_PROTO_NUMBER) | 53 | if (*(__le32 *)hdr->ProtocolId != SMB2_PROTO_NUMBER) |
52 | cifs_dbg(VFS, "Bad protocol string signature header %x\n", | 54 | cifs_dbg(VFS, "Bad protocol string signature header %x\n", |
53 | *(unsigned int *) hdr->ProtocolId); | 55 | *(unsigned int *) hdr->ProtocolId); |
54 | if (mid != hdr->MessageId) | 56 | if (mid != wire_mid) |
55 | cifs_dbg(VFS, "Mids do not match: %llu and %llu\n", | 57 | cifs_dbg(VFS, "Mids do not match: %llu and %llu\n", |
56 | mid, hdr->MessageId); | 58 | mid, wire_mid); |
57 | } | 59 | } |
58 | cifs_dbg(VFS, "Bad SMB detected. The Mid=%llu\n", hdr->MessageId); | 60 | cifs_dbg(VFS, "Bad SMB detected. The Mid=%llu\n", wire_mid); |
59 | return 1; | 61 | return 1; |
60 | } | 62 | } |
61 | 63 | ||
@@ -95,7 +97,7 @@ smb2_check_message(char *buf, unsigned int length) | |||
95 | { | 97 | { |
96 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; | 98 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; |
97 | struct smb2_pdu *pdu = (struct smb2_pdu *)hdr; | 99 | struct smb2_pdu *pdu = (struct smb2_pdu *)hdr; |
98 | __u64 mid = hdr->MessageId; | 100 | __u64 mid = le64_to_cpu(hdr->MessageId); |
99 | __u32 len = get_rfc1002_length(buf); | 101 | __u32 len = get_rfc1002_length(buf); |
100 | __u32 clc_len; /* calculated length */ | 102 | __u32 clc_len; /* calculated length */ |
101 | int command; | 103 | int command; |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 93fd0586f9ec..96b5d40a2ece 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -176,10 +176,11 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf) | |||
176 | { | 176 | { |
177 | struct mid_q_entry *mid; | 177 | struct mid_q_entry *mid; |
178 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; | 178 | struct smb2_hdr *hdr = (struct smb2_hdr *)buf; |
179 | __u64 wire_mid = le64_to_cpu(hdr->MessageId); | ||
179 | 180 | ||
180 | spin_lock(&GlobalMid_Lock); | 181 | spin_lock(&GlobalMid_Lock); |
181 | list_for_each_entry(mid, &server->pending_mid_q, qhead) { | 182 | list_for_each_entry(mid, &server->pending_mid_q, qhead) { |
182 | if ((mid->mid == hdr->MessageId) && | 183 | if ((mid->mid == wire_mid) && |
183 | (mid->mid_state == MID_REQUEST_SUBMITTED) && | 184 | (mid->mid_state == MID_REQUEST_SUBMITTED) && |
184 | (mid->command == hdr->Command)) { | 185 | (mid->command == hdr->Command)) { |
185 | spin_unlock(&GlobalMid_Lock); | 186 | spin_unlock(&GlobalMid_Lock); |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index ce858477002a..70867d54fb8b 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
@@ -110,7 +110,7 @@ struct smb2_hdr { | |||
110 | __le16 CreditRequest; /* CreditResponse */ | 110 | __le16 CreditRequest; /* CreditResponse */ |
111 | __le32 Flags; | 111 | __le32 Flags; |
112 | __le32 NextCommand; | 112 | __le32 NextCommand; |
113 | __u64 MessageId; /* opaque - so can stay little endian */ | 113 | __le64 MessageId; |
114 | __le32 ProcessId; | 114 | __le32 ProcessId; |
115 | __u32 TreeId; /* opaque - so do not make little endian */ | 115 | __u32 TreeId; /* opaque - so do not make little endian */ |
116 | __u64 SessionId; /* opaque - so do not make little endian */ | 116 | __u64 SessionId; /* opaque - so do not make little endian */ |
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 5111e7272db6..d4c5b6f109a7 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c | |||
@@ -490,7 +490,7 @@ smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer, | |||
490 | return temp; | 490 | return temp; |
491 | else { | 491 | else { |
492 | memset(temp, 0, sizeof(struct mid_q_entry)); | 492 | memset(temp, 0, sizeof(struct mid_q_entry)); |
493 | temp->mid = smb_buffer->MessageId; /* always LE */ | 493 | temp->mid = le64_to_cpu(smb_buffer->MessageId); |
494 | temp->pid = current->pid; | 494 | temp->pid = current->pid; |
495 | temp->command = smb_buffer->Command; /* Always LE */ | 495 | temp->command = smb_buffer->Command; /* Always LE */ |
496 | temp->when_alloc = jiffies; | 496 | temp->when_alloc = jiffies; |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index e5d3eadf47b1..bed43081720f 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -5166,8 +5166,8 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
5166 | 5166 | ||
5167 | /* fallback to generic here if not in extents fmt */ | 5167 | /* fallback to generic here if not in extents fmt */ |
5168 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) | 5168 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) |
5169 | return __generic_block_fiemap(inode, fieinfo, start, len, | 5169 | return generic_block_fiemap(inode, fieinfo, start, len, |
5170 | ext4_get_block); | 5170 | ext4_get_block); |
5171 | 5171 | ||
5172 | if (fiemap_check_flags(fieinfo, EXT4_FIEMAP_FLAGS)) | 5172 | if (fiemap_check_flags(fieinfo, EXT4_FIEMAP_FLAGS)) |
5173 | return -EBADR; | 5173 | return -EBADR; |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 513c12cf444c..8131be8c0af3 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -273,19 +273,24 @@ static int ext4_file_open(struct inode * inode, struct file * filp) | |||
273 | * we determine this extent as a data or a hole according to whether the | 273 | * we determine this extent as a data or a hole according to whether the |
274 | * page cache has data or not. | 274 | * page cache has data or not. |
275 | */ | 275 | */ |
276 | static int ext4_find_unwritten_pgoff(struct inode *inode, int whence, | 276 | static int ext4_find_unwritten_pgoff(struct inode *inode, |
277 | loff_t endoff, loff_t *offset) | 277 | int whence, |
278 | struct ext4_map_blocks *map, | ||
279 | loff_t *offset) | ||
278 | { | 280 | { |
279 | struct pagevec pvec; | 281 | struct pagevec pvec; |
282 | unsigned int blkbits; | ||
280 | pgoff_t index; | 283 | pgoff_t index; |
281 | pgoff_t end; | 284 | pgoff_t end; |
285 | loff_t endoff; | ||
282 | loff_t startoff; | 286 | loff_t startoff; |
283 | loff_t lastoff; | 287 | loff_t lastoff; |
284 | int found = 0; | 288 | int found = 0; |
285 | 289 | ||
290 | blkbits = inode->i_sb->s_blocksize_bits; | ||
286 | startoff = *offset; | 291 | startoff = *offset; |
287 | lastoff = startoff; | 292 | lastoff = startoff; |
288 | 293 | endoff = (loff_t)(map->m_lblk + map->m_len) << blkbits; | |
289 | 294 | ||
290 | index = startoff >> PAGE_CACHE_SHIFT; | 295 | index = startoff >> PAGE_CACHE_SHIFT; |
291 | end = endoff >> PAGE_CACHE_SHIFT; | 296 | end = endoff >> PAGE_CACHE_SHIFT; |
@@ -403,144 +408,147 @@ out: | |||
403 | static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) | 408 | static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) |
404 | { | 409 | { |
405 | struct inode *inode = file->f_mapping->host; | 410 | struct inode *inode = file->f_mapping->host; |
406 | struct fiemap_extent_info fie; | 411 | struct ext4_map_blocks map; |
407 | struct fiemap_extent ext[2]; | 412 | struct extent_status es; |
408 | loff_t next; | 413 | ext4_lblk_t start, last, end; |
409 | int i, ret = 0; | 414 | loff_t dataoff, isize; |
415 | int blkbits; | ||
416 | int ret = 0; | ||
410 | 417 | ||
411 | mutex_lock(&inode->i_mutex); | 418 | mutex_lock(&inode->i_mutex); |
412 | if (offset >= inode->i_size) { | 419 | |
420 | isize = i_size_read(inode); | ||
421 | if (offset >= isize) { | ||
413 | mutex_unlock(&inode->i_mutex); | 422 | mutex_unlock(&inode->i_mutex); |
414 | return -ENXIO; | 423 | return -ENXIO; |
415 | } | 424 | } |
416 | fie.fi_flags = 0; | 425 | |
417 | fie.fi_extents_max = 2; | 426 | blkbits = inode->i_sb->s_blocksize_bits; |
418 | fie.fi_extents_start = (struct fiemap_extent __user *) &ext; | 427 | start = offset >> blkbits; |
419 | while (1) { | 428 | last = start; |
420 | mm_segment_t old_fs = get_fs(); | 429 | end = isize >> blkbits; |
421 | 430 | dataoff = offset; | |
422 | fie.fi_extents_mapped = 0; | 431 | |
423 | memset(ext, 0, sizeof(*ext) * fie.fi_extents_max); | 432 | do { |
424 | 433 | map.m_lblk = last; | |
425 | set_fs(get_ds()); | 434 | map.m_len = end - last + 1; |
426 | ret = ext4_fiemap(inode, &fie, offset, maxsize - offset); | 435 | ret = ext4_map_blocks(NULL, inode, &map, 0); |
427 | set_fs(old_fs); | 436 | if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) { |
428 | if (ret) | 437 | if (last != start) |
438 | dataoff = (loff_t)last << blkbits; | ||
429 | break; | 439 | break; |
440 | } | ||
430 | 441 | ||
431 | /* No extents found, EOF */ | 442 | /* |
432 | if (!fie.fi_extents_mapped) { | 443 | * If there is a delay extent at this offset, |
433 | ret = -ENXIO; | 444 | * it will be as a data. |
445 | */ | ||
446 | ext4_es_find_delayed_extent_range(inode, last, last, &es); | ||
447 | if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) { | ||
448 | if (last != start) | ||
449 | dataoff = (loff_t)last << blkbits; | ||
434 | break; | 450 | break; |
435 | } | 451 | } |
436 | for (i = 0; i < fie.fi_extents_mapped; i++) { | ||
437 | next = (loff_t)(ext[i].fe_length + ext[i].fe_logical); | ||
438 | 452 | ||
439 | if (offset < (loff_t)ext[i].fe_logical) | 453 | /* |
440 | offset = (loff_t)ext[i].fe_logical; | 454 | * If there is a unwritten extent at this offset, |
441 | /* | 455 | * it will be as a data or a hole according to page |
442 | * If extent is not unwritten, then it contains valid | 456 | * cache that has data or not. |
443 | * data, mapped or delayed. | 457 | */ |
444 | */ | 458 | if (map.m_flags & EXT4_MAP_UNWRITTEN) { |
445 | if (!(ext[i].fe_flags & FIEMAP_EXTENT_UNWRITTEN)) | 459 | int unwritten; |
446 | goto out; | 460 | unwritten = ext4_find_unwritten_pgoff(inode, SEEK_DATA, |
461 | &map, &dataoff); | ||
462 | if (unwritten) | ||
463 | break; | ||
464 | } | ||
447 | 465 | ||
448 | /* | 466 | last++; |
449 | * If there is a unwritten extent at this offset, | 467 | dataoff = (loff_t)last << blkbits; |
450 | * it will be as a data or a hole according to page | 468 | } while (last <= end); |
451 | * cache that has data or not. | ||
452 | */ | ||
453 | if (ext4_find_unwritten_pgoff(inode, SEEK_DATA, | ||
454 | next, &offset)) | ||
455 | goto out; | ||
456 | 469 | ||
457 | if (ext[i].fe_flags & FIEMAP_EXTENT_LAST) { | ||
458 | ret = -ENXIO; | ||
459 | goto out; | ||
460 | } | ||
461 | offset = next; | ||
462 | } | ||
463 | } | ||
464 | if (offset > inode->i_size) | ||
465 | offset = inode->i_size; | ||
466 | out: | ||
467 | mutex_unlock(&inode->i_mutex); | 470 | mutex_unlock(&inode->i_mutex); |
468 | if (ret) | ||
469 | return ret; | ||
470 | 471 | ||
471 | return vfs_setpos(file, offset, maxsize); | 472 | if (dataoff > isize) |
473 | return -ENXIO; | ||
474 | |||
475 | return vfs_setpos(file, dataoff, maxsize); | ||
472 | } | 476 | } |
473 | 477 | ||
474 | /* | 478 | /* |
475 | * ext4_seek_hole() retrieves the offset for SEEK_HOLE | 479 | * ext4_seek_hole() retrieves the offset for SEEK_HOLE. |
476 | */ | 480 | */ |
477 | static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) | 481 | static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) |
478 | { | 482 | { |
479 | struct inode *inode = file->f_mapping->host; | 483 | struct inode *inode = file->f_mapping->host; |
480 | struct fiemap_extent_info fie; | 484 | struct ext4_map_blocks map; |
481 | struct fiemap_extent ext[2]; | 485 | struct extent_status es; |
482 | loff_t next; | 486 | ext4_lblk_t start, last, end; |
483 | int i, ret = 0; | 487 | loff_t holeoff, isize; |
488 | int blkbits; | ||
489 | int ret = 0; | ||
484 | 490 | ||
485 | mutex_lock(&inode->i_mutex); | 491 | mutex_lock(&inode->i_mutex); |
486 | if (offset >= inode->i_size) { | 492 | |
493 | isize = i_size_read(inode); | ||
494 | if (offset >= isize) { | ||
487 | mutex_unlock(&inode->i_mutex); | 495 | mutex_unlock(&inode->i_mutex); |
488 | return -ENXIO; | 496 | return -ENXIO; |
489 | } | 497 | } |
490 | 498 | ||
491 | fie.fi_flags = 0; | 499 | blkbits = inode->i_sb->s_blocksize_bits; |
492 | fie.fi_extents_max = 2; | 500 | start = offset >> blkbits; |
493 | fie.fi_extents_start = (struct fiemap_extent __user *)&ext; | 501 | last = start; |
494 | while (1) { | 502 | end = isize >> blkbits; |
495 | mm_segment_t old_fs = get_fs(); | 503 | holeoff = offset; |
496 | |||
497 | fie.fi_extents_mapped = 0; | ||
498 | memset(ext, 0, sizeof(*ext)); | ||
499 | 504 | ||
500 | set_fs(get_ds()); | 505 | do { |
501 | ret = ext4_fiemap(inode, &fie, offset, maxsize - offset); | 506 | map.m_lblk = last; |
502 | set_fs(old_fs); | 507 | map.m_len = end - last + 1; |
503 | if (ret) | 508 | ret = ext4_map_blocks(NULL, inode, &map, 0); |
504 | break; | 509 | if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) { |
510 | last += ret; | ||
511 | holeoff = (loff_t)last << blkbits; | ||
512 | continue; | ||
513 | } | ||
505 | 514 | ||
506 | /* No extents found */ | 515 | /* |
507 | if (!fie.fi_extents_mapped) | 516 | * If there is a delay extent at this offset, |
508 | break; | 517 | * we will skip this extent. |
518 | */ | ||
519 | ext4_es_find_delayed_extent_range(inode, last, last, &es); | ||
520 | if (es.es_len != 0 && in_range(last, es.es_lblk, es.es_len)) { | ||
521 | last = es.es_lblk + es.es_len; | ||
522 | holeoff = (loff_t)last << blkbits; | ||
523 | continue; | ||
524 | } | ||
509 | 525 | ||
510 | for (i = 0; i < fie.fi_extents_mapped; i++) { | 526 | /* |
511 | next = (loff_t)(ext[i].fe_logical + ext[i].fe_length); | 527 | * If there is a unwritten extent at this offset, |
512 | /* | 528 | * it will be as a data or a hole according to page |
513 | * If extent is not unwritten, then it contains valid | 529 | * cache that has data or not. |
514 | * data, mapped or delayed. | 530 | */ |
515 | */ | 531 | if (map.m_flags & EXT4_MAP_UNWRITTEN) { |
516 | if (!(ext[i].fe_flags & FIEMAP_EXTENT_UNWRITTEN)) { | 532 | int unwritten; |
517 | if (offset < (loff_t)ext[i].fe_logical) | 533 | unwritten = ext4_find_unwritten_pgoff(inode, SEEK_HOLE, |
518 | goto out; | 534 | &map, &holeoff); |
519 | offset = next; | 535 | if (!unwritten) { |
536 | last += ret; | ||
537 | holeoff = (loff_t)last << blkbits; | ||
520 | continue; | 538 | continue; |
521 | } | 539 | } |
522 | /* | ||
523 | * If there is a unwritten extent at this offset, | ||
524 | * it will be as a data or a hole according to page | ||
525 | * cache that has data or not. | ||
526 | */ | ||
527 | if (ext4_find_unwritten_pgoff(inode, SEEK_HOLE, | ||
528 | next, &offset)) | ||
529 | goto out; | ||
530 | |||
531 | offset = next; | ||
532 | if (ext[i].fe_flags & FIEMAP_EXTENT_LAST) | ||
533 | goto out; | ||
534 | } | 540 | } |
535 | } | 541 | |
536 | if (offset > inode->i_size) | 542 | /* find a hole */ |
537 | offset = inode->i_size; | 543 | break; |
538 | out: | 544 | } while (last <= end); |
545 | |||
539 | mutex_unlock(&inode->i_mutex); | 546 | mutex_unlock(&inode->i_mutex); |
540 | if (ret) | ||
541 | return ret; | ||
542 | 547 | ||
543 | return vfs_setpos(file, offset, maxsize); | 548 | if (holeoff > isize) |
549 | holeoff = isize; | ||
550 | |||
551 | return vfs_setpos(file, holeoff, maxsize); | ||
544 | } | 552 | } |
545 | 553 | ||
546 | /* | 554 | /* |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index bf76f405a5f9..8a8ec6293b19 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -24,6 +24,18 @@ int ext4_resize_begin(struct super_block *sb) | |||
24 | return -EPERM; | 24 | return -EPERM; |
25 | 25 | ||
26 | /* | 26 | /* |
27 | * If we are not using the primary superblock/GDT copy don't resize, | ||
28 | * because the user tools have no way of handling this. Probably a | ||
29 | * bad time to do it anyways. | ||
30 | */ | ||
31 | if (EXT4_SB(sb)->s_sbh->b_blocknr != | ||
32 | le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) { | ||
33 | ext4_warning(sb, "won't resize using backup superblock at %llu", | ||
34 | (unsigned long long)EXT4_SB(sb)->s_sbh->b_blocknr); | ||
35 | return -EPERM; | ||
36 | } | ||
37 | |||
38 | /* | ||
27 | * We are not allowed to do online-resizing on a filesystem mounted | 39 | * We are not allowed to do online-resizing on a filesystem mounted |
28 | * with error, because it can destroy the filesystem easily. | 40 | * with error, because it can destroy the filesystem easily. |
29 | */ | 41 | */ |
@@ -758,18 +770,6 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
758 | "EXT4-fs: ext4_add_new_gdb: adding group block %lu\n", | 770 | "EXT4-fs: ext4_add_new_gdb: adding group block %lu\n", |
759 | gdb_num); | 771 | gdb_num); |
760 | 772 | ||
761 | /* | ||
762 | * If we are not using the primary superblock/GDT copy don't resize, | ||
763 | * because the user tools have no way of handling this. Probably a | ||
764 | * bad time to do it anyways. | ||
765 | */ | ||
766 | if (EXT4_SB(sb)->s_sbh->b_blocknr != | ||
767 | le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) { | ||
768 | ext4_warning(sb, "won't resize using backup superblock at %llu", | ||
769 | (unsigned long long)EXT4_SB(sb)->s_sbh->b_blocknr); | ||
770 | return -EPERM; | ||
771 | } | ||
772 | |||
773 | gdb_bh = sb_bread(sb, gdblock); | 773 | gdb_bh = sb_bread(sb, gdblock); |
774 | if (!gdb_bh) | 774 | if (!gdb_bh) |
775 | return -EIO; | 775 | return -EIO; |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 43c92b1685cb..74c5f53595fb 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -3482,7 +3482,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3482 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 3482 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, |
3483 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) && | 3483 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) && |
3484 | EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) | 3484 | EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) |
3485 | ext4_warning(sb, KERN_INFO "metadata_csum and uninit_bg are " | 3485 | ext4_warning(sb, "metadata_csum and uninit_bg are " |
3486 | "redundant flags; please run fsck."); | 3486 | "redundant flags; please run fsck."); |
3487 | 3487 | ||
3488 | /* Check for a known checksum algorithm */ | 3488 | /* Check for a known checksum algorithm */ |
diff --git a/fs/fcntl.c b/fs/fcntl.c index 99d440a4a6ba..ee85cd4e136a 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -740,14 +740,15 @@ static int __init fcntl_init(void) | |||
740 | * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY | 740 | * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY |
741 | * is defined as O_NONBLOCK on some platforms and not on others. | 741 | * is defined as O_NONBLOCK on some platforms and not on others. |
742 | */ | 742 | */ |
743 | BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32( | 743 | BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32( |
744 | O_RDONLY | O_WRONLY | O_RDWR | | 744 | O_RDONLY | O_WRONLY | O_RDWR | |
745 | O_CREAT | O_EXCL | O_NOCTTY | | 745 | O_CREAT | O_EXCL | O_NOCTTY | |
746 | O_TRUNC | O_APPEND | /* O_NONBLOCK | */ | 746 | O_TRUNC | O_APPEND | /* O_NONBLOCK | */ |
747 | __O_SYNC | O_DSYNC | FASYNC | | 747 | __O_SYNC | O_DSYNC | FASYNC | |
748 | O_DIRECT | O_LARGEFILE | O_DIRECTORY | | 748 | O_DIRECT | O_LARGEFILE | O_DIRECTORY | |
749 | O_NOFOLLOW | O_NOATIME | O_CLOEXEC | | 749 | O_NOFOLLOW | O_NOATIME | O_CLOEXEC | |
750 | __FMODE_EXEC | O_PATH | __O_TMPFILE | 750 | __FMODE_EXEC | O_PATH | __O_TMPFILE | |
751 | __FMODE_NONOTIFY | ||
751 | )); | 752 | )); |
752 | 753 | ||
753 | fasync_cache = kmem_cache_create("fasync_cache", | 754 | fasync_cache = kmem_cache_create("fasync_cache", |
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index bb63254ed848..735d7522a3a9 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c | |||
@@ -362,6 +362,9 @@ repeat: | |||
362 | rs.cont_size = isonum_733(rr->u.CE.size); | 362 | rs.cont_size = isonum_733(rr->u.CE.size); |
363 | break; | 363 | break; |
364 | case SIG('E', 'R'): | 364 | case SIG('E', 'R'): |
365 | /* Invalid length of ER tag id? */ | ||
366 | if (rr->u.ER.len_id + offsetof(struct rock_ridge, u.ER.data) > rr->len) | ||
367 | goto out; | ||
365 | ISOFS_SB(inode->i_sb)->s_rock = 1; | 368 | ISOFS_SB(inode->i_sb)->s_rock = 1; |
366 | printk(KERN_DEBUG "ISO 9660 Extensions: "); | 369 | printk(KERN_DEBUG "ISO 9660 Extensions: "); |
367 | { | 370 | { |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 3550a9c87616..c06a1ba80d73 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -3897,11 +3897,11 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh, | |||
3897 | status = nfs4_setlease(dp); | 3897 | status = nfs4_setlease(dp); |
3898 | goto out; | 3898 | goto out; |
3899 | } | 3899 | } |
3900 | atomic_inc(&fp->fi_delegees); | ||
3901 | if (fp->fi_had_conflict) { | 3900 | if (fp->fi_had_conflict) { |
3902 | status = -EAGAIN; | 3901 | status = -EAGAIN; |
3903 | goto out_unlock; | 3902 | goto out_unlock; |
3904 | } | 3903 | } |
3904 | atomic_inc(&fp->fi_delegees); | ||
3905 | hash_delegation_locked(dp, fp); | 3905 | hash_delegation_locked(dp, fp); |
3906 | status = 0; | 3906 | status = 0; |
3907 | out_unlock: | 3907 | out_unlock: |
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index c991616acca9..bff8567aa42d 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
@@ -259,16 +259,15 @@ static ssize_t fanotify_read(struct file *file, char __user *buf, | |||
259 | struct fsnotify_event *kevent; | 259 | struct fsnotify_event *kevent; |
260 | char __user *start; | 260 | char __user *start; |
261 | int ret; | 261 | int ret; |
262 | DEFINE_WAIT(wait); | 262 | DEFINE_WAIT_FUNC(wait, woken_wake_function); |
263 | 263 | ||
264 | start = buf; | 264 | start = buf; |
265 | group = file->private_data; | 265 | group = file->private_data; |
266 | 266 | ||
267 | pr_debug("%s: group=%p\n", __func__, group); | 267 | pr_debug("%s: group=%p\n", __func__, group); |
268 | 268 | ||
269 | add_wait_queue(&group->notification_waitq, &wait); | ||
269 | while (1) { | 270 | while (1) { |
270 | prepare_to_wait(&group->notification_waitq, &wait, TASK_INTERRUPTIBLE); | ||
271 | |||
272 | mutex_lock(&group->notification_mutex); | 271 | mutex_lock(&group->notification_mutex); |
273 | kevent = get_one_event(group, count); | 272 | kevent = get_one_event(group, count); |
274 | mutex_unlock(&group->notification_mutex); | 273 | mutex_unlock(&group->notification_mutex); |
@@ -289,7 +288,8 @@ static ssize_t fanotify_read(struct file *file, char __user *buf, | |||
289 | 288 | ||
290 | if (start != buf) | 289 | if (start != buf) |
291 | break; | 290 | break; |
292 | schedule(); | 291 | |
292 | wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); | ||
293 | continue; | 293 | continue; |
294 | } | 294 | } |
295 | 295 | ||
@@ -318,8 +318,8 @@ static ssize_t fanotify_read(struct file *file, char __user *buf, | |||
318 | buf += ret; | 318 | buf += ret; |
319 | count -= ret; | 319 | count -= ret; |
320 | } | 320 | } |
321 | remove_wait_queue(&group->notification_waitq, &wait); | ||
321 | 322 | ||
322 | finish_wait(&group->notification_waitq, &wait); | ||
323 | if (start != buf && ret != -EFAULT) | 323 | if (start != buf && ret != -EFAULT) |
324 | ret = buf - start; | 324 | ret = buf - start; |
325 | return ret; | 325 | return ret; |
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index 79b5af5e6a7b..cecd875653e4 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c | |||
@@ -2023,11 +2023,8 @@ leave: | |||
2023 | dlm_lockres_drop_inflight_ref(dlm, res); | 2023 | dlm_lockres_drop_inflight_ref(dlm, res); |
2024 | spin_unlock(&res->spinlock); | 2024 | spin_unlock(&res->spinlock); |
2025 | 2025 | ||
2026 | if (ret < 0) { | 2026 | if (ret < 0) |
2027 | mlog_errno(ret); | 2027 | mlog_errno(ret); |
2028 | if (newlock) | ||
2029 | dlm_lock_put(newlock); | ||
2030 | } | ||
2031 | 2028 | ||
2032 | return ret; | 2029 | return ret; |
2033 | } | 2030 | } |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index b931e04e3388..914c121ec890 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -94,6 +94,14 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb, | |||
94 | struct inode *inode, | 94 | struct inode *inode, |
95 | const char *symname); | 95 | const char *symname); |
96 | 96 | ||
97 | static int ocfs2_double_lock(struct ocfs2_super *osb, | ||
98 | struct buffer_head **bh1, | ||
99 | struct inode *inode1, | ||
100 | struct buffer_head **bh2, | ||
101 | struct inode *inode2, | ||
102 | int rename); | ||
103 | |||
104 | static void ocfs2_double_unlock(struct inode *inode1, struct inode *inode2); | ||
97 | /* An orphan dir name is an 8 byte value, printed as a hex string */ | 105 | /* An orphan dir name is an 8 byte value, printed as a hex string */ |
98 | #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) | 106 | #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) |
99 | 107 | ||
@@ -678,8 +686,10 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
678 | { | 686 | { |
679 | handle_t *handle; | 687 | handle_t *handle; |
680 | struct inode *inode = old_dentry->d_inode; | 688 | struct inode *inode = old_dentry->d_inode; |
689 | struct inode *old_dir = old_dentry->d_parent->d_inode; | ||
681 | int err; | 690 | int err; |
682 | struct buffer_head *fe_bh = NULL; | 691 | struct buffer_head *fe_bh = NULL; |
692 | struct buffer_head *old_dir_bh = NULL; | ||
683 | struct buffer_head *parent_fe_bh = NULL; | 693 | struct buffer_head *parent_fe_bh = NULL; |
684 | struct ocfs2_dinode *fe = NULL; | 694 | struct ocfs2_dinode *fe = NULL; |
685 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | 695 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); |
@@ -696,19 +706,33 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
696 | 706 | ||
697 | dquot_initialize(dir); | 707 | dquot_initialize(dir); |
698 | 708 | ||
699 | err = ocfs2_inode_lock_nested(dir, &parent_fe_bh, 1, OI_LS_PARENT); | 709 | err = ocfs2_double_lock(osb, &old_dir_bh, old_dir, |
710 | &parent_fe_bh, dir, 0); | ||
700 | if (err < 0) { | 711 | if (err < 0) { |
701 | if (err != -ENOENT) | 712 | if (err != -ENOENT) |
702 | mlog_errno(err); | 713 | mlog_errno(err); |
703 | return err; | 714 | return err; |
704 | } | 715 | } |
705 | 716 | ||
717 | /* make sure both dirs have bhs | ||
718 | * get an extra ref on old_dir_bh if old==new */ | ||
719 | if (!parent_fe_bh) { | ||
720 | if (old_dir_bh) { | ||
721 | parent_fe_bh = old_dir_bh; | ||
722 | get_bh(parent_fe_bh); | ||
723 | } else { | ||
724 | mlog(ML_ERROR, "%s: no old_dir_bh!\n", osb->uuid_str); | ||
725 | err = -EIO; | ||
726 | goto out; | ||
727 | } | ||
728 | } | ||
729 | |||
706 | if (!dir->i_nlink) { | 730 | if (!dir->i_nlink) { |
707 | err = -ENOENT; | 731 | err = -ENOENT; |
708 | goto out; | 732 | goto out; |
709 | } | 733 | } |
710 | 734 | ||
711 | err = ocfs2_lookup_ino_from_name(dir, old_dentry->d_name.name, | 735 | err = ocfs2_lookup_ino_from_name(old_dir, old_dentry->d_name.name, |
712 | old_dentry->d_name.len, &old_de_ino); | 736 | old_dentry->d_name.len, &old_de_ino); |
713 | if (err) { | 737 | if (err) { |
714 | err = -ENOENT; | 738 | err = -ENOENT; |
@@ -801,10 +825,11 @@ out_unlock_inode: | |||
801 | ocfs2_inode_unlock(inode, 1); | 825 | ocfs2_inode_unlock(inode, 1); |
802 | 826 | ||
803 | out: | 827 | out: |
804 | ocfs2_inode_unlock(dir, 1); | 828 | ocfs2_double_unlock(old_dir, dir); |
805 | 829 | ||
806 | brelse(fe_bh); | 830 | brelse(fe_bh); |
807 | brelse(parent_fe_bh); | 831 | brelse(parent_fe_bh); |
832 | brelse(old_dir_bh); | ||
808 | 833 | ||
809 | ocfs2_free_dir_lookup_result(&lookup); | 834 | ocfs2_free_dir_lookup_result(&lookup); |
810 | 835 | ||
@@ -1072,14 +1097,15 @@ static int ocfs2_check_if_ancestor(struct ocfs2_super *osb, | |||
1072 | } | 1097 | } |
1073 | 1098 | ||
1074 | /* | 1099 | /* |
1075 | * The only place this should be used is rename! | 1100 | * The only place this should be used is rename and link! |
1076 | * if they have the same id, then the 1st one is the only one locked. | 1101 | * if they have the same id, then the 1st one is the only one locked. |
1077 | */ | 1102 | */ |
1078 | static int ocfs2_double_lock(struct ocfs2_super *osb, | 1103 | static int ocfs2_double_lock(struct ocfs2_super *osb, |
1079 | struct buffer_head **bh1, | 1104 | struct buffer_head **bh1, |
1080 | struct inode *inode1, | 1105 | struct inode *inode1, |
1081 | struct buffer_head **bh2, | 1106 | struct buffer_head **bh2, |
1082 | struct inode *inode2) | 1107 | struct inode *inode2, |
1108 | int rename) | ||
1083 | { | 1109 | { |
1084 | int status; | 1110 | int status; |
1085 | int inode1_is_ancestor, inode2_is_ancestor; | 1111 | int inode1_is_ancestor, inode2_is_ancestor; |
@@ -1127,7 +1153,7 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, | |||
1127 | } | 1153 | } |
1128 | /* lock id2 */ | 1154 | /* lock id2 */ |
1129 | status = ocfs2_inode_lock_nested(inode2, bh2, 1, | 1155 | status = ocfs2_inode_lock_nested(inode2, bh2, 1, |
1130 | OI_LS_RENAME1); | 1156 | rename == 1 ? OI_LS_RENAME1 : OI_LS_PARENT); |
1131 | if (status < 0) { | 1157 | if (status < 0) { |
1132 | if (status != -ENOENT) | 1158 | if (status != -ENOENT) |
1133 | mlog_errno(status); | 1159 | mlog_errno(status); |
@@ -1136,7 +1162,8 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, | |||
1136 | } | 1162 | } |
1137 | 1163 | ||
1138 | /* lock id1 */ | 1164 | /* lock id1 */ |
1139 | status = ocfs2_inode_lock_nested(inode1, bh1, 1, OI_LS_RENAME2); | 1165 | status = ocfs2_inode_lock_nested(inode1, bh1, 1, |
1166 | rename == 1 ? OI_LS_RENAME2 : OI_LS_PARENT); | ||
1140 | if (status < 0) { | 1167 | if (status < 0) { |
1141 | /* | 1168 | /* |
1142 | * An error return must mean that no cluster locks | 1169 | * An error return must mean that no cluster locks |
@@ -1252,7 +1279,7 @@ static int ocfs2_rename(struct inode *old_dir, | |||
1252 | 1279 | ||
1253 | /* if old and new are the same, this'll just do one lock. */ | 1280 | /* if old and new are the same, this'll just do one lock. */ |
1254 | status = ocfs2_double_lock(osb, &old_dir_bh, old_dir, | 1281 | status = ocfs2_double_lock(osb, &old_dir_bh, old_dir, |
1255 | &new_dir_bh, new_dir); | 1282 | &new_dir_bh, new_dir, 1); |
1256 | if (status < 0) { | 1283 | if (status < 0) { |
1257 | mlog_errno(status); | 1284 | mlog_errno(status); |
1258 | goto bail; | 1285 | goto bail; |
diff --git a/fs/udf/dir.c b/fs/udf/dir.c index a012c51caffd..05e90edd1992 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c | |||
@@ -57,6 +57,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) | |||
57 | sector_t offset; | 57 | sector_t offset; |
58 | int i, num, ret = 0; | 58 | int i, num, ret = 0; |
59 | struct extent_position epos = { NULL, 0, {0, 0} }; | 59 | struct extent_position epos = { NULL, 0, {0, 0} }; |
60 | struct super_block *sb = dir->i_sb; | ||
60 | 61 | ||
61 | if (ctx->pos == 0) { | 62 | if (ctx->pos == 0) { |
62 | if (!dir_emit_dot(file, ctx)) | 63 | if (!dir_emit_dot(file, ctx)) |
@@ -76,16 +77,16 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) | |||
76 | if (nf_pos == 0) | 77 | if (nf_pos == 0) |
77 | nf_pos = udf_ext0_offset(dir); | 78 | nf_pos = udf_ext0_offset(dir); |
78 | 79 | ||
79 | fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1); | 80 | fibh.soffset = fibh.eoffset = nf_pos & (sb->s_blocksize - 1); |
80 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { | 81 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { |
81 | if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits, | 82 | if (inode_bmap(dir, nf_pos >> sb->s_blocksize_bits, |
82 | &epos, &eloc, &elen, &offset) | 83 | &epos, &eloc, &elen, &offset) |
83 | != (EXT_RECORDED_ALLOCATED >> 30)) { | 84 | != (EXT_RECORDED_ALLOCATED >> 30)) { |
84 | ret = -ENOENT; | 85 | ret = -ENOENT; |
85 | goto out; | 86 | goto out; |
86 | } | 87 | } |
87 | block = udf_get_lb_pblock(dir->i_sb, &eloc, offset); | 88 | block = udf_get_lb_pblock(sb, &eloc, offset); |
88 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { | 89 | if ((++offset << sb->s_blocksize_bits) < elen) { |
89 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 90 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
90 | epos.offset -= sizeof(struct short_ad); | 91 | epos.offset -= sizeof(struct short_ad); |
91 | else if (iinfo->i_alloc_type == | 92 | else if (iinfo->i_alloc_type == |
@@ -95,18 +96,18 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) | |||
95 | offset = 0; | 96 | offset = 0; |
96 | } | 97 | } |
97 | 98 | ||
98 | if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) { | 99 | if (!(fibh.sbh = fibh.ebh = udf_tread(sb, block))) { |
99 | ret = -EIO; | 100 | ret = -EIO; |
100 | goto out; | 101 | goto out; |
101 | } | 102 | } |
102 | 103 | ||
103 | if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) { | 104 | if (!(offset & ((16 >> (sb->s_blocksize_bits - 9)) - 1))) { |
104 | i = 16 >> (dir->i_sb->s_blocksize_bits - 9); | 105 | i = 16 >> (sb->s_blocksize_bits - 9); |
105 | if (i + offset > (elen >> dir->i_sb->s_blocksize_bits)) | 106 | if (i + offset > (elen >> sb->s_blocksize_bits)) |
106 | i = (elen >> dir->i_sb->s_blocksize_bits) - offset; | 107 | i = (elen >> sb->s_blocksize_bits) - offset; |
107 | for (num = 0; i > 0; i--) { | 108 | for (num = 0; i > 0; i--) { |
108 | block = udf_get_lb_pblock(dir->i_sb, &eloc, offset + i); | 109 | block = udf_get_lb_pblock(sb, &eloc, offset + i); |
109 | tmp = udf_tgetblk(dir->i_sb, block); | 110 | tmp = udf_tgetblk(sb, block); |
110 | if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp)) | 111 | if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp)) |
111 | bha[num++] = tmp; | 112 | bha[num++] = tmp; |
112 | else | 113 | else |
@@ -152,12 +153,12 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) | |||
152 | } | 153 | } |
153 | 154 | ||
154 | if ((cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { | 155 | if ((cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { |
155 | if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE)) | 156 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE)) |
156 | continue; | 157 | continue; |
157 | } | 158 | } |
158 | 159 | ||
159 | if ((cfi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) { | 160 | if ((cfi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) { |
160 | if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE)) | 161 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE)) |
161 | continue; | 162 | continue; |
162 | } | 163 | } |
163 | 164 | ||
@@ -167,12 +168,12 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) | |||
167 | continue; | 168 | continue; |
168 | } | 169 | } |
169 | 170 | ||
170 | flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); | 171 | flen = udf_get_filename(sb, nameptr, lfi, fname, UDF_NAME_LEN); |
171 | if (!flen) | 172 | if (!flen) |
172 | continue; | 173 | continue; |
173 | 174 | ||
174 | tloc = lelb_to_cpu(cfi.icb.extLocation); | 175 | tloc = lelb_to_cpu(cfi.icb.extLocation); |
175 | iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0); | 176 | iblock = udf_get_lb_pblock(sb, &tloc, 0); |
176 | if (!dir_emit(ctx, fname, flen, iblock, DT_UNKNOWN)) | 177 | if (!dir_emit(ctx, fname, flen, iblock, DT_UNKNOWN)) |
177 | goto out; | 178 | goto out; |
178 | } /* end while */ | 179 | } /* end while */ |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index c9b4df5810d5..5bc71d9a674a 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
@@ -1489,6 +1489,20 @@ reread: | |||
1489 | } | 1489 | } |
1490 | inode->i_generation = iinfo->i_unique; | 1490 | inode->i_generation = iinfo->i_unique; |
1491 | 1491 | ||
1492 | /* Sanity checks for files in ICB so that we don't get confused later */ | ||
1493 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { | ||
1494 | /* | ||
1495 | * For file in ICB data is stored in allocation descriptor | ||
1496 | * so sizes should match | ||
1497 | */ | ||
1498 | if (iinfo->i_lenAlloc != inode->i_size) | ||
1499 | goto out; | ||
1500 | /* File in ICB has to fit in there... */ | ||
1501 | if (inode->i_size > inode->i_sb->s_blocksize - | ||
1502 | udf_file_entry_alloc_offset(inode)) | ||
1503 | goto out; | ||
1504 | } | ||
1505 | |||
1492 | switch (fe->icbTag.fileType) { | 1506 | switch (fe->icbTag.fileType) { |
1493 | case ICBTAG_FILE_TYPE_DIRECTORY: | 1507 | case ICBTAG_FILE_TYPE_DIRECTORY: |
1494 | inode->i_op = &udf_dir_inode_operations; | 1508 | inode->i_op = &udf_dir_inode_operations; |
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index c12e260fd6c4..33b246b82c98 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
@@ -159,18 +159,19 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
159 | struct udf_inode_info *dinfo = UDF_I(dir); | 159 | struct udf_inode_info *dinfo = UDF_I(dir); |
160 | int isdotdot = child->len == 2 && | 160 | int isdotdot = child->len == 2 && |
161 | child->name[0] == '.' && child->name[1] == '.'; | 161 | child->name[0] == '.' && child->name[1] == '.'; |
162 | struct super_block *sb = dir->i_sb; | ||
162 | 163 | ||
163 | size = udf_ext0_offset(dir) + dir->i_size; | 164 | size = udf_ext0_offset(dir) + dir->i_size; |
164 | f_pos = udf_ext0_offset(dir); | 165 | f_pos = udf_ext0_offset(dir); |
165 | 166 | ||
166 | fibh->sbh = fibh->ebh = NULL; | 167 | fibh->sbh = fibh->ebh = NULL; |
167 | fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1); | 168 | fibh->soffset = fibh->eoffset = f_pos & (sb->s_blocksize - 1); |
168 | if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { | 169 | if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { |
169 | if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos, | 170 | if (inode_bmap(dir, f_pos >> sb->s_blocksize_bits, &epos, |
170 | &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) | 171 | &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) |
171 | goto out_err; | 172 | goto out_err; |
172 | block = udf_get_lb_pblock(dir->i_sb, &eloc, offset); | 173 | block = udf_get_lb_pblock(sb, &eloc, offset); |
173 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { | 174 | if ((++offset << sb->s_blocksize_bits) < elen) { |
174 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 175 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
175 | epos.offset -= sizeof(struct short_ad); | 176 | epos.offset -= sizeof(struct short_ad); |
176 | else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 177 | else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
@@ -178,7 +179,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
178 | } else | 179 | } else |
179 | offset = 0; | 180 | offset = 0; |
180 | 181 | ||
181 | fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); | 182 | fibh->sbh = fibh->ebh = udf_tread(sb, block); |
182 | if (!fibh->sbh) | 183 | if (!fibh->sbh) |
183 | goto out_err; | 184 | goto out_err; |
184 | } | 185 | } |
@@ -217,12 +218,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
217 | } | 218 | } |
218 | 219 | ||
219 | if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { | 220 | if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { |
220 | if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE)) | 221 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE)) |
221 | continue; | 222 | continue; |
222 | } | 223 | } |
223 | 224 | ||
224 | if ((cfi->fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) { | 225 | if ((cfi->fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) { |
225 | if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE)) | 226 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE)) |
226 | continue; | 227 | continue; |
227 | } | 228 | } |
228 | 229 | ||
@@ -233,7 +234,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
233 | if (!lfi) | 234 | if (!lfi) |
234 | continue; | 235 | continue; |
235 | 236 | ||
236 | flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); | 237 | flen = udf_get_filename(sb, nameptr, lfi, fname, UDF_NAME_LEN); |
237 | if (flen && udf_match(flen, fname, child->len, child->name)) | 238 | if (flen && udf_match(flen, fname, child->len, child->name)) |
238 | goto out_ok; | 239 | goto out_ok; |
239 | } | 240 | } |
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index 6fb7945c1e6e..ac10ca939f26 100644 --- a/fs/udf/symlink.c +++ b/fs/udf/symlink.c | |||
@@ -30,49 +30,73 @@ | |||
30 | #include <linux/buffer_head.h> | 30 | #include <linux/buffer_head.h> |
31 | #include "udf_i.h" | 31 | #include "udf_i.h" |
32 | 32 | ||
33 | static void udf_pc_to_char(struct super_block *sb, unsigned char *from, | 33 | static int udf_pc_to_char(struct super_block *sb, unsigned char *from, |
34 | int fromlen, unsigned char *to) | 34 | int fromlen, unsigned char *to, int tolen) |
35 | { | 35 | { |
36 | struct pathComponent *pc; | 36 | struct pathComponent *pc; |
37 | int elen = 0; | 37 | int elen = 0; |
38 | int comp_len; | ||
38 | unsigned char *p = to; | 39 | unsigned char *p = to; |
39 | 40 | ||
41 | /* Reserve one byte for terminating \0 */ | ||
42 | tolen--; | ||
40 | while (elen < fromlen) { | 43 | while (elen < fromlen) { |
41 | pc = (struct pathComponent *)(from + elen); | 44 | pc = (struct pathComponent *)(from + elen); |
45 | elen += sizeof(struct pathComponent); | ||
42 | switch (pc->componentType) { | 46 | switch (pc->componentType) { |
43 | case 1: | 47 | case 1: |
44 | /* | 48 | /* |
45 | * Symlink points to some place which should be agreed | 49 | * Symlink points to some place which should be agreed |
46 | * upon between originator and receiver of the media. Ignore. | 50 | * upon between originator and receiver of the media. Ignore. |
47 | */ | 51 | */ |
48 | if (pc->lengthComponentIdent > 0) | 52 | if (pc->lengthComponentIdent > 0) { |
53 | elen += pc->lengthComponentIdent; | ||
49 | break; | 54 | break; |
55 | } | ||
50 | /* Fall through */ | 56 | /* Fall through */ |
51 | case 2: | 57 | case 2: |
58 | if (tolen == 0) | ||
59 | return -ENAMETOOLONG; | ||
52 | p = to; | 60 | p = to; |
53 | *p++ = '/'; | 61 | *p++ = '/'; |
62 | tolen--; | ||
54 | break; | 63 | break; |
55 | case 3: | 64 | case 3: |
65 | if (tolen < 3) | ||
66 | return -ENAMETOOLONG; | ||
56 | memcpy(p, "../", 3); | 67 | memcpy(p, "../", 3); |
57 | p += 3; | 68 | p += 3; |
69 | tolen -= 3; | ||
58 | break; | 70 | break; |
59 | case 4: | 71 | case 4: |
72 | if (tolen < 2) | ||
73 | return -ENAMETOOLONG; | ||
60 | memcpy(p, "./", 2); | 74 | memcpy(p, "./", 2); |
61 | p += 2; | 75 | p += 2; |
76 | tolen -= 2; | ||
62 | /* that would be . - just ignore */ | 77 | /* that would be . - just ignore */ |
63 | break; | 78 | break; |
64 | case 5: | 79 | case 5: |
65 | p += udf_get_filename(sb, pc->componentIdent, p, | 80 | elen += pc->lengthComponentIdent; |
66 | pc->lengthComponentIdent); | 81 | if (elen > fromlen) |
82 | return -EIO; | ||
83 | comp_len = udf_get_filename(sb, pc->componentIdent, | ||
84 | pc->lengthComponentIdent, | ||
85 | p, tolen); | ||
86 | p += comp_len; | ||
87 | tolen -= comp_len; | ||
88 | if (tolen == 0) | ||
89 | return -ENAMETOOLONG; | ||
67 | *p++ = '/'; | 90 | *p++ = '/'; |
91 | tolen--; | ||
68 | break; | 92 | break; |
69 | } | 93 | } |
70 | elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; | ||
71 | } | 94 | } |
72 | if (p > to + 1) | 95 | if (p > to + 1) |
73 | p[-1] = '\0'; | 96 | p[-1] = '\0'; |
74 | else | 97 | else |
75 | p[0] = '\0'; | 98 | p[0] = '\0'; |
99 | return 0; | ||
76 | } | 100 | } |
77 | 101 | ||
78 | static int udf_symlink_filler(struct file *file, struct page *page) | 102 | static int udf_symlink_filler(struct file *file, struct page *page) |
@@ -80,11 +104,17 @@ static int udf_symlink_filler(struct file *file, struct page *page) | |||
80 | struct inode *inode = page->mapping->host; | 104 | struct inode *inode = page->mapping->host; |
81 | struct buffer_head *bh = NULL; | 105 | struct buffer_head *bh = NULL; |
82 | unsigned char *symlink; | 106 | unsigned char *symlink; |
83 | int err = -EIO; | 107 | int err; |
84 | unsigned char *p = kmap(page); | 108 | unsigned char *p = kmap(page); |
85 | struct udf_inode_info *iinfo; | 109 | struct udf_inode_info *iinfo; |
86 | uint32_t pos; | 110 | uint32_t pos; |
87 | 111 | ||
112 | /* We don't support symlinks longer than one block */ | ||
113 | if (inode->i_size > inode->i_sb->s_blocksize) { | ||
114 | err = -ENAMETOOLONG; | ||
115 | goto out_unmap; | ||
116 | } | ||
117 | |||
88 | iinfo = UDF_I(inode); | 118 | iinfo = UDF_I(inode); |
89 | pos = udf_block_map(inode, 0); | 119 | pos = udf_block_map(inode, 0); |
90 | 120 | ||
@@ -94,14 +124,18 @@ static int udf_symlink_filler(struct file *file, struct page *page) | |||
94 | } else { | 124 | } else { |
95 | bh = sb_bread(inode->i_sb, pos); | 125 | bh = sb_bread(inode->i_sb, pos); |
96 | 126 | ||
97 | if (!bh) | 127 | if (!bh) { |
98 | goto out; | 128 | err = -EIO; |
129 | goto out_unlock_inode; | ||
130 | } | ||
99 | 131 | ||
100 | symlink = bh->b_data; | 132 | symlink = bh->b_data; |
101 | } | 133 | } |
102 | 134 | ||
103 | udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p); | 135 | err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE); |
104 | brelse(bh); | 136 | brelse(bh); |
137 | if (err) | ||
138 | goto out_unlock_inode; | ||
105 | 139 | ||
106 | up_read(&iinfo->i_data_sem); | 140 | up_read(&iinfo->i_data_sem); |
107 | SetPageUptodate(page); | 141 | SetPageUptodate(page); |
@@ -109,9 +143,10 @@ static int udf_symlink_filler(struct file *file, struct page *page) | |||
109 | unlock_page(page); | 143 | unlock_page(page); |
110 | return 0; | 144 | return 0; |
111 | 145 | ||
112 | out: | 146 | out_unlock_inode: |
113 | up_read(&iinfo->i_data_sem); | 147 | up_read(&iinfo->i_data_sem); |
114 | SetPageError(page); | 148 | SetPageError(page); |
149 | out_unmap: | ||
115 | kunmap(page); | 150 | kunmap(page); |
116 | unlock_page(page); | 151 | unlock_page(page); |
117 | return err; | 152 | return err; |
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 1cc3c993ebd0..47bb3f5ca360 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h | |||
@@ -211,7 +211,8 @@ udf_get_lb_pblock(struct super_block *sb, struct kernel_lb_addr *loc, | |||
211 | } | 211 | } |
212 | 212 | ||
213 | /* unicode.c */ | 213 | /* unicode.c */ |
214 | extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int); | 214 | extern int udf_get_filename(struct super_block *, uint8_t *, int, uint8_t *, |
215 | int); | ||
215 | extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, | 216 | extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, |
216 | int); | 217 | int); |
217 | extern int udf_build_ustr(struct ustr *, dstring *, int); | 218 | extern int udf_build_ustr(struct ustr *, dstring *, int); |
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index afd470e588ff..b84fee372734 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c | |||
@@ -28,7 +28,8 @@ | |||
28 | 28 | ||
29 | #include "udf_sb.h" | 29 | #include "udf_sb.h" |
30 | 30 | ||
31 | static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int); | 31 | static int udf_translate_to_linux(uint8_t *, int, uint8_t *, int, uint8_t *, |
32 | int); | ||
32 | 33 | ||
33 | static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen) | 34 | static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen) |
34 | { | 35 | { |
@@ -333,8 +334,8 @@ try_again: | |||
333 | return u_len + 1; | 334 | return u_len + 1; |
334 | } | 335 | } |
335 | 336 | ||
336 | int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, | 337 | int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, |
337 | int flen) | 338 | uint8_t *dname, int dlen) |
338 | { | 339 | { |
339 | struct ustr *filename, *unifilename; | 340 | struct ustr *filename, *unifilename; |
340 | int len = 0; | 341 | int len = 0; |
@@ -347,7 +348,7 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, | |||
347 | if (!unifilename) | 348 | if (!unifilename) |
348 | goto out1; | 349 | goto out1; |
349 | 350 | ||
350 | if (udf_build_ustr_exact(unifilename, sname, flen)) | 351 | if (udf_build_ustr_exact(unifilename, sname, slen)) |
351 | goto out2; | 352 | goto out2; |
352 | 353 | ||
353 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { | 354 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { |
@@ -366,7 +367,8 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, | |||
366 | } else | 367 | } else |
367 | goto out2; | 368 | goto out2; |
368 | 369 | ||
369 | len = udf_translate_to_linux(dname, filename->u_name, filename->u_len, | 370 | len = udf_translate_to_linux(dname, dlen, |
371 | filename->u_name, filename->u_len, | ||
370 | unifilename->u_name, unifilename->u_len); | 372 | unifilename->u_name, unifilename->u_len); |
371 | out2: | 373 | out2: |
372 | kfree(unifilename); | 374 | kfree(unifilename); |
@@ -403,10 +405,12 @@ int udf_put_filename(struct super_block *sb, const uint8_t *sname, | |||
403 | #define EXT_MARK '.' | 405 | #define EXT_MARK '.' |
404 | #define CRC_MARK '#' | 406 | #define CRC_MARK '#' |
405 | #define EXT_SIZE 5 | 407 | #define EXT_SIZE 5 |
408 | /* Number of chars we need to store generated CRC to make filename unique */ | ||
409 | #define CRC_LEN 5 | ||
406 | 410 | ||
407 | static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, | 411 | static int udf_translate_to_linux(uint8_t *newName, int newLen, |
408 | int udfLen, uint8_t *fidName, | 412 | uint8_t *udfName, int udfLen, |
409 | int fidNameLen) | 413 | uint8_t *fidName, int fidNameLen) |
410 | { | 414 | { |
411 | int index, newIndex = 0, needsCRC = 0; | 415 | int index, newIndex = 0, needsCRC = 0; |
412 | int extIndex = 0, newExtIndex = 0, hasExt = 0; | 416 | int extIndex = 0, newExtIndex = 0, hasExt = 0; |
@@ -439,7 +443,7 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, | |||
439 | newExtIndex = newIndex; | 443 | newExtIndex = newIndex; |
440 | } | 444 | } |
441 | } | 445 | } |
442 | if (newIndex < 256) | 446 | if (newIndex < newLen) |
443 | newName[newIndex++] = curr; | 447 | newName[newIndex++] = curr; |
444 | else | 448 | else |
445 | needsCRC = 1; | 449 | needsCRC = 1; |
@@ -467,13 +471,13 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, | |||
467 | } | 471 | } |
468 | ext[localExtIndex++] = curr; | 472 | ext[localExtIndex++] = curr; |
469 | } | 473 | } |
470 | maxFilenameLen = 250 - localExtIndex; | 474 | maxFilenameLen = newLen - CRC_LEN - localExtIndex; |
471 | if (newIndex > maxFilenameLen) | 475 | if (newIndex > maxFilenameLen) |
472 | newIndex = maxFilenameLen; | 476 | newIndex = maxFilenameLen; |
473 | else | 477 | else |
474 | newIndex = newExtIndex; | 478 | newIndex = newExtIndex; |
475 | } else if (newIndex > 250) | 479 | } else if (newIndex > newLen - CRC_LEN) |
476 | newIndex = 250; | 480 | newIndex = newLen - CRC_LEN; |
477 | newName[newIndex++] = CRC_MARK; | 481 | newName[newIndex++] = CRC_MARK; |
478 | valueCRC = crc_itu_t(0, fidName, fidNameLen); | 482 | valueCRC = crc_itu_t(0, fidName, fidNameLen); |
479 | newName[newIndex++] = hex_asc_upper_hi(valueCRC >> 8); | 483 | newName[newIndex++] = hex_asc_upper_hi(valueCRC >> 8); |