aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r--fs/cifs/dir.c74
1 files changed, 33 insertions, 41 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 4326ffd90fa9..1f42f772865a 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -24,6 +24,7 @@
24#include <linux/stat.h> 24#include <linux/stat.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/namei.h> 26#include <linux/namei.h>
27#include <linux/mount.h>
27#include "cifsfs.h" 28#include "cifsfs.h"
28#include "cifspdu.h" 29#include "cifspdu.h"
29#include "cifsglob.h" 30#include "cifsglob.h"
@@ -129,44 +130,45 @@ cifs_bp_rename_retry:
129 return full_path; 130 return full_path;
130} 131}
131 132
132static void 133struct cifsFileInfo *
133cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle, 134cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
134 struct cifsTconInfo *tcon, bool write_only) 135 struct file *file, struct vfsmount *mnt, unsigned int oflags)
135{ 136{
136 int oplock = 0; 137 int oplock = 0;
137 struct cifsFileInfo *pCifsFile; 138 struct cifsFileInfo *pCifsFile;
138 struct cifsInodeInfo *pCifsInode; 139 struct cifsInodeInfo *pCifsInode;
140 struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
139 141
140 pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 142 pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
141
142 if (pCifsFile == NULL) 143 if (pCifsFile == NULL)
143 return; 144 return pCifsFile;
144 145
145 if (oplockEnabled) 146 if (oplockEnabled)
146 oplock = REQ_OPLOCK; 147 oplock = REQ_OPLOCK;
147 148
148 pCifsFile->netfid = fileHandle; 149 pCifsFile->netfid = fileHandle;
149 pCifsFile->pid = current->tgid; 150 pCifsFile->pid = current->tgid;
150 pCifsFile->pInode = newinode; 151 pCifsFile->pInode = igrab(newinode);
152 pCifsFile->mnt = mnt;
153 pCifsFile->pfile = file;
151 pCifsFile->invalidHandle = false; 154 pCifsFile->invalidHandle = false;
152 pCifsFile->closePend = false; 155 pCifsFile->closePend = false;
153 mutex_init(&pCifsFile->fh_mutex); 156 mutex_init(&pCifsFile->fh_mutex);
154 mutex_init(&pCifsFile->lock_mutex); 157 mutex_init(&pCifsFile->lock_mutex);
155 INIT_LIST_HEAD(&pCifsFile->llist); 158 INIT_LIST_HEAD(&pCifsFile->llist);
156 atomic_set(&pCifsFile->wrtPending, 0); 159 atomic_set(&pCifsFile->count, 1);
160 slow_work_init(&pCifsFile->oplock_break, &cifs_oplock_break_ops);
157 161
158 /* set the following in open now
159 pCifsFile->pfile = file; */
160 write_lock(&GlobalSMBSeslock); 162 write_lock(&GlobalSMBSeslock);
161 list_add(&pCifsFile->tlist, &tcon->openFileList); 163 list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
162 pCifsInode = CIFS_I(newinode); 164 pCifsInode = CIFS_I(newinode);
163 if (pCifsInode) { 165 if (pCifsInode) {
164 /* if readable file instance put first in list*/ 166 /* if readable file instance put first in list*/
165 if (write_only) 167 if (oflags & FMODE_READ)
168 list_add(&pCifsFile->flist, &pCifsInode->openFileList);
169 else
166 list_add_tail(&pCifsFile->flist, 170 list_add_tail(&pCifsFile->flist,
167 &pCifsInode->openFileList); 171 &pCifsInode->openFileList);
168 else
169 list_add(&pCifsFile->flist, &pCifsInode->openFileList);
170 172
171 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { 173 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
172 pCifsInode->clientCanCacheAll = true; 174 pCifsInode->clientCanCacheAll = true;
@@ -176,18 +178,18 @@ cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle,
176 pCifsInode->clientCanCacheRead = true; 178 pCifsInode->clientCanCacheRead = true;
177 } 179 }
178 write_unlock(&GlobalSMBSeslock); 180 write_unlock(&GlobalSMBSeslock);
181
182 return pCifsFile;
179} 183}
180 184
181int cifs_posix_open(char *full_path, struct inode **pinode, 185int cifs_posix_open(char *full_path, struct inode **pinode,
182 struct super_block *sb, int mode, int oflags, 186 struct vfsmount *mnt, int mode, int oflags,
183 int *poplock, __u16 *pnetfid, int xid) 187 __u32 *poplock, __u16 *pnetfid, int xid)
184{ 188{
185 int rc; 189 int rc;
186 __u32 oplock;
187 bool write_only = false;
188 FILE_UNIX_BASIC_INFO *presp_data; 190 FILE_UNIX_BASIC_INFO *presp_data;
189 __u32 posix_flags = 0; 191 __u32 posix_flags = 0;
190 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 192 struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
191 struct cifs_fattr fattr; 193 struct cifs_fattr fattr;
192 194
193 cFYI(1, ("posix open %s", full_path)); 195 cFYI(1, ("posix open %s", full_path));
@@ -212,8 +214,6 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
212 posix_flags |= SMB_O_EXCL; 214 posix_flags |= SMB_O_EXCL;
213 if (oflags & O_TRUNC) 215 if (oflags & O_TRUNC)
214 posix_flags |= SMB_O_TRUNC; 216 posix_flags |= SMB_O_TRUNC;
215 if (oflags & O_APPEND)
216 posix_flags |= SMB_O_APPEND;
217 if (oflags & O_SYNC) 217 if (oflags & O_SYNC)
218 posix_flags |= SMB_O_SYNC; 218 posix_flags |= SMB_O_SYNC;
219 if (oflags & O_DIRECTORY) 219 if (oflags & O_DIRECTORY)
@@ -223,12 +223,9 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
223 if (oflags & O_DIRECT) 223 if (oflags & O_DIRECT)
224 posix_flags |= SMB_O_DIRECT; 224 posix_flags |= SMB_O_DIRECT;
225 225
226 if (!(oflags & FMODE_READ))
227 write_only = true;
228
229 mode &= ~current_umask(); 226 mode &= ~current_umask();
230 rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode, 227 rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
231 pnetfid, presp_data, &oplock, full_path, 228 pnetfid, presp_data, poplock, full_path,
232 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 229 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
233 CIFS_MOUNT_MAP_SPECIAL_CHR); 230 CIFS_MOUNT_MAP_SPECIAL_CHR);
234 if (rc) 231 if (rc)
@@ -244,7 +241,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
244 241
245 /* get new inode and set it up */ 242 /* get new inode and set it up */
246 if (*pinode == NULL) { 243 if (*pinode == NULL) {
247 *pinode = cifs_iget(sb, &fattr); 244 *pinode = cifs_iget(mnt->mnt_sb, &fattr);
248 if (!*pinode) { 245 if (!*pinode) {
249 rc = -ENOMEM; 246 rc = -ENOMEM;
250 goto posix_open_ret; 247 goto posix_open_ret;
@@ -253,7 +250,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
253 cifs_fattr_to_inode(*pinode, &fattr); 250 cifs_fattr_to_inode(*pinode, &fattr);
254 } 251 }
255 252
256 cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); 253 cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags);
257 254
258posix_open_ret: 255posix_open_ret:
259 kfree(presp_data); 256 kfree(presp_data);
@@ -280,7 +277,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
280 int rc = -ENOENT; 277 int rc = -ENOENT;
281 int xid; 278 int xid;
282 int create_options = CREATE_NOT_DIR; 279 int create_options = CREATE_NOT_DIR;
283 int oplock = 0; 280 __u32 oplock = 0;
284 int oflags; 281 int oflags;
285 bool posix_create = false; 282 bool posix_create = false;
286 /* 283 /*
@@ -298,7 +295,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
298 FILE_ALL_INFO *buf = NULL; 295 FILE_ALL_INFO *buf = NULL;
299 struct inode *newinode = NULL; 296 struct inode *newinode = NULL;
300 int disposition = FILE_OVERWRITE_IF; 297 int disposition = FILE_OVERWRITE_IF;
301 bool write_only = false;
302 298
303 xid = GetXid(); 299 xid = GetXid();
304 300
@@ -323,7 +319,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
323 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && 319 if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
324 (CIFS_UNIX_POSIX_PATH_OPS_CAP & 320 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
325 le64_to_cpu(tcon->fsUnixInfo.Capability))) { 321 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
326 rc = cifs_posix_open(full_path, &newinode, inode->i_sb, 322 rc = cifs_posix_open(full_path, &newinode, nd->path.mnt,
327 mode, oflags, &oplock, &fileHandle, xid); 323 mode, oflags, &oplock, &fileHandle, xid);
328 /* EIO could indicate that (posix open) operation is not 324 /* EIO could indicate that (posix open) operation is not
329 supported, despite what server claimed in capability 325 supported, despite what server claimed in capability
@@ -351,11 +347,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
351 desiredAccess = 0; 347 desiredAccess = 0;
352 if (oflags & FMODE_READ) 348 if (oflags & FMODE_READ)
353 desiredAccess |= GENERIC_READ; /* is this too little? */ 349 desiredAccess |= GENERIC_READ; /* is this too little? */
354 if (oflags & FMODE_WRITE) { 350 if (oflags & FMODE_WRITE)
355 desiredAccess |= GENERIC_WRITE; 351 desiredAccess |= GENERIC_WRITE;
356 if (!(oflags & FMODE_READ))
357 write_only = true;
358 }
359 352
360 if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) 353 if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
361 disposition = FILE_CREATE; 354 disposition = FILE_CREATE;
@@ -470,8 +463,8 @@ cifs_create_set_dentry:
470 /* mknod case - do not leave file open */ 463 /* mknod case - do not leave file open */
471 CIFSSMBClose(xid, tcon, fileHandle); 464 CIFSSMBClose(xid, tcon, fileHandle);
472 } else if (!(posix_create) && (newinode)) { 465 } else if (!(posix_create) && (newinode)) {
473 cifs_fill_fileinfo(newinode, fileHandle, 466 cifs_new_fileinfo(newinode, fileHandle, NULL,
474 cifs_sb->tcon, write_only); 467 nd->path.mnt, oflags);
475 } 468 }
476cifs_create_out: 469cifs_create_out:
477 kfree(buf); 470 kfree(buf);
@@ -611,7 +604,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
611{ 604{
612 int xid; 605 int xid;
613 int rc = 0; /* to get around spurious gcc warning, set to zero here */ 606 int rc = 0; /* to get around spurious gcc warning, set to zero here */
614 int oplock = 0; 607 __u32 oplock = 0;
615 __u16 fileHandle = 0; 608 __u16 fileHandle = 0;
616 bool posix_open = false; 609 bool posix_open = false;
617 struct cifs_sb_info *cifs_sb; 610 struct cifs_sb_info *cifs_sb;
@@ -648,9 +641,9 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
648 * O_EXCL: optimize away the lookup, but don't hash the dentry. Let 641 * O_EXCL: optimize away the lookup, but don't hash the dentry. Let
649 * the VFS handle the create. 642 * the VFS handle the create.
650 */ 643 */
651 if (nd->flags & LOOKUP_EXCL) { 644 if (nd && (nd->flags & LOOKUP_EXCL)) {
652 d_instantiate(direntry, NULL); 645 d_instantiate(direntry, NULL);
653 return 0; 646 return NULL;
654 } 647 }
655 648
656 /* can not grab the rename sem here since it would 649 /* can not grab the rename sem here since it would
@@ -680,11 +673,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
680 * reduction in network traffic in the other paths. 673 * reduction in network traffic in the other paths.
681 */ 674 */
682 if (pTcon->unix_ext) { 675 if (pTcon->unix_ext) {
683 if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && 676 if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
684 (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && 677 (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
685 (nd->intent.open.flags & O_CREAT)) { 678 (nd->intent.open.flags & O_CREAT)) {
686 rc = cifs_posix_open(full_path, &newInode, 679 rc = cifs_posix_open(full_path, &newInode, nd->path.mnt,
687 parent_dir_inode->i_sb,
688 nd->intent.open.create_mode, 680 nd->intent.open.create_mode,
689 nd->intent.open.flags, &oplock, 681 nd->intent.open.flags, &oplock,
690 &fileHandle, xid); 682 &fileHandle, xid);