diff options
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r-- | fs/cifs/dir.c | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 7dc6b74f9def..4326ffd90fa9 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -188,6 +188,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
188 | FILE_UNIX_BASIC_INFO *presp_data; | 188 | FILE_UNIX_BASIC_INFO *presp_data; |
189 | __u32 posix_flags = 0; | 189 | __u32 posix_flags = 0; |
190 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 190 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
191 | struct cifs_fattr fattr; | ||
191 | 192 | ||
192 | cFYI(1, ("posix open %s", full_path)); | 193 | cFYI(1, ("posix open %s", full_path)); |
193 | 194 | ||
@@ -236,22 +237,21 @@ int cifs_posix_open(char *full_path, struct inode **pinode, | |||
236 | if (presp_data->Type == cpu_to_le32(-1)) | 237 | if (presp_data->Type == cpu_to_le32(-1)) |
237 | goto posix_open_ret; /* open ok, caller does qpathinfo */ | 238 | goto posix_open_ret; /* open ok, caller does qpathinfo */ |
238 | 239 | ||
239 | /* get new inode and set it up */ | ||
240 | if (!pinode) | 240 | if (!pinode) |
241 | goto posix_open_ret; /* caller does not need info */ | 241 | goto posix_open_ret; /* caller does not need info */ |
242 | 242 | ||
243 | cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb); | ||
244 | |||
245 | /* get new inode and set it up */ | ||
243 | if (*pinode == NULL) { | 246 | if (*pinode == NULL) { |
244 | __u64 unique_id = le64_to_cpu(presp_data->UniqueId); | 247 | *pinode = cifs_iget(sb, &fattr); |
245 | *pinode = cifs_new_inode(sb, &unique_id); | 248 | if (!*pinode) { |
249 | rc = -ENOMEM; | ||
250 | goto posix_open_ret; | ||
251 | } | ||
252 | } else { | ||
253 | cifs_fattr_to_inode(*pinode, &fattr); | ||
246 | } | 254 | } |
247 | /* else an inode was passed in. Update its info, don't create one */ | ||
248 | |||
249 | /* We do not need to close the file if new_inode fails since | ||
250 | the caller will retry qpathinfo as long as inode is null */ | ||
251 | if (*pinode == NULL) | ||
252 | goto posix_open_ret; | ||
253 | |||
254 | posix_fill_in_inode(*pinode, presp_data, 1); | ||
255 | 255 | ||
256 | cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); | 256 | cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only); |
257 | 257 | ||
@@ -425,9 +425,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
425 | args.uid = NO_CHANGE_64; | 425 | args.uid = NO_CHANGE_64; |
426 | args.gid = NO_CHANGE_64; | 426 | args.gid = NO_CHANGE_64; |
427 | } | 427 | } |
428 | CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, | 428 | CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, |
429 | cifs_sb->local_nls, | 429 | cifs_sb->local_nls, |
430 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 430 | cifs_sb->mnt_cifs_flags & |
431 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
431 | } else { | 432 | } else { |
432 | /* BB implement mode setting via Windows security | 433 | /* BB implement mode setting via Windows security |
433 | descriptors e.g. */ | 434 | descriptors e.g. */ |
@@ -515,10 +516,10 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
515 | args.uid = NO_CHANGE_64; | 516 | args.uid = NO_CHANGE_64; |
516 | args.gid = NO_CHANGE_64; | 517 | args.gid = NO_CHANGE_64; |
517 | } | 518 | } |
518 | rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, | 519 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, |
519 | &args, cifs_sb->local_nls, | 520 | cifs_sb->local_nls, |
520 | cifs_sb->mnt_cifs_flags & | 521 | cifs_sb->mnt_cifs_flags & |
521 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 522 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
522 | 523 | ||
523 | if (!rc) { | 524 | if (!rc) { |
524 | rc = cifs_get_inode_info_unix(&newinode, full_path, | 525 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
@@ -643,6 +644,15 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
643 | } | 644 | } |
644 | } | 645 | } |
645 | 646 | ||
647 | /* | ||
648 | * O_EXCL: optimize away the lookup, but don't hash the dentry. Let | ||
649 | * the VFS handle the create. | ||
650 | */ | ||
651 | if (nd->flags & LOOKUP_EXCL) { | ||
652 | d_instantiate(direntry, NULL); | ||
653 | return 0; | ||
654 | } | ||
655 | |||
646 | /* can not grab the rename sem here since it would | 656 | /* can not grab the rename sem here since it would |
647 | deadlock in the cases (beginning of sys_rename itself) | 657 | deadlock in the cases (beginning of sys_rename itself) |
648 | in which we already have the sb rename sem */ | 658 | in which we already have the sb rename sem */ |