aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifsglob.h4
-rw-r--r--fs/cifs/cifsproto.h8
-rw-r--r--fs/cifs/cifssmb.c20
-rw-r--r--fs/cifs/link.c74
-rw-r--r--fs/cifs/smb1ops.c1
5 files changed, 63 insertions, 44 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index a0105c547ffd..8595d498ad80 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -278,6 +278,10 @@ struct smb_version_operations {
278 /* send rename request */ 278 /* send rename request */
279 int (*rename)(const unsigned int, struct cifs_tcon *, const char *, 279 int (*rename)(const unsigned int, struct cifs_tcon *, const char *,
280 const char *, struct cifs_sb_info *); 280 const char *, struct cifs_sb_info *);
281 /* send create hardlink request */
282 int (*create_hardlink)(const unsigned int, struct cifs_tcon *,
283 const char *, const char *,
284 struct cifs_sb_info *);
281 /* open a file for non-posix mounts */ 285 /* open a file for non-posix mounts */
282 int (*open)(const unsigned int, struct cifs_tcon *, const char *, int, 286 int (*open)(const unsigned int, struct cifs_tcon *, const char *, int,
283 int, int, struct cifs_fid *, __u32 *, FILE_ALL_INFO *, 287 int, int, struct cifs_fid *, __u32 *, FILE_ALL_INFO *,
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index eecd233c6912..3c50555c7735 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -316,11 +316,9 @@ extern int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon,
316 int netfid, const char *target_name, 316 int netfid, const char *target_name,
317 const struct nls_table *nls_codepage, 317 const struct nls_table *nls_codepage,
318 int remap_special_chars); 318 int remap_special_chars);
319extern int CIFSCreateHardLink(const unsigned int xid, 319extern int CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
320 struct cifs_tcon *tcon, 320 const char *from_name, const char *to_name,
321 const char *fromName, const char *toName, 321 struct cifs_sb_info *cifs_sb);
322 const struct nls_table *nls_codepage,
323 int remap_special_chars);
324extern int CIFSUnixCreateHardLink(const unsigned int xid, 322extern int CIFSUnixCreateHardLink(const unsigned int xid,
325 struct cifs_tcon *tcon, 323 struct cifs_tcon *tcon,
326 const char *fromName, const char *toName, 324 const char *fromName, const char *toName,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index b8cd335d6f11..eb3d2cf76e6e 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2924,8 +2924,8 @@ createHardLinkRetry:
2924 2924
2925int 2925int
2926CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon, 2926CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2927 const char *fromName, const char *toName, 2927 const char *from_name, const char *to_name,
2928 const struct nls_table *nls_codepage, int remap) 2928 struct cifs_sb_info *cifs_sb)
2929{ 2929{
2930 int rc = 0; 2930 int rc = 0;
2931 NT_RENAME_REQ *pSMB = NULL; 2931 NT_RENAME_REQ *pSMB = NULL;
@@ -2933,6 +2933,7 @@ CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2933 int bytes_returned; 2933 int bytes_returned;
2934 int name_len, name_len2; 2934 int name_len, name_len2;
2935 __u16 count; 2935 __u16 count;
2936 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
2936 2937
2937 cFYI(1, "In CIFSCreateHardLink"); 2938 cFYI(1, "In CIFSCreateHardLink");
2938winCreateHardLinkRetry: 2939winCreateHardLinkRetry:
@@ -2952,8 +2953,8 @@ winCreateHardLinkRetry:
2952 2953
2953 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2954 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2954 name_len = 2955 name_len =
2955 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName, 2956 cifsConvertToUTF16((__le16 *) pSMB->OldFileName, from_name,
2956 PATH_MAX, nls_codepage, remap); 2957 PATH_MAX, cifs_sb->local_nls, remap);
2957 name_len++; /* trailing null */ 2958 name_len++; /* trailing null */
2958 name_len *= 2; 2959 name_len *= 2;
2959 2960
@@ -2962,17 +2963,18 @@ winCreateHardLinkRetry:
2962 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */ 2963 pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
2963 name_len2 = 2964 name_len2 =
2964 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2], 2965 cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
2965 toName, PATH_MAX, nls_codepage, remap); 2966 to_name, PATH_MAX, cifs_sb->local_nls,
2967 remap);
2966 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; 2968 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
2967 name_len2 *= 2; /* convert to bytes */ 2969 name_len2 *= 2; /* convert to bytes */
2968 } else { /* BB improve the check for buffer overruns BB */ 2970 } else { /* BB improve the check for buffer overruns BB */
2969 name_len = strnlen(fromName, PATH_MAX); 2971 name_len = strnlen(from_name, PATH_MAX);
2970 name_len++; /* trailing null */ 2972 name_len++; /* trailing null */
2971 strncpy(pSMB->OldFileName, fromName, name_len); 2973 strncpy(pSMB->OldFileName, from_name, name_len);
2972 name_len2 = strnlen(toName, PATH_MAX); 2974 name_len2 = strnlen(to_name, PATH_MAX);
2973 name_len2++; /* trailing null */ 2975 name_len2++; /* trailing null */
2974 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ 2976 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
2975 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); 2977 strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
2976 name_len2++; /* trailing null */ 2978 name_len2++; /* trailing null */
2977 name_len2++; /* signature byte */ 2979 name_len2++; /* signature byte */
2978 } 2980 }
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index e6ce3b112875..51dc2fb6e854 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -391,72 +391,86 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
391{ 391{
392 int rc = -EACCES; 392 int rc = -EACCES;
393 unsigned int xid; 393 unsigned int xid;
394 char *fromName = NULL; 394 char *from_name = NULL;
395 char *toName = NULL; 395 char *to_name = NULL;
396 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 396 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
397 struct tcon_link *tlink; 397 struct tcon_link *tlink;
398 struct cifs_tcon *pTcon; 398 struct cifs_tcon *tcon;
399 struct TCP_Server_Info *server;
399 struct cifsInodeInfo *cifsInode; 400 struct cifsInodeInfo *cifsInode;
400 401
401 tlink = cifs_sb_tlink(cifs_sb); 402 tlink = cifs_sb_tlink(cifs_sb);
402 if (IS_ERR(tlink)) 403 if (IS_ERR(tlink))
403 return PTR_ERR(tlink); 404 return PTR_ERR(tlink);
404 pTcon = tlink_tcon(tlink); 405 tcon = tlink_tcon(tlink);
405 406
406 xid = get_xid(); 407 xid = get_xid();
407 408
408 fromName = build_path_from_dentry(old_file); 409 from_name = build_path_from_dentry(old_file);
409 toName = build_path_from_dentry(direntry); 410 to_name = build_path_from_dentry(direntry);
410 if ((fromName == NULL) || (toName == NULL)) { 411 if ((from_name == NULL) || (to_name == NULL)) {
411 rc = -ENOMEM; 412 rc = -ENOMEM;
412 goto cifs_hl_exit; 413 goto cifs_hl_exit;
413 } 414 }
414 415
415 if (pTcon->unix_ext) 416 if (tcon->unix_ext)
416 rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, 417 rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name,
417 cifs_sb->local_nls, 418 cifs_sb->local_nls,
418 cifs_sb->mnt_cifs_flags & 419 cifs_sb->mnt_cifs_flags &
419 CIFS_MOUNT_MAP_SPECIAL_CHR); 420 CIFS_MOUNT_MAP_SPECIAL_CHR);
420 else { 421 else {
421 rc = CIFSCreateHardLink(xid, pTcon, fromName, toName, 422 server = tcon->ses->server;
422 cifs_sb->local_nls, 423 if (!server->ops->create_hardlink)
423 cifs_sb->mnt_cifs_flags & 424 return -ENOSYS;
424 CIFS_MOUNT_MAP_SPECIAL_CHR); 425 rc = server->ops->create_hardlink(xid, tcon, from_name, to_name,
426 cifs_sb);
425 if ((rc == -EIO) || (rc == -EINVAL)) 427 if ((rc == -EIO) || (rc == -EINVAL))
426 rc = -EOPNOTSUPP; 428 rc = -EOPNOTSUPP;
427 } 429 }
428 430
429 d_drop(direntry); /* force new lookup from server of target */ 431 d_drop(direntry); /* force new lookup from server of target */
430 432
431 /* if source file is cached (oplocked) revalidate will not go to server 433 /*
432 until the file is closed or oplock broken so update nlinks locally */ 434 * if source file is cached (oplocked) revalidate will not go to server
435 * until the file is closed or oplock broken so update nlinks locally
436 */
433 if (old_file->d_inode) { 437 if (old_file->d_inode) {
434 cifsInode = CIFS_I(old_file->d_inode); 438 cifsInode = CIFS_I(old_file->d_inode);
435 if (rc == 0) { 439 if (rc == 0) {
436 spin_lock(&old_file->d_inode->i_lock); 440 spin_lock(&old_file->d_inode->i_lock);
437 inc_nlink(old_file->d_inode); 441 inc_nlink(old_file->d_inode);
438 spin_unlock(&old_file->d_inode->i_lock); 442 spin_unlock(&old_file->d_inode->i_lock);
439/* BB should we make this contingent on superblock flag NOATIME? */ 443 /*
440/* old_file->d_inode->i_ctime = CURRENT_TIME;*/ 444 * BB should we make this contingent on superblock flag
441 /* parent dir timestamps will update from srv 445 * NOATIME?
442 within a second, would it really be worth it 446 */
443 to set the parent dir cifs inode time to zero 447 /* old_file->d_inode->i_ctime = CURRENT_TIME; */
444 to force revalidate (faster) for it too? */ 448 /*
449 * parent dir timestamps will update from srv within a
450 * second, would it really be worth it to set the parent
451 * dir cifs inode time to zero to force revalidate
452 * (faster) for it too?
453 */
445 } 454 }
446 /* if not oplocked will force revalidate to get info 455 /*
447 on source file from srv */ 456 * if not oplocked will force revalidate to get info on source
457 * file from srv
458 */
448 cifsInode->time = 0; 459 cifsInode->time = 0;
449 460
450 /* Will update parent dir timestamps from srv within a second. 461 /*
451 Would it really be worth it to set the parent dir (cifs 462 * Will update parent dir timestamps from srv within a second.
452 inode) time field to zero to force revalidate on parent 463 * Would it really be worth it to set the parent dir (cifs
453 directory faster ie 464 * inode) time field to zero to force revalidate on parent
454 CIFS_I(inode)->time = 0; */ 465 * directory faster ie
466 *
467 * CIFS_I(inode)->time = 0;
468 */
455 } 469 }
456 470
457cifs_hl_exit: 471cifs_hl_exit:
458 kfree(fromName); 472 kfree(from_name);
459 kfree(toName); 473 kfree(to_name);
460 free_xid(xid); 474 free_xid(xid);
461 cifs_put_tlink(tlink); 475 cifs_put_tlink(tlink);
462 return rc; 476 return rc;
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 377392003655..e5d63444f0ff 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -801,6 +801,7 @@ struct smb_version_operations smb1_operations = {
801 .unlink = CIFSSMBDelFile, 801 .unlink = CIFSSMBDelFile,
802 .rename_pending_delete = cifs_rename_pending_delete, 802 .rename_pending_delete = cifs_rename_pending_delete,
803 .rename = CIFSSMBRename, 803 .rename = CIFSSMBRename,
804 .create_hardlink = CIFSCreateHardLink,
804 .open = cifs_open_file, 805 .open = cifs_open_file,
805 .set_fid = cifs_set_fid, 806 .set_fid = cifs_set_fid,
806 .close = cifs_close_file, 807 .close = cifs_close_file,