diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/cifs/file.c | 69 | ||||
| -rw-r--r-- | fs/cifs/xattr.c | 6 | ||||
| -rw-r--r-- | fs/inode.c | 4 | ||||
| -rw-r--r-- | fs/namei.c | 4 | ||||
| -rw-r--r-- | fs/udf/file.c | 2 |
5 files changed, 63 insertions, 22 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 4dd9283885e7..5e64748a2917 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -920,16 +920,26 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
| 920 | for (lockp = &inode->i_flock; *lockp != NULL; \ | 920 | for (lockp = &inode->i_flock; *lockp != NULL; \ |
| 921 | lockp = &(*lockp)->fl_next) | 921 | lockp = &(*lockp)->fl_next) |
| 922 | 922 | ||
| 923 | struct lock_to_push { | ||
| 924 | struct list_head llist; | ||
| 925 | __u64 offset; | ||
| 926 | __u64 length; | ||
| 927 | __u32 pid; | ||
| 928 | __u16 netfid; | ||
| 929 | __u8 type; | ||
| 930 | }; | ||
| 931 | |||
| 923 | static int | 932 | static int |
| 924 | cifs_push_posix_locks(struct cifsFileInfo *cfile) | 933 | cifs_push_posix_locks(struct cifsFileInfo *cfile) |
| 925 | { | 934 | { |
| 926 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); | 935 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); |
| 927 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | 936 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
| 928 | struct file_lock *flock, **before; | 937 | struct file_lock *flock, **before; |
| 929 | struct cifsLockInfo *lck, *tmp; | 938 | unsigned int count = 0, i = 0; |
| 930 | int rc = 0, xid, type; | 939 | int rc = 0, xid, type; |
| 940 | struct list_head locks_to_send, *el; | ||
| 941 | struct lock_to_push *lck, *tmp; | ||
| 931 | __u64 length; | 942 | __u64 length; |
| 932 | struct list_head locks_to_send; | ||
| 933 | 943 | ||
| 934 | xid = GetXid(); | 944 | xid = GetXid(); |
| 935 | 945 | ||
| @@ -940,29 +950,55 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | |||
| 940 | return rc; | 950 | return rc; |
| 941 | } | 951 | } |
| 942 | 952 | ||
| 953 | lock_flocks(); | ||
| 954 | cifs_for_each_lock(cfile->dentry->d_inode, before) { | ||
| 955 | if ((*before)->fl_flags & FL_POSIX) | ||
| 956 | count++; | ||
| 957 | } | ||
| 958 | unlock_flocks(); | ||
| 959 | |||
| 943 | INIT_LIST_HEAD(&locks_to_send); | 960 | INIT_LIST_HEAD(&locks_to_send); |
| 944 | 961 | ||
| 962 | /* | ||
| 963 | * Allocating count locks is enough because no locks can be added to | ||
| 964 | * the list while we are holding cinode->lock_mutex that protects | ||
| 965 | * locking operations of this inode. | ||
| 966 | */ | ||
| 967 | for (; i < count; i++) { | ||
| 968 | lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL); | ||
| 969 | if (!lck) { | ||
| 970 | rc = -ENOMEM; | ||
| 971 | goto err_out; | ||
| 972 | } | ||
| 973 | list_add_tail(&lck->llist, &locks_to_send); | ||
| 974 | } | ||
| 975 | |||
| 976 | i = 0; | ||
| 977 | el = locks_to_send.next; | ||
| 945 | lock_flocks(); | 978 | lock_flocks(); |
| 946 | cifs_for_each_lock(cfile->dentry->d_inode, before) { | 979 | cifs_for_each_lock(cfile->dentry->d_inode, before) { |
| 980 | if (el == &locks_to_send) { | ||
| 981 | /* something is really wrong */ | ||
| 982 | cERROR(1, "Can't push all brlocks!"); | ||
| 983 | break; | ||
| 984 | } | ||
| 947 | flock = *before; | 985 | flock = *before; |
| 986 | if ((flock->fl_flags & FL_POSIX) == 0) | ||
| 987 | continue; | ||
| 948 | length = 1 + flock->fl_end - flock->fl_start; | 988 | length = 1 + flock->fl_end - flock->fl_start; |
| 949 | if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK) | 989 | if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK) |
| 950 | type = CIFS_RDLCK; | 990 | type = CIFS_RDLCK; |
| 951 | else | 991 | else |
| 952 | type = CIFS_WRLCK; | 992 | type = CIFS_WRLCK; |
| 953 | 993 | lck = list_entry(el, struct lock_to_push, llist); | |
| 954 | lck = cifs_lock_init(flock->fl_start, length, type, | ||
| 955 | cfile->netfid); | ||
| 956 | if (!lck) { | ||
| 957 | rc = -ENOMEM; | ||
| 958 | goto send_locks; | ||
| 959 | } | ||
| 960 | lck->pid = flock->fl_pid; | 994 | lck->pid = flock->fl_pid; |
| 961 | 995 | lck->netfid = cfile->netfid; | |
| 962 | list_add_tail(&lck->llist, &locks_to_send); | 996 | lck->length = length; |
| 997 | lck->type = type; | ||
| 998 | lck->offset = flock->fl_start; | ||
| 999 | i++; | ||
| 1000 | el = el->next; | ||
| 963 | } | 1001 | } |
| 964 | |||
| 965 | send_locks: | ||
| 966 | unlock_flocks(); | 1002 | unlock_flocks(); |
| 967 | 1003 | ||
| 968 | list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) { | 1004 | list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) { |
| @@ -979,11 +1015,18 @@ send_locks: | |||
| 979 | kfree(lck); | 1015 | kfree(lck); |
| 980 | } | 1016 | } |
| 981 | 1017 | ||
| 1018 | out: | ||
| 982 | cinode->can_cache_brlcks = false; | 1019 | cinode->can_cache_brlcks = false; |
| 983 | mutex_unlock(&cinode->lock_mutex); | 1020 | mutex_unlock(&cinode->lock_mutex); |
| 984 | 1021 | ||
| 985 | FreeXid(xid); | 1022 | FreeXid(xid); |
| 986 | return rc; | 1023 | return rc; |
| 1024 | err_out: | ||
| 1025 | list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) { | ||
| 1026 | list_del(&lck->llist); | ||
| 1027 | kfree(lck); | ||
| 1028 | } | ||
| 1029 | goto out; | ||
| 987 | } | 1030 | } |
| 988 | 1031 | ||
| 989 | static int | 1032 | static int |
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 45f07c46f3ed..10d92cf57ab6 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
| @@ -105,7 +105,6 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
| 105 | struct cifs_tcon *pTcon; | 105 | struct cifs_tcon *pTcon; |
| 106 | struct super_block *sb; | 106 | struct super_block *sb; |
| 107 | char *full_path; | 107 | char *full_path; |
| 108 | struct cifs_ntsd *pacl; | ||
| 109 | 108 | ||
| 110 | if (direntry == NULL) | 109 | if (direntry == NULL) |
| 111 | return -EIO; | 110 | return -EIO; |
| @@ -164,23 +163,24 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
| 164 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 163 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 165 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, | 164 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, |
| 166 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { | 165 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { |
| 166 | #ifdef CONFIG_CIFS_ACL | ||
| 167 | struct cifs_ntsd *pacl; | ||
| 167 | pacl = kmalloc(value_size, GFP_KERNEL); | 168 | pacl = kmalloc(value_size, GFP_KERNEL); |
| 168 | if (!pacl) { | 169 | if (!pacl) { |
| 169 | cFYI(1, "%s: Can't allocate memory for ACL", | 170 | cFYI(1, "%s: Can't allocate memory for ACL", |
| 170 | __func__); | 171 | __func__); |
| 171 | rc = -ENOMEM; | 172 | rc = -ENOMEM; |
| 172 | } else { | 173 | } else { |
| 173 | #ifdef CONFIG_CIFS_ACL | ||
| 174 | memcpy(pacl, ea_value, value_size); | 174 | memcpy(pacl, ea_value, value_size); |
| 175 | rc = set_cifs_acl(pacl, value_size, | 175 | rc = set_cifs_acl(pacl, value_size, |
| 176 | direntry->d_inode, full_path, CIFS_ACL_DACL); | 176 | direntry->d_inode, full_path, CIFS_ACL_DACL); |
| 177 | if (rc == 0) /* force revalidate of the inode */ | 177 | if (rc == 0) /* force revalidate of the inode */ |
| 178 | CIFS_I(direntry->d_inode)->time = 0; | 178 | CIFS_I(direntry->d_inode)->time = 0; |
| 179 | kfree(pacl); | 179 | kfree(pacl); |
| 180 | } | ||
| 180 | #else | 181 | #else |
| 181 | cFYI(1, "Set CIFS ACL not supported yet"); | 182 | cFYI(1, "Set CIFS ACL not supported yet"); |
| 182 | #endif /* CONFIG_CIFS_ACL */ | 183 | #endif /* CONFIG_CIFS_ACL */ |
| 183 | } | ||
| 184 | } else { | 184 | } else { |
| 185 | int temp; | 185 | int temp; |
| 186 | temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, | 186 | temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, |
diff --git a/fs/inode.c b/fs/inode.c index d3ebdbe723d0..83ab215baab1 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -938,8 +938,7 @@ void lockdep_annotate_inode_mutex_key(struct inode *inode) | |||
| 938 | struct file_system_type *type = inode->i_sb->s_type; | 938 | struct file_system_type *type = inode->i_sb->s_type; |
| 939 | 939 | ||
| 940 | /* Set new key only if filesystem hasn't already changed it */ | 940 | /* Set new key only if filesystem hasn't already changed it */ |
| 941 | if (!lockdep_match_class(&inode->i_mutex, | 941 | if (lockdep_match_class(&inode->i_mutex, &type->i_mutex_key)) { |
| 942 | &type->i_mutex_key)) { | ||
| 943 | /* | 942 | /* |
| 944 | * ensure nobody is actually holding i_mutex | 943 | * ensure nobody is actually holding i_mutex |
| 945 | */ | 944 | */ |
| @@ -966,6 +965,7 @@ void unlock_new_inode(struct inode *inode) | |||
| 966 | spin_lock(&inode->i_lock); | 965 | spin_lock(&inode->i_lock); |
| 967 | WARN_ON(!(inode->i_state & I_NEW)); | 966 | WARN_ON(!(inode->i_state & I_NEW)); |
| 968 | inode->i_state &= ~I_NEW; | 967 | inode->i_state &= ~I_NEW; |
| 968 | smp_mb(); | ||
| 969 | wake_up_bit(&inode->i_state, __I_NEW); | 969 | wake_up_bit(&inode->i_state, __I_NEW); |
| 970 | spin_unlock(&inode->i_lock); | 970 | spin_unlock(&inode->i_lock); |
| 971 | } | 971 | } |
diff --git a/fs/namei.c b/fs/namei.c index e2ba62820a0f..46ea9cc16647 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -2162,7 +2162,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
| 2162 | /* sayonara */ | 2162 | /* sayonara */ |
| 2163 | error = complete_walk(nd); | 2163 | error = complete_walk(nd); |
| 2164 | if (error) | 2164 | if (error) |
| 2165 | return ERR_PTR(-ECHILD); | 2165 | return ERR_PTR(error); |
| 2166 | 2166 | ||
| 2167 | error = -ENOTDIR; | 2167 | error = -ENOTDIR; |
| 2168 | if (nd->flags & LOOKUP_DIRECTORY) { | 2168 | if (nd->flags & LOOKUP_DIRECTORY) { |
| @@ -2261,7 +2261,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
| 2261 | /* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */ | 2261 | /* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */ |
| 2262 | error = complete_walk(nd); | 2262 | error = complete_walk(nd); |
| 2263 | if (error) | 2263 | if (error) |
| 2264 | goto exit; | 2264 | return ERR_PTR(error); |
| 2265 | error = -EISDIR; | 2265 | error = -EISDIR; |
| 2266 | if (S_ISDIR(nd->inode->i_mode)) | 2266 | if (S_ISDIR(nd->inode->i_mode)) |
| 2267 | goto exit; | 2267 | goto exit; |
diff --git a/fs/udf/file.c b/fs/udf/file.c index dca0c3881e82..d567b8448dfc 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
| @@ -201,12 +201,10 @@ out: | |||
| 201 | static int udf_release_file(struct inode *inode, struct file *filp) | 201 | static int udf_release_file(struct inode *inode, struct file *filp) |
| 202 | { | 202 | { |
| 203 | if (filp->f_mode & FMODE_WRITE) { | 203 | if (filp->f_mode & FMODE_WRITE) { |
| 204 | mutex_lock(&inode->i_mutex); | ||
| 205 | down_write(&UDF_I(inode)->i_data_sem); | 204 | down_write(&UDF_I(inode)->i_data_sem); |
| 206 | udf_discard_prealloc(inode); | 205 | udf_discard_prealloc(inode); |
| 207 | udf_truncate_tail_extent(inode); | 206 | udf_truncate_tail_extent(inode); |
| 208 | up_write(&UDF_I(inode)->i_data_sem); | 207 | up_write(&UDF_I(inode)->i_data_sem); |
| 209 | mutex_unlock(&inode->i_mutex); | ||
| 210 | } | 208 | } |
| 211 | return 0; | 209 | return 0; |
| 212 | } | 210 | } |
