diff options
| -rw-r--r-- | fs/cifs/dir.c | 56 |
1 files changed, 31 insertions, 25 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 838d9c720a5c..964aad03c5ad 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -129,6 +129,17 @@ cifs_bp_rename_retry: | |||
| 129 | return full_path; | 129 | return full_path; |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | static void setup_cifs_dentry(struct cifsTconInfo *tcon, | ||
| 133 | struct dentry *direntry, | ||
| 134 | struct inode *newinode) | ||
| 135 | { | ||
| 136 | if (tcon->nocase) | ||
| 137 | direntry->d_op = &cifs_ci_dentry_ops; | ||
| 138 | else | ||
| 139 | direntry->d_op = &cifs_dentry_ops; | ||
| 140 | d_instantiate(direntry, newinode); | ||
| 141 | } | ||
| 142 | |||
| 132 | /* Inode operations in similar order to how they appear in Linux file fs.h */ | 143 | /* Inode operations in similar order to how they appear in Linux file fs.h */ |
| 133 | 144 | ||
| 134 | int | 145 | int |
| @@ -139,14 +150,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 139 | int xid; | 150 | int xid; |
| 140 | int create_options = CREATE_NOT_DIR; | 151 | int create_options = CREATE_NOT_DIR; |
| 141 | int oplock = 0; | 152 | int oplock = 0; |
| 153 | /* BB below access is too much for the mknod to request */ | ||
| 142 | int desiredAccess = GENERIC_READ | GENERIC_WRITE; | 154 | int desiredAccess = GENERIC_READ | GENERIC_WRITE; |
| 143 | __u16 fileHandle; | 155 | __u16 fileHandle; |
| 144 | struct cifs_sb_info *cifs_sb; | 156 | struct cifs_sb_info *cifs_sb; |
| 145 | struct cifsTconInfo *pTcon; | 157 | struct cifsTconInfo *tcon; |
| 146 | char *full_path = NULL; | 158 | char *full_path = NULL; |
| 147 | FILE_ALL_INFO *buf = NULL; | 159 | FILE_ALL_INFO *buf = NULL; |
| 148 | struct inode *newinode = NULL; | 160 | struct inode *newinode = NULL; |
| 149 | struct cifsFileInfo *pCifsFile = NULL; | ||
| 150 | struct cifsInodeInfo *pCifsInode; | 161 | struct cifsInodeInfo *pCifsInode; |
| 151 | int disposition = FILE_OVERWRITE_IF; | 162 | int disposition = FILE_OVERWRITE_IF; |
| 152 | bool write_only = false; | 163 | bool write_only = false; |
| @@ -154,7 +165,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 154 | xid = GetXid(); | 165 | xid = GetXid(); |
| 155 | 166 | ||
| 156 | cifs_sb = CIFS_SB(inode->i_sb); | 167 | cifs_sb = CIFS_SB(inode->i_sb); |
| 157 | pTcon = cifs_sb->tcon; | 168 | tcon = cifs_sb->tcon; |
| 158 | 169 | ||
| 159 | full_path = build_path_from_dentry(direntry); | 170 | full_path = build_path_from_dentry(direntry); |
| 160 | if (full_path == NULL) { | 171 | if (full_path == NULL) { |
| @@ -162,6 +173,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 162 | return -ENOMEM; | 173 | return -ENOMEM; |
| 163 | } | 174 | } |
| 164 | 175 | ||
| 176 | mode &= ~current->fs->umask; | ||
| 177 | |||
| 165 | if (nd && (nd->flags & LOOKUP_OPEN)) { | 178 | if (nd && (nd->flags & LOOKUP_OPEN)) { |
| 166 | int oflags = nd->intent.open.flags; | 179 | int oflags = nd->intent.open.flags; |
| 167 | 180 | ||
| @@ -196,17 +209,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 196 | return -ENOMEM; | 209 | return -ENOMEM; |
| 197 | } | 210 | } |
| 198 | 211 | ||
| 199 | mode &= ~current->fs->umask; | ||
| 200 | |||
| 201 | /* | 212 | /* |
| 202 | * if we're not using unix extensions, see if we need to set | 213 | * if we're not using unix extensions, see if we need to set |
| 203 | * ATTR_READONLY on the create call | 214 | * ATTR_READONLY on the create call |
| 204 | */ | 215 | */ |
| 205 | if (!pTcon->unix_ext && (mode & S_IWUGO) == 0) | 216 | if (!tcon->unix_ext && (mode & S_IWUGO) == 0) |
| 206 | create_options |= CREATE_OPTION_READONLY; | 217 | create_options |= CREATE_OPTION_READONLY; |
| 207 | 218 | ||
| 208 | if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) | 219 | if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) |
| 209 | rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, | 220 | rc = CIFSSMBOpen(xid, tcon, full_path, disposition, |
| 210 | desiredAccess, create_options, | 221 | desiredAccess, create_options, |
| 211 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | 222 | &fileHandle, &oplock, buf, cifs_sb->local_nls, |
| 212 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 223 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
| @@ -215,7 +226,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 215 | 226 | ||
| 216 | if (rc == -EIO) { | 227 | if (rc == -EIO) { |
| 217 | /* old server, retry the open legacy style */ | 228 | /* old server, retry the open legacy style */ |
| 218 | rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, | 229 | rc = SMBLegacyOpen(xid, tcon, full_path, disposition, |
| 219 | desiredAccess, create_options, | 230 | desiredAccess, create_options, |
| 220 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | 231 | &fileHandle, &oplock, buf, cifs_sb->local_nls, |
| 221 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 232 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
| @@ -225,7 +236,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 225 | } else { | 236 | } else { |
| 226 | /* If Open reported that we actually created a file | 237 | /* If Open reported that we actually created a file |
| 227 | then we now have to set the mode if possible */ | 238 | then we now have to set the mode if possible */ |
| 228 | if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { | 239 | if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { |
| 229 | struct cifs_unix_set_info_args args = { | 240 | struct cifs_unix_set_info_args args = { |
| 230 | .mode = mode, | 241 | .mode = mode, |
| 231 | .ctime = NO_CHANGE_64, | 242 | .ctime = NO_CHANGE_64, |
| @@ -244,20 +255,20 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 244 | args.uid = NO_CHANGE_64; | 255 | args.uid = NO_CHANGE_64; |
| 245 | args.gid = NO_CHANGE_64; | 256 | args.gid = NO_CHANGE_64; |
| 246 | } | 257 | } |
| 247 | CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, | 258 | CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, |
| 248 | cifs_sb->local_nls, | 259 | cifs_sb->local_nls, |
| 249 | cifs_sb->mnt_cifs_flags & | 260 | cifs_sb->mnt_cifs_flags & |
| 250 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 261 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 251 | } else { | 262 | } else { |
| 252 | /* BB implement mode setting via Windows security | 263 | /* BB implement mode setting via Windows security |
| 253 | descriptors e.g. */ | 264 | descriptors e.g. */ |
| 254 | /* CIFSSMBWinSetPerms(xid,pTcon,path,mode,-1,-1,nls);*/ | 265 | /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/ |
| 255 | 266 | ||
| 256 | /* Could set r/o dos attribute if mode & 0222 == 0 */ | 267 | /* Could set r/o dos attribute if mode & 0222 == 0 */ |
| 257 | } | 268 | } |
| 258 | 269 | ||
| 259 | /* server might mask mode so we have to query for it */ | 270 | /* server might mask mode so we have to query for it */ |
| 260 | if (pTcon->unix_ext) | 271 | if (tcon->unix_ext) |
| 261 | rc = cifs_get_inode_info_unix(&newinode, full_path, | 272 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
| 262 | inode->i_sb, xid); | 273 | inode->i_sb, xid); |
| 263 | else { | 274 | else { |
| @@ -283,22 +294,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 283 | } | 294 | } |
| 284 | 295 | ||
| 285 | if (rc != 0) { | 296 | if (rc != 0) { |
| 286 | cFYI(1, | 297 | cFYI(1, ("Create worked, get_inode_info failed rc = %d", |
| 287 | ("Create worked but get_inode_info failed rc = %d", | 298 | rc)); |
| 288 | rc)); | 299 | } else |
| 289 | } else { | 300 | setup_cifs_dentry(tcon, direntry, newinode); |
| 290 | if (pTcon->nocase) | 301 | |
| 291 | direntry->d_op = &cifs_ci_dentry_ops; | ||
| 292 | else | ||
| 293 | direntry->d_op = &cifs_dentry_ops; | ||
| 294 | d_instantiate(direntry, newinode); | ||
| 295 | } | ||
| 296 | if ((nd == NULL /* nfsd case - nfs srv does not set nd */) || | 302 | if ((nd == NULL /* nfsd case - nfs srv does not set nd */) || |
| 297 | (!(nd->flags & LOOKUP_OPEN))) { | 303 | (!(nd->flags & LOOKUP_OPEN))) { |
| 298 | /* mknod case - do not leave file open */ | 304 | /* mknod case - do not leave file open */ |
| 299 | CIFSSMBClose(xid, pTcon, fileHandle); | 305 | CIFSSMBClose(xid, tcon, fileHandle); |
| 300 | } else if (newinode) { | 306 | } else if (newinode) { |
| 301 | pCifsFile = | 307 | struct cifsFileInfo *pCifsFile = |
| 302 | kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); | 308 | kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); |
| 303 | 309 | ||
| 304 | if (pCifsFile == NULL) | 310 | if (pCifsFile == NULL) |
| @@ -316,7 +322,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 316 | /* set the following in open now | 322 | /* set the following in open now |
| 317 | pCifsFile->pfile = file; */ | 323 | pCifsFile->pfile = file; */ |
| 318 | write_lock(&GlobalSMBSeslock); | 324 | write_lock(&GlobalSMBSeslock); |
| 319 | list_add(&pCifsFile->tlist, &pTcon->openFileList); | 325 | list_add(&pCifsFile->tlist, &tcon->openFileList); |
| 320 | pCifsInode = CIFS_I(newinode); | 326 | pCifsInode = CIFS_I(newinode); |
| 321 | if (pCifsInode) { | 327 | if (pCifsInode) { |
| 322 | /* if readable file instance put first in list*/ | 328 | /* if readable file instance put first in list*/ |
