diff options
Diffstat (limited to 'fs/cifs/dir.c')
-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*/ |