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); |
