diff options
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r-- | fs/cifs/dir.c | 64 |
1 files changed, 29 insertions, 35 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index a6424cfc0121..627a60a6c1b1 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 | ||
132 | static void | 133 | struct cifsFileInfo * |
133 | cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle, | 134 | cifs_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->count, 1); | 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 | ||
181 | int cifs_posix_open(char *full_path, struct inode **pinode, | 185 | int 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)); |
@@ -223,12 +225,9 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
223 | if (oflags & O_DIRECT) | 225 | if (oflags & O_DIRECT) |
224 | posix_flags |= SMB_O_DIRECT; | 226 | posix_flags |= SMB_O_DIRECT; |
225 | 227 | ||
226 | if (!(oflags & FMODE_READ)) | ||
227 | write_only = true; | ||
228 | |||
229 | mode &= ~current_umask(); | 228 | mode &= ~current_umask(); |
230 | rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode, | 229 | rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode, |
231 | pnetfid, presp_data, &oplock, full_path, | 230 | pnetfid, presp_data, poplock, full_path, |
232 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 231 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
233 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 232 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
234 | if (rc) | 233 | if (rc) |
@@ -244,7 +243,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
244 | 243 | ||
245 | /* get new inode and set it up */ | 244 | /* get new inode and set it up */ |
246 | if (*pinode == NULL) { | 245 | if (*pinode == NULL) { |
247 | *pinode = cifs_iget(sb, &fattr); | 246 | *pinode = cifs_iget(mnt->mnt_sb, &fattr); |
248 | if (!*pinode) { | 247 | if (!*pinode) { |
249 | rc = -ENOMEM; | 248 | rc = -ENOMEM; |
250 | goto posix_open_ret; | 249 | goto posix_open_ret; |
@@ -253,7 +252,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
253 | cifs_fattr_to_inode(*pinode, &fattr); | 252 | cifs_fattr_to_inode(*pinode, &fattr); |
254 | } | 253 | } |
255 | 254 | ||
256 | cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); | 255 | cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags); |
257 | 256 | ||
258 | posix_open_ret: | 257 | posix_open_ret: |
259 | kfree(presp_data); | 258 | kfree(presp_data); |
@@ -280,7 +279,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
280 | int rc = -ENOENT; | 279 | int rc = -ENOENT; |
281 | int xid; | 280 | int xid; |
282 | int create_options = CREATE_NOT_DIR; | 281 | int create_options = CREATE_NOT_DIR; |
283 | int oplock = 0; | 282 | __u32 oplock = 0; |
284 | int oflags; | 283 | int oflags; |
285 | bool posix_create = false; | 284 | bool posix_create = false; |
286 | /* | 285 | /* |
@@ -298,7 +297,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
298 | FILE_ALL_INFO *buf = NULL; | 297 | FILE_ALL_INFO *buf = NULL; |
299 | struct inode *newinode = NULL; | 298 | struct inode *newinode = NULL; |
300 | int disposition = FILE_OVERWRITE_IF; | 299 | int disposition = FILE_OVERWRITE_IF; |
301 | bool write_only = false; | ||
302 | 300 | ||
303 | xid = GetXid(); | 301 | xid = GetXid(); |
304 | 302 | ||
@@ -323,7 +321,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
323 | if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && | 321 | if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && |
324 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & | 322 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
325 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 323 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
326 | rc = cifs_posix_open(full_path, &newinode, inode->i_sb, | 324 | rc = cifs_posix_open(full_path, &newinode, nd->path.mnt, |
327 | mode, oflags, &oplock, &fileHandle, xid); | 325 | mode, oflags, &oplock, &fileHandle, xid); |
328 | /* EIO could indicate that (posix open) operation is not | 326 | /* EIO could indicate that (posix open) operation is not |
329 | supported, despite what server claimed in capability | 327 | supported, despite what server claimed in capability |
@@ -351,11 +349,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
351 | desiredAccess = 0; | 349 | desiredAccess = 0; |
352 | if (oflags & FMODE_READ) | 350 | if (oflags & FMODE_READ) |
353 | desiredAccess |= GENERIC_READ; /* is this too little? */ | 351 | desiredAccess |= GENERIC_READ; /* is this too little? */ |
354 | if (oflags & FMODE_WRITE) { | 352 | if (oflags & FMODE_WRITE) |
355 | desiredAccess |= GENERIC_WRITE; | 353 | desiredAccess |= GENERIC_WRITE; |
356 | if (!(oflags & FMODE_READ)) | ||
357 | write_only = true; | ||
358 | } | ||
359 | 354 | ||
360 | if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) | 355 | if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) |
361 | disposition = FILE_CREATE; | 356 | disposition = FILE_CREATE; |
@@ -470,8 +465,8 @@ cifs_create_set_dentry: | |||
470 | /* mknod case - do not leave file open */ | 465 | /* mknod case - do not leave file open */ |
471 | CIFSSMBClose(xid, tcon, fileHandle); | 466 | CIFSSMBClose(xid, tcon, fileHandle); |
472 | } else if (!(posix_create) && (newinode)) { | 467 | } else if (!(posix_create) && (newinode)) { |
473 | cifs_fill_fileinfo(newinode, fileHandle, | 468 | cifs_new_fileinfo(newinode, fileHandle, NULL, |
474 | cifs_sb->tcon, write_only); | 469 | nd->path.mnt, oflags); |
475 | } | 470 | } |
476 | cifs_create_out: | 471 | cifs_create_out: |
477 | kfree(buf); | 472 | kfree(buf); |
@@ -611,7 +606,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
611 | { | 606 | { |
612 | int xid; | 607 | int xid; |
613 | int rc = 0; /* to get around spurious gcc warning, set to zero here */ | 608 | int rc = 0; /* to get around spurious gcc warning, set to zero here */ |
614 | int oplock = 0; | 609 | __u32 oplock = 0; |
615 | __u16 fileHandle = 0; | 610 | __u16 fileHandle = 0; |
616 | bool posix_open = false; | 611 | bool posix_open = false; |
617 | struct cifs_sb_info *cifs_sb; | 612 | struct cifs_sb_info *cifs_sb; |
@@ -683,8 +678,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
683 | if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && | 678 | if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && |
684 | (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && | 679 | (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && |
685 | (nd->intent.open.flags & O_CREAT)) { | 680 | (nd->intent.open.flags & O_CREAT)) { |
686 | rc = cifs_posix_open(full_path, &newInode, | 681 | rc = cifs_posix_open(full_path, &newInode, nd->path.mnt, |
687 | parent_dir_inode->i_sb, | ||
688 | nd->intent.open.create_mode, | 682 | nd->intent.open.create_mode, |
689 | nd->intent.open.flags, &oplock, | 683 | nd->intent.open.flags, &oplock, |
690 | &fileHandle, xid); | 684 | &fileHandle, xid); |