.. | .. |
---|
31 | 31 | #include "nterr.h" |
---|
32 | 32 | #include "cifs_unicode.h" |
---|
33 | 33 | #include "smb2pdu.h" |
---|
| 34 | +#include "cifsfs.h" |
---|
| 35 | +#ifdef CONFIG_CIFS_DFS_UPCALL |
---|
| 36 | +#include "dns_resolve.h" |
---|
| 37 | +#endif |
---|
34 | 38 | |
---|
35 | 39 | extern mempool_t *cifs_sm_req_poolp; |
---|
36 | 40 | extern mempool_t *cifs_req_poolp; |
---|
.. | .. |
---|
99 | 103 | kfree(buf_to_free->serverOS); |
---|
100 | 104 | kfree(buf_to_free->serverDomain); |
---|
101 | 105 | kfree(buf_to_free->serverNOS); |
---|
102 | | - kzfree(buf_to_free->password); |
---|
| 106 | + kfree_sensitive(buf_to_free->password); |
---|
103 | 107 | kfree(buf_to_free->user_name); |
---|
104 | 108 | kfree(buf_to_free->domainName); |
---|
105 | | - kzfree(buf_to_free->auth_key.response); |
---|
| 109 | + kfree_sensitive(buf_to_free->auth_key.response); |
---|
106 | 110 | kfree(buf_to_free->iface_list); |
---|
107 | | - kzfree(buf_to_free); |
---|
| 111 | + kfree_sensitive(buf_to_free); |
---|
108 | 112 | } |
---|
109 | 113 | |
---|
110 | 114 | struct cifs_tcon * |
---|
111 | 115 | tconInfoAlloc(void) |
---|
112 | 116 | { |
---|
113 | 117 | struct cifs_tcon *ret_buf; |
---|
114 | | - ret_buf = kzalloc(sizeof(struct cifs_tcon), GFP_KERNEL); |
---|
115 | | - if (ret_buf) { |
---|
116 | | - atomic_inc(&tconInfoAllocCount); |
---|
117 | | - ret_buf->tidStatus = CifsNew; |
---|
118 | | - ++ret_buf->tc_count; |
---|
119 | | - INIT_LIST_HEAD(&ret_buf->openFileList); |
---|
120 | | - INIT_LIST_HEAD(&ret_buf->tcon_list); |
---|
121 | | - spin_lock_init(&ret_buf->open_file_lock); |
---|
122 | | - mutex_init(&ret_buf->crfid.fid_mutex); |
---|
123 | | - ret_buf->crfid.fid = kzalloc(sizeof(struct cifs_fid), |
---|
124 | | - GFP_KERNEL); |
---|
125 | | - spin_lock_init(&ret_buf->stat_lock); |
---|
| 118 | + |
---|
| 119 | + ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL); |
---|
| 120 | + if (!ret_buf) |
---|
| 121 | + return NULL; |
---|
| 122 | + ret_buf->crfid.fid = kzalloc(sizeof(*ret_buf->crfid.fid), GFP_KERNEL); |
---|
| 123 | + if (!ret_buf->crfid.fid) { |
---|
| 124 | + kfree(ret_buf); |
---|
| 125 | + return NULL; |
---|
126 | 126 | } |
---|
| 127 | + |
---|
| 128 | + atomic_inc(&tconInfoAllocCount); |
---|
| 129 | + ret_buf->tidStatus = CifsNew; |
---|
| 130 | + ++ret_buf->tc_count; |
---|
| 131 | + INIT_LIST_HEAD(&ret_buf->openFileList); |
---|
| 132 | + INIT_LIST_HEAD(&ret_buf->tcon_list); |
---|
| 133 | + spin_lock_init(&ret_buf->open_file_lock); |
---|
| 134 | + mutex_init(&ret_buf->crfid.fid_mutex); |
---|
| 135 | + spin_lock_init(&ret_buf->stat_lock); |
---|
| 136 | + atomic_set(&ret_buf->num_local_opens, 0); |
---|
| 137 | + atomic_set(&ret_buf->num_remote_opens, 0); |
---|
| 138 | + |
---|
127 | 139 | return ret_buf; |
---|
128 | 140 | } |
---|
129 | 141 | |
---|
.. | .. |
---|
136 | 148 | } |
---|
137 | 149 | atomic_dec(&tconInfoAllocCount); |
---|
138 | 150 | kfree(buf_to_free->nativeFileSystem); |
---|
139 | | - kzfree(buf_to_free->password); |
---|
| 151 | + kfree_sensitive(buf_to_free->password); |
---|
140 | 152 | kfree(buf_to_free->crfid.fid); |
---|
| 153 | +#ifdef CONFIG_CIFS_DFS_UPCALL |
---|
| 154 | + kfree(buf_to_free->dfs_path); |
---|
| 155 | +#endif |
---|
141 | 156 | kfree(buf_to_free); |
---|
142 | 157 | } |
---|
143 | 158 | |
---|
.. | .. |
---|
409 | 424 | |
---|
410 | 425 | if (data_offset > |
---|
411 | 426 | len - sizeof(struct file_notify_information)) { |
---|
412 | | - cifs_dbg(FYI, "invalid data_offset %u\n", |
---|
| 427 | + cifs_dbg(FYI, "Invalid data_offset %u\n", |
---|
413 | 428 | data_offset); |
---|
414 | 429 | return true; |
---|
415 | 430 | } |
---|
.. | .. |
---|
437 | 452 | large dirty files cached on the client */ |
---|
438 | 453 | if ((NT_STATUS_INVALID_HANDLE) == |
---|
439 | 454 | le32_to_cpu(pSMB->hdr.Status.CifsError)) { |
---|
440 | | - cifs_dbg(FYI, "invalid handle on oplock break\n"); |
---|
| 455 | + cifs_dbg(FYI, "Invalid handle on oplock break\n"); |
---|
441 | 456 | return true; |
---|
442 | 457 | } else if (ERRbadfid == |
---|
443 | 458 | le16_to_cpu(pSMB->hdr.Status.DosError.Error)) { |
---|
.. | .. |
---|
511 | 526 | cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) |
---|
512 | 527 | { |
---|
513 | 528 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
---|
| 529 | + struct cifs_tcon *tcon = NULL; |
---|
| 530 | + |
---|
| 531 | + if (cifs_sb->master_tlink) |
---|
| 532 | + tcon = cifs_sb_master_tcon(cifs_sb); |
---|
| 533 | + |
---|
514 | 534 | cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; |
---|
515 | 535 | cifs_sb->mnt_cifs_serverino_autodisabled = true; |
---|
516 | | - cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s. This server doesn't seem to support them properly. Hardlinks will not be recognized on this mount. Consider mounting with the \"noserverino\" option to silence this message.\n", |
---|
517 | | - cifs_sb_master_tcon(cifs_sb)->treeName); |
---|
| 536 | + cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s\n", |
---|
| 537 | + tcon ? tcon->treeName : "new server"); |
---|
| 538 | + cifs_dbg(VFS, "The server doesn't seem to support them properly or the files might be on different servers (DFS)\n"); |
---|
| 539 | + cifs_dbg(VFS, "Hardlinks will not be recognized on this mount. Consider mounting with the \"noserverino\" option to silence this message.\n"); |
---|
| 540 | + |
---|
518 | 541 | } |
---|
519 | 542 | } |
---|
520 | 543 | |
---|
.. | .. |
---|
741 | 764 | goto parse_DFS_referrals_exit; |
---|
742 | 765 | } |
---|
743 | 766 | |
---|
| 767 | + node->ttl = le32_to_cpu(ref->TimeToLive); |
---|
| 768 | + |
---|
744 | 769 | ref++; |
---|
745 | 770 | } |
---|
746 | 771 | |
---|
.. | .. |
---|
758 | 783 | { |
---|
759 | 784 | struct cifs_aio_ctx *ctx; |
---|
760 | 785 | |
---|
| 786 | + /* |
---|
| 787 | + * Must use kzalloc to initialize ctx->bv to NULL and ctx->direct_io |
---|
| 788 | + * to false so that we know when we have to unreference pages within |
---|
| 789 | + * cifs_aio_ctx_release() |
---|
| 790 | + */ |
---|
761 | 791 | ctx = kzalloc(sizeof(struct cifs_aio_ctx), GFP_KERNEL); |
---|
762 | 792 | if (!ctx) |
---|
763 | 793 | return NULL; |
---|
.. | .. |
---|
776 | 806 | struct cifs_aio_ctx, refcount); |
---|
777 | 807 | |
---|
778 | 808 | cifsFileInfo_put(ctx->cfile); |
---|
779 | | - kvfree(ctx->bv); |
---|
| 809 | + |
---|
| 810 | + /* |
---|
| 811 | + * ctx->bv is only set if setup_aio_ctx_iter() was call successfuly |
---|
| 812 | + * which means that iov_iter_get_pages() was a success and thus that |
---|
| 813 | + * we have taken reference on pages. |
---|
| 814 | + */ |
---|
| 815 | + if (ctx->bv) { |
---|
| 816 | + unsigned i; |
---|
| 817 | + |
---|
| 818 | + for (i = 0; i < ctx->npages; i++) { |
---|
| 819 | + if (ctx->should_dirty) |
---|
| 820 | + set_page_dirty(ctx->bv[i].bv_page); |
---|
| 821 | + put_page(ctx->bv[i].bv_page); |
---|
| 822 | + } |
---|
| 823 | + kvfree(ctx->bv); |
---|
| 824 | + } |
---|
| 825 | + |
---|
780 | 826 | kfree(ctx); |
---|
781 | 827 | } |
---|
782 | 828 | |
---|
.. | .. |
---|
797 | 843 | struct page **pages = NULL; |
---|
798 | 844 | struct bio_vec *bv = NULL; |
---|
799 | 845 | |
---|
800 | | - if (iter->type & ITER_KVEC) { |
---|
801 | | - memcpy(&ctx->iter, iter, sizeof(struct iov_iter)); |
---|
| 846 | + if (iov_iter_is_kvec(iter)) { |
---|
| 847 | + memcpy(&ctx->iter, iter, sizeof(*iter)); |
---|
802 | 848 | ctx->len = count; |
---|
803 | 849 | iov_iter_advance(iter, count); |
---|
804 | 850 | return 0; |
---|
805 | 851 | } |
---|
806 | 852 | |
---|
807 | | - if (max_pages * sizeof(struct bio_vec) <= CIFS_AIO_KMALLOC_LIMIT) |
---|
808 | | - bv = kmalloc_array(max_pages, sizeof(struct bio_vec), |
---|
809 | | - GFP_KERNEL); |
---|
| 853 | + if (array_size(max_pages, sizeof(*bv)) <= CIFS_AIO_KMALLOC_LIMIT) |
---|
| 854 | + bv = kmalloc_array(max_pages, sizeof(*bv), GFP_KERNEL); |
---|
810 | 855 | |
---|
811 | 856 | if (!bv) { |
---|
812 | | - bv = vmalloc(array_size(max_pages, sizeof(struct bio_vec))); |
---|
| 857 | + bv = vmalloc(array_size(max_pages, sizeof(*bv))); |
---|
813 | 858 | if (!bv) |
---|
814 | 859 | return -ENOMEM; |
---|
815 | 860 | } |
---|
816 | 861 | |
---|
817 | | - if (max_pages * sizeof(struct page *) <= CIFS_AIO_KMALLOC_LIMIT) |
---|
818 | | - pages = kmalloc_array(max_pages, sizeof(struct page *), |
---|
819 | | - GFP_KERNEL); |
---|
| 862 | + if (array_size(max_pages, sizeof(*pages)) <= CIFS_AIO_KMALLOC_LIMIT) |
---|
| 863 | + pages = kmalloc_array(max_pages, sizeof(*pages), GFP_KERNEL); |
---|
820 | 864 | |
---|
821 | 865 | if (!pages) { |
---|
822 | | - pages = vmalloc(array_size(max_pages, sizeof(struct page *))); |
---|
| 866 | + pages = vmalloc(array_size(max_pages, sizeof(*pages))); |
---|
823 | 867 | if (!pages) { |
---|
824 | 868 | kvfree(bv); |
---|
825 | 869 | return -ENOMEM; |
---|
.. | .. |
---|
831 | 875 | while (count && npages < max_pages) { |
---|
832 | 876 | rc = iov_iter_get_pages(iter, pages, count, max_pages, &start); |
---|
833 | 877 | if (rc < 0) { |
---|
834 | | - cifs_dbg(VFS, "couldn't get user pages (rc=%zd)\n", rc); |
---|
| 878 | + cifs_dbg(VFS, "Couldn't get user pages (rc=%zd)\n", rc); |
---|
835 | 879 | break; |
---|
836 | 880 | } |
---|
837 | 881 | |
---|
.. | .. |
---|
868 | 912 | ctx->bv = bv; |
---|
869 | 913 | ctx->len = saved_len - count; |
---|
870 | 914 | ctx->npages = npages; |
---|
871 | | - iov_iter_bvec(&ctx->iter, ITER_BVEC | rw, ctx->bv, npages, ctx->len); |
---|
| 915 | + iov_iter_bvec(&ctx->iter, rw, ctx->bv, npages, ctx->len); |
---|
872 | 916 | return 0; |
---|
873 | 917 | } |
---|
874 | 918 | |
---|
.. | .. |
---|
890 | 934 | |
---|
891 | 935 | *shash = crypto_alloc_shash(name, 0, 0); |
---|
892 | 936 | if (IS_ERR(*shash)) { |
---|
893 | | - cifs_dbg(VFS, "could not allocate crypto %s\n", name); |
---|
| 937 | + cifs_dbg(VFS, "Could not allocate crypto %s\n", name); |
---|
894 | 938 | rc = PTR_ERR(*shash); |
---|
895 | 939 | *shash = NULL; |
---|
896 | 940 | *sdesc = NULL; |
---|
.. | .. |
---|
907 | 951 | } |
---|
908 | 952 | |
---|
909 | 953 | (*sdesc)->shash.tfm = *shash; |
---|
910 | | - (*sdesc)->shash.flags = 0x0; |
---|
911 | 954 | return 0; |
---|
912 | 955 | } |
---|
913 | 956 | |
---|
.. | .. |
---|
931 | 974 | * Input: rqst - a smb_rqst, page - a page index for rqst |
---|
932 | 975 | * Output: *len - the length for this page, *offset - the offset for this page |
---|
933 | 976 | */ |
---|
934 | | -void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page, |
---|
935 | | - unsigned int *len, unsigned int *offset) |
---|
| 977 | +void rqst_page_get_length(const struct smb_rqst *rqst, unsigned int page, |
---|
| 978 | + unsigned int *len, unsigned int *offset) |
---|
936 | 979 | { |
---|
937 | 980 | *len = rqst->rq_pagesz; |
---|
938 | 981 | *offset = (page == 0) ? rqst->rq_offset : 0; |
---|
.. | .. |
---|
942 | 985 | else if (page == 0) |
---|
943 | 986 | *len = rqst->rq_pagesz - rqst->rq_offset; |
---|
944 | 987 | } |
---|
| 988 | + |
---|
| 989 | +void extract_unc_hostname(const char *unc, const char **h, size_t *len) |
---|
| 990 | +{ |
---|
| 991 | + const char *end; |
---|
| 992 | + |
---|
| 993 | + /* skip initial slashes */ |
---|
| 994 | + while (*unc && (*unc == '\\' || *unc == '/')) |
---|
| 995 | + unc++; |
---|
| 996 | + |
---|
| 997 | + end = unc; |
---|
| 998 | + |
---|
| 999 | + while (*end && !(*end == '\\' || *end == '/')) |
---|
| 1000 | + end++; |
---|
| 1001 | + |
---|
| 1002 | + *h = unc; |
---|
| 1003 | + *len = end - unc; |
---|
| 1004 | +} |
---|
| 1005 | + |
---|
| 1006 | +/** |
---|
| 1007 | + * copy_path_name - copy src path to dst, possibly truncating |
---|
| 1008 | + * |
---|
| 1009 | + * returns number of bytes written (including trailing nul) |
---|
| 1010 | + */ |
---|
| 1011 | +int copy_path_name(char *dst, const char *src) |
---|
| 1012 | +{ |
---|
| 1013 | + int name_len; |
---|
| 1014 | + |
---|
| 1015 | + /* |
---|
| 1016 | + * PATH_MAX includes nul, so if strlen(src) >= PATH_MAX it |
---|
| 1017 | + * will truncate and strlen(dst) will be PATH_MAX-1 |
---|
| 1018 | + */ |
---|
| 1019 | + name_len = strscpy(dst, src, PATH_MAX); |
---|
| 1020 | + if (WARN_ON_ONCE(name_len < 0)) |
---|
| 1021 | + name_len = PATH_MAX-1; |
---|
| 1022 | + |
---|
| 1023 | + /* we count the trailing nul */ |
---|
| 1024 | + name_len++; |
---|
| 1025 | + return name_len; |
---|
| 1026 | +} |
---|
| 1027 | + |
---|
| 1028 | +struct super_cb_data { |
---|
| 1029 | + void *data; |
---|
| 1030 | + struct super_block *sb; |
---|
| 1031 | +}; |
---|
| 1032 | + |
---|
| 1033 | +static void tcp_super_cb(struct super_block *sb, void *arg) |
---|
| 1034 | +{ |
---|
| 1035 | + struct super_cb_data *sd = arg; |
---|
| 1036 | + struct TCP_Server_Info *server = sd->data; |
---|
| 1037 | + struct cifs_sb_info *cifs_sb; |
---|
| 1038 | + struct cifs_tcon *tcon; |
---|
| 1039 | + |
---|
| 1040 | + if (sd->sb) |
---|
| 1041 | + return; |
---|
| 1042 | + |
---|
| 1043 | + cifs_sb = CIFS_SB(sb); |
---|
| 1044 | + tcon = cifs_sb_master_tcon(cifs_sb); |
---|
| 1045 | + if (tcon->ses->server == server) |
---|
| 1046 | + sd->sb = sb; |
---|
| 1047 | +} |
---|
| 1048 | + |
---|
| 1049 | +static struct super_block *__cifs_get_super(void (*f)(struct super_block *, void *), |
---|
| 1050 | + void *data) |
---|
| 1051 | +{ |
---|
| 1052 | + struct super_cb_data sd = { |
---|
| 1053 | + .data = data, |
---|
| 1054 | + .sb = NULL, |
---|
| 1055 | + }; |
---|
| 1056 | + struct file_system_type **fs_type = (struct file_system_type *[]) { |
---|
| 1057 | + &cifs_fs_type, &smb3_fs_type, NULL, |
---|
| 1058 | + }; |
---|
| 1059 | + |
---|
| 1060 | + for (; *fs_type; fs_type++) { |
---|
| 1061 | + iterate_supers_type(*fs_type, f, &sd); |
---|
| 1062 | + if (sd.sb) { |
---|
| 1063 | + /* |
---|
| 1064 | + * Grab an active reference in order to prevent automounts (DFS links) |
---|
| 1065 | + * of expiring and then freeing up our cifs superblock pointer while |
---|
| 1066 | + * we're doing failover. |
---|
| 1067 | + */ |
---|
| 1068 | + cifs_sb_active(sd.sb); |
---|
| 1069 | + return sd.sb; |
---|
| 1070 | + } |
---|
| 1071 | + } |
---|
| 1072 | + return ERR_PTR(-EINVAL); |
---|
| 1073 | +} |
---|
| 1074 | + |
---|
| 1075 | +static void __cifs_put_super(struct super_block *sb) |
---|
| 1076 | +{ |
---|
| 1077 | + if (!IS_ERR_OR_NULL(sb)) |
---|
| 1078 | + cifs_sb_deactive(sb); |
---|
| 1079 | +} |
---|
| 1080 | + |
---|
| 1081 | +struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server) |
---|
| 1082 | +{ |
---|
| 1083 | + return __cifs_get_super(tcp_super_cb, server); |
---|
| 1084 | +} |
---|
| 1085 | + |
---|
| 1086 | +void cifs_put_tcp_super(struct super_block *sb) |
---|
| 1087 | +{ |
---|
| 1088 | + __cifs_put_super(sb); |
---|
| 1089 | +} |
---|
| 1090 | + |
---|
| 1091 | +#ifdef CONFIG_CIFS_DFS_UPCALL |
---|
| 1092 | +int match_target_ip(struct TCP_Server_Info *server, |
---|
| 1093 | + const char *share, size_t share_len, |
---|
| 1094 | + bool *result) |
---|
| 1095 | +{ |
---|
| 1096 | + int rc; |
---|
| 1097 | + char *target, *tip = NULL; |
---|
| 1098 | + struct sockaddr tipaddr; |
---|
| 1099 | + |
---|
| 1100 | + *result = false; |
---|
| 1101 | + |
---|
| 1102 | + target = kzalloc(share_len + 3, GFP_KERNEL); |
---|
| 1103 | + if (!target) { |
---|
| 1104 | + rc = -ENOMEM; |
---|
| 1105 | + goto out; |
---|
| 1106 | + } |
---|
| 1107 | + |
---|
| 1108 | + scnprintf(target, share_len + 3, "\\\\%.*s", (int)share_len, share); |
---|
| 1109 | + |
---|
| 1110 | + cifs_dbg(FYI, "%s: target name: %s\n", __func__, target + 2); |
---|
| 1111 | + |
---|
| 1112 | + rc = dns_resolve_server_name_to_ip(target, &tip); |
---|
| 1113 | + if (rc < 0) |
---|
| 1114 | + goto out; |
---|
| 1115 | + |
---|
| 1116 | + cifs_dbg(FYI, "%s: target ip: %s\n", __func__, tip); |
---|
| 1117 | + |
---|
| 1118 | + if (!cifs_convert_address(&tipaddr, tip, strlen(tip))) { |
---|
| 1119 | + cifs_dbg(VFS, "%s: failed to convert target ip address\n", |
---|
| 1120 | + __func__); |
---|
| 1121 | + rc = -EINVAL; |
---|
| 1122 | + goto out; |
---|
| 1123 | + } |
---|
| 1124 | + |
---|
| 1125 | + *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, |
---|
| 1126 | + &tipaddr); |
---|
| 1127 | + cifs_dbg(FYI, "%s: ip addresses match: %u\n", __func__, *result); |
---|
| 1128 | + rc = 0; |
---|
| 1129 | + |
---|
| 1130 | +out: |
---|
| 1131 | + kfree(target); |
---|
| 1132 | + kfree(tip); |
---|
| 1133 | + |
---|
| 1134 | + return rc; |
---|
| 1135 | +} |
---|
| 1136 | + |
---|
| 1137 | +static void tcon_super_cb(struct super_block *sb, void *arg) |
---|
| 1138 | +{ |
---|
| 1139 | + struct super_cb_data *sd = arg; |
---|
| 1140 | + struct cifs_tcon *tcon = sd->data; |
---|
| 1141 | + struct cifs_sb_info *cifs_sb; |
---|
| 1142 | + |
---|
| 1143 | + if (sd->sb) |
---|
| 1144 | + return; |
---|
| 1145 | + |
---|
| 1146 | + cifs_sb = CIFS_SB(sb); |
---|
| 1147 | + if (tcon->dfs_path && cifs_sb->origin_fullpath && |
---|
| 1148 | + !strcasecmp(tcon->dfs_path, cifs_sb->origin_fullpath)) |
---|
| 1149 | + sd->sb = sb; |
---|
| 1150 | +} |
---|
| 1151 | + |
---|
| 1152 | +static inline struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon) |
---|
| 1153 | +{ |
---|
| 1154 | + return __cifs_get_super(tcon_super_cb, tcon); |
---|
| 1155 | +} |
---|
| 1156 | + |
---|
| 1157 | +static inline void cifs_put_tcon_super(struct super_block *sb) |
---|
| 1158 | +{ |
---|
| 1159 | + __cifs_put_super(sb); |
---|
| 1160 | +} |
---|
| 1161 | +#else |
---|
| 1162 | +static inline struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon) |
---|
| 1163 | +{ |
---|
| 1164 | + return ERR_PTR(-EOPNOTSUPP); |
---|
| 1165 | +} |
---|
| 1166 | + |
---|
| 1167 | +static inline void cifs_put_tcon_super(struct super_block *sb) |
---|
| 1168 | +{ |
---|
| 1169 | +} |
---|
| 1170 | +#endif |
---|
| 1171 | + |
---|
| 1172 | +int update_super_prepath(struct cifs_tcon *tcon, char *prefix) |
---|
| 1173 | +{ |
---|
| 1174 | + struct super_block *sb; |
---|
| 1175 | + struct cifs_sb_info *cifs_sb; |
---|
| 1176 | + int rc = 0; |
---|
| 1177 | + |
---|
| 1178 | + sb = cifs_get_tcon_super(tcon); |
---|
| 1179 | + if (IS_ERR(sb)) |
---|
| 1180 | + return PTR_ERR(sb); |
---|
| 1181 | + |
---|
| 1182 | + cifs_sb = CIFS_SB(sb); |
---|
| 1183 | + |
---|
| 1184 | + kfree(cifs_sb->prepath); |
---|
| 1185 | + |
---|
| 1186 | + if (prefix && *prefix) { |
---|
| 1187 | + cifs_sb->prepath = kstrndup(prefix, strlen(prefix), GFP_ATOMIC); |
---|
| 1188 | + if (!cifs_sb->prepath) { |
---|
| 1189 | + rc = -ENOMEM; |
---|
| 1190 | + goto out; |
---|
| 1191 | + } |
---|
| 1192 | + |
---|
| 1193 | + convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb)); |
---|
| 1194 | + } else |
---|
| 1195 | + cifs_sb->prepath = NULL; |
---|
| 1196 | + |
---|
| 1197 | + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; |
---|
| 1198 | + |
---|
| 1199 | +out: |
---|
| 1200 | + cifs_put_tcon_super(sb); |
---|
| 1201 | + return rc; |
---|
| 1202 | +} |
---|