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); |
