Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'v6.12-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:
"Most are from the recent SMB3.1.1 test event, and also an important
netfs fix for a cifs mtime write regression

- fix mode reported by stat of readonly directories and files

- DFS (global namespace) related fixes

- fixes for special file support via reparse points

- mount improvement and reconnect fix

- fix for noisy log message on umount

- two netfs related fixes, one fixing a recent regression, and add
new write tracepoint"

* tag 'v6.12-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6:
netfs, cifs: Fix mtime/ctime update for mmapped writes
cifs: update internal version number
smb: client: print failed session logoffs with FYI
cifs: Fix reversion of the iter in cifs_readv_receive().
smb3: fix incorrect mode displayed for read-only files
smb: client: fix parsing of device numbers
smb: client: set correct device number on nfs reparse points
smb: client: propagate error from cifs_construct_tcon()
smb: client: fix DFS failover in multiuser mounts
cifs: Make the write_{enter,done,err} tracepoints display netfs info
smb: client: fix DFS interlink failover
smb: client: improve purging of cached referrals
smb: client: avoid unnecessary reconnects when refreshing referrals

+288 -230
+1
fs/netfs/buffered_write.c
··· 552 552 trace_netfs_folio(folio, netfs_folio_trace_mkwrite); 553 553 netfs_set_group(folio, netfs_group); 554 554 file_update_time(file); 555 + set_bit(NETFS_ICTX_MODIFIED_ATTR, &ictx->flags); 555 556 if (ictx->ops->post_modify) 556 557 ictx->ops->post_modify(inode); 557 558 ret = VM_FAULT_LOCKED;
+2 -2
fs/smb/client/cifsfs.h
··· 146 146 #endif /* CONFIG_CIFS_NFSD_EXPORT */ 147 147 148 148 /* when changing internal version - update following two lines at same time */ 149 - #define SMB3_PRODUCT_BUILD 50 150 - #define CIFS_VERSION "2.50" 149 + #define SMB3_PRODUCT_BUILD 51 150 + #define CIFS_VERSION "2.51" 151 151 #endif /* _CIFSFS_H */
+3
fs/smb/client/cifsglob.h
··· 821 821 * format: \\HOST\SHARE[\OPTIONAL PATH] 822 822 */ 823 823 char *leaf_fullpath; 824 + bool dfs_conn:1; 824 825 }; 825 826 826 827 static inline bool is_smb1(struct TCP_Server_Info *server) ··· 1060 1059 struct list_head smb_ses_list; 1061 1060 struct list_head rlist; /* reconnect list */ 1062 1061 struct list_head tcon_list; 1062 + struct list_head dlist; /* dfs list */ 1063 1063 struct cifs_tcon *tcon_ipc; 1064 1064 spinlock_t ses_lock; /* protect anything here that is not protected */ 1065 1065 struct mutex session_mutex; ··· 1289 1287 /* BB add field for back pointer to sb struct(s)? */ 1290 1288 #ifdef CONFIG_CIFS_DFS_UPCALL 1291 1289 struct delayed_work dfs_cache_work; 1290 + struct list_head dfs_ses_list; 1292 1291 #endif 1293 1292 struct delayed_work query_interfaces; /* query interfaces workqueue job */ 1294 1293 char *origin_fullpath; /* canonical copy of smb3_fs_context::source */
+2 -10
fs/smb/client/cifsproto.h
··· 724 724 725 725 int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry); 726 726 727 - /* Put references of @ses and its children */ 728 727 static inline void cifs_put_smb_ses(struct cifs_ses *ses) 729 728 { 730 - struct cifs_ses *next; 731 - 732 - do { 733 - next = ses->dfs_root_ses; 734 - __cifs_put_smb_ses(ses); 735 - } while ((ses = next)); 729 + __cifs_put_smb_ses(ses); 736 730 } 737 731 738 732 /* Get an active reference of @ses and its children. ··· 740 746 static inline void cifs_smb_ses_inc_refcount(struct cifs_ses *ses) 741 747 { 742 748 lockdep_assert_held(&cifs_tcp_ses_lock); 743 - 744 - for (; ses; ses = ses->dfs_root_ses) 745 - ses->ses_count++; 749 + ses->ses_count++; 746 750 } 747 751 748 752 static inline bool dfs_src_pathname_equal(const char *s1, const char *s2)
+32 -34
fs/smb/client/connect.c
··· 811 811 unsigned int to_read) 812 812 { 813 813 struct msghdr smb_msg = { .msg_iter = *iter }; 814 - int ret; 815 814 816 815 iov_iter_truncate(&smb_msg.msg_iter, to_read); 817 - ret = cifs_readv_from_socket(server, &smb_msg); 818 - if (ret > 0) 819 - iov_iter_advance(iter, ret); 820 - return ret; 816 + return cifs_readv_from_socket(server, &smb_msg); 821 817 } 822 818 823 819 static bool ··· 1526 1530 if (server->nosharesock) 1527 1531 return 0; 1528 1532 1533 + if (!match_super && (ctx->dfs_conn || server->dfs_conn)) 1534 + return 0; 1535 + 1529 1536 /* If multidialect negotiation see if existing sessions match one */ 1530 1537 if (strcmp(ctx->vals->version_string, SMB3ANY_VERSION_STRING) == 0) { 1531 1538 if (server->vals->protocol_id < SMB30_PROT_ID) ··· 1722 1723 1723 1724 if (ctx->nosharesock) 1724 1725 tcp_ses->nosharesock = true; 1726 + tcp_ses->dfs_conn = ctx->dfs_conn; 1725 1727 1726 1728 tcp_ses->ops = ctx->ops; 1727 1729 tcp_ses->vals = ctx->vals; ··· 1873 1873 } 1874 1874 1875 1875 /* this function must be called with ses_lock and chan_lock held */ 1876 - static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx) 1876 + static int match_session(struct cifs_ses *ses, 1877 + struct smb3_fs_context *ctx, 1878 + bool match_super) 1877 1879 { 1878 1880 if (ctx->sectype != Unspecified && 1879 1881 ctx->sectype != ses->sectype) 1880 1882 return 0; 1881 1883 1882 - if (ctx->dfs_root_ses != ses->dfs_root_ses) 1884 + if (!match_super && ctx->dfs_root_ses != ses->dfs_root_ses) 1883 1885 return 0; 1884 1886 1885 1887 /* ··· 2000 1998 continue; 2001 1999 } 2002 2000 spin_lock(&ses->chan_lock); 2003 - if (match_session(ses, ctx)) { 2001 + if (match_session(ses, ctx, false)) { 2004 2002 spin_unlock(&ses->chan_lock); 2005 2003 spin_unlock(&ses->ses_lock); 2006 2004 ret = ses; ··· 2060 2058 if (do_logoff) { 2061 2059 xid = get_xid(); 2062 2060 rc = server->ops->logoff(xid, ses); 2063 - if (rc) 2064 - cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n", 2061 + cifs_server_dbg(FYI, "%s: Session Logoff: rc=%d\n", 2065 2062 __func__, rc); 2066 2063 _free_xid(xid); 2067 2064 } ··· 2383 2382 * need to lock before changing something in the session. 2384 2383 */ 2385 2384 spin_lock(&cifs_tcp_ses_lock); 2386 - if (ctx->dfs_root_ses) 2387 - cifs_smb_ses_inc_refcount(ctx->dfs_root_ses); 2388 2385 ses->dfs_root_ses = ctx->dfs_root_ses; 2389 2386 list_add(&ses->smb_ses_list, &server->smb_ses_list); 2390 2387 spin_unlock(&cifs_tcp_ses_lock); ··· 2457 2458 { 2458 2459 unsigned int xid; 2459 2460 struct cifs_ses *ses; 2461 + LIST_HEAD(ses_list); 2460 2462 2461 2463 /* 2462 2464 * IPC tcon share the lifetime of their session and are ··· 2482 2482 2483 2483 list_del_init(&tcon->tcon_list); 2484 2484 tcon->status = TID_EXITING; 2485 + #ifdef CONFIG_CIFS_DFS_UPCALL 2486 + list_replace_init(&tcon->dfs_ses_list, &ses_list); 2487 + #endif 2485 2488 spin_unlock(&tcon->tc_lock); 2486 2489 spin_unlock(&cifs_tcp_ses_lock); 2487 2490 ··· 2512 2509 cifs_fscache_release_super_cookie(tcon); 2513 2510 tconInfoFree(tcon, netfs_trace_tcon_ref_free); 2514 2511 cifs_put_smb_ses(ses); 2512 + #ifdef CONFIG_CIFS_DFS_UPCALL 2513 + dfs_put_root_smb_sessions(&ses_list); 2514 + #endif 2515 2515 } 2516 2516 2517 2517 /** ··· 2898 2892 spin_lock(&ses->chan_lock); 2899 2893 spin_lock(&tcon->tc_lock); 2900 2894 if (!match_server(tcp_srv, ctx, true) || 2901 - !match_session(ses, ctx) || 2895 + !match_session(ses, ctx, true) || 2902 2896 !match_tcon(tcon, ctx) || 2903 2897 !match_prepath(sb, tcon, mnt_data)) { 2904 2898 rc = 0; ··· 3629 3623 int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx) 3630 3624 { 3631 3625 struct cifs_mount_ctx mnt_ctx = { .cifs_sb = cifs_sb, .fs_ctx = ctx, }; 3632 - bool isdfs; 3633 3626 int rc; 3634 3627 3635 - rc = dfs_mount_share(&mnt_ctx, &isdfs); 3628 + rc = dfs_mount_share(&mnt_ctx); 3636 3629 if (rc) 3637 3630 goto error; 3638 - if (!isdfs) 3631 + if (!ctx->dfs_conn) 3639 3632 goto out; 3640 3633 3641 3634 /* ··· 4039 4034 } 4040 4035 4041 4036 static struct cifs_tcon * 4042 - __cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid) 4037 + cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid) 4043 4038 { 4044 4039 int rc; 4045 4040 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb); ··· 4137 4132 return tcon; 4138 4133 } 4139 4134 4140 - static struct cifs_tcon * 4141 - cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid) 4142 - { 4143 - struct cifs_tcon *ret; 4144 - 4145 - cifs_mount_lock(); 4146 - ret = __cifs_construct_tcon(cifs_sb, fsuid); 4147 - cifs_mount_unlock(); 4148 - return ret; 4149 - } 4150 - 4151 4135 struct cifs_tcon * 4152 4136 cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb) 4153 4137 { ··· 4206 4212 struct tcon_link * 4207 4213 cifs_sb_tlink(struct cifs_sb_info *cifs_sb) 4208 4214 { 4209 - int ret; 4210 - kuid_t fsuid = current_fsuid(); 4211 4215 struct tcon_link *tlink, *newtlink; 4216 + kuid_t fsuid = current_fsuid(); 4217 + int err; 4212 4218 4213 4219 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) 4214 4220 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb)); ··· 4243 4249 spin_unlock(&cifs_sb->tlink_tree_lock); 4244 4250 } else { 4245 4251 wait_for_construction: 4246 - ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING, 4252 + err = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING, 4247 4253 TASK_INTERRUPTIBLE); 4248 - if (ret) { 4254 + if (err) { 4249 4255 cifs_put_tlink(tlink); 4250 4256 return ERR_PTR(-ERESTARTSYS); 4251 4257 } ··· 4256 4262 4257 4263 /* return error if we tried this already recently */ 4258 4264 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) { 4265 + err = PTR_ERR(tlink->tl_tcon); 4259 4266 cifs_put_tlink(tlink); 4260 - return ERR_PTR(-EACCES); 4267 + return ERR_PTR(err); 4261 4268 } 4262 4269 4263 4270 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags)) ··· 4270 4275 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING); 4271 4276 4272 4277 if (IS_ERR(tlink->tl_tcon)) { 4278 + err = PTR_ERR(tlink->tl_tcon); 4279 + if (err == -ENOKEY) 4280 + err = -EACCES; 4273 4281 cifs_put_tlink(tlink); 4274 - return ERR_PTR(-EACCES); 4282 + return ERR_PTR(err); 4275 4283 } 4276 4284 4277 4285 return tlink;
+35 -38
fs/smb/client/dfs.c
··· 69 69 * Get an active reference of @ses so that next call to cifs_put_tcon() won't 70 70 * release it as any new DFS referrals must go through its IPC tcon. 71 71 */ 72 - static void add_root_smb_session(struct cifs_mount_ctx *mnt_ctx) 72 + static void set_root_smb_session(struct cifs_mount_ctx *mnt_ctx) 73 73 { 74 74 struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; 75 75 struct cifs_ses *ses = mnt_ctx->ses; ··· 95 95 return rc; 96 96 } 97 97 98 - static int set_ref_paths(struct cifs_mount_ctx *mnt_ctx, 98 + static int setup_dfs_ref(struct cifs_mount_ctx *mnt_ctx, 99 99 struct dfs_info3_param *tgt, 100 100 struct dfs_ref_walk *rw) 101 101 { ··· 120 120 } 121 121 ref_walk_path(rw) = ref_path; 122 122 ref_walk_fpath(rw) = full_path; 123 + ref_walk_ses(rw) = ctx->dfs_root_ses; 123 124 return 0; 124 125 } 125 126 ··· 129 128 { 130 129 struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; 131 130 struct dfs_info3_param tgt = {}; 132 - bool is_refsrv; 133 131 int rc = -ENOENT; 134 132 135 133 again: 136 134 do { 135 + ctx->dfs_root_ses = ref_walk_ses(rw); 137 136 if (ref_walk_empty(rw)) { 138 137 rc = dfs_get_referral(mnt_ctx, ref_walk_path(rw) + 1, 139 138 NULL, ref_walk_tl(rw)); ··· 159 158 if (rc) 160 159 continue; 161 160 162 - is_refsrv = tgt.server_type == DFS_TYPE_ROOT || 163 - DFS_INTERLINK(tgt.flags); 164 161 ref_walk_set_tgt_hint(rw); 165 - 166 162 if (tgt.flags & DFSREF_STORAGE_SERVER) { 167 163 rc = cifs_mount_get_tcon(mnt_ctx); 168 164 if (!rc) ··· 170 172 continue; 171 173 } 172 174 173 - if (is_refsrv) 174 - add_root_smb_session(mnt_ctx); 175 - 175 + set_root_smb_session(mnt_ctx); 176 176 rc = ref_walk_advance(rw); 177 177 if (!rc) { 178 - rc = set_ref_paths(mnt_ctx, &tgt, rw); 178 + rc = setup_dfs_ref(mnt_ctx, &tgt, rw); 179 179 if (!rc) { 180 180 rc = -EREMOTE; 181 181 goto again; ··· 189 193 return rc; 190 194 } 191 195 192 - static int dfs_referral_walk(struct cifs_mount_ctx *mnt_ctx) 196 + static int dfs_referral_walk(struct cifs_mount_ctx *mnt_ctx, 197 + struct dfs_ref_walk **rw) 193 198 { 194 - struct dfs_ref_walk *rw; 195 199 int rc; 196 200 197 - rw = ref_walk_alloc(); 198 - if (IS_ERR(rw)) 199 - return PTR_ERR(rw); 201 + *rw = ref_walk_alloc(); 202 + if (IS_ERR(*rw)) { 203 + rc = PTR_ERR(*rw); 204 + *rw = NULL; 205 + return rc; 206 + } 200 207 201 - ref_walk_init(rw); 202 - rc = set_ref_paths(mnt_ctx, NULL, rw); 208 + ref_walk_init(*rw); 209 + rc = setup_dfs_ref(mnt_ctx, NULL, *rw); 203 210 if (!rc) 204 - rc = __dfs_referral_walk(mnt_ctx, rw); 205 - ref_walk_free(rw); 211 + rc = __dfs_referral_walk(mnt_ctx, *rw); 206 212 return rc; 207 213 } 208 214 ··· 212 214 { 213 215 struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb; 214 216 struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; 217 + struct dfs_ref_walk *rw = NULL; 215 218 struct cifs_tcon *tcon; 216 219 char *origin_fullpath; 217 - bool new_tcon = true; 218 220 int rc; 219 221 220 222 origin_fullpath = dfs_get_path(cifs_sb, ctx->source); 221 223 if (IS_ERR(origin_fullpath)) 222 224 return PTR_ERR(origin_fullpath); 223 225 224 - rc = dfs_referral_walk(mnt_ctx); 226 + rc = dfs_referral_walk(mnt_ctx, &rw); 225 227 if (!rc) { 226 228 /* 227 229 * Prevent superblock from being created with any missing ··· 239 241 240 242 tcon = mnt_ctx->tcon; 241 243 spin_lock(&tcon->tc_lock); 242 - if (!tcon->origin_fullpath) { 243 - tcon->origin_fullpath = origin_fullpath; 244 - origin_fullpath = NULL; 245 - } else { 246 - new_tcon = false; 247 - } 244 + tcon->origin_fullpath = origin_fullpath; 245 + origin_fullpath = NULL; 246 + ref_walk_set_tcon(rw, tcon); 248 247 spin_unlock(&tcon->tc_lock); 249 - 250 - if (new_tcon) { 251 - queue_delayed_work(dfscache_wq, &tcon->dfs_cache_work, 252 - dfs_cache_get_ttl() * HZ); 253 - } 248 + queue_delayed_work(dfscache_wq, &tcon->dfs_cache_work, 249 + dfs_cache_get_ttl() * HZ); 254 250 255 251 out: 256 252 kfree(origin_fullpath); 253 + ref_walk_free(rw); 257 254 return rc; 258 255 } 259 256 ··· 272 279 return rc; 273 280 } 274 281 275 - int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs) 282 + int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx) 276 283 { 277 284 struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; 278 285 bool nodfs = ctx->nodfs; ··· 282 289 if (rc) 283 290 return rc; 284 291 285 - *isdfs = false; 286 292 rc = get_session(mnt_ctx, NULL); 287 293 if (rc) 288 294 return rc; ··· 309 317 return rc; 310 318 } 311 319 312 - *isdfs = true; 313 - add_root_smb_session(mnt_ctx); 314 - rc = __dfs_mount_share(mnt_ctx); 315 - dfs_put_root_smb_sessions(mnt_ctx); 320 + if (!ctx->dfs_conn) { 321 + ctx->dfs_conn = true; 322 + cifs_mount_put_conns(mnt_ctx); 323 + rc = get_session(mnt_ctx, NULL); 324 + } 325 + if (!rc) { 326 + set_root_smb_session(mnt_ctx); 327 + rc = __dfs_mount_share(mnt_ctx); 328 + } 316 329 return rc; 317 330 } 318 331
+28 -14
fs/smb/client/dfs.h
··· 19 19 struct dfs_ref { 20 20 char *path; 21 21 char *full_path; 22 + struct cifs_ses *ses; 22 23 struct dfs_cache_tgt_list tl; 23 24 struct dfs_cache_tgt_iterator *tit; 24 25 }; ··· 39 38 #define ref_walk_path(w) (ref_walk_cur(w)->path) 40 39 #define ref_walk_fpath(w) (ref_walk_cur(w)->full_path) 41 40 #define ref_walk_tl(w) (&ref_walk_cur(w)->tl) 41 + #define ref_walk_ses(w) (ref_walk_cur(w)->ses) 42 42 43 43 static inline struct dfs_ref_walk *ref_walk_alloc(void) 44 44 { ··· 62 60 kfree(ref->path); 63 61 kfree(ref->full_path); 64 62 dfs_cache_free_tgts(&ref->tl); 63 + if (ref->ses) 64 + cifs_put_smb_ses(ref->ses); 65 65 memset(ref, 0, sizeof(*ref)); 66 66 } 67 67 68 68 static inline void ref_walk_free(struct dfs_ref_walk *rw) 69 69 { 70 - struct dfs_ref *ref = ref_walk_start(rw); 70 + struct dfs_ref *ref; 71 71 72 - for (; ref <= ref_walk_end(rw); ref++) 72 + if (!rw) 73 + return; 74 + 75 + for (ref = ref_walk_start(rw); ref <= ref_walk_end(rw); ref++) 73 76 __ref_walk_free(ref); 74 77 kfree(rw); 75 78 } ··· 123 116 ref_walk_tit(rw)); 124 117 } 125 118 119 + static inline void ref_walk_set_tcon(struct dfs_ref_walk *rw, 120 + struct cifs_tcon *tcon) 121 + { 122 + struct dfs_ref *ref = ref_walk_start(rw); 123 + 124 + for (; ref <= ref_walk_cur(rw); ref++) { 125 + if (WARN_ON_ONCE(!ref->ses)) 126 + continue; 127 + list_add(&ref->ses->dlist, &tcon->dfs_ses_list); 128 + ref->ses = NULL; 129 + } 130 + } 131 + 126 132 int dfs_parse_target_referral(const char *full_path, const struct dfs_info3_param *ref, 127 133 struct smb3_fs_context *ctx); 128 - int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs); 134 + int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx); 129 135 130 136 static inline char *dfs_get_path(struct cifs_sb_info *cifs_sb, const char *path) 131 137 { ··· 162 142 * references of all DFS root sessions that were used across the mount process 163 143 * in dfs_mount_share(). 164 144 */ 165 - static inline void dfs_put_root_smb_sessions(struct cifs_mount_ctx *mnt_ctx) 145 + static inline void dfs_put_root_smb_sessions(struct list_head *head) 166 146 { 167 - const struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; 168 - struct cifs_ses *ses = ctx->dfs_root_ses; 169 - struct cifs_ses *cur; 147 + struct cifs_ses *ses, *n; 170 148 171 - if (!ses) 172 - return; 173 - 174 - for (cur = ses; cur; cur = cur->dfs_root_ses) { 175 - if (cur->dfs_root_ses) 176 - cifs_put_smb_ses(cur->dfs_root_ses); 149 + list_for_each_entry_safe(ses, n, head, dlist) { 150 + list_del_init(&ses->dlist); 151 + cifs_put_smb_ses(ses); 177 152 } 178 - cifs_put_smb_ses(ses); 179 153 } 180 154 181 155 #endif /* _CIFS_DFS_H */
+137 -93
fs/smb/client/dfs_cache.c
··· 126 126 127 127 static inline void flush_cache_ent(struct cache_entry *ce) 128 128 { 129 + cifs_dbg(FYI, "%s: %s\n", __func__, ce->path); 129 130 hlist_del_init(&ce->hlist); 130 131 kfree(ce->path); 131 132 free_tgts(ce); ··· 442 441 return ce; 443 442 } 444 443 445 - static void remove_oldest_entry_locked(void) 444 + /* Remove all referrals that have a single target or oldest entry */ 445 + static void purge_cache(void) 446 446 { 447 447 int i; 448 448 struct cache_entry *ce; 449 - struct cache_entry *to_del = NULL; 450 - 451 - WARN_ON(!rwsem_is_locked(&htable_rw_lock)); 449 + struct cache_entry *oldest = NULL; 452 450 453 451 for (i = 0; i < CACHE_HTABLE_SIZE; i++) { 454 452 struct hlist_head *l = &cache_htable[i]; 453 + struct hlist_node *n; 455 454 456 - hlist_for_each_entry(ce, l, hlist) { 455 + hlist_for_each_entry_safe(ce, n, l, hlist) { 457 456 if (hlist_unhashed(&ce->hlist)) 458 457 continue; 459 - if (!to_del || timespec64_compare(&ce->etime, 460 - &to_del->etime) < 0) 461 - to_del = ce; 458 + if (ce->numtgts == 1) 459 + flush_cache_ent(ce); 460 + else if (!oldest || 461 + timespec64_compare(&ce->etime, 462 + &oldest->etime) < 0) 463 + oldest = ce; 462 464 } 463 465 } 464 466 465 - if (!to_del) { 466 - cifs_dbg(FYI, "%s: no entry to remove\n", __func__); 467 - return; 468 - } 469 - 470 - cifs_dbg(FYI, "%s: removing entry\n", __func__); 471 - dump_ce(to_del); 472 - flush_cache_ent(to_del); 467 + if (atomic_read(&cache_count) >= CACHE_MAX_ENTRIES && oldest) 468 + flush_cache_ent(oldest); 473 469 } 474 470 475 471 /* Add a new DFS cache entry */ ··· 482 484 483 485 if (atomic_read(&cache_count) >= CACHE_MAX_ENTRIES) { 484 486 cifs_dbg(FYI, "%s: reached max cache size (%d)\n", __func__, CACHE_MAX_ENTRIES); 485 - remove_oldest_entry_locked(); 487 + purge_cache(); 486 488 } 487 489 488 490 rc = cache_entry_hash(refs[0].path_name, strlen(refs[0].path_name), &hash); ··· 1093 1095 return 0; 1094 1096 } 1095 1097 1096 - static bool target_share_equal(struct TCP_Server_Info *server, const char *s1, const char *s2) 1098 + static bool target_share_equal(struct cifs_tcon *tcon, const char *s1) 1097 1099 { 1098 - char unc[sizeof("\\\\") + SERVER_NAME_LENGTH] = {0}; 1099 - const char *host; 1100 - size_t hostlen; 1100 + struct TCP_Server_Info *server = tcon->ses->server; 1101 1101 struct sockaddr_storage ss; 1102 + const char *host; 1103 + const char *s2 = &tcon->tree_name[1]; 1104 + size_t hostlen; 1105 + char unc[sizeof("\\\\") + SERVER_NAME_LENGTH] = {0}; 1102 1106 bool match; 1103 1107 int rc; 1104 1108 1105 - if (strcasecmp(s1, s2)) 1109 + if (strcasecmp(s2, s1)) 1106 1110 return false; 1107 1111 1108 1112 /* ··· 1128 1128 return match; 1129 1129 } 1130 1130 1131 - /* 1132 - * Mark dfs tcon for reconnecting when the currently connected tcon does not match any of the new 1133 - * target shares in @refs. 1134 - */ 1135 - static void mark_for_reconnect_if_needed(struct TCP_Server_Info *server, 1136 - const char *path, 1137 - struct dfs_cache_tgt_list *old_tl, 1138 - struct dfs_cache_tgt_list *new_tl) 1139 - { 1140 - struct dfs_cache_tgt_iterator *oit, *nit; 1141 - 1142 - for (oit = dfs_cache_get_tgt_iterator(old_tl); oit; 1143 - oit = dfs_cache_get_next_tgt(old_tl, oit)) { 1144 - for (nit = dfs_cache_get_tgt_iterator(new_tl); nit; 1145 - nit = dfs_cache_get_next_tgt(new_tl, nit)) { 1146 - if (target_share_equal(server, 1147 - dfs_cache_get_tgt_name(oit), 1148 - dfs_cache_get_tgt_name(nit))) { 1149 - dfs_cache_noreq_update_tgthint(path, nit); 1150 - return; 1151 - } 1152 - } 1153 - } 1154 - 1155 - cifs_dbg(FYI, "%s: no cached or matched targets. mark dfs share for reconnect.\n", __func__); 1156 - cifs_signal_cifsd_for_reconnect(server, true); 1157 - } 1158 - 1159 1131 static bool is_ses_good(struct cifs_ses *ses) 1160 1132 { 1161 1133 struct TCP_Server_Info *server = ses->server; ··· 1144 1172 return ret; 1145 1173 } 1146 1174 1147 - /* Refresh dfs referral of @ses and mark it for reconnect if needed */ 1148 - static void __refresh_ses_referral(struct cifs_ses *ses, bool force_refresh) 1175 + static char *get_ses_refpath(struct cifs_ses *ses) 1149 1176 { 1150 1177 struct TCP_Server_Info *server = ses->server; 1151 - DFS_CACHE_TGT_LIST(old_tl); 1152 - DFS_CACHE_TGT_LIST(new_tl); 1153 - bool needs_refresh = false; 1154 - struct cache_entry *ce; 1155 - unsigned int xid; 1156 - char *path = NULL; 1157 - int rc = 0; 1158 - 1159 - xid = get_xid(); 1178 + char *path = ERR_PTR(-ENOENT); 1160 1179 1161 1180 mutex_lock(&server->refpath_lock); 1162 1181 if (server->leaf_fullpath) { 1163 1182 path = kstrdup(server->leaf_fullpath + 1, GFP_ATOMIC); 1164 1183 if (!path) 1165 - rc = -ENOMEM; 1184 + path = ERR_PTR(-ENOMEM); 1166 1185 } 1167 1186 mutex_unlock(&server->refpath_lock); 1168 - if (!path) 1169 - goto out; 1187 + return path; 1188 + } 1170 1189 1171 - down_read(&htable_rw_lock); 1172 - ce = lookup_cache_entry(path); 1173 - needs_refresh = force_refresh || IS_ERR(ce) || cache_entry_expired(ce); 1174 - if (!IS_ERR(ce)) { 1175 - rc = get_targets(ce, &old_tl); 1176 - cifs_dbg(FYI, "%s: get_targets: %d\n", __func__, rc); 1177 - } 1178 - up_read(&htable_rw_lock); 1190 + /* Refresh dfs referral of @ses */ 1191 + static void refresh_ses_referral(struct cifs_ses *ses) 1192 + { 1193 + struct cache_entry *ce; 1194 + unsigned int xid; 1195 + char *path; 1196 + int rc = 0; 1179 1197 1180 - if (!needs_refresh) { 1181 - rc = 0; 1198 + xid = get_xid(); 1199 + 1200 + path = get_ses_refpath(ses); 1201 + if (IS_ERR(path)) { 1202 + rc = PTR_ERR(path); 1203 + path = NULL; 1182 1204 goto out; 1183 1205 } 1184 1206 ··· 1183 1217 goto out; 1184 1218 } 1185 1219 1186 - ce = cache_refresh_path(xid, ses, path, true); 1187 - if (!IS_ERR(ce)) { 1188 - rc = get_targets(ce, &new_tl); 1220 + ce = cache_refresh_path(xid, ses, path, false); 1221 + if (!IS_ERR(ce)) 1189 1222 up_read(&htable_rw_lock); 1190 - cifs_dbg(FYI, "%s: get_targets: %d\n", __func__, rc); 1191 - mark_for_reconnect_if_needed(server, path, &old_tl, &new_tl); 1223 + else 1224 + rc = PTR_ERR(ce); 1225 + 1226 + out: 1227 + free_xid(xid); 1228 + kfree(path); 1229 + } 1230 + 1231 + static int __refresh_tcon_referral(struct cifs_tcon *tcon, 1232 + const char *path, 1233 + struct dfs_info3_param *refs, 1234 + int numrefs, bool force_refresh) 1235 + { 1236 + struct cache_entry *ce; 1237 + bool reconnect = force_refresh; 1238 + int rc = 0; 1239 + int i; 1240 + 1241 + if (unlikely(!numrefs)) 1242 + return 0; 1243 + 1244 + if (force_refresh) { 1245 + for (i = 0; i < numrefs; i++) { 1246 + /* TODO: include prefix paths in the matching */ 1247 + if (target_share_equal(tcon, refs[i].node_name)) { 1248 + reconnect = false; 1249 + break; 1250 + } 1251 + } 1252 + } 1253 + 1254 + down_write(&htable_rw_lock); 1255 + ce = lookup_cache_entry(path); 1256 + if (!IS_ERR(ce)) { 1257 + if (force_refresh || cache_entry_expired(ce)) 1258 + rc = update_cache_entry_locked(ce, refs, numrefs); 1259 + } else if (PTR_ERR(ce) == -ENOENT) { 1260 + ce = add_cache_entry_locked(refs, numrefs); 1261 + } 1262 + up_write(&htable_rw_lock); 1263 + 1264 + if (IS_ERR(ce)) 1265 + rc = PTR_ERR(ce); 1266 + if (reconnect) { 1267 + cifs_tcon_dbg(FYI, "%s: mark for reconnect\n", __func__); 1268 + cifs_signal_cifsd_for_reconnect(tcon->ses->server, true); 1269 + } 1270 + return rc; 1271 + } 1272 + 1273 + static void refresh_tcon_referral(struct cifs_tcon *tcon, bool force_refresh) 1274 + { 1275 + struct dfs_info3_param *refs = NULL; 1276 + struct cache_entry *ce; 1277 + struct cifs_ses *ses; 1278 + unsigned int xid; 1279 + bool needs_refresh; 1280 + char *path; 1281 + int numrefs = 0; 1282 + int rc = 0; 1283 + 1284 + xid = get_xid(); 1285 + ses = tcon->ses; 1286 + 1287 + path = get_ses_refpath(ses); 1288 + if (IS_ERR(path)) { 1289 + rc = PTR_ERR(path); 1290 + path = NULL; 1291 + goto out; 1292 + } 1293 + 1294 + down_read(&htable_rw_lock); 1295 + ce = lookup_cache_entry(path); 1296 + needs_refresh = force_refresh || IS_ERR(ce) || cache_entry_expired(ce); 1297 + if (!needs_refresh) { 1298 + up_read(&htable_rw_lock); 1299 + goto out; 1300 + } 1301 + up_read(&htable_rw_lock); 1302 + 1303 + ses = CIFS_DFS_ROOT_SES(ses); 1304 + if (!is_ses_good(ses)) { 1305 + cifs_dbg(FYI, "%s: skip cache refresh due to disconnected ipc\n", 1306 + __func__); 1307 + goto out; 1308 + } 1309 + 1310 + rc = get_dfs_referral(xid, ses, path, &refs, &numrefs); 1311 + if (!rc) { 1312 + rc = __refresh_tcon_referral(tcon, path, refs, 1313 + numrefs, force_refresh); 1192 1314 } 1193 1315 1194 1316 out: 1195 1317 free_xid(xid); 1196 - dfs_cache_free_tgts(&old_tl); 1197 - dfs_cache_free_tgts(&new_tl); 1198 1318 kfree(path); 1199 - } 1200 - 1201 - static inline void refresh_ses_referral(struct cifs_ses *ses) 1202 - { 1203 - __refresh_ses_referral(ses, false); 1204 - } 1205 - 1206 - static inline void force_refresh_ses_referral(struct cifs_ses *ses) 1207 - { 1208 - __refresh_ses_referral(ses, true); 1319 + free_dfs_info_array(refs, numrefs); 1209 1320 } 1210 1321 1211 1322 /** ··· 1323 1280 */ 1324 1281 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; 1325 1282 1326 - force_refresh_ses_referral(tcon->ses); 1283 + refresh_tcon_referral(tcon, true); 1327 1284 return 0; 1328 1285 } 1329 1286 ··· 1335 1292 1336 1293 tcon = container_of(work, struct cifs_tcon, dfs_cache_work.work); 1337 1294 1338 - for (ses = tcon->ses; ses; ses = ses->dfs_root_ses) 1295 + list_for_each_entry(ses, &tcon->dfs_ses_list, dlist) 1339 1296 refresh_ses_referral(ses); 1297 + refresh_tcon_referral(tcon, false); 1340 1298 1341 1299 queue_delayed_work(dfscache_wq, &tcon->dfs_cache_work, 1342 1300 atomic_read(&dfs_cache_ttl) * HZ);
+1
fs/smb/client/fs_context.h
··· 284 284 struct cifs_ses *dfs_root_ses; 285 285 bool dfs_automount:1; /* set for dfs automount only */ 286 286 enum cifs_reparse_type reparse_type; 287 + bool dfs_conn:1; /* set for dfs mounts */ 287 288 }; 288 289 289 290 extern const struct fs_parameter_spec smb3_fs_parameters[];
+11 -8
fs/smb/client/inode.c
··· 834 834 fattr->cf_mode = S_IFREG | cifs_sb->ctx->file_mode; 835 835 fattr->cf_dtype = DT_REG; 836 836 837 - /* clear write bits if ATTR_READONLY is set */ 838 - if (fattr->cf_cifsattrs & ATTR_READONLY) 839 - fattr->cf_mode &= ~(S_IWUGO); 840 - 841 837 /* 842 838 * Don't accept zero nlink from non-unix servers unless 843 839 * delete is pending. Instead mark it as unknown. ··· 845 849 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK; 846 850 } 847 851 } 852 + 853 + /* clear write bits if ATTR_READONLY is set */ 854 + if (fattr->cf_cifsattrs & ATTR_READONLY) 855 + fattr->cf_mode &= ~(S_IWUGO); 848 856 849 857 out_reparse: 850 858 if (S_ISLNK(fattr->cf_mode)) { ··· 1267 1267 __func__, rc); 1268 1268 goto out; 1269 1269 } 1270 - } 1271 - 1272 - /* fill in remaining high mode bits e.g. SUID, VTX */ 1273 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) 1270 + } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) 1271 + /* fill in remaining high mode bits e.g. SUID, VTX */ 1274 1272 cifs_sfu_mode(fattr, full_path, cifs_sb, xid); 1273 + else if (!(tcon->posix_extensions)) 1274 + /* clear write bits if ATTR_READONLY is set */ 1275 + if (fattr->cf_cifsattrs & ATTR_READONLY) 1276 + fattr->cf_mode &= ~(S_IWUGO); 1277 + 1275 1278 1276 1279 /* check for Minshall+French symlinks */ 1277 1280 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
+5 -1
fs/smb/client/misc.c
··· 145 145 mutex_init(&ret_buf->fscache_lock); 146 146 #endif 147 147 trace_smb3_tcon_ref(ret_buf->debug_id, ret_buf->tc_count, trace); 148 + #ifdef CONFIG_CIFS_DFS_UPCALL 149 + INIT_LIST_HEAD(&ret_buf->dfs_ses_list); 150 + #endif 148 151 149 152 return ret_buf; 150 153 } ··· 1111 1108 t2 = cifs_sb_master_tcon(cifs_sb); 1112 1109 1113 1110 spin_lock(&t2->tc_lock); 1114 - if (t1->ses == t2->ses && 1111 + if ((t1->ses == t2->ses || 1112 + t1->ses->dfs_root_ses == t2->ses->dfs_root_ses) && 1115 1113 t1->ses->server == t2->ses->server && 1116 1114 t2->origin_fullpath && 1117 1115 dfs_src_pathname_equal(t2->origin_fullpath, t1->origin_fullpath))
+1 -1
fs/smb/client/namespace.c
··· 240 240 ctx->source = NULL; 241 241 goto out; 242 242 } 243 - ctx->dfs_automount = is_dfs_mount(mntpt); 243 + ctx->dfs_automount = ctx->dfs_conn = is_dfs_mount(mntpt); 244 244 cifs_dbg(FYI, "%s: ctx: source=%s UNC=%s prepath=%s dfs_automount=%d\n", 245 245 __func__, ctx->source, ctx->UNC, ctx->prepath, ctx->dfs_automount); 246 246
+5 -5
fs/smb/client/reparse.c
··· 108 108 buf->InodeType = cpu_to_le64(type); 109 109 buf->ReparseDataLength = cpu_to_le16(len + dlen - 110 110 sizeof(struct reparse_data_buffer)); 111 - *(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MAJOR(dev) << 32) | 112 - MINOR(dev)); 111 + *(__le64 *)buf->DataBuffer = cpu_to_le64(((u64)MINOR(dev) << 32) | 112 + MAJOR(dev)); 113 113 iov->iov_base = buf; 114 114 iov->iov_len = len + dlen; 115 115 return 0; ··· 468 468 else if (!strncmp(name, SMB2_WSL_XATTR_MODE, nlen)) 469 469 fattr->cf_mode = (umode_t)le32_to_cpu(*(__le32 *)v); 470 470 else if (!strncmp(name, SMB2_WSL_XATTR_DEV, nlen)) 471 - fattr->cf_rdev = wsl_mkdev(v); 471 + fattr->cf_rdev = reparse_mkdev(v); 472 472 } while (next); 473 473 out: 474 474 fattr->cf_dtype = S_DT(fattr->cf_mode); ··· 485 485 switch (le64_to_cpu(buf->InodeType)) { 486 486 case NFS_SPECFILE_CHR: 487 487 fattr->cf_mode |= S_IFCHR; 488 - fattr->cf_rdev = reparse_nfs_mkdev(buf); 488 + fattr->cf_rdev = reparse_mkdev(buf->DataBuffer); 489 489 break; 490 490 case NFS_SPECFILE_BLK: 491 491 fattr->cf_mode |= S_IFBLK; 492 - fattr->cf_rdev = reparse_nfs_mkdev(buf); 492 + fattr->cf_rdev = reparse_mkdev(buf->DataBuffer); 493 493 break; 494 494 case NFS_SPECFILE_FIFO: 495 495 fattr->cf_mode |= S_IFIFO;
+1 -8
fs/smb/client/reparse.h
··· 18 18 */ 19 19 #define IO_REPARSE_TAG_INTERNAL ((__u32)~0U) 20 20 21 - static inline dev_t reparse_nfs_mkdev(struct reparse_posix_data *buf) 22 - { 23 - u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer); 24 - 25 - return MKDEV(v >> 32, v & 0xffffffff); 26 - } 27 - 28 - static inline dev_t wsl_mkdev(void *ptr) 21 + static inline dev_t reparse_mkdev(void *ptr) 29 22 { 30 23 u64 v = le64_to_cpu(*(__le64 *)ptr); 31 24
+6 -3
fs/smb/client/smb2ops.c
··· 4869 4869 goto discard_data; 4870 4870 4871 4871 server->total_read += rc; 4872 - if (rc < len) 4873 - iov_iter_zero(len - rc, &iter); 4874 - iov_iter_revert(&iter, len); 4872 + if (rc < len) { 4873 + struct iov_iter tmp = iter; 4874 + 4875 + iov_iter_advance(&tmp, rc); 4876 + iov_iter_zero(len - rc, &tmp); 4877 + } 4875 4878 iov_iter_truncate(&iter, dw->len); 4876 4879 4877 4880 rc = cifs_discard_remaining_data(server);
+15 -7
fs/smb/client/smb2pdu.c
··· 4866 4866 #endif 4867 4867 if (result) { 4868 4868 cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); 4869 - trace_smb3_write_err(wdata->xid, 4869 + trace_smb3_write_err(wdata->rreq->debug_id, 4870 + wdata->subreq.debug_index, 4871 + wdata->xid, 4870 4872 wdata->req->cfile->fid.persistent_fid, 4871 4873 tcon->tid, tcon->ses->Suid, wdata->subreq.start, 4872 4874 wdata->subreq.len, wdata->result); ··· 4876 4874 pr_warn_once("Out of space writing to %s\n", 4877 4875 tcon->tree_name); 4878 4876 } else 4879 - trace_smb3_write_done(0 /* no xid */, 4877 + trace_smb3_write_done(wdata->rreq->debug_id, 4878 + wdata->subreq.debug_index, 4879 + wdata->xid, 4880 4880 wdata->req->cfile->fid.persistent_fid, 4881 4881 tcon->tid, tcon->ses->Suid, 4882 4882 wdata->subreq.start, wdata->subreq.len); ··· 4956 4952 offsetof(struct smb2_write_req, Buffer)); 4957 4953 req->RemainingBytes = 0; 4958 4954 4959 - trace_smb3_write_enter(wdata->xid, 4955 + trace_smb3_write_enter(wdata->rreq->debug_id, 4956 + wdata->subreq.debug_index, 4957 + wdata->xid, 4960 4958 io_parms->persistent_fid, 4961 4959 io_parms->tcon->tid, 4962 4960 io_parms->tcon->ses->Suid, ··· 5038 5032 wdata, flags, &wdata->credits); 5039 5033 /* Can't touch wdata if rc == 0 */ 5040 5034 if (rc) { 5041 - trace_smb3_write_err(xid, 5035 + trace_smb3_write_err(wdata->rreq->debug_id, 5036 + wdata->subreq.debug_index, 5037 + xid, 5042 5038 io_parms->persistent_fid, 5043 5039 io_parms->tcon->tid, 5044 5040 io_parms->tcon->ses->Suid, ··· 5120 5112 offsetof(struct smb2_write_req, Buffer)); 5121 5113 req->RemainingBytes = 0; 5122 5114 5123 - trace_smb3_write_enter(xid, io_parms->persistent_fid, 5115 + trace_smb3_write_enter(0, 0, xid, io_parms->persistent_fid, 5124 5116 io_parms->tcon->tid, io_parms->tcon->ses->Suid, 5125 5117 io_parms->offset, io_parms->length); 5126 5118 ··· 5141 5133 rsp = (struct smb2_write_rsp *)rsp_iov.iov_base; 5142 5134 5143 5135 if (rc) { 5144 - trace_smb3_write_err(xid, 5136 + trace_smb3_write_err(0, 0, xid, 5145 5137 req->PersistentFileId, 5146 5138 io_parms->tcon->tid, 5147 5139 io_parms->tcon->ses->Suid, ··· 5150 5142 cifs_dbg(VFS, "Send error in write = %d\n", rc); 5151 5143 } else { 5152 5144 *nbytes = le32_to_cpu(rsp->DataLength); 5153 - trace_smb3_write_done(xid, 5145 + trace_smb3_write_done(0, 0, xid, 5154 5146 req->PersistentFileId, 5155 5147 io_parms->tcon->tid, 5156 5148 io_parms->tcon->ses->Suid,
+3 -3
fs/smb/client/trace.h
··· 157 157 TP_ARGS(rreq_debug_id, rreq_debug_index, xid, fid, tid, sesid, offset, len, rc)) 158 158 159 159 DEFINE_SMB3_RW_ERR_EVENT(read_err); 160 + DEFINE_SMB3_RW_ERR_EVENT(write_err); 160 161 161 162 /* For logging errors in other file I/O ops */ 162 163 DECLARE_EVENT_CLASS(smb3_other_err_class, ··· 203 202 int rc), \ 204 203 TP_ARGS(xid, fid, tid, sesid, offset, len, rc)) 205 204 206 - DEFINE_SMB3_OTHER_ERR_EVENT(write_err); 207 205 DEFINE_SMB3_OTHER_ERR_EVENT(query_dir_err); 208 206 DEFINE_SMB3_OTHER_ERR_EVENT(zero_err); 209 207 DEFINE_SMB3_OTHER_ERR_EVENT(falloc_err); ··· 370 370 371 371 DEFINE_SMB3_RW_DONE_EVENT(read_enter); 372 372 DEFINE_SMB3_RW_DONE_EVENT(read_done); 373 + DEFINE_SMB3_RW_DONE_EVENT(write_enter); 374 + DEFINE_SMB3_RW_DONE_EVENT(write_done); 373 375 374 376 /* For logging successful other op */ 375 377 DECLARE_EVENT_CLASS(smb3_other_done_class, ··· 413 411 __u32 len), \ 414 412 TP_ARGS(xid, fid, tid, sesid, offset, len)) 415 413 416 - DEFINE_SMB3_OTHER_DONE_EVENT(write_enter); 417 414 DEFINE_SMB3_OTHER_DONE_EVENT(query_dir_enter); 418 415 DEFINE_SMB3_OTHER_DONE_EVENT(zero_enter); 419 416 DEFINE_SMB3_OTHER_DONE_EVENT(falloc_enter); 420 - DEFINE_SMB3_OTHER_DONE_EVENT(write_done); 421 417 DEFINE_SMB3_OTHER_DONE_EVENT(query_dir_done); 422 418 DEFINE_SMB3_OTHER_DONE_EVENT(zero_done); 423 419 DEFINE_SMB3_OTHER_DONE_EVENT(falloc_done);
-3
fs/smb/client/transport.c
··· 1817 1817 length = data_len; /* An RDMA read is already done. */ 1818 1818 else 1819 1819 #endif 1820 - { 1821 1820 length = cifs_read_iter_from_socket(server, &rdata->subreq.io_iter, 1822 1821 data_len); 1823 - iov_iter_revert(&rdata->subreq.io_iter, data_len); 1824 - } 1825 1822 if (length > 0) 1826 1823 rdata->got_bytes += length; 1827 1824 server->total_read += length;