Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
cifs: fix locking and list handling code in cifs_open and its helper
[CIFS] Remove build warning
cifs: fix problems with last two commits
[CIFS] Fix build break when keys support turned off
cifs: eliminate cifs_init_private
cifs: convert oplock breaks to use slow_work facility (try #4)
cifs: have cifsFileInfo hold an extra inode reference
cifs: take read lock on GlobalSMBSes_lock in is_valid_oplock_break
cifs: remove cifsInodeInfo.oplockPending flag
cifs: fix oplock request handling in posix codepath
[CIFS] Re-enable Lanman security

+159 -258
+1
fs/cifs/Kconfig
··· 2 2 tristate "CIFS support (advanced network filesystem, SMBFS successor)" 3 3 depends on INET 4 4 select NLS 5 + select SLOW_WORK 5 6 help 6 7 This is the client VFS module for the Common Internet File System 7 8 (CIFS) protocol which is the successor to the Server Message Block
+4 -89
fs/cifs/cifsfs.c
··· 64 64 unsigned int extended_security = CIFSSEC_DEF; 65 65 /* unsigned int ntlmv2_support = 0; */ 66 66 unsigned int sign_CIFS_PDUs = 1; 67 - extern struct task_struct *oplockThread; /* remove sparse warning */ 68 - struct task_struct *oplockThread = NULL; 69 - /* extern struct task_struct * dnotifyThread; remove sparse warning */ 70 67 static const struct super_operations cifs_super_ops; 71 68 unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; 72 69 module_param(CIFSMaxBufSize, int, 0); ··· 969 972 kmem_cache_destroy(cifs_oplock_cachep); 970 973 } 971 974 972 - static int cifs_oplock_thread(void *dummyarg) 973 - { 974 - struct oplock_q_entry *oplock_item; 975 - struct cifsTconInfo *pTcon; 976 - struct inode *inode; 977 - __u16 netfid; 978 - int rc, waitrc = 0; 979 - 980 - set_freezable(); 981 - do { 982 - if (try_to_freeze()) 983 - continue; 984 - 985 - spin_lock(&cifs_oplock_lock); 986 - if (list_empty(&cifs_oplock_list)) { 987 - spin_unlock(&cifs_oplock_lock); 988 - set_current_state(TASK_INTERRUPTIBLE); 989 - schedule_timeout(39*HZ); 990 - } else { 991 - oplock_item = list_entry(cifs_oplock_list.next, 992 - struct oplock_q_entry, qhead); 993 - cFYI(1, ("found oplock item to write out")); 994 - pTcon = oplock_item->tcon; 995 - inode = oplock_item->pinode; 996 - netfid = oplock_item->netfid; 997 - spin_unlock(&cifs_oplock_lock); 998 - DeleteOplockQEntry(oplock_item); 999 - /* can not grab inode sem here since it would 1000 - deadlock when oplock received on delete 1001 - since vfs_unlink holds the i_mutex across 1002 - the call */ 1003 - /* mutex_lock(&inode->i_mutex);*/ 1004 - if (S_ISREG(inode->i_mode)) { 1005 - #ifdef CONFIG_CIFS_EXPERIMENTAL 1006 - if (CIFS_I(inode)->clientCanCacheAll == 0) 1007 - break_lease(inode, FMODE_READ); 1008 - else if (CIFS_I(inode)->clientCanCacheRead == 0) 1009 - break_lease(inode, FMODE_WRITE); 1010 - #endif 1011 - rc = filemap_fdatawrite(inode->i_mapping); 1012 - if (CIFS_I(inode)->clientCanCacheRead == 0) { 1013 - waitrc = filemap_fdatawait( 1014 - inode->i_mapping); 1015 - invalidate_remote_inode(inode); 1016 - } 1017 - if (rc == 0) 1018 - rc = waitrc; 1019 - } else 1020 - rc = 0; 1021 - /* mutex_unlock(&inode->i_mutex);*/ 1022 - if (rc) 1023 - CIFS_I(inode)->write_behind_rc = rc; 1024 - cFYI(1, ("Oplock flush inode %p rc %d", 1025 - inode, rc)); 1026 - 1027 - /* releasing stale oplock after recent reconnect 1028 - of smb session using a now incorrect file 1029 - handle is not a data integrity issue but do 1030 - not bother sending an oplock release if session 1031 - to server still is disconnected since oplock 1032 - already released by the server in that case */ 1033 - if (!pTcon->need_reconnect) { 1034 - rc = CIFSSMBLock(0, pTcon, netfid, 1035 - 0 /* len */ , 0 /* offset */, 0, 1036 - 0, LOCKING_ANDX_OPLOCK_RELEASE, 1037 - false /* wait flag */); 1038 - cFYI(1, ("Oplock release rc = %d", rc)); 1039 - } 1040 - set_current_state(TASK_INTERRUPTIBLE); 1041 - schedule_timeout(1); /* yield in case q were corrupt */ 1042 - } 1043 - } while (!kthread_should_stop()); 1044 - 1045 - return 0; 1046 - } 1047 - 1048 975 static int __init 1049 976 init_cifs(void) 1050 977 { 1051 978 int rc = 0; 1052 979 cifs_proc_init(); 1053 980 INIT_LIST_HEAD(&cifs_tcp_ses_list); 1054 - INIT_LIST_HEAD(&cifs_oplock_list); 1055 981 #ifdef CONFIG_CIFS_EXPERIMENTAL 1056 982 INIT_LIST_HEAD(&GlobalDnotifyReqList); 1057 983 INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); ··· 1003 1083 rwlock_init(&GlobalSMBSeslock); 1004 1084 rwlock_init(&cifs_tcp_ses_lock); 1005 1085 spin_lock_init(&GlobalMid_Lock); 1006 - spin_lock_init(&cifs_oplock_lock); 1007 1086 1008 1087 if (cifs_max_pending < 2) { 1009 1088 cifs_max_pending = 2; ··· 1037 1118 if (rc) 1038 1119 goto out_unregister_key_type; 1039 1120 #endif 1040 - oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd"); 1041 - if (IS_ERR(oplockThread)) { 1042 - rc = PTR_ERR(oplockThread); 1043 - cERROR(1, ("error %d create oplock thread", rc)); 1044 - goto out_unregister_dfs_key_type; 1045 - } 1121 + rc = slow_work_register_user(); 1122 + if (rc) 1123 + goto out_unregister_resolver_key; 1046 1124 1047 1125 return 0; 1048 1126 1049 - out_unregister_dfs_key_type: 1127 + out_unregister_resolver_key: 1050 1128 #ifdef CONFIG_CIFS_DFS_UPCALL 1051 1129 unregister_key_type(&key_type_dns_resolver); 1052 1130 out_unregister_key_type: ··· 1080 1164 cifs_destroy_inodecache(); 1081 1165 cifs_destroy_mids(); 1082 1166 cifs_destroy_request_bufs(); 1083 - kthread_stop(oplockThread); 1084 1167 } 1085 1168 1086 1169 MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
+10 -11
fs/cifs/cifsglob.h
··· 18 18 */ 19 19 #include <linux/in.h> 20 20 #include <linux/in6.h> 21 + #include <linux/slow-work.h> 21 22 #include "cifs_fs_sb.h" 22 23 #include "cifsacl.h" 23 24 /* ··· 347 346 /* lock scope id (0 if none) */ 348 347 struct file *pfile; /* needed for writepage */ 349 348 struct inode *pInode; /* needed for oplock break */ 349 + struct vfsmount *mnt; 350 350 struct mutex lock_mutex; 351 351 struct list_head llist; /* list of byte range locks we have. */ 352 352 bool closePend:1; /* file is marked to close */ 353 353 bool invalidHandle:1; /* file closed via session abend */ 354 - bool messageMode:1; /* for pipes: message vs byte mode */ 354 + bool oplock_break_cancelled:1; 355 355 atomic_t count; /* reference count */ 356 356 struct mutex fh_mutex; /* prevents reopen race after dead ses*/ 357 357 struct cifs_search_info srch_inf; 358 + struct slow_work oplock_break; /* slow_work job for oplock breaks */ 358 359 }; 359 360 360 361 /* Take a reference on the file private data */ ··· 368 365 /* Release a reference on the file private data */ 369 366 static inline void cifsFileInfo_put(struct cifsFileInfo *cifs_file) 370 367 { 371 - if (atomic_dec_and_test(&cifs_file->count)) 368 + if (atomic_dec_and_test(&cifs_file->count)) { 369 + iput(cifs_file->pInode); 372 370 kfree(cifs_file); 371 + } 373 372 } 374 373 375 374 /* ··· 387 382 unsigned long time; /* jiffies of last update/check of inode */ 388 383 bool clientCanCacheRead:1; /* read oplock */ 389 384 bool clientCanCacheAll:1; /* read and writebehind oplock */ 390 - bool oplockPending:1; 391 385 bool delete_pending:1; /* DELETE_ON_CLOSE is set */ 392 386 u64 server_eof; /* current file size on server */ 393 387 u64 uniqueid; /* server inode number */ ··· 589 585 #define CIFSSEC_MUST_LANMAN 0x10010 590 586 #define CIFSSEC_MUST_PLNTXT 0x20020 591 587 #ifdef CONFIG_CIFS_UPCALL 592 - #define CIFSSEC_MASK 0xAF0AF /* allows weak security but also krb5 */ 588 + #define CIFSSEC_MASK 0xBF0BF /* allows weak security but also krb5 */ 593 589 #else 594 - #define CIFSSEC_MASK 0xA70A7 /* current flags supported if weak */ 590 + #define CIFSSEC_MASK 0xB70B7 /* current flags supported if weak */ 595 591 #endif /* UPCALL */ 596 592 #else /* do not allow weak pw hash */ 597 593 #ifdef CONFIG_CIFS_UPCALL ··· 673 669 */ 674 670 GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; 675 671 676 - /* Global list of oplocks */ 677 - GLOBAL_EXTERN struct list_head cifs_oplock_list; 678 - 679 - /* Protects the cifs_oplock_list */ 680 - GLOBAL_EXTERN spinlock_t cifs_oplock_lock; 681 - 682 672 /* Outstanding dir notify requests */ 683 673 GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; 684 674 /* DirNotify response queue */ ··· 723 725 GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ 724 726 GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ 725 727 728 + extern const struct slow_work_ops cifs_oplock_break_ops;
+5 -6
fs/cifs/cifsproto.h
··· 86 86 const int stage, 87 87 const struct nls_table *nls_cp); 88 88 extern __u16 GetNextMid(struct TCP_Server_Info *server); 89 - extern struct oplock_q_entry *AllocOplockQEntry(struct inode *, u16, 90 - struct cifsTconInfo *); 91 - extern void DeleteOplockQEntry(struct oplock_q_entry *); 92 - extern void DeleteTconOplockQEntries(struct cifsTconInfo *); 93 89 extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); 94 90 extern u64 cifs_UnixTimeToNT(struct timespec); 95 91 extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, 96 92 int offset); 97 93 94 + extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode, 95 + __u16 fileHandle, struct file *file, 96 + struct vfsmount *mnt, unsigned int oflags); 98 97 extern int cifs_posix_open(char *full_path, struct inode **pinode, 99 - struct super_block *sb, int mode, int oflags, 100 - int *poplock, __u16 *pnetfid, int xid); 98 + struct vfsmount *mnt, int mode, int oflags, 99 + __u32 *poplock, __u16 *pnetfid, int xid); 101 100 extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, 102 101 FILE_UNIX_BASIC_INFO *info, 103 102 struct cifs_sb_info *cifs_sb);
+1
fs/cifs/cifssmb.c
··· 94 94 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { 95 95 open_file = list_entry(tmp, struct cifsFileInfo, tlist); 96 96 open_file->invalidHandle = true; 97 + open_file->oplock_break_cancelled = true; 97 98 } 98 99 write_unlock(&GlobalSMBSeslock); 99 100 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
-1
fs/cifs/connect.c
··· 1670 1670 CIFSSMBTDis(xid, tcon); 1671 1671 _FreeXid(xid); 1672 1672 1673 - DeleteTconOplockQEntries(tcon); 1674 1673 tconInfoFree(tcon); 1675 1674 cifs_put_smb_ses(ses); 1676 1675 }
+29 -35
fs/cifs/dir.c
··· 24 24 #include <linux/stat.h> 25 25 #include <linux/slab.h> 26 26 #include <linux/namei.h> 27 + #include <linux/mount.h> 27 28 #include "cifsfs.h" 28 29 #include "cifspdu.h" 29 30 #include "cifsglob.h" ··· 130 129 return full_path; 131 130 } 132 131 133 - static void 134 - cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle, 135 - struct cifsTconInfo *tcon, bool write_only) 132 + struct cifsFileInfo * 133 + cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, 134 + struct file *file, struct vfsmount *mnt, unsigned int oflags) 136 135 { 137 136 int oplock = 0; 138 137 struct cifsFileInfo *pCifsFile; 139 138 struct cifsInodeInfo *pCifsInode; 139 + struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb); 140 140 141 141 pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 142 - 143 142 if (pCifsFile == NULL) 144 - return; 143 + return pCifsFile; 145 144 146 145 if (oplockEnabled) 147 146 oplock = REQ_OPLOCK; 148 147 149 148 pCifsFile->netfid = fileHandle; 150 149 pCifsFile->pid = current->tgid; 151 - pCifsFile->pInode = newinode; 150 + pCifsFile->pInode = igrab(newinode); 151 + pCifsFile->mnt = mnt; 152 + pCifsFile->pfile = file; 152 153 pCifsFile->invalidHandle = false; 153 154 pCifsFile->closePend = false; 154 155 mutex_init(&pCifsFile->fh_mutex); 155 156 mutex_init(&pCifsFile->lock_mutex); 156 157 INIT_LIST_HEAD(&pCifsFile->llist); 157 158 atomic_set(&pCifsFile->count, 1); 159 + slow_work_init(&pCifsFile->oplock_break, &cifs_oplock_break_ops); 158 160 159 - /* set the following in open now 160 - pCifsFile->pfile = file; */ 161 161 write_lock(&GlobalSMBSeslock); 162 - list_add(&pCifsFile->tlist, &tcon->openFileList); 162 + list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList); 163 163 pCifsInode = CIFS_I(newinode); 164 164 if (pCifsInode) { 165 165 /* if readable file instance put first in list*/ 166 - if (write_only) 166 + if (oflags & FMODE_READ) 167 + list_add(&pCifsFile->flist, &pCifsInode->openFileList); 168 + else 167 169 list_add_tail(&pCifsFile->flist, 168 170 &pCifsInode->openFileList); 169 - else 170 - list_add(&pCifsFile->flist, &pCifsInode->openFileList); 171 171 172 172 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { 173 173 pCifsInode->clientCanCacheAll = true; ··· 178 176 pCifsInode->clientCanCacheRead = true; 179 177 } 180 178 write_unlock(&GlobalSMBSeslock); 179 + 180 + return pCifsFile; 181 181 } 182 182 183 183 int cifs_posix_open(char *full_path, struct inode **pinode, 184 - struct super_block *sb, int mode, int oflags, 185 - int *poplock, __u16 *pnetfid, int xid) 184 + struct vfsmount *mnt, int mode, int oflags, 185 + __u32 *poplock, __u16 *pnetfid, int xid) 186 186 { 187 187 int rc; 188 - __u32 oplock; 189 - bool write_only = false; 190 188 FILE_UNIX_BASIC_INFO *presp_data; 191 189 __u32 posix_flags = 0; 192 - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 190 + struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb); 193 191 struct cifs_fattr fattr; 194 192 195 193 cFYI(1, ("posix open %s", full_path)); ··· 225 223 if (oflags & O_DIRECT) 226 224 posix_flags |= SMB_O_DIRECT; 227 225 228 - if (!(oflags & FMODE_READ)) 229 - write_only = true; 230 - 231 226 mode &= ~current_umask(); 232 227 rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode, 233 - pnetfid, presp_data, &oplock, full_path, 228 + pnetfid, presp_data, poplock, full_path, 234 229 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 235 230 CIFS_MOUNT_MAP_SPECIAL_CHR); 236 231 if (rc) ··· 243 244 244 245 /* get new inode and set it up */ 245 246 if (*pinode == NULL) { 246 - *pinode = cifs_iget(sb, &fattr); 247 + *pinode = cifs_iget(mnt->mnt_sb, &fattr); 247 248 if (!*pinode) { 248 249 rc = -ENOMEM; 249 250 goto posix_open_ret; ··· 252 253 cifs_fattr_to_inode(*pinode, &fattr); 253 254 } 254 255 255 - cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); 256 + cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags); 256 257 257 258 posix_open_ret: 258 259 kfree(presp_data); ··· 279 280 int rc = -ENOENT; 280 281 int xid; 281 282 int create_options = CREATE_NOT_DIR; 282 - int oplock = 0; 283 + __u32 oplock = 0; 283 284 int oflags; 284 285 bool posix_create = false; 285 286 /* ··· 297 298 FILE_ALL_INFO *buf = NULL; 298 299 struct inode *newinode = NULL; 299 300 int disposition = FILE_OVERWRITE_IF; 300 - bool write_only = false; 301 301 302 302 xid = GetXid(); 303 303 ··· 321 323 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && 322 324 (CIFS_UNIX_POSIX_PATH_OPS_CAP & 323 325 le64_to_cpu(tcon->fsUnixInfo.Capability))) { 324 - rc = cifs_posix_open(full_path, &newinode, inode->i_sb, 326 + rc = cifs_posix_open(full_path, &newinode, nd->path.mnt, 325 327 mode, oflags, &oplock, &fileHandle, xid); 326 328 /* EIO could indicate that (posix open) operation is not 327 329 supported, despite what server claimed in capability ··· 349 351 desiredAccess = 0; 350 352 if (oflags & FMODE_READ) 351 353 desiredAccess |= GENERIC_READ; /* is this too little? */ 352 - if (oflags & FMODE_WRITE) { 354 + if (oflags & FMODE_WRITE) 353 355 desiredAccess |= GENERIC_WRITE; 354 - if (!(oflags & FMODE_READ)) 355 - write_only = true; 356 - } 357 356 358 357 if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) 359 358 disposition = FILE_CREATE; ··· 465 470 /* mknod case - do not leave file open */ 466 471 CIFSSMBClose(xid, tcon, fileHandle); 467 472 } else if (!(posix_create) && (newinode)) { 468 - cifs_fill_fileinfo(newinode, fileHandle, 469 - cifs_sb->tcon, write_only); 473 + cifs_new_fileinfo(newinode, fileHandle, NULL, 474 + nd->path.mnt, oflags); 470 475 } 471 476 cifs_create_out: 472 477 kfree(buf); ··· 606 611 { 607 612 int xid; 608 613 int rc = 0; /* to get around spurious gcc warning, set to zero here */ 609 - int oplock = 0; 614 + __u32 oplock = 0; 610 615 __u16 fileHandle = 0; 611 616 bool posix_open = false; 612 617 struct cifs_sb_info *cifs_sb; ··· 678 683 if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && 679 684 (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && 680 685 (nd->intent.open.flags & O_CREAT)) { 681 - rc = cifs_posix_open(full_path, &newInode, 682 - parent_dir_inode->i_sb, 686 + rc = cifs_posix_open(full_path, &newInode, nd->path.mnt, 683 687 nd->intent.open.create_mode, 684 688 nd->intent.open.flags, &oplock, 685 689 &fileHandle, xid);
+85 -52
fs/cifs/file.c
··· 30 30 #include <linux/writeback.h> 31 31 #include <linux/task_io_accounting_ops.h> 32 32 #include <linux/delay.h> 33 + #include <linux/mount.h> 33 34 #include <asm/div64.h> 34 35 #include "cifsfs.h" 35 36 #include "cifspdu.h" ··· 39 38 #include "cifs_unicode.h" 40 39 #include "cifs_debug.h" 41 40 #include "cifs_fs_sb.h" 42 - 43 - static inline struct cifsFileInfo *cifs_init_private( 44 - struct cifsFileInfo *private_data, struct inode *inode, 45 - struct file *file, __u16 netfid) 46 - { 47 - memset(private_data, 0, sizeof(struct cifsFileInfo)); 48 - private_data->netfid = netfid; 49 - private_data->pid = current->tgid; 50 - mutex_init(&private_data->fh_mutex); 51 - mutex_init(&private_data->lock_mutex); 52 - INIT_LIST_HEAD(&private_data->llist); 53 - private_data->pfile = file; /* needed for writepage */ 54 - private_data->pInode = inode; 55 - private_data->invalidHandle = false; 56 - private_data->closePend = false; 57 - /* Initialize reference count to one. The private data is 58 - freed on the release of the last reference */ 59 - atomic_set(&private_data->count, 1); 60 - 61 - return private_data; 62 - } 63 41 64 42 static inline int cifs_convert_flags(unsigned int flags) 65 43 { ··· 103 123 } 104 124 105 125 /* all arguments to this function must be checked for validity in caller */ 106 - static inline int cifs_posix_open_inode_helper(struct inode *inode, 107 - struct file *file, struct cifsInodeInfo *pCifsInode, 108 - struct cifsFileInfo *pCifsFile, int oplock, u16 netfid) 126 + static inline int 127 + cifs_posix_open_inode_helper(struct inode *inode, struct file *file, 128 + struct cifsInodeInfo *pCifsInode, 129 + struct cifsFileInfo *pCifsFile, __u32 oplock, 130 + u16 netfid) 109 131 { 110 132 111 133 write_lock(&GlobalSMBSeslock); ··· 201 219 struct timespec temp; 202 220 int rc; 203 221 204 - /* want handles we can use to read with first 205 - in the list so we do not have to walk the 206 - list to search for one in write_begin */ 207 - if ((file->f_flags & O_ACCMODE) == O_WRONLY) { 208 - list_add_tail(&pCifsFile->flist, 209 - &pCifsInode->openFileList); 210 - } else { 211 - list_add(&pCifsFile->flist, 212 - &pCifsInode->openFileList); 213 - } 214 - write_unlock(&GlobalSMBSeslock); 215 222 if (pCifsInode->clientCanCacheRead) { 216 223 /* we have the inode open somewhere else 217 224 no need to discard cache data */ ··· 250 279 int cifs_open(struct inode *inode, struct file *file) 251 280 { 252 281 int rc = -EACCES; 253 - int xid, oplock; 282 + int xid; 283 + __u32 oplock; 254 284 struct cifs_sb_info *cifs_sb; 255 285 struct cifsTconInfo *tcon; 256 286 struct cifsFileInfo *pCifsFile; ··· 296 324 le64_to_cpu(tcon->fsUnixInfo.Capability))) { 297 325 int oflags = (int) cifs_posix_convert_flags(file->f_flags); 298 326 /* can not refresh inode info since size could be stale */ 299 - rc = cifs_posix_open(full_path, &inode, inode->i_sb, 327 + rc = cifs_posix_open(full_path, &inode, file->f_path.mnt, 300 328 cifs_sb->mnt_file_mode /* ignored */, 301 329 oflags, &oplock, &netfid, xid); 302 330 if (rc == 0) { ··· 386 414 cFYI(1, ("cifs_open returned 0x%x", rc)); 387 415 goto out; 388 416 } 389 - file->private_data = 390 - kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 417 + 418 + pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt, 419 + file->f_flags); 420 + file->private_data = pCifsFile; 391 421 if (file->private_data == NULL) { 392 422 rc = -ENOMEM; 393 423 goto out; 394 424 } 395 - pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); 396 - write_lock(&GlobalSMBSeslock); 397 - list_add(&pCifsFile->tlist, &tcon->openFileList); 398 425 399 - pCifsInode = CIFS_I(file->f_path.dentry->d_inode); 400 - if (pCifsInode) { 401 - rc = cifs_open_inode_helper(inode, file, pCifsInode, 402 - pCifsFile, tcon, 403 - &oplock, buf, full_path, xid); 404 - } else { 405 - write_unlock(&GlobalSMBSeslock); 406 - } 426 + rc = cifs_open_inode_helper(inode, file, pCifsInode, pCifsFile, tcon, 427 + &oplock, buf, full_path, xid); 407 428 408 429 if (oplock & CIFS_CREATE_ACTION) { 409 430 /* time to set mode which we can not set earlier due to ··· 439 474 static int cifs_reopen_file(struct file *file, bool can_flush) 440 475 { 441 476 int rc = -EACCES; 442 - int xid, oplock; 477 + int xid; 478 + __u32 oplock; 443 479 struct cifs_sb_info *cifs_sb; 444 480 struct cifsTconInfo *tcon; 445 481 struct cifsFileInfo *pCifsFile; ··· 509 543 le64_to_cpu(tcon->fsUnixInfo.Capability))) { 510 544 int oflags = (int) cifs_posix_convert_flags(file->f_flags); 511 545 /* can not refresh inode info since size could be stale */ 512 - rc = cifs_posix_open(full_path, NULL, inode->i_sb, 546 + rc = cifs_posix_open(full_path, NULL, file->f_path.mnt, 513 547 cifs_sb->mnt_file_mode /* ignored */, 514 548 oflags, &oplock, &netfid, xid); 515 549 if (rc == 0) { ··· 2273 2307 *pagep = page; 2274 2308 return rc; 2275 2309 } 2310 + 2311 + static void 2312 + cifs_oplock_break(struct slow_work *work) 2313 + { 2314 + struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, 2315 + oplock_break); 2316 + struct inode *inode = cfile->pInode; 2317 + struct cifsInodeInfo *cinode = CIFS_I(inode); 2318 + struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->mnt->mnt_sb); 2319 + int rc, waitrc = 0; 2320 + 2321 + if (inode && S_ISREG(inode->i_mode)) { 2322 + #ifdef CONFIG_CIFS_EXPERIMENTAL 2323 + if (cinode->clientCanCacheAll == 0) 2324 + break_lease(inode, FMODE_READ); 2325 + else if (cinode->clientCanCacheRead == 0) 2326 + break_lease(inode, FMODE_WRITE); 2327 + #endif 2328 + rc = filemap_fdatawrite(inode->i_mapping); 2329 + if (cinode->clientCanCacheRead == 0) { 2330 + waitrc = filemap_fdatawait(inode->i_mapping); 2331 + invalidate_remote_inode(inode); 2332 + } 2333 + if (!rc) 2334 + rc = waitrc; 2335 + if (rc) 2336 + cinode->write_behind_rc = rc; 2337 + cFYI(1, ("Oplock flush inode %p rc %d", inode, rc)); 2338 + } 2339 + 2340 + /* 2341 + * releasing stale oplock after recent reconnect of smb session using 2342 + * a now incorrect file handle is not a data integrity issue but do 2343 + * not bother sending an oplock release if session to server still is 2344 + * disconnected since oplock already released by the server 2345 + */ 2346 + if (!cfile->closePend && !cfile->oplock_break_cancelled) { 2347 + rc = CIFSSMBLock(0, cifs_sb->tcon, cfile->netfid, 0, 0, 0, 0, 2348 + LOCKING_ANDX_OPLOCK_RELEASE, false); 2349 + cFYI(1, ("Oplock release rc = %d", rc)); 2350 + } 2351 + } 2352 + 2353 + static int 2354 + cifs_oplock_break_get(struct slow_work *work) 2355 + { 2356 + struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, 2357 + oplock_break); 2358 + mntget(cfile->mnt); 2359 + cifsFileInfo_get(cfile); 2360 + return 0; 2361 + } 2362 + 2363 + static void 2364 + cifs_oplock_break_put(struct slow_work *work) 2365 + { 2366 + struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, 2367 + oplock_break); 2368 + mntput(cfile->mnt); 2369 + cifsFileInfo_put(cfile); 2370 + } 2371 + 2372 + const struct slow_work_ops cifs_oplock_break_ops = { 2373 + .get_ref = cifs_oplock_break_get, 2374 + .put_ref = cifs_oplock_break_put, 2375 + .execute = cifs_oplock_break, 2376 + }; 2276 2377 2277 2378 const struct address_space_operations cifs_addr_ops = { 2278 2379 .readpage = cifs_readpage,
+22 -12
fs/cifs/misc.c
··· 32 32 33 33 extern mempool_t *cifs_sm_req_poolp; 34 34 extern mempool_t *cifs_req_poolp; 35 - extern struct task_struct *oplockThread; 36 35 37 36 /* The xid serves as a useful identifier for each incoming vfs request, 38 37 in a similar way to the mid which is useful to track each sent smb, ··· 499 500 struct cifsTconInfo *tcon; 500 501 struct cifsInodeInfo *pCifsInode; 501 502 struct cifsFileInfo *netfile; 503 + int rc; 502 504 503 505 cFYI(1, ("Checking for oplock break or dnotify response")); 504 506 if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) && ··· 562 562 continue; 563 563 564 564 cifs_stats_inc(&tcon->num_oplock_brks); 565 - write_lock(&GlobalSMBSeslock); 565 + read_lock(&GlobalSMBSeslock); 566 566 list_for_each(tmp2, &tcon->openFileList) { 567 567 netfile = list_entry(tmp2, struct cifsFileInfo, 568 568 tlist); 569 569 if (pSMB->Fid != netfile->netfid) 570 570 continue; 571 571 572 - write_unlock(&GlobalSMBSeslock); 573 - read_unlock(&cifs_tcp_ses_lock); 572 + /* 573 + * don't do anything if file is about to be 574 + * closed anyway. 575 + */ 576 + if (netfile->closePend) { 577 + read_unlock(&GlobalSMBSeslock); 578 + read_unlock(&cifs_tcp_ses_lock); 579 + return true; 580 + } 581 + 574 582 cFYI(1, ("file id match, oplock break")); 575 583 pCifsInode = CIFS_I(netfile->pInode); 576 584 pCifsInode->clientCanCacheAll = false; 577 585 if (pSMB->OplockLevel == 0) 578 586 pCifsInode->clientCanCacheRead = false; 579 - pCifsInode->oplockPending = true; 580 - AllocOplockQEntry(netfile->pInode, 581 - netfile->netfid, tcon); 582 - cFYI(1, ("about to wake up oplock thread")); 583 - if (oplockThread) 584 - wake_up_process(oplockThread); 585 - 587 + rc = slow_work_enqueue(&netfile->oplock_break); 588 + if (rc) { 589 + cERROR(1, ("failed to enqueue oplock " 590 + "break: %d\n", rc)); 591 + } else { 592 + netfile->oplock_break_cancelled = false; 593 + } 594 + read_unlock(&GlobalSMBSeslock); 595 + read_unlock(&cifs_tcp_ses_lock); 586 596 return true; 587 597 } 588 - write_unlock(&GlobalSMBSeslock); 598 + read_unlock(&GlobalSMBSeslock); 589 599 read_unlock(&cifs_tcp_ses_lock); 590 600 cFYI(1, ("No matching file for oplock break")); 591 601 return true;
+2 -2
fs/cifs/readdir.c
··· 146 146 } 147 147 } 148 148 149 - void 149 + static void 150 150 cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, 151 151 struct cifs_sb_info *cifs_sb) 152 152 { ··· 161 161 cifs_fill_common_info(fattr, cifs_sb); 162 162 } 163 163 164 - void 164 + static void 165 165 cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info, 166 166 struct cifs_sb_info *cifs_sb) 167 167 {
-50
fs/cifs/transport.c
··· 103 103 mempool_free(midEntry, cifs_mid_poolp); 104 104 } 105 105 106 - struct oplock_q_entry * 107 - AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon) 108 - { 109 - struct oplock_q_entry *temp; 110 - if ((pinode == NULL) || (tcon == NULL)) { 111 - cERROR(1, ("Null parms passed to AllocOplockQEntry")); 112 - return NULL; 113 - } 114 - temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep, 115 - GFP_KERNEL); 116 - if (temp == NULL) 117 - return temp; 118 - else { 119 - temp->pinode = pinode; 120 - temp->tcon = tcon; 121 - temp->netfid = fid; 122 - spin_lock(&cifs_oplock_lock); 123 - list_add_tail(&temp->qhead, &cifs_oplock_list); 124 - spin_unlock(&cifs_oplock_lock); 125 - } 126 - return temp; 127 - } 128 - 129 - void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry) 130 - { 131 - spin_lock(&cifs_oplock_lock); 132 - /* should we check if list empty first? */ 133 - list_del(&oplockEntry->qhead); 134 - spin_unlock(&cifs_oplock_lock); 135 - kmem_cache_free(cifs_oplock_cachep, oplockEntry); 136 - } 137 - 138 - 139 - void DeleteTconOplockQEntries(struct cifsTconInfo *tcon) 140 - { 141 - struct oplock_q_entry *temp; 142 - 143 - if (tcon == NULL) 144 - return; 145 - 146 - spin_lock(&cifs_oplock_lock); 147 - list_for_each_entry(temp, &cifs_oplock_list, qhead) { 148 - if ((temp->tcon) && (temp->tcon == tcon)) { 149 - list_del(&temp->qhead); 150 - kmem_cache_free(cifs_oplock_cachep, temp); 151 - } 152 - } 153 - spin_unlock(&cifs_oplock_lock); 154 - } 155 - 156 106 static int 157 107 smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) 158 108 {