diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /fs/cifs/link.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'fs/cifs/link.c')
-rw-r--r-- | fs/cifs/link.c | 139 |
1 files changed, 58 insertions, 81 deletions
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 51dc2fb6e85..db3f18cdf02 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -56,14 +56,14 @@ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash) | |||
56 | md5 = crypto_alloc_shash("md5", 0, 0); | 56 | md5 = crypto_alloc_shash("md5", 0, 0); |
57 | if (IS_ERR(md5)) { | 57 | if (IS_ERR(md5)) { |
58 | rc = PTR_ERR(md5); | 58 | rc = PTR_ERR(md5); |
59 | cERROR(1, "%s: Crypto md5 allocation error %d", __func__, rc); | 59 | cERROR(1, "%s: Crypto md5 allocation error %d\n", __func__, rc); |
60 | return rc; | 60 | return rc; |
61 | } | 61 | } |
62 | size = sizeof(struct shash_desc) + crypto_shash_descsize(md5); | 62 | size = sizeof(struct shash_desc) + crypto_shash_descsize(md5); |
63 | sdescmd5 = kmalloc(size, GFP_KERNEL); | 63 | sdescmd5 = kmalloc(size, GFP_KERNEL); |
64 | if (!sdescmd5) { | 64 | if (!sdescmd5) { |
65 | rc = -ENOMEM; | 65 | rc = -ENOMEM; |
66 | cERROR(1, "%s: Memory allocation failure", __func__); | 66 | cERROR(1, "%s: Memory allocation failure\n", __func__); |
67 | goto symlink_hash_err; | 67 | goto symlink_hash_err; |
68 | } | 68 | } |
69 | sdescmd5->shash.tfm = md5; | 69 | sdescmd5->shash.tfm = md5; |
@@ -71,17 +71,17 @@ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash) | |||
71 | 71 | ||
72 | rc = crypto_shash_init(&sdescmd5->shash); | 72 | rc = crypto_shash_init(&sdescmd5->shash); |
73 | if (rc) { | 73 | if (rc) { |
74 | cERROR(1, "%s: Could not init md5 shash", __func__); | 74 | cERROR(1, "%s: Could not init md5 shash\n", __func__); |
75 | goto symlink_hash_err; | 75 | goto symlink_hash_err; |
76 | } | 76 | } |
77 | rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len); | 77 | rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len); |
78 | if (rc) { | 78 | if (rc) { |
79 | cERROR(1, "%s: Could not update iwth link_str", __func__); | 79 | cERROR(1, "%s: Could not update iwth link_str\n", __func__); |
80 | goto symlink_hash_err; | 80 | goto symlink_hash_err; |
81 | } | 81 | } |
82 | rc = crypto_shash_final(&sdescmd5->shash, md5_hash); | 82 | rc = crypto_shash_final(&sdescmd5->shash, md5_hash); |
83 | if (rc) | 83 | if (rc) |
84 | cERROR(1, "%s: Could not generate md5 hash", __func__); | 84 | cERROR(1, "%s: Could not generate md5 hash\n", __func__); |
85 | 85 | ||
86 | symlink_hash_err: | 86 | symlink_hash_err: |
87 | crypto_free_shash(md5); | 87 | crypto_free_shash(md5); |
@@ -115,7 +115,7 @@ CIFSParseMFSymlink(const u8 *buf, | |||
115 | 115 | ||
116 | rc = symlink_hash(link_len, link_str, md5_hash); | 116 | rc = symlink_hash(link_len, link_str, md5_hash); |
117 | if (rc) { | 117 | if (rc) { |
118 | cFYI(1, "%s: MD5 hash failure: %d", __func__, rc); | 118 | cFYI(1, "%s: MD5 hash failure: %d\n", __func__, rc); |
119 | return rc; | 119 | return rc; |
120 | } | 120 | } |
121 | 121 | ||
@@ -154,7 +154,7 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) | |||
154 | 154 | ||
155 | rc = symlink_hash(link_len, link_str, md5_hash); | 155 | rc = symlink_hash(link_len, link_str, md5_hash); |
156 | if (rc) { | 156 | if (rc) { |
157 | cFYI(1, "%s: MD5 hash failure: %d", __func__, rc); | 157 | cFYI(1, "%s: MD5 hash failure: %d\n", __func__, rc); |
158 | return rc; | 158 | return rc; |
159 | } | 159 | } |
160 | 160 | ||
@@ -181,22 +181,16 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) | |||
181 | } | 181 | } |
182 | 182 | ||
183 | static int | 183 | static int |
184 | CIFSCreateMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, | 184 | CIFSCreateMFSymLink(const int xid, struct cifs_tcon *tcon, |
185 | const char *fromName, const char *toName, | 185 | const char *fromName, const char *toName, |
186 | struct cifs_sb_info *cifs_sb) | 186 | const struct nls_table *nls_codepage, int remap) |
187 | { | 187 | { |
188 | int rc; | 188 | int rc; |
189 | int oplock = 0; | 189 | int oplock = 0; |
190 | int remap; | ||
191 | int create_options = CREATE_NOT_DIR; | ||
192 | __u16 netfid = 0; | 190 | __u16 netfid = 0; |
193 | u8 *buf; | 191 | u8 *buf; |
194 | unsigned int bytes_written = 0; | 192 | unsigned int bytes_written = 0; |
195 | struct cifs_io_parms io_parms; | 193 | struct cifs_io_parms io_parms; |
196 | struct nls_table *nls_codepage; | ||
197 | |||
198 | nls_codepage = cifs_sb->local_nls; | ||
199 | remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | ||
200 | 194 | ||
201 | buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); | 195 | buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); |
202 | if (!buf) | 196 | if (!buf) |
@@ -208,11 +202,8 @@ CIFSCreateMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, | |||
208 | return rc; | 202 | return rc; |
209 | } | 203 | } |
210 | 204 | ||
211 | if (backup_cred(cifs_sb)) | ||
212 | create_options |= CREATE_OPEN_BACKUP_INTENT; | ||
213 | |||
214 | rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE, | 205 | rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE, |
215 | create_options, &netfid, &oplock, NULL, | 206 | CREATE_NOT_DIR, &netfid, &oplock, NULL, |
216 | nls_codepage, remap); | 207 | nls_codepage, remap); |
217 | if (rc != 0) { | 208 | if (rc != 0) { |
218 | kfree(buf); | 209 | kfree(buf); |
@@ -238,7 +229,7 @@ CIFSCreateMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, | |||
238 | } | 229 | } |
239 | 230 | ||
240 | static int | 231 | static int |
241 | CIFSQueryMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, | 232 | CIFSQueryMFSymLink(const int xid, struct cifs_tcon *tcon, |
242 | const unsigned char *searchName, char **symlinkinfo, | 233 | const unsigned char *searchName, char **symlinkinfo, |
243 | const struct nls_table *nls_codepage, int remap) | 234 | const struct nls_table *nls_codepage, int remap) |
244 | { | 235 | { |
@@ -307,7 +298,7 @@ CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr) | |||
307 | int | 298 | int |
308 | CIFSCheckMFSymlink(struct cifs_fattr *fattr, | 299 | CIFSCheckMFSymlink(struct cifs_fattr *fattr, |
309 | const unsigned char *path, | 300 | const unsigned char *path, |
310 | struct cifs_sb_info *cifs_sb, unsigned int xid) | 301 | struct cifs_sb_info *cifs_sb, int xid) |
311 | { | 302 | { |
312 | int rc; | 303 | int rc; |
313 | int oplock = 0; | 304 | int oplock = 0; |
@@ -390,88 +381,72 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, | |||
390 | struct dentry *direntry) | 381 | struct dentry *direntry) |
391 | { | 382 | { |
392 | int rc = -EACCES; | 383 | int rc = -EACCES; |
393 | unsigned int xid; | 384 | int xid; |
394 | char *from_name = NULL; | 385 | char *fromName = NULL; |
395 | char *to_name = NULL; | 386 | char *toName = NULL; |
396 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 387 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
397 | struct tcon_link *tlink; | 388 | struct tcon_link *tlink; |
398 | struct cifs_tcon *tcon; | 389 | struct cifs_tcon *pTcon; |
399 | struct TCP_Server_Info *server; | ||
400 | struct cifsInodeInfo *cifsInode; | 390 | struct cifsInodeInfo *cifsInode; |
401 | 391 | ||
402 | tlink = cifs_sb_tlink(cifs_sb); | 392 | tlink = cifs_sb_tlink(cifs_sb); |
403 | if (IS_ERR(tlink)) | 393 | if (IS_ERR(tlink)) |
404 | return PTR_ERR(tlink); | 394 | return PTR_ERR(tlink); |
405 | tcon = tlink_tcon(tlink); | 395 | pTcon = tlink_tcon(tlink); |
406 | 396 | ||
407 | xid = get_xid(); | 397 | xid = GetXid(); |
408 | 398 | ||
409 | from_name = build_path_from_dentry(old_file); | 399 | fromName = build_path_from_dentry(old_file); |
410 | to_name = build_path_from_dentry(direntry); | 400 | toName = build_path_from_dentry(direntry); |
411 | if ((from_name == NULL) || (to_name == NULL)) { | 401 | if ((fromName == NULL) || (toName == NULL)) { |
412 | rc = -ENOMEM; | 402 | rc = -ENOMEM; |
413 | goto cifs_hl_exit; | 403 | goto cifs_hl_exit; |
414 | } | 404 | } |
415 | 405 | ||
416 | if (tcon->unix_ext) | 406 | if (pTcon->unix_ext) |
417 | rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name, | 407 | rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, |
418 | cifs_sb->local_nls, | 408 | cifs_sb->local_nls, |
419 | cifs_sb->mnt_cifs_flags & | 409 | cifs_sb->mnt_cifs_flags & |
420 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 410 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
421 | else { | 411 | else { |
422 | server = tcon->ses->server; | 412 | rc = CIFSCreateHardLink(xid, pTcon, fromName, toName, |
423 | if (!server->ops->create_hardlink) | 413 | cifs_sb->local_nls, |
424 | return -ENOSYS; | 414 | cifs_sb->mnt_cifs_flags & |
425 | rc = server->ops->create_hardlink(xid, tcon, from_name, to_name, | 415 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
426 | cifs_sb); | ||
427 | if ((rc == -EIO) || (rc == -EINVAL)) | 416 | if ((rc == -EIO) || (rc == -EINVAL)) |
428 | rc = -EOPNOTSUPP; | 417 | rc = -EOPNOTSUPP; |
429 | } | 418 | } |
430 | 419 | ||
431 | d_drop(direntry); /* force new lookup from server of target */ | 420 | d_drop(direntry); /* force new lookup from server of target */ |
432 | 421 | ||
433 | /* | 422 | /* if source file is cached (oplocked) revalidate will not go to server |
434 | * if source file is cached (oplocked) revalidate will not go to server | 423 | until the file is closed or oplock broken so update nlinks locally */ |
435 | * until the file is closed or oplock broken so update nlinks locally | ||
436 | */ | ||
437 | if (old_file->d_inode) { | 424 | if (old_file->d_inode) { |
438 | cifsInode = CIFS_I(old_file->d_inode); | 425 | cifsInode = CIFS_I(old_file->d_inode); |
439 | if (rc == 0) { | 426 | if (rc == 0) { |
440 | spin_lock(&old_file->d_inode->i_lock); | 427 | old_file->d_inode->i_nlink++; |
441 | inc_nlink(old_file->d_inode); | 428 | /* BB should we make this contingent on superblock flag NOATIME? */ |
442 | spin_unlock(&old_file->d_inode->i_lock); | 429 | /* old_file->d_inode->i_ctime = CURRENT_TIME;*/ |
443 | /* | 430 | /* parent dir timestamps will update from srv |
444 | * BB should we make this contingent on superblock flag | 431 | within a second, would it really be worth it |
445 | * NOATIME? | 432 | to set the parent dir cifs inode time to zero |
446 | */ | 433 | to force revalidate (faster) for it too? */ |
447 | /* old_file->d_inode->i_ctime = CURRENT_TIME; */ | ||
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 | */ | ||
454 | } | 434 | } |
455 | /* | 435 | /* if not oplocked will force revalidate to get info |
456 | * if not oplocked will force revalidate to get info on source | 436 | on source file from srv */ |
457 | * file from srv | ||
458 | */ | ||
459 | cifsInode->time = 0; | 437 | cifsInode->time = 0; |
460 | 438 | ||
461 | /* | 439 | /* Will update parent dir timestamps from srv within a second. |
462 | * Will update parent dir timestamps from srv within a second. | 440 | Would it really be worth it to set the parent dir (cifs |
463 | * Would it really be worth it to set the parent dir (cifs | 441 | inode) time field to zero to force revalidate on parent |
464 | * inode) time field to zero to force revalidate on parent | 442 | directory faster ie |
465 | * directory faster ie | 443 | CIFS_I(inode)->time = 0; */ |
466 | * | ||
467 | * CIFS_I(inode)->time = 0; | ||
468 | */ | ||
469 | } | 444 | } |
470 | 445 | ||
471 | cifs_hl_exit: | 446 | cifs_hl_exit: |
472 | kfree(from_name); | 447 | kfree(fromName); |
473 | kfree(to_name); | 448 | kfree(toName); |
474 | free_xid(xid); | 449 | FreeXid(xid); |
475 | cifs_put_tlink(tlink); | 450 | cifs_put_tlink(tlink); |
476 | return rc; | 451 | return rc; |
477 | } | 452 | } |
@@ -481,14 +456,14 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) | |||
481 | { | 456 | { |
482 | struct inode *inode = direntry->d_inode; | 457 | struct inode *inode = direntry->d_inode; |
483 | int rc = -ENOMEM; | 458 | int rc = -ENOMEM; |
484 | unsigned int xid; | 459 | int xid; |
485 | char *full_path = NULL; | 460 | char *full_path = NULL; |
486 | char *target_path = NULL; | 461 | char *target_path = NULL; |
487 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 462 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
488 | struct tcon_link *tlink = NULL; | 463 | struct tcon_link *tlink = NULL; |
489 | struct cifs_tcon *tcon; | 464 | struct cifs_tcon *tcon; |
490 | 465 | ||
491 | xid = get_xid(); | 466 | xid = GetXid(); |
492 | 467 | ||
493 | tlink = cifs_sb_tlink(cifs_sb); | 468 | tlink = cifs_sb_tlink(cifs_sb); |
494 | if (IS_ERR(tlink)) { | 469 | if (IS_ERR(tlink)) { |
@@ -511,8 +486,8 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) | |||
511 | * but there doesn't seem to be any harm in allowing the client to | 486 | * but there doesn't seem to be any harm in allowing the client to |
512 | * read them. | 487 | * read them. |
513 | */ | 488 | */ |
514 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) && | 489 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) |
515 | !cap_unix(tcon->ses)) { | 490 | && !(tcon->ses->capabilities & CAP_UNIX)) { |
516 | rc = -EACCES; | 491 | rc = -EACCES; |
517 | goto out; | 492 | goto out; |
518 | } | 493 | } |
@@ -534,7 +509,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) | |||
534 | cifs_sb->mnt_cifs_flags & | 509 | cifs_sb->mnt_cifs_flags & |
535 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 510 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
536 | 511 | ||
537 | if ((rc != 0) && cap_unix(tcon->ses)) | 512 | if ((rc != 0) && (tcon->ses->capabilities & CAP_UNIX)) |
538 | rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path, | 513 | rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path, |
539 | cifs_sb->local_nls); | 514 | cifs_sb->local_nls); |
540 | 515 | ||
@@ -545,7 +520,7 @@ out: | |||
545 | target_path = ERR_PTR(rc); | 520 | target_path = ERR_PTR(rc); |
546 | } | 521 | } |
547 | 522 | ||
548 | free_xid(xid); | 523 | FreeXid(xid); |
549 | if (tlink) | 524 | if (tlink) |
550 | cifs_put_tlink(tlink); | 525 | cifs_put_tlink(tlink); |
551 | nd_set_link(nd, target_path); | 526 | nd_set_link(nd, target_path); |
@@ -556,14 +531,14 @@ int | |||
556 | cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) | 531 | cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) |
557 | { | 532 | { |
558 | int rc = -EOPNOTSUPP; | 533 | int rc = -EOPNOTSUPP; |
559 | unsigned int xid; | 534 | int xid; |
560 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 535 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
561 | struct tcon_link *tlink; | 536 | struct tcon_link *tlink; |
562 | struct cifs_tcon *pTcon; | 537 | struct cifs_tcon *pTcon; |
563 | char *full_path = NULL; | 538 | char *full_path = NULL; |
564 | struct inode *newinode = NULL; | 539 | struct inode *newinode = NULL; |
565 | 540 | ||
566 | xid = get_xid(); | 541 | xid = GetXid(); |
567 | 542 | ||
568 | tlink = cifs_sb_tlink(cifs_sb); | 543 | tlink = cifs_sb_tlink(cifs_sb); |
569 | if (IS_ERR(tlink)) { | 544 | if (IS_ERR(tlink)) { |
@@ -584,7 +559,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) | |||
584 | /* BB what if DFS and this volume is on different share? BB */ | 559 | /* BB what if DFS and this volume is on different share? BB */ |
585 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) | 560 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) |
586 | rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname, | 561 | rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname, |
587 | cifs_sb); | 562 | cifs_sb->local_nls, |
563 | cifs_sb->mnt_cifs_flags & | ||
564 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
588 | else if (pTcon->unix_ext) | 565 | else if (pTcon->unix_ext) |
589 | rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, | 566 | rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, |
590 | cifs_sb->local_nls); | 567 | cifs_sb->local_nls); |
@@ -610,7 +587,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) | |||
610 | symlink_exit: | 587 | symlink_exit: |
611 | kfree(full_path); | 588 | kfree(full_path); |
612 | cifs_put_tlink(tlink); | 589 | cifs_put_tlink(tlink); |
613 | free_xid(xid); | 590 | FreeXid(xid); |
614 | return rc; | 591 | return rc; |
615 | } | 592 | } |
616 | 593 | ||