diff options
| -rw-r--r-- | fs/cifs/file.c | 69 | ||||
| -rw-r--r-- | fs/cifs/xattr.c | 6 |
2 files changed, 59 insertions, 16 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, |
