diff options
Diffstat (limited to 'fs/cifs/file.c')
| -rw-r--r-- | fs/cifs/file.c | 791 |
1 files changed, 379 insertions, 412 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index de748c652d11..8c81e7b14d53 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -60,34 +60,32 @@ static inline int cifs_convert_flags(unsigned int flags) | |||
| 60 | FILE_READ_DATA); | 60 | FILE_READ_DATA); |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | static inline fmode_t cifs_posix_convert_flags(unsigned int flags) | 63 | static u32 cifs_posix_convert_flags(unsigned int flags) |
| 64 | { | 64 | { |
| 65 | fmode_t posix_flags = 0; | 65 | u32 posix_flags = 0; |
| 66 | 66 | ||
| 67 | if ((flags & O_ACCMODE) == O_RDONLY) | 67 | if ((flags & O_ACCMODE) == O_RDONLY) |
| 68 | posix_flags = FMODE_READ; | 68 | posix_flags = SMB_O_RDONLY; |
| 69 | else if ((flags & O_ACCMODE) == O_WRONLY) | 69 | else if ((flags & O_ACCMODE) == O_WRONLY) |
| 70 | posix_flags = FMODE_WRITE; | 70 | posix_flags = SMB_O_WRONLY; |
| 71 | else if ((flags & O_ACCMODE) == O_RDWR) { | 71 | else if ((flags & O_ACCMODE) == O_RDWR) |
| 72 | /* GENERIC_ALL is too much permission to request | 72 | posix_flags = SMB_O_RDWR; |
| 73 | can cause unnecessary access denied on create */ | 73 | |
| 74 | /* return GENERIC_ALL; */ | 74 | if (flags & O_CREAT) |
| 75 | posix_flags = FMODE_READ | FMODE_WRITE; | 75 | posix_flags |= SMB_O_CREAT; |
| 76 | } | 76 | if (flags & O_EXCL) |
| 77 | /* can not map O_CREAT or O_EXCL or O_TRUNC flags when | 77 | posix_flags |= SMB_O_EXCL; |
| 78 | reopening a file. They had their effect on the original open */ | 78 | if (flags & O_TRUNC) |
| 79 | if (flags & O_APPEND) | 79 | posix_flags |= SMB_O_TRUNC; |
| 80 | posix_flags |= (fmode_t)O_APPEND; | 80 | /* be safe and imply O_SYNC for O_DSYNC */ |
| 81 | if (flags & O_DSYNC) | 81 | if (flags & O_DSYNC) |
| 82 | posix_flags |= (fmode_t)O_DSYNC; | 82 | posix_flags |= SMB_O_SYNC; |
| 83 | if (flags & __O_SYNC) | ||
| 84 | posix_flags |= (fmode_t)__O_SYNC; | ||
| 85 | if (flags & O_DIRECTORY) | 83 | if (flags & O_DIRECTORY) |
| 86 | posix_flags |= (fmode_t)O_DIRECTORY; | 84 | posix_flags |= SMB_O_DIRECTORY; |
| 87 | if (flags & O_NOFOLLOW) | 85 | if (flags & O_NOFOLLOW) |
| 88 | posix_flags |= (fmode_t)O_NOFOLLOW; | 86 | posix_flags |= SMB_O_NOFOLLOW; |
| 89 | if (flags & O_DIRECT) | 87 | if (flags & O_DIRECT) |
| 90 | posix_flags |= (fmode_t)O_DIRECT; | 88 | posix_flags |= SMB_O_DIRECT; |
| 91 | 89 | ||
| 92 | return posix_flags; | 90 | return posix_flags; |
| 93 | } | 91 | } |
| @@ -106,66 +104,8 @@ static inline int cifs_get_disposition(unsigned int flags) | |||
| 106 | return FILE_OPEN; | 104 | return FILE_OPEN; |
| 107 | } | 105 | } |
| 108 | 106 | ||
| 109 | /* all arguments to this function must be checked for validity in caller */ | ||
| 110 | static inline int | ||
| 111 | cifs_posix_open_inode_helper(struct inode *inode, struct file *file, | ||
| 112 | struct cifsInodeInfo *pCifsInode, __u32 oplock, | ||
| 113 | u16 netfid) | ||
| 114 | { | ||
| 115 | |||
| 116 | write_lock(&GlobalSMBSeslock); | ||
| 117 | |||
| 118 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); | ||
| 119 | if (pCifsInode == NULL) { | ||
| 120 | write_unlock(&GlobalSMBSeslock); | ||
| 121 | return -EINVAL; | ||
| 122 | } | ||
| 123 | |||
| 124 | if (pCifsInode->clientCanCacheRead) { | ||
| 125 | /* we have the inode open somewhere else | ||
| 126 | no need to discard cache data */ | ||
| 127 | goto psx_client_can_cache; | ||
| 128 | } | ||
| 129 | |||
| 130 | /* BB FIXME need to fix this check to move it earlier into posix_open | ||
| 131 | BB fIX following section BB FIXME */ | ||
| 132 | |||
| 133 | /* if not oplocked, invalidate inode pages if mtime or file | ||
| 134 | size changed */ | ||
| 135 | /* temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime)); | ||
| 136 | if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) && | ||
| 137 | (file->f_path.dentry->d_inode->i_size == | ||
| 138 | (loff_t)le64_to_cpu(buf->EndOfFile))) { | ||
| 139 | cFYI(1, "inode unchanged on server"); | ||
| 140 | } else { | ||
| 141 | if (file->f_path.dentry->d_inode->i_mapping) { | ||
| 142 | rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); | ||
| 143 | if (rc != 0) | ||
| 144 | CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc; | ||
| 145 | } | ||
| 146 | cFYI(1, "invalidating remote inode since open detected it " | ||
| 147 | "changed"); | ||
| 148 | invalidate_remote_inode(file->f_path.dentry->d_inode); | ||
| 149 | } */ | ||
| 150 | |||
| 151 | psx_client_can_cache: | ||
| 152 | if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { | ||
| 153 | pCifsInode->clientCanCacheAll = true; | ||
| 154 | pCifsInode->clientCanCacheRead = true; | ||
| 155 | cFYI(1, "Exclusive Oplock granted on inode %p", | ||
| 156 | file->f_path.dentry->d_inode); | ||
| 157 | } else if ((oplock & 0xF) == OPLOCK_READ) | ||
| 158 | pCifsInode->clientCanCacheRead = true; | ||
| 159 | |||
| 160 | /* will have to change the unlock if we reenable the | ||
| 161 | filemap_fdatawrite (which does not seem necessary */ | ||
| 162 | write_unlock(&GlobalSMBSeslock); | ||
| 163 | return 0; | ||
| 164 | } | ||
| 165 | |||
| 166 | /* all arguments to this function must be checked for validity in caller */ | ||
| 167 | static inline int cifs_open_inode_helper(struct inode *inode, | 107 | static inline int cifs_open_inode_helper(struct inode *inode, |
| 168 | struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf, | 108 | struct cifsTconInfo *pTcon, __u32 oplock, FILE_ALL_INFO *buf, |
| 169 | char *full_path, int xid) | 109 | char *full_path, int xid) |
| 170 | { | 110 | { |
| 171 | struct cifsInodeInfo *pCifsInode = CIFS_I(inode); | 111 | struct cifsInodeInfo *pCifsInode = CIFS_I(inode); |
| @@ -207,16 +147,175 @@ client_can_cache: | |||
| 207 | rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, | 147 | rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, |
| 208 | xid, NULL); | 148 | xid, NULL); |
| 209 | 149 | ||
| 210 | if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) { | 150 | if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { |
| 211 | pCifsInode->clientCanCacheAll = true; | 151 | pCifsInode->clientCanCacheAll = true; |
| 212 | pCifsInode->clientCanCacheRead = true; | 152 | pCifsInode->clientCanCacheRead = true; |
| 213 | cFYI(1, "Exclusive Oplock granted on inode %p", inode); | 153 | cFYI(1, "Exclusive Oplock granted on inode %p", inode); |
| 214 | } else if ((*oplock & 0xF) == OPLOCK_READ) | 154 | } else if ((oplock & 0xF) == OPLOCK_READ) |
| 215 | pCifsInode->clientCanCacheRead = true; | 155 | pCifsInode->clientCanCacheRead = true; |
| 216 | 156 | ||
| 217 | return rc; | 157 | return rc; |
| 218 | } | 158 | } |
| 219 | 159 | ||
| 160 | int cifs_posix_open(char *full_path, struct inode **pinode, | ||
| 161 | struct super_block *sb, int mode, unsigned int f_flags, | ||
| 162 | __u32 *poplock, __u16 *pnetfid, int xid) | ||
| 163 | { | ||
| 164 | int rc; | ||
| 165 | FILE_UNIX_BASIC_INFO *presp_data; | ||
| 166 | __u32 posix_flags = 0; | ||
| 167 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | ||
| 168 | struct cifs_fattr fattr; | ||
| 169 | struct tcon_link *tlink; | ||
| 170 | struct cifsTconInfo *tcon; | ||
| 171 | |||
| 172 | cFYI(1, "posix open %s", full_path); | ||
| 173 | |||
| 174 | presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); | ||
| 175 | if (presp_data == NULL) | ||
| 176 | return -ENOMEM; | ||
| 177 | |||
| 178 | tlink = cifs_sb_tlink(cifs_sb); | ||
| 179 | if (IS_ERR(tlink)) { | ||
| 180 | rc = PTR_ERR(tlink); | ||
| 181 | goto posix_open_ret; | ||
| 182 | } | ||
| 183 | |||
| 184 | tcon = tlink_tcon(tlink); | ||
| 185 | mode &= ~current_umask(); | ||
| 186 | |||
| 187 | posix_flags = cifs_posix_convert_flags(f_flags); | ||
| 188 | rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data, | ||
| 189 | poplock, full_path, cifs_sb->local_nls, | ||
| 190 | cifs_sb->mnt_cifs_flags & | ||
| 191 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 192 | cifs_put_tlink(tlink); | ||
| 193 | |||
| 194 | if (rc) | ||
| 195 | goto posix_open_ret; | ||
| 196 | |||
| 197 | if (presp_data->Type == cpu_to_le32(-1)) | ||
| 198 | goto posix_open_ret; /* open ok, caller does qpathinfo */ | ||
| 199 | |||
| 200 | if (!pinode) | ||
| 201 | goto posix_open_ret; /* caller does not need info */ | ||
| 202 | |||
| 203 | cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb); | ||
| 204 | |||
| 205 | /* get new inode and set it up */ | ||
| 206 | if (*pinode == NULL) { | ||
| 207 | cifs_fill_uniqueid(sb, &fattr); | ||
| 208 | *pinode = cifs_iget(sb, &fattr); | ||
| 209 | if (!*pinode) { | ||
| 210 | rc = -ENOMEM; | ||
| 211 | goto posix_open_ret; | ||
| 212 | } | ||
| 213 | } else { | ||
| 214 | cifs_fattr_to_inode(*pinode, &fattr); | ||
| 215 | } | ||
| 216 | |||
| 217 | posix_open_ret: | ||
| 218 | kfree(presp_data); | ||
| 219 | return rc; | ||
| 220 | } | ||
| 221 | |||
| 222 | struct cifsFileInfo * | ||
| 223 | cifs_new_fileinfo(__u16 fileHandle, struct file *file, | ||
| 224 | struct tcon_link *tlink, __u32 oplock) | ||
| 225 | { | ||
| 226 | struct dentry *dentry = file->f_path.dentry; | ||
| 227 | struct inode *inode = dentry->d_inode; | ||
| 228 | struct cifsInodeInfo *pCifsInode = CIFS_I(inode); | ||
| 229 | struct cifsFileInfo *pCifsFile; | ||
| 230 | |||
| 231 | pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); | ||
| 232 | if (pCifsFile == NULL) | ||
| 233 | return pCifsFile; | ||
| 234 | |||
| 235 | pCifsFile->netfid = fileHandle; | ||
| 236 | pCifsFile->pid = current->tgid; | ||
| 237 | pCifsFile->uid = current_fsuid(); | ||
| 238 | pCifsFile->dentry = dget(dentry); | ||
| 239 | pCifsFile->f_flags = file->f_flags; | ||
| 240 | pCifsFile->invalidHandle = false; | ||
| 241 | pCifsFile->tlink = cifs_get_tlink(tlink); | ||
| 242 | mutex_init(&pCifsFile->fh_mutex); | ||
| 243 | mutex_init(&pCifsFile->lock_mutex); | ||
| 244 | INIT_LIST_HEAD(&pCifsFile->llist); | ||
| 245 | atomic_set(&pCifsFile->count, 1); | ||
| 246 | INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break); | ||
| 247 | |||
| 248 | spin_lock(&cifs_file_list_lock); | ||
| 249 | list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList)); | ||
| 250 | /* if readable file instance put first in list*/ | ||
| 251 | if (file->f_mode & FMODE_READ) | ||
| 252 | list_add(&pCifsFile->flist, &pCifsInode->openFileList); | ||
| 253 | else | ||
| 254 | list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList); | ||
| 255 | spin_unlock(&cifs_file_list_lock); | ||
| 256 | |||
| 257 | if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { | ||
| 258 | pCifsInode->clientCanCacheAll = true; | ||
| 259 | pCifsInode->clientCanCacheRead = true; | ||
| 260 | cFYI(1, "Exclusive Oplock inode %p", inode); | ||
| 261 | } else if ((oplock & 0xF) == OPLOCK_READ) | ||
| 262 | pCifsInode->clientCanCacheRead = true; | ||
| 263 | |||
| 264 | file->private_data = pCifsFile; | ||
| 265 | return pCifsFile; | ||
| 266 | } | ||
| 267 | |||
| 268 | /* | ||
| 269 | * Release a reference on the file private data. This may involve closing | ||
| 270 | * the filehandle out on the server. | ||
| 271 | */ | ||
| 272 | void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | ||
| 273 | { | ||
| 274 | struct cifsTconInfo *tcon = tlink_tcon(cifs_file->tlink); | ||
| 275 | struct cifsInodeInfo *cifsi = CIFS_I(cifs_file->dentry->d_inode); | ||
| 276 | struct cifsLockInfo *li, *tmp; | ||
| 277 | |||
| 278 | spin_lock(&cifs_file_list_lock); | ||
| 279 | if (!atomic_dec_and_test(&cifs_file->count)) { | ||
| 280 | spin_unlock(&cifs_file_list_lock); | ||
| 281 | return; | ||
| 282 | } | ||
| 283 | |||
| 284 | /* remove it from the lists */ | ||
| 285 | list_del(&cifs_file->flist); | ||
| 286 | list_del(&cifs_file->tlist); | ||
| 287 | |||
| 288 | if (list_empty(&cifsi->openFileList)) { | ||
| 289 | cFYI(1, "closing last open instance for inode %p", | ||
| 290 | cifs_file->dentry->d_inode); | ||
| 291 | cifsi->clientCanCacheRead = false; | ||
| 292 | cifsi->clientCanCacheAll = false; | ||
| 293 | } | ||
| 294 | spin_unlock(&cifs_file_list_lock); | ||
| 295 | |||
| 296 | if (!tcon->need_reconnect && !cifs_file->invalidHandle) { | ||
| 297 | int xid, rc; | ||
| 298 | |||
| 299 | xid = GetXid(); | ||
| 300 | rc = CIFSSMBClose(xid, tcon, cifs_file->netfid); | ||
| 301 | FreeXid(xid); | ||
| 302 | } | ||
| 303 | |||
| 304 | /* Delete any outstanding lock records. We'll lose them when the file | ||
| 305 | * is closed anyway. | ||
| 306 | */ | ||
| 307 | mutex_lock(&cifs_file->lock_mutex); | ||
| 308 | list_for_each_entry_safe(li, tmp, &cifs_file->llist, llist) { | ||
| 309 | list_del(&li->llist); | ||
| 310 | kfree(li); | ||
| 311 | } | ||
| 312 | mutex_unlock(&cifs_file->lock_mutex); | ||
| 313 | |||
| 314 | cifs_put_tlink(cifs_file->tlink); | ||
| 315 | dput(cifs_file->dentry); | ||
| 316 | kfree(cifs_file); | ||
| 317 | } | ||
| 318 | |||
| 220 | int cifs_open(struct inode *inode, struct file *file) | 319 | int cifs_open(struct inode *inode, struct file *file) |
| 221 | { | 320 | { |
| 222 | int rc = -EACCES; | 321 | int rc = -EACCES; |
| @@ -224,6 +323,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 224 | __u32 oplock; | 323 | __u32 oplock; |
| 225 | struct cifs_sb_info *cifs_sb; | 324 | struct cifs_sb_info *cifs_sb; |
| 226 | struct cifsTconInfo *tcon; | 325 | struct cifsTconInfo *tcon; |
| 326 | struct tcon_link *tlink; | ||
| 227 | struct cifsFileInfo *pCifsFile = NULL; | 327 | struct cifsFileInfo *pCifsFile = NULL; |
| 228 | struct cifsInodeInfo *pCifsInode; | 328 | struct cifsInodeInfo *pCifsInode; |
| 229 | char *full_path = NULL; | 329 | char *full_path = NULL; |
| @@ -235,7 +335,12 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 235 | xid = GetXid(); | 335 | xid = GetXid(); |
| 236 | 336 | ||
| 237 | cifs_sb = CIFS_SB(inode->i_sb); | 337 | cifs_sb = CIFS_SB(inode->i_sb); |
| 238 | tcon = cifs_sb->tcon; | 338 | tlink = cifs_sb_tlink(cifs_sb); |
| 339 | if (IS_ERR(tlink)) { | ||
| 340 | FreeXid(xid); | ||
| 341 | return PTR_ERR(tlink); | ||
| 342 | } | ||
| 343 | tcon = tlink_tcon(tlink); | ||
| 239 | 344 | ||
| 240 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); | 345 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); |
| 241 | 346 | ||
| @@ -257,27 +362,15 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 257 | (tcon->ses->capabilities & CAP_UNIX) && | 362 | (tcon->ses->capabilities & CAP_UNIX) && |
| 258 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & | 363 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
| 259 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 364 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
| 260 | int oflags = (int) cifs_posix_convert_flags(file->f_flags); | ||
| 261 | oflags |= SMB_O_CREAT; | ||
| 262 | /* can not refresh inode info since size could be stale */ | 365 | /* can not refresh inode info since size could be stale */ |
| 263 | rc = cifs_posix_open(full_path, &inode, inode->i_sb, | 366 | rc = cifs_posix_open(full_path, &inode, inode->i_sb, |
| 264 | cifs_sb->mnt_file_mode /* ignored */, | 367 | cifs_sb->mnt_file_mode /* ignored */, |
| 265 | oflags, &oplock, &netfid, xid); | 368 | file->f_flags, &oplock, &netfid, xid); |
| 266 | if (rc == 0) { | 369 | if (rc == 0) { |
| 267 | cFYI(1, "posix open succeeded"); | 370 | cFYI(1, "posix open succeeded"); |
| 268 | /* no need for special case handling of setting mode | ||
| 269 | on read only files needed here */ | ||
| 270 | 371 | ||
| 271 | rc = cifs_posix_open_inode_helper(inode, file, | 372 | pCifsFile = cifs_new_fileinfo(netfid, file, tlink, |
| 272 | pCifsInode, oplock, netfid); | 373 | oplock); |
| 273 | if (rc != 0) { | ||
| 274 | CIFSSMBClose(xid, tcon, netfid); | ||
| 275 | goto out; | ||
| 276 | } | ||
| 277 | |||
| 278 | pCifsFile = cifs_new_fileinfo(inode, netfid, file, | ||
| 279 | file->f_path.mnt, | ||
| 280 | oflags); | ||
| 281 | if (pCifsFile == NULL) { | 374 | if (pCifsFile == NULL) { |
| 282 | CIFSSMBClose(xid, tcon, netfid); | 375 | CIFSSMBClose(xid, tcon, netfid); |
| 283 | rc = -ENOMEM; | 376 | rc = -ENOMEM; |
| @@ -345,7 +438,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 345 | goto out; | 438 | goto out; |
| 346 | } | 439 | } |
| 347 | 440 | ||
| 348 | if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) | 441 | if (tcon->ses->capabilities & CAP_NT_SMBS) |
| 349 | rc = CIFSSMBOpen(xid, tcon, full_path, disposition, | 442 | rc = CIFSSMBOpen(xid, tcon, full_path, disposition, |
| 350 | desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, | 443 | desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, |
| 351 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags | 444 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags |
| @@ -365,12 +458,11 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 365 | goto out; | 458 | goto out; |
| 366 | } | 459 | } |
| 367 | 460 | ||
| 368 | rc = cifs_open_inode_helper(inode, tcon, &oplock, buf, full_path, xid); | 461 | rc = cifs_open_inode_helper(inode, tcon, oplock, buf, full_path, xid); |
| 369 | if (rc != 0) | 462 | if (rc != 0) |
| 370 | goto out; | 463 | goto out; |
| 371 | 464 | ||
| 372 | pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, | 465 | pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock); |
| 373 | file->f_flags); | ||
| 374 | if (pCifsFile == NULL) { | 466 | if (pCifsFile == NULL) { |
| 375 | rc = -ENOMEM; | 467 | rc = -ENOMEM; |
| 376 | goto out; | 468 | goto out; |
| @@ -402,6 +494,7 @@ out: | |||
| 402 | kfree(buf); | 494 | kfree(buf); |
| 403 | kfree(full_path); | 495 | kfree(full_path); |
| 404 | FreeXid(xid); | 496 | FreeXid(xid); |
| 497 | cifs_put_tlink(tlink); | ||
| 405 | return rc; | 498 | return rc; |
| 406 | } | 499 | } |
| 407 | 500 | ||
| @@ -416,14 +509,13 @@ static int cifs_relock_file(struct cifsFileInfo *cifsFile) | |||
| 416 | return rc; | 509 | return rc; |
| 417 | } | 510 | } |
| 418 | 511 | ||
| 419 | static int cifs_reopen_file(struct file *file, bool can_flush) | 512 | static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush) |
| 420 | { | 513 | { |
| 421 | int rc = -EACCES; | 514 | int rc = -EACCES; |
| 422 | int xid; | 515 | int xid; |
| 423 | __u32 oplock; | 516 | __u32 oplock; |
| 424 | struct cifs_sb_info *cifs_sb; | 517 | struct cifs_sb_info *cifs_sb; |
| 425 | struct cifsTconInfo *tcon; | 518 | struct cifsTconInfo *tcon; |
| 426 | struct cifsFileInfo *pCifsFile; | ||
| 427 | struct cifsInodeInfo *pCifsInode; | 519 | struct cifsInodeInfo *pCifsInode; |
| 428 | struct inode *inode; | 520 | struct inode *inode; |
| 429 | char *full_path = NULL; | 521 | char *full_path = NULL; |
| @@ -431,11 +523,6 @@ static int cifs_reopen_file(struct file *file, bool can_flush) | |||
| 431 | int disposition = FILE_OPEN; | 523 | int disposition = FILE_OPEN; |
| 432 | __u16 netfid; | 524 | __u16 netfid; |
| 433 | 525 | ||
| 434 | if (file->private_data) | ||
| 435 | pCifsFile = file->private_data; | ||
| 436 | else | ||
| 437 | return -EBADF; | ||
| 438 | |||
| 439 | xid = GetXid(); | 526 | xid = GetXid(); |
| 440 | mutex_lock(&pCifsFile->fh_mutex); | 527 | mutex_lock(&pCifsFile->fh_mutex); |
| 441 | if (!pCifsFile->invalidHandle) { | 528 | if (!pCifsFile->invalidHandle) { |
| @@ -445,39 +532,24 @@ static int cifs_reopen_file(struct file *file, bool can_flush) | |||
| 445 | return rc; | 532 | return rc; |
| 446 | } | 533 | } |
| 447 | 534 | ||
| 448 | if (file->f_path.dentry == NULL) { | 535 | inode = pCifsFile->dentry->d_inode; |
| 449 | cERROR(1, "no valid name if dentry freed"); | ||
| 450 | dump_stack(); | ||
| 451 | rc = -EBADF; | ||
| 452 | goto reopen_error_exit; | ||
| 453 | } | ||
| 454 | |||
| 455 | inode = file->f_path.dentry->d_inode; | ||
| 456 | if (inode == NULL) { | ||
| 457 | cERROR(1, "inode not valid"); | ||
| 458 | dump_stack(); | ||
| 459 | rc = -EBADF; | ||
| 460 | goto reopen_error_exit; | ||
| 461 | } | ||
| 462 | |||
| 463 | cifs_sb = CIFS_SB(inode->i_sb); | 536 | cifs_sb = CIFS_SB(inode->i_sb); |
| 464 | tcon = cifs_sb->tcon; | 537 | tcon = tlink_tcon(pCifsFile->tlink); |
| 465 | 538 | ||
| 466 | /* can not grab rename sem here because various ops, including | 539 | /* can not grab rename sem here because various ops, including |
| 467 | those that already have the rename sem can end up causing writepage | 540 | those that already have the rename sem can end up causing writepage |
| 468 | to get called and if the server was down that means we end up here, | 541 | to get called and if the server was down that means we end up here, |
| 469 | and we can never tell if the caller already has the rename_sem */ | 542 | and we can never tell if the caller already has the rename_sem */ |
| 470 | full_path = build_path_from_dentry(file->f_path.dentry); | 543 | full_path = build_path_from_dentry(pCifsFile->dentry); |
| 471 | if (full_path == NULL) { | 544 | if (full_path == NULL) { |
| 472 | rc = -ENOMEM; | 545 | rc = -ENOMEM; |
| 473 | reopen_error_exit: | ||
| 474 | mutex_unlock(&pCifsFile->fh_mutex); | 546 | mutex_unlock(&pCifsFile->fh_mutex); |
| 475 | FreeXid(xid); | 547 | FreeXid(xid); |
| 476 | return rc; | 548 | return rc; |
| 477 | } | 549 | } |
| 478 | 550 | ||
| 479 | cFYI(1, "inode = 0x%p file flags 0x%x for %s", | 551 | cFYI(1, "inode = 0x%p file flags 0x%x for %s", |
| 480 | inode, file->f_flags, full_path); | 552 | inode, pCifsFile->f_flags, full_path); |
| 481 | 553 | ||
| 482 | if (oplockEnabled) | 554 | if (oplockEnabled) |
| 483 | oplock = REQ_OPLOCK; | 555 | oplock = REQ_OPLOCK; |
| @@ -487,8 +559,14 @@ reopen_error_exit: | |||
| 487 | if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && | 559 | if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && |
| 488 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & | 560 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
| 489 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 561 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
| 490 | int oflags = (int) cifs_posix_convert_flags(file->f_flags); | 562 | |
| 491 | /* can not refresh inode info since size could be stale */ | 563 | /* |
| 564 | * O_CREAT, O_EXCL and O_TRUNC already had their effect on the | ||
| 565 | * original open. Must mask them off for a reopen. | ||
| 566 | */ | ||
| 567 | unsigned int oflags = pCifsFile->f_flags & | ||
| 568 | ~(O_CREAT | O_EXCL | O_TRUNC); | ||
| 569 | |||
| 492 | rc = cifs_posix_open(full_path, NULL, inode->i_sb, | 570 | rc = cifs_posix_open(full_path, NULL, inode->i_sb, |
| 493 | cifs_sb->mnt_file_mode /* ignored */, | 571 | cifs_sb->mnt_file_mode /* ignored */, |
| 494 | oflags, &oplock, &netfid, xid); | 572 | oflags, &oplock, &netfid, xid); |
| @@ -500,7 +578,7 @@ reopen_error_exit: | |||
| 500 | in the reconnect path it is important to retry hard */ | 578 | in the reconnect path it is important to retry hard */ |
| 501 | } | 579 | } |
| 502 | 580 | ||
| 503 | desiredAccess = cifs_convert_flags(file->f_flags); | 581 | desiredAccess = cifs_convert_flags(pCifsFile->f_flags); |
| 504 | 582 | ||
| 505 | /* Can not refresh inode by passing in file_info buf to be returned | 583 | /* Can not refresh inode by passing in file_info buf to be returned |
| 506 | by SMBOpen and then calling get_inode_info with returned buf | 584 | by SMBOpen and then calling get_inode_info with returned buf |
| @@ -516,49 +594,50 @@ reopen_error_exit: | |||
| 516 | mutex_unlock(&pCifsFile->fh_mutex); | 594 | mutex_unlock(&pCifsFile->fh_mutex); |
| 517 | cFYI(1, "cifs_open returned 0x%x", rc); | 595 | cFYI(1, "cifs_open returned 0x%x", rc); |
| 518 | cFYI(1, "oplock: %d", oplock); | 596 | cFYI(1, "oplock: %d", oplock); |
| 519 | } else { | 597 | goto reopen_error_exit; |
| 598 | } | ||
| 599 | |||
| 520 | reopen_success: | 600 | reopen_success: |
| 521 | pCifsFile->netfid = netfid; | 601 | pCifsFile->netfid = netfid; |
| 522 | pCifsFile->invalidHandle = false; | 602 | pCifsFile->invalidHandle = false; |
| 523 | mutex_unlock(&pCifsFile->fh_mutex); | 603 | mutex_unlock(&pCifsFile->fh_mutex); |
| 524 | pCifsInode = CIFS_I(inode); | 604 | pCifsInode = CIFS_I(inode); |
| 525 | if (pCifsInode) { | 605 | |
| 526 | if (can_flush) { | 606 | if (can_flush) { |
| 527 | rc = filemap_write_and_wait(inode->i_mapping); | 607 | rc = filemap_write_and_wait(inode->i_mapping); |
| 528 | if (rc != 0) | 608 | if (rc != 0) |
| 529 | CIFS_I(inode)->write_behind_rc = rc; | 609 | CIFS_I(inode)->write_behind_rc = rc; |
| 530 | /* temporarily disable caching while we | 610 | |
| 531 | go to server to get inode info */ | 611 | pCifsInode->clientCanCacheAll = false; |
| 532 | pCifsInode->clientCanCacheAll = false; | 612 | pCifsInode->clientCanCacheRead = false; |
| 533 | pCifsInode->clientCanCacheRead = false; | 613 | if (tcon->unix_ext) |
| 534 | if (tcon->unix_ext) | 614 | rc = cifs_get_inode_info_unix(&inode, |
| 535 | rc = cifs_get_inode_info_unix(&inode, | 615 | full_path, inode->i_sb, xid); |
| 536 | full_path, inode->i_sb, xid); | 616 | else |
| 537 | else | 617 | rc = cifs_get_inode_info(&inode, |
| 538 | rc = cifs_get_inode_info(&inode, | 618 | full_path, NULL, inode->i_sb, |
| 539 | full_path, NULL, inode->i_sb, | 619 | xid, NULL); |
| 540 | xid, NULL); | 620 | } /* else we are writing out data to server already |
| 541 | } /* else we are writing out data to server already | 621 | and could deadlock if we tried to flush data, and |
| 542 | and could deadlock if we tried to flush data, and | 622 | since we do not know if we have data that would |
| 543 | since we do not know if we have data that would | 623 | invalidate the current end of file on the server |
| 544 | invalidate the current end of file on the server | 624 | we can not go to the server to get the new inod |
| 545 | we can not go to the server to get the new inod | 625 | info */ |
| 546 | info */ | 626 | if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { |
| 547 | if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { | 627 | pCifsInode->clientCanCacheAll = true; |
| 548 | pCifsInode->clientCanCacheAll = true; | 628 | pCifsInode->clientCanCacheRead = true; |
| 549 | pCifsInode->clientCanCacheRead = true; | 629 | cFYI(1, "Exclusive Oplock granted on inode %p", |
| 550 | cFYI(1, "Exclusive Oplock granted on inode %p", | 630 | pCifsFile->dentry->d_inode); |
| 551 | file->f_path.dentry->d_inode); | 631 | } else if ((oplock & 0xF) == OPLOCK_READ) { |
| 552 | } else if ((oplock & 0xF) == OPLOCK_READ) { | 632 | pCifsInode->clientCanCacheRead = true; |
| 553 | pCifsInode->clientCanCacheRead = true; | 633 | pCifsInode->clientCanCacheAll = false; |
| 554 | pCifsInode->clientCanCacheAll = false; | 634 | } else { |
| 555 | } else { | 635 | pCifsInode->clientCanCacheRead = false; |
| 556 | pCifsInode->clientCanCacheRead = false; | 636 | pCifsInode->clientCanCacheAll = false; |
| 557 | pCifsInode->clientCanCacheAll = false; | ||
| 558 | } | ||
| 559 | cifs_relock_file(pCifsFile); | ||
| 560 | } | ||
| 561 | } | 637 | } |
| 638 | cifs_relock_file(pCifsFile); | ||
| 639 | |||
| 640 | reopen_error_exit: | ||
| 562 | kfree(full_path); | 641 | kfree(full_path); |
| 563 | FreeXid(xid); | 642 | FreeXid(xid); |
| 564 | return rc; | 643 | return rc; |
| @@ -566,79 +645,11 @@ reopen_success: | |||
| 566 | 645 | ||
| 567 | int cifs_close(struct inode *inode, struct file *file) | 646 | int cifs_close(struct inode *inode, struct file *file) |
| 568 | { | 647 | { |
| 569 | int rc = 0; | 648 | cifsFileInfo_put(file->private_data); |
| 570 | int xid, timeout; | 649 | file->private_data = NULL; |
| 571 | struct cifs_sb_info *cifs_sb; | ||
| 572 | struct cifsTconInfo *pTcon; | ||
| 573 | struct cifsFileInfo *pSMBFile = file->private_data; | ||
| 574 | 650 | ||
| 575 | xid = GetXid(); | 651 | /* return code from the ->release op is always ignored */ |
| 576 | 652 | return 0; | |
| 577 | cifs_sb = CIFS_SB(inode->i_sb); | ||
| 578 | pTcon = cifs_sb->tcon; | ||
| 579 | if (pSMBFile) { | ||
| 580 | struct cifsLockInfo *li, *tmp; | ||
| 581 | write_lock(&GlobalSMBSeslock); | ||
| 582 | pSMBFile->closePend = true; | ||
| 583 | if (pTcon) { | ||
| 584 | /* no sense reconnecting to close a file that is | ||
| 585 | already closed */ | ||
| 586 | if (!pTcon->need_reconnect) { | ||
| 587 | write_unlock(&GlobalSMBSeslock); | ||
| 588 | timeout = 2; | ||
| 589 | while ((atomic_read(&pSMBFile->count) != 1) | ||
| 590 | && (timeout <= 2048)) { | ||
| 591 | /* Give write a better chance to get to | ||
| 592 | server ahead of the close. We do not | ||
| 593 | want to add a wait_q here as it would | ||
| 594 | increase the memory utilization as | ||
| 595 | the struct would be in each open file, | ||
| 596 | but this should give enough time to | ||
| 597 | clear the socket */ | ||
| 598 | cFYI(DBG2, "close delay, write pending"); | ||
| 599 | msleep(timeout); | ||
| 600 | timeout *= 4; | ||
| 601 | } | ||
| 602 | if (!pTcon->need_reconnect && | ||
| 603 | !pSMBFile->invalidHandle) | ||
| 604 | rc = CIFSSMBClose(xid, pTcon, | ||
| 605 | pSMBFile->netfid); | ||
| 606 | } else | ||
| 607 | write_unlock(&GlobalSMBSeslock); | ||
| 608 | } else | ||
| 609 | write_unlock(&GlobalSMBSeslock); | ||
| 610 | |||
| 611 | /* Delete any outstanding lock records. | ||
| 612 | We'll lose them when the file is closed anyway. */ | ||
| 613 | mutex_lock(&pSMBFile->lock_mutex); | ||
| 614 | list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) { | ||
| 615 | list_del(&li->llist); | ||
| 616 | kfree(li); | ||
| 617 | } | ||
| 618 | mutex_unlock(&pSMBFile->lock_mutex); | ||
| 619 | |||
| 620 | write_lock(&GlobalSMBSeslock); | ||
| 621 | list_del(&pSMBFile->flist); | ||
| 622 | list_del(&pSMBFile->tlist); | ||
| 623 | write_unlock(&GlobalSMBSeslock); | ||
| 624 | cifsFileInfo_put(file->private_data); | ||
| 625 | file->private_data = NULL; | ||
| 626 | } else | ||
| 627 | rc = -EBADF; | ||
| 628 | |||
| 629 | read_lock(&GlobalSMBSeslock); | ||
| 630 | if (list_empty(&(CIFS_I(inode)->openFileList))) { | ||
| 631 | cFYI(1, "closing last open instance for inode %p", inode); | ||
| 632 | /* if the file is not open we do not know if we can cache info | ||
| 633 | on this inode, much less write behind and read ahead */ | ||
| 634 | CIFS_I(inode)->clientCanCacheRead = false; | ||
| 635 | CIFS_I(inode)->clientCanCacheAll = false; | ||
| 636 | } | ||
| 637 | read_unlock(&GlobalSMBSeslock); | ||
| 638 | if ((rc == 0) && CIFS_I(inode)->write_behind_rc) | ||
| 639 | rc = CIFS_I(inode)->write_behind_rc; | ||
| 640 | FreeXid(xid); | ||
| 641 | return rc; | ||
| 642 | } | 653 | } |
| 643 | 654 | ||
| 644 | int cifs_closedir(struct inode *inode, struct file *file) | 655 | int cifs_closedir(struct inode *inode, struct file *file) |
| @@ -653,25 +664,21 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
| 653 | xid = GetXid(); | 664 | xid = GetXid(); |
| 654 | 665 | ||
| 655 | if (pCFileStruct) { | 666 | if (pCFileStruct) { |
| 656 | struct cifsTconInfo *pTcon; | 667 | struct cifsTconInfo *pTcon = tlink_tcon(pCFileStruct->tlink); |
| 657 | struct cifs_sb_info *cifs_sb = | ||
| 658 | CIFS_SB(file->f_path.dentry->d_sb); | ||
| 659 | |||
| 660 | pTcon = cifs_sb->tcon; | ||
| 661 | 668 | ||
| 662 | cFYI(1, "Freeing private data in close dir"); | 669 | cFYI(1, "Freeing private data in close dir"); |
| 663 | write_lock(&GlobalSMBSeslock); | 670 | spin_lock(&cifs_file_list_lock); |
| 664 | if (!pCFileStruct->srch_inf.endOfSearch && | 671 | if (!pCFileStruct->srch_inf.endOfSearch && |
| 665 | !pCFileStruct->invalidHandle) { | 672 | !pCFileStruct->invalidHandle) { |
| 666 | pCFileStruct->invalidHandle = true; | 673 | pCFileStruct->invalidHandle = true; |
| 667 | write_unlock(&GlobalSMBSeslock); | 674 | spin_unlock(&cifs_file_list_lock); |
| 668 | rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid); | 675 | rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid); |
| 669 | cFYI(1, "Closing uncompleted readdir with rc %d", | 676 | cFYI(1, "Closing uncompleted readdir with rc %d", |
| 670 | rc); | 677 | rc); |
| 671 | /* not much we can do if it fails anyway, ignore rc */ | 678 | /* not much we can do if it fails anyway, ignore rc */ |
| 672 | rc = 0; | 679 | rc = 0; |
| 673 | } else | 680 | } else |
| 674 | write_unlock(&GlobalSMBSeslock); | 681 | spin_unlock(&cifs_file_list_lock); |
| 675 | ptmp = pCFileStruct->srch_inf.ntwrk_buf_start; | 682 | ptmp = pCFileStruct->srch_inf.ntwrk_buf_start; |
| 676 | if (ptmp) { | 683 | if (ptmp) { |
| 677 | cFYI(1, "closedir free smb buf in srch struct"); | 684 | cFYI(1, "closedir free smb buf in srch struct"); |
| @@ -681,6 +688,7 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
| 681 | else | 688 | else |
| 682 | cifs_buf_release(ptmp); | 689 | cifs_buf_release(ptmp); |
| 683 | } | 690 | } |
| 691 | cifs_put_tlink(pCFileStruct->tlink); | ||
| 684 | kfree(file->private_data); | 692 | kfree(file->private_data); |
| 685 | file->private_data = NULL; | 693 | file->private_data = NULL; |
| 686 | } | 694 | } |
| @@ -767,7 +775,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
| 767 | cFYI(1, "Unknown type of lock"); | 775 | cFYI(1, "Unknown type of lock"); |
| 768 | 776 | ||
| 769 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 777 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
| 770 | tcon = cifs_sb->tcon; | 778 | tcon = tlink_tcon(((struct cifsFileInfo *)file->private_data)->tlink); |
| 771 | 779 | ||
| 772 | if (file->private_data == NULL) { | 780 | if (file->private_data == NULL) { |
| 773 | rc = -EBADF; | 781 | rc = -EBADF; |
| @@ -960,14 +968,14 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
| 960 | 968 | ||
| 961 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 969 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
| 962 | 970 | ||
| 963 | pTcon = cifs_sb->tcon; | ||
| 964 | |||
| 965 | /* cFYI(1, " write %d bytes to offset %lld of %s", write_size, | 971 | /* cFYI(1, " write %d bytes to offset %lld of %s", write_size, |
| 966 | *poffset, file->f_path.dentry->d_name.name); */ | 972 | *poffset, file->f_path.dentry->d_name.name); */ |
| 967 | 973 | ||
| 968 | if (file->private_data == NULL) | 974 | if (file->private_data == NULL) |
| 969 | return -EBADF; | 975 | return -EBADF; |
| 976 | |||
| 970 | open_file = file->private_data; | 977 | open_file = file->private_data; |
| 978 | pTcon = tlink_tcon(open_file->tlink); | ||
| 971 | 979 | ||
| 972 | rc = generic_write_checks(file, poffset, &write_size, 0); | 980 | rc = generic_write_checks(file, poffset, &write_size, 0); |
| 973 | if (rc) | 981 | if (rc) |
| @@ -988,19 +996,12 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
| 988 | we blocked so return what we managed to write */ | 996 | we blocked so return what we managed to write */ |
| 989 | return total_written; | 997 | return total_written; |
| 990 | } | 998 | } |
| 991 | if (open_file->closePend) { | ||
| 992 | FreeXid(xid); | ||
| 993 | if (total_written) | ||
| 994 | return total_written; | ||
| 995 | else | ||
| 996 | return -EBADF; | ||
| 997 | } | ||
| 998 | if (open_file->invalidHandle) { | 999 | if (open_file->invalidHandle) { |
| 999 | /* we could deadlock if we called | 1000 | /* we could deadlock if we called |
| 1000 | filemap_fdatawait from here so tell | 1001 | filemap_fdatawait from here so tell |
| 1001 | reopen_file not to flush data to server | 1002 | reopen_file not to flush data to server |
| 1002 | now */ | 1003 | now */ |
| 1003 | rc = cifs_reopen_file(file, false); | 1004 | rc = cifs_reopen_file(open_file, false); |
| 1004 | if (rc != 0) | 1005 | if (rc != 0) |
| 1005 | break; | 1006 | break; |
| 1006 | } | 1007 | } |
| @@ -1048,8 +1049,9 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
| 1048 | return total_written; | 1049 | return total_written; |
| 1049 | } | 1050 | } |
| 1050 | 1051 | ||
| 1051 | static ssize_t cifs_write(struct file *file, const char *write_data, | 1052 | static ssize_t cifs_write(struct cifsFileInfo *open_file, |
| 1052 | size_t write_size, loff_t *poffset) | 1053 | const char *write_data, size_t write_size, |
| 1054 | loff_t *poffset) | ||
| 1053 | { | 1055 | { |
| 1054 | int rc = 0; | 1056 | int rc = 0; |
| 1055 | unsigned int bytes_written = 0; | 1057 | unsigned int bytes_written = 0; |
| @@ -1057,19 +1059,15 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
| 1057 | struct cifs_sb_info *cifs_sb; | 1059 | struct cifs_sb_info *cifs_sb; |
| 1058 | struct cifsTconInfo *pTcon; | 1060 | struct cifsTconInfo *pTcon; |
| 1059 | int xid, long_op; | 1061 | int xid, long_op; |
| 1060 | struct cifsFileInfo *open_file; | 1062 | struct dentry *dentry = open_file->dentry; |
| 1061 | struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode); | 1063 | struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); |
| 1062 | 1064 | ||
| 1063 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1065 | cifs_sb = CIFS_SB(dentry->d_sb); |
| 1064 | |||
| 1065 | pTcon = cifs_sb->tcon; | ||
| 1066 | 1066 | ||
| 1067 | cFYI(1, "write %zd bytes to offset %lld of %s", write_size, | 1067 | cFYI(1, "write %zd bytes to offset %lld of %s", write_size, |
| 1068 | *poffset, file->f_path.dentry->d_name.name); | 1068 | *poffset, dentry->d_name.name); |
| 1069 | 1069 | ||
| 1070 | if (file->private_data == NULL) | 1070 | pTcon = tlink_tcon(open_file->tlink); |
| 1071 | return -EBADF; | ||
| 1072 | open_file = file->private_data; | ||
| 1073 | 1071 | ||
| 1074 | xid = GetXid(); | 1072 | xid = GetXid(); |
| 1075 | 1073 | ||
| @@ -1078,28 +1076,12 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
| 1078 | total_written += bytes_written) { | 1076 | total_written += bytes_written) { |
| 1079 | rc = -EAGAIN; | 1077 | rc = -EAGAIN; |
| 1080 | while (rc == -EAGAIN) { | 1078 | while (rc == -EAGAIN) { |
| 1081 | if (file->private_data == NULL) { | ||
| 1082 | /* file has been closed on us */ | ||
| 1083 | FreeXid(xid); | ||
| 1084 | /* if we have gotten here we have written some data | ||
| 1085 | and blocked, and the file has been freed on us | ||
| 1086 | while we blocked so return what we managed to | ||
| 1087 | write */ | ||
| 1088 | return total_written; | ||
| 1089 | } | ||
| 1090 | if (open_file->closePend) { | ||
| 1091 | FreeXid(xid); | ||
| 1092 | if (total_written) | ||
| 1093 | return total_written; | ||
| 1094 | else | ||
| 1095 | return -EBADF; | ||
| 1096 | } | ||
| 1097 | if (open_file->invalidHandle) { | 1079 | if (open_file->invalidHandle) { |
| 1098 | /* we could deadlock if we called | 1080 | /* we could deadlock if we called |
| 1099 | filemap_fdatawait from here so tell | 1081 | filemap_fdatawait from here so tell |
| 1100 | reopen_file not to flush data to | 1082 | reopen_file not to flush data to |
| 1101 | server now */ | 1083 | server now */ |
| 1102 | rc = cifs_reopen_file(file, false); | 1084 | rc = cifs_reopen_file(open_file, false); |
| 1103 | if (rc != 0) | 1085 | if (rc != 0) |
| 1104 | break; | 1086 | break; |
| 1105 | } | 1087 | } |
| @@ -1146,43 +1128,41 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
| 1146 | 1128 | ||
| 1147 | cifs_stats_bytes_written(pTcon, total_written); | 1129 | cifs_stats_bytes_written(pTcon, total_written); |
| 1148 | 1130 | ||
| 1149 | /* since the write may have blocked check these pointers again */ | 1131 | if (total_written > 0) { |
| 1150 | if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) { | 1132 | spin_lock(&dentry->d_inode->i_lock); |
| 1151 | /*BB We could make this contingent on superblock ATIME flag too */ | 1133 | if (*poffset > dentry->d_inode->i_size) |
| 1152 | /* file->f_path.dentry->d_inode->i_ctime = | 1134 | i_size_write(dentry->d_inode, *poffset); |
| 1153 | file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;*/ | 1135 | spin_unlock(&dentry->d_inode->i_lock); |
| 1154 | if (total_written > 0) { | ||
| 1155 | spin_lock(&file->f_path.dentry->d_inode->i_lock); | ||
| 1156 | if (*poffset > file->f_path.dentry->d_inode->i_size) | ||
| 1157 | i_size_write(file->f_path.dentry->d_inode, | ||
| 1158 | *poffset); | ||
| 1159 | spin_unlock(&file->f_path.dentry->d_inode->i_lock); | ||
| 1160 | } | ||
| 1161 | mark_inode_dirty_sync(file->f_path.dentry->d_inode); | ||
| 1162 | } | 1136 | } |
| 1137 | mark_inode_dirty_sync(dentry->d_inode); | ||
| 1163 | FreeXid(xid); | 1138 | FreeXid(xid); |
| 1164 | return total_written; | 1139 | return total_written; |
| 1165 | } | 1140 | } |
| 1166 | 1141 | ||
| 1167 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 1142 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 1168 | struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode) | 1143 | struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, |
| 1144 | bool fsuid_only) | ||
| 1169 | { | 1145 | { |
| 1170 | struct cifsFileInfo *open_file = NULL; | 1146 | struct cifsFileInfo *open_file = NULL; |
| 1147 | struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb); | ||
| 1148 | |||
| 1149 | /* only filter by fsuid on multiuser mounts */ | ||
| 1150 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) | ||
| 1151 | fsuid_only = false; | ||
| 1171 | 1152 | ||
| 1172 | read_lock(&GlobalSMBSeslock); | 1153 | spin_lock(&cifs_file_list_lock); |
| 1173 | /* we could simply get the first_list_entry since write-only entries | 1154 | /* we could simply get the first_list_entry since write-only entries |
| 1174 | are always at the end of the list but since the first entry might | 1155 | are always at the end of the list but since the first entry might |
| 1175 | have a close pending, we go through the whole list */ | 1156 | have a close pending, we go through the whole list */ |
| 1176 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { | 1157 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { |
| 1177 | if (open_file->closePend) | 1158 | if (fsuid_only && open_file->uid != current_fsuid()) |
| 1178 | continue; | 1159 | continue; |
| 1179 | if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) || | 1160 | if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) { |
| 1180 | (open_file->pfile->f_flags & O_RDONLY))) { | ||
| 1181 | if (!open_file->invalidHandle) { | 1161 | if (!open_file->invalidHandle) { |
| 1182 | /* found a good file */ | 1162 | /* found a good file */ |
| 1183 | /* lock it so it will not be closed on us */ | 1163 | /* lock it so it will not be closed on us */ |
| 1184 | cifsFileInfo_get(open_file); | 1164 | cifsFileInfo_get(open_file); |
| 1185 | read_unlock(&GlobalSMBSeslock); | 1165 | spin_unlock(&cifs_file_list_lock); |
| 1186 | return open_file; | 1166 | return open_file; |
| 1187 | } /* else might as well continue, and look for | 1167 | } /* else might as well continue, and look for |
| 1188 | another, or simply have the caller reopen it | 1168 | another, or simply have the caller reopen it |
| @@ -1190,14 +1170,16 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode) | |||
| 1190 | } else /* write only file */ | 1170 | } else /* write only file */ |
| 1191 | break; /* write only files are last so must be done */ | 1171 | break; /* write only files are last so must be done */ |
| 1192 | } | 1172 | } |
| 1193 | read_unlock(&GlobalSMBSeslock); | 1173 | spin_unlock(&cifs_file_list_lock); |
| 1194 | return NULL; | 1174 | return NULL; |
| 1195 | } | 1175 | } |
| 1196 | #endif | 1176 | #endif |
| 1197 | 1177 | ||
| 1198 | struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) | 1178 | struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, |
| 1179 | bool fsuid_only) | ||
| 1199 | { | 1180 | { |
| 1200 | struct cifsFileInfo *open_file; | 1181 | struct cifsFileInfo *open_file; |
| 1182 | struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb); | ||
| 1201 | bool any_available = false; | 1183 | bool any_available = false; |
| 1202 | int rc; | 1184 | int rc; |
| 1203 | 1185 | ||
| @@ -1211,53 +1193,39 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) | |||
| 1211 | return NULL; | 1193 | return NULL; |
| 1212 | } | 1194 | } |
| 1213 | 1195 | ||
| 1214 | read_lock(&GlobalSMBSeslock); | 1196 | /* only filter by fsuid on multiuser mounts */ |
| 1197 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) | ||
| 1198 | fsuid_only = false; | ||
| 1199 | |||
| 1200 | spin_lock(&cifs_file_list_lock); | ||
| 1215 | refind_writable: | 1201 | refind_writable: |
| 1216 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { | 1202 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { |
| 1217 | if (open_file->closePend || | 1203 | if (!any_available && open_file->pid != current->tgid) |
| 1218 | (!any_available && open_file->pid != current->tgid)) | ||
| 1219 | continue; | 1204 | continue; |
| 1220 | 1205 | if (fsuid_only && open_file->uid != current_fsuid()) | |
| 1221 | if (open_file->pfile && | 1206 | continue; |
| 1222 | ((open_file->pfile->f_flags & O_RDWR) || | 1207 | if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { |
| 1223 | (open_file->pfile->f_flags & O_WRONLY))) { | ||
| 1224 | cifsFileInfo_get(open_file); | 1208 | cifsFileInfo_get(open_file); |
| 1225 | 1209 | ||
| 1226 | if (!open_file->invalidHandle) { | 1210 | if (!open_file->invalidHandle) { |
| 1227 | /* found a good writable file */ | 1211 | /* found a good writable file */ |
| 1228 | read_unlock(&GlobalSMBSeslock); | 1212 | spin_unlock(&cifs_file_list_lock); |
| 1229 | return open_file; | 1213 | return open_file; |
| 1230 | } | 1214 | } |
| 1231 | 1215 | ||
| 1232 | read_unlock(&GlobalSMBSeslock); | 1216 | spin_unlock(&cifs_file_list_lock); |
| 1217 | |||
| 1233 | /* Had to unlock since following call can block */ | 1218 | /* Had to unlock since following call can block */ |
| 1234 | rc = cifs_reopen_file(open_file->pfile, false); | 1219 | rc = cifs_reopen_file(open_file, false); |
| 1235 | if (!rc) { | 1220 | if (!rc) |
| 1236 | if (!open_file->closePend) | 1221 | return open_file; |
| 1237 | return open_file; | ||
| 1238 | else { /* start over in case this was deleted */ | ||
| 1239 | /* since the list could be modified */ | ||
| 1240 | read_lock(&GlobalSMBSeslock); | ||
| 1241 | cifsFileInfo_put(open_file); | ||
| 1242 | goto refind_writable; | ||
| 1243 | } | ||
| 1244 | } | ||
| 1245 | 1222 | ||
| 1246 | /* if it fails, try another handle if possible - | 1223 | /* if it fails, try another handle if possible */ |
| 1247 | (we can not do this if closePending since | ||
| 1248 | loop could be modified - in which case we | ||
| 1249 | have to start at the beginning of the list | ||
| 1250 | again. Note that it would be bad | ||
| 1251 | to hold up writepages here (rather than | ||
| 1252 | in caller) with continuous retries */ | ||
| 1253 | cFYI(1, "wp failed on reopen file"); | 1224 | cFYI(1, "wp failed on reopen file"); |
| 1254 | read_lock(&GlobalSMBSeslock); | ||
| 1255 | /* can not use this handle, no write | ||
| 1256 | pending on this one after all */ | ||
| 1257 | cifsFileInfo_put(open_file); | 1225 | cifsFileInfo_put(open_file); |
| 1258 | 1226 | ||
| 1259 | if (open_file->closePend) /* list could have changed */ | 1227 | spin_lock(&cifs_file_list_lock); |
| 1260 | goto refind_writable; | 1228 | |
| 1261 | /* else we simply continue to the next entry. Thus | 1229 | /* else we simply continue to the next entry. Thus |
| 1262 | we do not loop on reopen errors. If we | 1230 | we do not loop on reopen errors. If we |
| 1263 | can not reopen the file, for example if we | 1231 | can not reopen the file, for example if we |
| @@ -1272,7 +1240,7 @@ refind_writable: | |||
| 1272 | any_available = true; | 1240 | any_available = true; |
| 1273 | goto refind_writable; | 1241 | goto refind_writable; |
| 1274 | } | 1242 | } |
| 1275 | read_unlock(&GlobalSMBSeslock); | 1243 | spin_unlock(&cifs_file_list_lock); |
| 1276 | return NULL; | 1244 | return NULL; |
| 1277 | } | 1245 | } |
| 1278 | 1246 | ||
| @@ -1284,7 +1252,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | |||
| 1284 | int rc = -EFAULT; | 1252 | int rc = -EFAULT; |
| 1285 | int bytes_written = 0; | 1253 | int bytes_written = 0; |
| 1286 | struct cifs_sb_info *cifs_sb; | 1254 | struct cifs_sb_info *cifs_sb; |
| 1287 | struct cifsTconInfo *pTcon; | ||
| 1288 | struct inode *inode; | 1255 | struct inode *inode; |
| 1289 | struct cifsFileInfo *open_file; | 1256 | struct cifsFileInfo *open_file; |
| 1290 | 1257 | ||
| @@ -1293,7 +1260,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | |||
| 1293 | 1260 | ||
| 1294 | inode = page->mapping->host; | 1261 | inode = page->mapping->host; |
| 1295 | cifs_sb = CIFS_SB(inode->i_sb); | 1262 | cifs_sb = CIFS_SB(inode->i_sb); |
| 1296 | pTcon = cifs_sb->tcon; | ||
| 1297 | 1263 | ||
| 1298 | offset += (loff_t)from; | 1264 | offset += (loff_t)from; |
| 1299 | write_data = kmap(page); | 1265 | write_data = kmap(page); |
| @@ -1314,10 +1280,10 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | |||
| 1314 | if (mapping->host->i_size - offset < (loff_t)to) | 1280 | if (mapping->host->i_size - offset < (loff_t)to) |
| 1315 | to = (unsigned)(mapping->host->i_size - offset); | 1281 | to = (unsigned)(mapping->host->i_size - offset); |
| 1316 | 1282 | ||
| 1317 | open_file = find_writable_file(CIFS_I(mapping->host)); | 1283 | open_file = find_writable_file(CIFS_I(mapping->host), false); |
| 1318 | if (open_file) { | 1284 | if (open_file) { |
| 1319 | bytes_written = cifs_write(open_file->pfile, write_data, | 1285 | bytes_written = cifs_write(open_file, write_data, |
| 1320 | to-from, &offset); | 1286 | to - from, &offset); |
| 1321 | cifsFileInfo_put(open_file); | 1287 | cifsFileInfo_put(open_file); |
| 1322 | /* Does mm or vfs already set times? */ | 1288 | /* Does mm or vfs already set times? */ |
| 1323 | inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb); | 1289 | inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb); |
| @@ -1352,6 +1318,7 @@ static int cifs_writepages(struct address_space *mapping, | |||
| 1352 | int nr_pages; | 1318 | int nr_pages; |
| 1353 | __u64 offset = 0; | 1319 | __u64 offset = 0; |
| 1354 | struct cifsFileInfo *open_file; | 1320 | struct cifsFileInfo *open_file; |
| 1321 | struct cifsTconInfo *tcon; | ||
| 1355 | struct cifsInodeInfo *cifsi = CIFS_I(mapping->host); | 1322 | struct cifsInodeInfo *cifsi = CIFS_I(mapping->host); |
| 1356 | struct page *page; | 1323 | struct page *page; |
| 1357 | struct pagevec pvec; | 1324 | struct pagevec pvec; |
| @@ -1359,6 +1326,15 @@ static int cifs_writepages(struct address_space *mapping, | |||
| 1359 | int scanned = 0; | 1326 | int scanned = 0; |
| 1360 | int xid, long_op; | 1327 | int xid, long_op; |
| 1361 | 1328 | ||
| 1329 | /* | ||
| 1330 | * BB: Is this meaningful for a non-block-device file system? | ||
| 1331 | * If it is, we should test it again after we do I/O | ||
| 1332 | */ | ||
| 1333 | if (wbc->nonblocking && bdi_write_congested(bdi)) { | ||
| 1334 | wbc->encountered_congestion = 1; | ||
| 1335 | return 0; | ||
| 1336 | } | ||
| 1337 | |||
| 1362 | cifs_sb = CIFS_SB(mapping->host->i_sb); | 1338 | cifs_sb = CIFS_SB(mapping->host->i_sb); |
| 1363 | 1339 | ||
| 1364 | /* | 1340 | /* |
| @@ -1368,27 +1344,29 @@ static int cifs_writepages(struct address_space *mapping, | |||
| 1368 | if (cifs_sb->wsize < PAGE_CACHE_SIZE) | 1344 | if (cifs_sb->wsize < PAGE_CACHE_SIZE) |
| 1369 | return generic_writepages(mapping, wbc); | 1345 | return generic_writepages(mapping, wbc); |
| 1370 | 1346 | ||
| 1371 | if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server)) | ||
| 1372 | if (cifs_sb->tcon->ses->server->secMode & | ||
| 1373 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
| 1374 | if (!experimEnabled) | ||
| 1375 | return generic_writepages(mapping, wbc); | ||
| 1376 | |||
| 1377 | iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL); | 1347 | iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL); |
| 1378 | if (iov == NULL) | 1348 | if (iov == NULL) |
| 1379 | return generic_writepages(mapping, wbc); | 1349 | return generic_writepages(mapping, wbc); |
| 1380 | 1350 | ||
| 1381 | |||
| 1382 | /* | 1351 | /* |
| 1383 | * BB: Is this meaningful for a non-block-device file system? | 1352 | * if there's no open file, then this is likely to fail too, |
| 1384 | * If it is, we should test it again after we do I/O | 1353 | * but it'll at least handle the return. Maybe it should be |
| 1354 | * a BUG() instead? | ||
| 1385 | */ | 1355 | */ |
| 1386 | if (wbc->nonblocking && bdi_write_congested(bdi)) { | 1356 | open_file = find_writable_file(CIFS_I(mapping->host), false); |
| 1387 | wbc->encountered_congestion = 1; | 1357 | if (!open_file) { |
| 1388 | kfree(iov); | 1358 | kfree(iov); |
| 1389 | return 0; | 1359 | return generic_writepages(mapping, wbc); |
| 1390 | } | 1360 | } |
| 1391 | 1361 | ||
| 1362 | tcon = tlink_tcon(open_file->tlink); | ||
| 1363 | if (!experimEnabled && tcon->ses->server->secMode & | ||
| 1364 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | ||
| 1365 | cifsFileInfo_put(open_file); | ||
| 1366 | return generic_writepages(mapping, wbc); | ||
| 1367 | } | ||
| 1368 | cifsFileInfo_put(open_file); | ||
| 1369 | |||
| 1392 | xid = GetXid(); | 1370 | xid = GetXid(); |
| 1393 | 1371 | ||
| 1394 | pagevec_init(&pvec, 0); | 1372 | pagevec_init(&pvec, 0); |
| @@ -1492,38 +1470,34 @@ retry: | |||
| 1492 | break; | 1470 | break; |
| 1493 | } | 1471 | } |
| 1494 | if (n_iov) { | 1472 | if (n_iov) { |
| 1495 | /* Search for a writable handle every time we call | 1473 | open_file = find_writable_file(CIFS_I(mapping->host), |
| 1496 | * CIFSSMBWrite2. We can't rely on the last handle | 1474 | false); |
| 1497 | * we used to still be valid | ||
| 1498 | */ | ||
| 1499 | open_file = find_writable_file(CIFS_I(mapping->host)); | ||
| 1500 | if (!open_file) { | 1475 | if (!open_file) { |
| 1501 | cERROR(1, "No writable handles for inode"); | 1476 | cERROR(1, "No writable handles for inode"); |
| 1502 | rc = -EBADF; | 1477 | rc = -EBADF; |
| 1503 | } else { | 1478 | } else { |
| 1504 | long_op = cifs_write_timeout(cifsi, offset); | 1479 | long_op = cifs_write_timeout(cifsi, offset); |
| 1505 | rc = CIFSSMBWrite2(xid, cifs_sb->tcon, | 1480 | rc = CIFSSMBWrite2(xid, tcon, open_file->netfid, |
| 1506 | open_file->netfid, | ||
| 1507 | bytes_to_write, offset, | 1481 | bytes_to_write, offset, |
| 1508 | &bytes_written, iov, n_iov, | 1482 | &bytes_written, iov, n_iov, |
| 1509 | long_op); | 1483 | long_op); |
| 1510 | cifsFileInfo_put(open_file); | 1484 | cifsFileInfo_put(open_file); |
| 1511 | cifs_update_eof(cifsi, offset, bytes_written); | 1485 | cifs_update_eof(cifsi, offset, bytes_written); |
| 1486 | } | ||
| 1512 | 1487 | ||
| 1513 | if (rc || bytes_written < bytes_to_write) { | 1488 | if (rc || bytes_written < bytes_to_write) { |
| 1514 | cERROR(1, "Write2 ret %d, wrote %d", | 1489 | cERROR(1, "Write2 ret %d, wrote %d", |
| 1515 | rc, bytes_written); | 1490 | rc, bytes_written); |
| 1516 | /* BB what if continued retry is | 1491 | /* BB what if continued retry is |
| 1517 | requested via mount flags? */ | 1492 | requested via mount flags? */ |
| 1518 | if (rc == -ENOSPC) | 1493 | if (rc == -ENOSPC) |
| 1519 | set_bit(AS_ENOSPC, &mapping->flags); | 1494 | set_bit(AS_ENOSPC, &mapping->flags); |
| 1520 | else | 1495 | else |
| 1521 | set_bit(AS_EIO, &mapping->flags); | 1496 | set_bit(AS_EIO, &mapping->flags); |
| 1522 | } else { | 1497 | } else { |
| 1523 | cifs_stats_bytes_written(cifs_sb->tcon, | 1498 | cifs_stats_bytes_written(tcon, bytes_written); |
| 1524 | bytes_written); | ||
| 1525 | } | ||
| 1526 | } | 1499 | } |
| 1500 | |||
| 1527 | for (i = 0; i < n_iov; i++) { | 1501 | for (i = 0; i < n_iov; i++) { |
| 1528 | page = pvec.pages[first + i]; | 1502 | page = pvec.pages[first + i]; |
| 1529 | /* Should we also set page error on | 1503 | /* Should we also set page error on |
| @@ -1624,7 +1598,8 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, | |||
| 1624 | /* BB check if anything else missing out of ppw | 1598 | /* BB check if anything else missing out of ppw |
| 1625 | such as updating last write time */ | 1599 | such as updating last write time */ |
| 1626 | page_data = kmap(page); | 1600 | page_data = kmap(page); |
| 1627 | rc = cifs_write(file, page_data + offset, copied, &pos); | 1601 | rc = cifs_write(file->private_data, page_data + offset, |
| 1602 | copied, &pos); | ||
| 1628 | /* if (rc < 0) should we set writebehind rc? */ | 1603 | /* if (rc < 0) should we set writebehind rc? */ |
| 1629 | kunmap(page); | 1604 | kunmap(page); |
| 1630 | 1605 | ||
| @@ -1665,7 +1640,7 @@ int cifs_fsync(struct file *file, int datasync) | |||
| 1665 | if (rc == 0) { | 1640 | if (rc == 0) { |
| 1666 | rc = CIFS_I(inode)->write_behind_rc; | 1641 | rc = CIFS_I(inode)->write_behind_rc; |
| 1667 | CIFS_I(inode)->write_behind_rc = 0; | 1642 | CIFS_I(inode)->write_behind_rc = 0; |
| 1668 | tcon = CIFS_SB(inode->i_sb)->tcon; | 1643 | tcon = tlink_tcon(smbfile->tlink); |
| 1669 | if (!rc && tcon && smbfile && | 1644 | if (!rc && tcon && smbfile && |
| 1670 | !(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | 1645 | !(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) |
| 1671 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | 1646 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); |
| @@ -1750,7 +1725,6 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
| 1750 | 1725 | ||
| 1751 | xid = GetXid(); | 1726 | xid = GetXid(); |
| 1752 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1727 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
| 1753 | pTcon = cifs_sb->tcon; | ||
| 1754 | 1728 | ||
| 1755 | if (file->private_data == NULL) { | 1729 | if (file->private_data == NULL) { |
| 1756 | rc = -EBADF; | 1730 | rc = -EBADF; |
| @@ -1758,6 +1732,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
| 1758 | return rc; | 1732 | return rc; |
| 1759 | } | 1733 | } |
| 1760 | open_file = file->private_data; | 1734 | open_file = file->private_data; |
| 1735 | pTcon = tlink_tcon(open_file->tlink); | ||
| 1761 | 1736 | ||
| 1762 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 1737 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) |
| 1763 | cFYI(1, "attempting read on write only file instance"); | 1738 | cFYI(1, "attempting read on write only file instance"); |
| @@ -1771,9 +1746,8 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
| 1771 | smb_read_data = NULL; | 1746 | smb_read_data = NULL; |
| 1772 | while (rc == -EAGAIN) { | 1747 | while (rc == -EAGAIN) { |
| 1773 | int buf_type = CIFS_NO_BUFFER; | 1748 | int buf_type = CIFS_NO_BUFFER; |
| 1774 | if ((open_file->invalidHandle) && | 1749 | if (open_file->invalidHandle) { |
| 1775 | (!open_file->closePend)) { | 1750 | rc = cifs_reopen_file(open_file, true); |
| 1776 | rc = cifs_reopen_file(file, true); | ||
| 1777 | if (rc != 0) | 1751 | if (rc != 0) |
| 1778 | break; | 1752 | break; |
| 1779 | } | 1753 | } |
| @@ -1831,7 +1805,6 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
| 1831 | 1805 | ||
| 1832 | xid = GetXid(); | 1806 | xid = GetXid(); |
| 1833 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1807 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
| 1834 | pTcon = cifs_sb->tcon; | ||
| 1835 | 1808 | ||
| 1836 | if (file->private_data == NULL) { | 1809 | if (file->private_data == NULL) { |
| 1837 | rc = -EBADF; | 1810 | rc = -EBADF; |
| @@ -1839,6 +1812,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
| 1839 | return rc; | 1812 | return rc; |
| 1840 | } | 1813 | } |
| 1841 | open_file = file->private_data; | 1814 | open_file = file->private_data; |
| 1815 | pTcon = tlink_tcon(open_file->tlink); | ||
| 1842 | 1816 | ||
| 1843 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 1817 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) |
| 1844 | cFYI(1, "attempting read on write only file instance"); | 1818 | cFYI(1, "attempting read on write only file instance"); |
| @@ -1857,9 +1831,8 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
| 1857 | } | 1831 | } |
| 1858 | rc = -EAGAIN; | 1832 | rc = -EAGAIN; |
| 1859 | while (rc == -EAGAIN) { | 1833 | while (rc == -EAGAIN) { |
| 1860 | if ((open_file->invalidHandle) && | 1834 | if (open_file->invalidHandle) { |
| 1861 | (!open_file->closePend)) { | 1835 | rc = cifs_reopen_file(open_file, true); |
| 1862 | rc = cifs_reopen_file(file, true); | ||
| 1863 | if (rc != 0) | 1836 | if (rc != 0) |
| 1864 | break; | 1837 | break; |
| 1865 | } | 1838 | } |
| @@ -1974,7 +1947,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
| 1974 | } | 1947 | } |
| 1975 | open_file = file->private_data; | 1948 | open_file = file->private_data; |
| 1976 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1949 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
| 1977 | pTcon = cifs_sb->tcon; | 1950 | pTcon = tlink_tcon(open_file->tlink); |
| 1978 | 1951 | ||
| 1979 | /* | 1952 | /* |
| 1980 | * Reads as many pages as possible from fscache. Returns -ENOBUFS | 1953 | * Reads as many pages as possible from fscache. Returns -ENOBUFS |
| @@ -2022,9 +1995,8 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
| 2022 | read_size, contig_pages); | 1995 | read_size, contig_pages); |
| 2023 | rc = -EAGAIN; | 1996 | rc = -EAGAIN; |
| 2024 | while (rc == -EAGAIN) { | 1997 | while (rc == -EAGAIN) { |
| 2025 | if ((open_file->invalidHandle) && | 1998 | if (open_file->invalidHandle) { |
| 2026 | (!open_file->closePend)) { | 1999 | rc = cifs_reopen_file(open_file, true); |
| 2027 | rc = cifs_reopen_file(file, true); | ||
| 2028 | if (rc != 0) | 2000 | if (rc != 0) |
| 2029 | break; | 2001 | break; |
| 2030 | } | 2002 | } |
| @@ -2173,18 +2145,14 @@ static int is_inode_writable(struct cifsInodeInfo *cifs_inode) | |||
| 2173 | { | 2145 | { |
| 2174 | struct cifsFileInfo *open_file; | 2146 | struct cifsFileInfo *open_file; |
| 2175 | 2147 | ||
| 2176 | read_lock(&GlobalSMBSeslock); | 2148 | spin_lock(&cifs_file_list_lock); |
| 2177 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { | 2149 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { |
| 2178 | if (open_file->closePend) | 2150 | if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { |
| 2179 | continue; | 2151 | spin_unlock(&cifs_file_list_lock); |
| 2180 | if (open_file->pfile && | ||
| 2181 | ((open_file->pfile->f_flags & O_RDWR) || | ||
| 2182 | (open_file->pfile->f_flags & O_WRONLY))) { | ||
| 2183 | read_unlock(&GlobalSMBSeslock); | ||
| 2184 | return 1; | 2152 | return 1; |
| 2185 | } | 2153 | } |
| 2186 | } | 2154 | } |
| 2187 | read_unlock(&GlobalSMBSeslock); | 2155 | spin_unlock(&cifs_file_list_lock); |
| 2188 | return 0; | 2156 | return 0; |
| 2189 | } | 2157 | } |
| 2190 | 2158 | ||
| @@ -2310,9 +2278,8 @@ void cifs_oplock_break(struct work_struct *work) | |||
| 2310 | { | 2278 | { |
| 2311 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, | 2279 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, |
| 2312 | oplock_break); | 2280 | oplock_break); |
| 2313 | struct inode *inode = cfile->pInode; | 2281 | struct inode *inode = cfile->dentry->d_inode; |
| 2314 | struct cifsInodeInfo *cinode = CIFS_I(inode); | 2282 | struct cifsInodeInfo *cinode = CIFS_I(inode); |
| 2315 | struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->mnt->mnt_sb); | ||
| 2316 | int rc, waitrc = 0; | 2283 | int rc, waitrc = 0; |
| 2317 | 2284 | ||
| 2318 | if (inode && S_ISREG(inode->i_mode)) { | 2285 | if (inode && S_ISREG(inode->i_mode)) { |
| @@ -2338,9 +2305,9 @@ void cifs_oplock_break(struct work_struct *work) | |||
| 2338 | * not bother sending an oplock release if session to server still is | 2305 | * not bother sending an oplock release if session to server still is |
| 2339 | * disconnected since oplock already released by the server | 2306 | * disconnected since oplock already released by the server |
| 2340 | */ | 2307 | */ |
| 2341 | if (!cfile->closePend && !cfile->oplock_break_cancelled) { | 2308 | if (!cfile->oplock_break_cancelled) { |
| 2342 | rc = CIFSSMBLock(0, cifs_sb->tcon, cfile->netfid, 0, 0, 0, 0, | 2309 | rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0, |
| 2343 | LOCKING_ANDX_OPLOCK_RELEASE, false); | 2310 | 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false); |
| 2344 | cFYI(1, "Oplock release rc = %d", rc); | 2311 | cFYI(1, "Oplock release rc = %d", rc); |
| 2345 | } | 2312 | } |
| 2346 | 2313 | ||
| @@ -2349,22 +2316,22 @@ void cifs_oplock_break(struct work_struct *work) | |||
| 2349 | * finished grabbing reference for us. Make sure it's done by | 2316 | * finished grabbing reference for us. Make sure it's done by |
| 2350 | * waiting for GlobalSMSSeslock. | 2317 | * waiting for GlobalSMSSeslock. |
| 2351 | */ | 2318 | */ |
| 2352 | write_lock(&GlobalSMBSeslock); | 2319 | spin_lock(&cifs_file_list_lock); |
| 2353 | write_unlock(&GlobalSMBSeslock); | 2320 | spin_unlock(&cifs_file_list_lock); |
| 2354 | 2321 | ||
| 2355 | cifs_oplock_break_put(cfile); | 2322 | cifs_oplock_break_put(cfile); |
| 2356 | } | 2323 | } |
| 2357 | 2324 | ||
| 2358 | void cifs_oplock_break_get(struct cifsFileInfo *cfile) | 2325 | void cifs_oplock_break_get(struct cifsFileInfo *cfile) |
| 2359 | { | 2326 | { |
| 2360 | mntget(cfile->mnt); | 2327 | cifs_sb_active(cfile->dentry->d_sb); |
| 2361 | cifsFileInfo_get(cfile); | 2328 | cifsFileInfo_get(cfile); |
| 2362 | } | 2329 | } |
| 2363 | 2330 | ||
| 2364 | void cifs_oplock_break_put(struct cifsFileInfo *cfile) | 2331 | void cifs_oplock_break_put(struct cifsFileInfo *cfile) |
| 2365 | { | 2332 | { |
| 2366 | mntput(cfile->mnt); | ||
| 2367 | cifsFileInfo_put(cfile); | 2333 | cifsFileInfo_put(cfile); |
| 2334 | cifs_sb_deactive(cfile->dentry->d_sb); | ||
| 2368 | } | 2335 | } |
| 2369 | 2336 | ||
| 2370 | const struct address_space_operations cifs_addr_ops = { | 2337 | const struct address_space_operations cifs_addr_ops = { |
