diff options
author | Jeff Layton <jlayton@redhat.com> | 2010-10-15 15:33:56 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2010-10-17 20:34:29 -0400 |
commit | 608712fe8609492a8670638ea86b97fafe49ebba (patch) | |
tree | b175e2ac5e71ab8d6541a82d496d5dc6cc812acf /fs/cifs/dir.c | |
parent | 2f4f26fcf393ef4a44abe10e79c1966e64e86055 (diff) |
cifs: fix flags handling in cifs_posix_open
The way flags are passed and converted for cifs_posix_open is rather
non-sensical. Some callers call cifs_posix_convert_flags on the flags
before they pass them to cifs_posix_open, whereas some don't. Two flag
conversion steps is just confusing though.
Change the function instead to clearly expect input in f_flags format,
and fix the callers to pass that in. Then, have cifs_posix_open call
cifs_convert_posix_flags to do the conversion. Move cifs_posix_open to
file.c as well so we can keep cifs_convert_posix_flags as a static
function.
Fix it also to not ignore O_CREAT, O_EXCL and O_TRUNC, and instead have
cifs_reopen_file mask those bits off before calling cifs_posix_open.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Reviewed-by: Suresh Jayaraman <sjayaraman@suse.de>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r-- | fs/cifs/dir.c | 99 |
1 files changed, 6 insertions, 93 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index c205ec9293ea..8c1af7128384 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -181,93 +181,6 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, | |||
181 | return pCifsFile; | 181 | return pCifsFile; |
182 | } | 182 | } |
183 | 183 | ||
184 | int cifs_posix_open(char *full_path, struct inode **pinode, | ||
185 | struct super_block *sb, int mode, int oflags, | ||
186 | __u32 *poplock, __u16 *pnetfid, int xid) | ||
187 | { | ||
188 | int rc; | ||
189 | FILE_UNIX_BASIC_INFO *presp_data; | ||
190 | __u32 posix_flags = 0; | ||
191 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | ||
192 | struct cifs_fattr fattr; | ||
193 | struct tcon_link *tlink; | ||
194 | struct cifsTconInfo *tcon; | ||
195 | |||
196 | cFYI(1, "posix open %s", full_path); | ||
197 | |||
198 | presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); | ||
199 | if (presp_data == NULL) | ||
200 | return -ENOMEM; | ||
201 | |||
202 | /* So far cifs posix extensions can only map the following flags. | ||
203 | There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but | ||
204 | so far we do not seem to need them, and we can treat them as local only */ | ||
205 | if ((oflags & (FMODE_READ | FMODE_WRITE)) == | ||
206 | (FMODE_READ | FMODE_WRITE)) | ||
207 | posix_flags = SMB_O_RDWR; | ||
208 | else if (oflags & FMODE_READ) | ||
209 | posix_flags = SMB_O_RDONLY; | ||
210 | else if (oflags & FMODE_WRITE) | ||
211 | posix_flags = SMB_O_WRONLY; | ||
212 | if (oflags & O_CREAT) | ||
213 | posix_flags |= SMB_O_CREAT; | ||
214 | if (oflags & O_EXCL) | ||
215 | posix_flags |= SMB_O_EXCL; | ||
216 | if (oflags & O_TRUNC) | ||
217 | posix_flags |= SMB_O_TRUNC; | ||
218 | /* be safe and imply O_SYNC for O_DSYNC */ | ||
219 | if (oflags & O_DSYNC) | ||
220 | posix_flags |= SMB_O_SYNC; | ||
221 | if (oflags & O_DIRECTORY) | ||
222 | posix_flags |= SMB_O_DIRECTORY; | ||
223 | if (oflags & O_NOFOLLOW) | ||
224 | posix_flags |= SMB_O_NOFOLLOW; | ||
225 | if (oflags & O_DIRECT) | ||
226 | posix_flags |= SMB_O_DIRECT; | ||
227 | |||
228 | mode &= ~current_umask(); | ||
229 | |||
230 | tlink = cifs_sb_tlink(cifs_sb); | ||
231 | if (IS_ERR(tlink)) { | ||
232 | rc = PTR_ERR(tlink); | ||
233 | goto posix_open_ret; | ||
234 | } | ||
235 | |||
236 | tcon = tlink_tcon(tlink); | ||
237 | rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data, | ||
238 | poplock, full_path, cifs_sb->local_nls, | ||
239 | cifs_sb->mnt_cifs_flags & | ||
240 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
241 | cifs_put_tlink(tlink); | ||
242 | |||
243 | if (rc) | ||
244 | goto posix_open_ret; | ||
245 | |||
246 | if (presp_data->Type == cpu_to_le32(-1)) | ||
247 | goto posix_open_ret; /* open ok, caller does qpathinfo */ | ||
248 | |||
249 | if (!pinode) | ||
250 | goto posix_open_ret; /* caller does not need info */ | ||
251 | |||
252 | cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb); | ||
253 | |||
254 | /* get new inode and set it up */ | ||
255 | if (*pinode == NULL) { | ||
256 | cifs_fill_uniqueid(sb, &fattr); | ||
257 | *pinode = cifs_iget(sb, &fattr); | ||
258 | if (!*pinode) { | ||
259 | rc = -ENOMEM; | ||
260 | goto posix_open_ret; | ||
261 | } | ||
262 | } else { | ||
263 | cifs_fattr_to_inode(*pinode, &fattr); | ||
264 | } | ||
265 | |||
266 | posix_open_ret: | ||
267 | kfree(presp_data); | ||
268 | return rc; | ||
269 | } | ||
270 | |||
271 | static void setup_cifs_dentry(struct cifsTconInfo *tcon, | 184 | static void setup_cifs_dentry(struct cifsTconInfo *tcon, |
272 | struct dentry *direntry, | 185 | struct dentry *direntry, |
273 | struct inode *newinode) | 186 | struct inode *newinode) |
@@ -321,9 +234,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
321 | oplock = REQ_OPLOCK; | 234 | oplock = REQ_OPLOCK; |
322 | 235 | ||
323 | if (nd && (nd->flags & LOOKUP_OPEN)) | 236 | if (nd && (nd->flags & LOOKUP_OPEN)) |
324 | oflags = nd->intent.open.flags; | 237 | oflags = nd->intent.open.file->f_flags; |
325 | else | 238 | else |
326 | oflags = FMODE_READ | SMB_O_CREAT; | 239 | oflags = O_RDONLY | O_CREAT; |
327 | 240 | ||
328 | full_path = build_path_from_dentry(direntry); | 241 | full_path = build_path_from_dentry(direntry); |
329 | if (full_path == NULL) { | 242 | if (full_path == NULL) { |
@@ -359,9 +272,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
359 | /* if the file is going to stay open, then we | 272 | /* if the file is going to stay open, then we |
360 | need to set the desired access properly */ | 273 | need to set the desired access properly */ |
361 | desiredAccess = 0; | 274 | desiredAccess = 0; |
362 | if (oflags & FMODE_READ) | 275 | if (OPEN_FMODE(oflags) & FMODE_READ) |
363 | desiredAccess |= GENERIC_READ; /* is this too little? */ | 276 | desiredAccess |= GENERIC_READ; /* is this too little? */ |
364 | if (oflags & FMODE_WRITE) | 277 | if (OPEN_FMODE(oflags) & FMODE_WRITE) |
365 | desiredAccess |= GENERIC_WRITE; | 278 | desiredAccess |= GENERIC_WRITE; |
366 | 279 | ||
367 | if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) | 280 | if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) |
@@ -716,11 +629,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
716 | if (pTcon->unix_ext) { | 629 | if (pTcon->unix_ext) { |
717 | if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && | 630 | if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && |
718 | (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && | 631 | (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && |
719 | (nd->intent.open.flags & O_CREAT)) { | 632 | (nd->intent.open.file->f_flags & O_CREAT)) { |
720 | rc = cifs_posix_open(full_path, &newInode, | 633 | rc = cifs_posix_open(full_path, &newInode, |
721 | parent_dir_inode->i_sb, | 634 | parent_dir_inode->i_sb, |
722 | nd->intent.open.create_mode, | 635 | nd->intent.open.create_mode, |
723 | nd->intent.open.flags, &oplock, | 636 | nd->intent.open.file->f_flags, &oplock, |
724 | &fileHandle, xid); | 637 | &fileHandle, xid); |
725 | /* | 638 | /* |
726 | * The check below works around a bug in POSIX | 639 | * The check below works around a bug in POSIX |