diff options
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r-- | fs/cifs/dir.c | 103 |
1 files changed, 68 insertions, 35 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index f9ed0751cc1..e249b561ce8 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -54,18 +54,18 @@ build_path_from_dentry(struct dentry *direntry) int dfsplen; char *full_path; char dirsep; - struct cifs_sb_info *cifs_sb; + struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); + struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); if (direntry == NULL) return NULL; /* not much we can do if dentry is freed and we need to reopen the file after it was closed implicitly when the server crashed */ - cifs_sb = CIFS_SB(direntry->d_sb); dirsep = CIFS_DIR_SEP(cifs_sb); pplen = cifs_sb->prepathlen; - if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS)) - dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1); + if (tcon->Flags & SMB_SHARE_IS_IN_DFS) + dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1); else dfsplen = 0; cifs_bp_rename_retry: @@ -117,7 +117,7 @@ cifs_bp_rename_retry: /* BB test paths to Windows with '/' in the midst of prepath */ if (dfsplen) { - strncpy(full_path, cifs_sb->tcon->treeName, dfsplen); + strncpy(full_path, tcon->treeName, dfsplen); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) { int i; for (i = 0; i < dfsplen; i++) { @@ -131,28 +131,26 @@ cifs_bp_rename_retry: } struct cifsFileInfo * -cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, - struct file *file, struct vfsmount *mnt, unsigned int oflags) +cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, + struct vfsmount *mnt, struct tcon_link *tlink, + unsigned int oflags, __u32 oplock) { - int oplock = 0; struct cifsFileInfo *pCifsFile; struct cifsInodeInfo *pCifsInode; - struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb); pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); if (pCifsFile == NULL) return pCifsFile; - if (oplockEnabled) - oplock = REQ_OPLOCK; - pCifsFile->netfid = fileHandle; pCifsFile->pid = current->tgid; + pCifsFile->uid = current_fsuid(); pCifsFile->pInode = igrab(newinode); pCifsFile->mnt = mnt; pCifsFile->pfile = file; pCifsFile->invalidHandle = false; pCifsFile->closePend = false; + pCifsFile->tlink = cifs_get_tlink(tlink); mutex_init(&pCifsFile->fh_mutex); mutex_init(&pCifsFile->lock_mutex); INIT_LIST_HEAD(&pCifsFile->llist); @@ -160,7 +158,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break); write_lock(&GlobalSMBSeslock); - list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList); + list_add(&pCifsFile->tlist, &(tlink_tcon(tlink)->openFileList)); pCifsInode = CIFS_I(newinode); if (pCifsInode) { /* if readable file instance put first in list*/ @@ -193,6 +191,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode, __u32 posix_flags = 0; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_fattr fattr; + struct tcon_link *tlink; + struct cifsTconInfo *tcon; cFYI(1, "posix open %s", full_path); @@ -227,10 +227,20 @@ int cifs_posix_open(char *full_path, struct inode **pinode, posix_flags |= SMB_O_DIRECT; mode &= ~current_umask(); - rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode, - pnetfid, presp_data, poplock, full_path, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) { + rc = PTR_ERR(tlink); + goto posix_open_ret; + } + + tcon = tlink_tcon(tlink); + rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data, + poplock, full_path, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + cifs_put_tlink(tlink); + if (rc) goto posix_open_ret; @@ -291,6 +301,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, int desiredAccess = GENERIC_READ | GENERIC_WRITE; __u16 fileHandle; struct cifs_sb_info *cifs_sb; + struct tcon_link *tlink; struct cifsTconInfo *tcon; char *full_path = NULL; FILE_ALL_INFO *buf = NULL; @@ -300,13 +311,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); - tcon = cifs_sb->tcon; - - full_path = build_path_from_dentry(direntry); - if (full_path == NULL) { - rc = -ENOMEM; - goto cifs_create_out; + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) { + FreeXid(xid); + return PTR_ERR(tlink); } + tcon = tlink_tcon(tlink); if (oplockEnabled) oplock = REQ_OPLOCK; @@ -316,6 +326,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, else oflags = FMODE_READ | SMB_O_CREAT; + full_path = build_path_from_dentry(direntry); + if (full_path == NULL) { + rc = -ENOMEM; + goto cifs_create_out; + } + if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))) { @@ -375,7 +391,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, if (!tcon->unix_ext && (mode & S_IWUGO) == 0) create_options |= CREATE_OPTION_READONLY; - if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) + if (tcon->ses->capabilities & CAP_NT_SMBS) rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess, create_options, &fileHandle, &oplock, buf, cifs_sb->local_nls, @@ -468,7 +484,8 @@ cifs_create_set_dentry: } pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp, - nd->path.mnt, oflags); + nd->path.mnt, tlink, oflags, + oplock); if (pfile_info == NULL) { fput(filp); CIFSSMBClose(xid, tcon, fileHandle); @@ -481,6 +498,7 @@ cifs_create_set_dentry: cifs_create_out: kfree(buf); kfree(full_path); + cifs_put_tlink(tlink); FreeXid(xid); return rc; } @@ -491,6 +509,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, int rc = -EPERM; int xid; struct cifs_sb_info *cifs_sb; + struct tcon_link *tlink; struct cifsTconInfo *pTcon; char *full_path = NULL; struct inode *newinode = NULL; @@ -503,10 +522,14 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, if (!old_valid_dev(device_number)) return -EINVAL; - xid = GetXid(); - cifs_sb = CIFS_SB(inode->i_sb); - pTcon = cifs_sb->tcon; + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + + pTcon = tlink_tcon(tlink); + + xid = GetXid(); full_path = build_path_from_dentry(direntry); if (full_path == NULL) { @@ -606,6 +629,7 @@ mknod_out: kfree(full_path); kfree(buf); FreeXid(xid); + cifs_put_tlink(tlink); return rc; } @@ -619,6 +643,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, __u16 fileHandle = 0; bool posix_open = false; struct cifs_sb_info *cifs_sb; + struct tcon_link *tlink; struct cifsTconInfo *pTcon; struct cifsFileInfo *cfile; struct inode *newInode = NULL; @@ -633,7 +658,12 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, /* check whether path exists */ cifs_sb = CIFS_SB(parent_dir_inode->i_sb); - pTcon = cifs_sb->tcon; + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) { + FreeXid(xid); + return (struct dentry *)tlink; + } + pTcon = tlink_tcon(tlink); /* * Don't allow the separator character in a path component. @@ -644,8 +674,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, for (i = 0; i < direntry->d_name.len; i++) if (direntry->d_name.name[i] == '\\') { cFYI(1, "Invalid file name"); - FreeXid(xid); - return ERR_PTR(-EINVAL); + rc = -EINVAL; + goto lookup_out; } } @@ -655,7 +685,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, */ if (nd && (nd->flags & LOOKUP_EXCL)) { d_instantiate(direntry, NULL); - return NULL; + rc = 0; + goto lookup_out; } /* can not grab the rename sem here since it would @@ -663,8 +694,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, in which we already have the sb rename sem */ full_path = build_path_from_dentry(direntry); if (full_path == NULL) { - FreeXid(xid); - return ERR_PTR(-ENOMEM); + rc = -ENOMEM; + goto lookup_out; } if (direntry->d_inode != NULL) { @@ -728,8 +759,9 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, } cfile = cifs_new_fileinfo(newInode, fileHandle, filp, - nd->path.mnt, - nd->intent.open.flags); + nd->path.mnt, tlink, + nd->intent.open.flags, + oplock); if (cfile == NULL) { fput(filp); CIFSSMBClose(xid, pTcon, fileHandle); @@ -759,6 +791,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, lookup_out: kfree(full_path); + cifs_put_tlink(tlink); FreeXid(xid); return ERR_PTR(rc); } |