Commit a5c984cc2986c3ed88615fec01e433f9019ff011
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6
Pull CIFS fixes from Steve French: "Small set of cifs fixes. Most important is Jeff's fix that works around disconnection problems which can be caused by simultaneous use of user space tools (starting a long running smbclient backup then doing a cifs kernel mount) or multiple cifs mounts through a NAT, and Jim's fix to deal with reexport of cifs share. I expect to send two more cifs fixes next week (being tested now) - fixes to address an SMB2 unmount hang when server dies and a fix for cifs symlink handling of Windows "NFS" symlinks" * 'for-linus' of git://git.samba.org/sfrench/cifs-2.6: [CIFS] update cifs.ko version [CIFS] Remove ext2 flags that have been moved to fs.h [CIFS] Provide sane values for nlink cifs: stop trying to use virtual circuits CIFS: FS-Cache: Uncache unread pages in cifs_readpages() before freeing them
Showing 10 changed files Side-by-side Diff
fs/cifs/cifsfs.h
fs/cifs/cifsglob.h
... | ... | @@ -547,9 +547,6 @@ |
547 | 547 | unsigned int max_rw; /* maxRw specifies the maximum */ |
548 | 548 | /* message size the server can send or receive for */ |
549 | 549 | /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ |
550 | - unsigned int max_vcs; /* maximum number of smb sessions, at least | |
551 | - those that can be specified uniquely with | |
552 | - vcnumbers */ | |
553 | 550 | unsigned int capabilities; /* selective disabling of caps by smb sess */ |
554 | 551 | int timeAdj; /* Adjust for difference in server time zone in sec */ |
555 | 552 | __u64 CurrentMid; /* multiplex id - rotating counter */ |
... | ... | @@ -715,7 +712,6 @@ |
715 | 712 | enum statusEnum status; |
716 | 713 | unsigned overrideSecFlg; /* if non-zero override global sec flags */ |
717 | 714 | __u16 ipc_tid; /* special tid for connection to IPC share */ |
718 | - __u16 vcnum; | |
719 | 715 | char *serverOS; /* name of operating system underlying server */ |
720 | 716 | char *serverNOS; /* name of network operating system of server */ |
721 | 717 | char *serverDomain; /* security realm of server */ |
... | ... | @@ -1272,6 +1268,7 @@ |
1272 | 1268 | #define CIFS_FATTR_DELETE_PENDING 0x2 |
1273 | 1269 | #define CIFS_FATTR_NEED_REVAL 0x4 |
1274 | 1270 | #define CIFS_FATTR_INO_COLLISION 0x8 |
1271 | +#define CIFS_FATTR_UNKNOWN_NLINK 0x10 | |
1275 | 1272 | |
1276 | 1273 | struct cifs_fattr { |
1277 | 1274 | u32 cf_flags; |
fs/cifs/cifspdu.h
... | ... | @@ -2652,26 +2652,7 @@ |
2652 | 2652 | } __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute info |
2653 | 2653 | level 0x205 */ |
2654 | 2654 | |
2655 | - | |
2656 | -/* flags for chattr command */ | |
2657 | -#define EXT_SECURE_DELETE 0x00000001 /* EXT3_SECRM_FL */ | |
2658 | -#define EXT_ENABLE_UNDELETE 0x00000002 /* EXT3_UNRM_FL */ | |
2659 | -/* Reserved for compress file 0x4 */ | |
2660 | -#define EXT_SYNCHRONOUS 0x00000008 /* EXT3_SYNC_FL */ | |
2661 | -#define EXT_IMMUTABLE_FL 0x00000010 /* EXT3_IMMUTABLE_FL */ | |
2662 | -#define EXT_OPEN_APPEND_ONLY 0x00000020 /* EXT3_APPEND_FL */ | |
2663 | -#define EXT_DO_NOT_BACKUP 0x00000040 /* EXT3_NODUMP_FL */ | |
2664 | -#define EXT_NO_UPDATE_ATIME 0x00000080 /* EXT3_NOATIME_FL */ | |
2665 | -/* 0x100 through 0x800 reserved for compression flags and are GET-ONLY */ | |
2666 | -#define EXT_HASH_TREE_INDEXED_DIR 0x00001000 /* GET-ONLY EXT3_INDEX_FL */ | |
2667 | -/* 0x2000 reserved for IMAGIC_FL */ | |
2668 | -#define EXT_JOURNAL_THIS_FILE 0x00004000 /* GET-ONLY EXT3_JOURNAL_DATA_FL */ | |
2669 | -/* 0x8000 reserved for EXT3_NOTAIL_FL */ | |
2670 | -#define EXT_SYNCHRONOUS_DIR 0x00010000 /* EXT3_DIRSYNC_FL */ | |
2671 | -#define EXT_TOPDIR 0x00020000 /* EXT3_TOPDIR_FL */ | |
2672 | - | |
2673 | -#define EXT_SET_MASK 0x000300FF | |
2674 | -#define EXT_GET_MASK 0x0003DFFF | |
2655 | +/* flags for lsattr and chflags commands removed arein uapi/linux/fs.h */ | |
2675 | 2656 | |
2676 | 2657 | typedef struct file_chattr_info { |
2677 | 2658 | __le64 mask; /* list of all possible attribute bits */ |
fs/cifs/cifssmb.c
... | ... | @@ -463,7 +463,6 @@ |
463 | 463 | cifs_max_pending); |
464 | 464 | set_credits(server, server->maxReq); |
465 | 465 | server->maxBuf = le16_to_cpu(rsp->MaxBufSize); |
466 | - server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); | |
467 | 466 | /* even though we do not use raw we might as well set this |
468 | 467 | accurately, in case we ever find a need for it */ |
469 | 468 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { |
fs/cifs/file.c
... | ... | @@ -3254,6 +3254,9 @@ |
3254 | 3254 | /* |
3255 | 3255 | * Reads as many pages as possible from fscache. Returns -ENOBUFS |
3256 | 3256 | * immediately if the cookie is negative |
3257 | + * | |
3258 | + * After this point, every page in the list might have PG_fscache set, | |
3259 | + * so we will need to clean that up off of every page we don't use. | |
3257 | 3260 | */ |
3258 | 3261 | rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list, |
3259 | 3262 | &num_pages); |
... | ... | @@ -3376,6 +3379,11 @@ |
3376 | 3379 | kref_put(&rdata->refcount, cifs_readdata_release); |
3377 | 3380 | } |
3378 | 3381 | |
3382 | + /* Any pages that have been shown to fscache but didn't get added to | |
3383 | + * the pagecache must be uncached before they get returned to the | |
3384 | + * allocator. | |
3385 | + */ | |
3386 | + cifs_fscache_readpages_cancel(mapping->host, page_list); | |
3379 | 3387 | return rc; |
3380 | 3388 | } |
3381 | 3389 |
fs/cifs/fscache.c
... | ... | @@ -223,6 +223,13 @@ |
223 | 223 | fscache_uncache_page(CIFS_I(inode)->fscache, page); |
224 | 224 | } |
225 | 225 | |
226 | +void __cifs_fscache_readpages_cancel(struct inode *inode, struct list_head *pages) | |
227 | +{ | |
228 | + cifs_dbg(FYI, "%s: (fsc: %p, i: %p)\n", | |
229 | + __func__, CIFS_I(inode)->fscache, inode); | |
230 | + fscache_readpages_cancel(CIFS_I(inode)->fscache, pages); | |
231 | +} | |
232 | + | |
226 | 233 | void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode) |
227 | 234 | { |
228 | 235 | struct cifsInodeInfo *cifsi = CIFS_I(inode); |
fs/cifs/fscache.h
... | ... | @@ -54,6 +54,7 @@ |
54 | 54 | struct address_space *, |
55 | 55 | struct list_head *, |
56 | 56 | unsigned *); |
57 | +extern void __cifs_fscache_readpages_cancel(struct inode *, struct list_head *); | |
57 | 58 | |
58 | 59 | extern void __cifs_readpage_to_fscache(struct inode *, struct page *); |
59 | 60 | |
... | ... | @@ -91,6 +92,13 @@ |
91 | 92 | __cifs_readpage_to_fscache(inode, page); |
92 | 93 | } |
93 | 94 | |
95 | +static inline void cifs_fscache_readpages_cancel(struct inode *inode, | |
96 | + struct list_head *pages) | |
97 | +{ | |
98 | + if (CIFS_I(inode)->fscache) | |
99 | + return __cifs_fscache_readpages_cancel(inode, pages); | |
100 | +} | |
101 | + | |
94 | 102 | #else /* CONFIG_CIFS_FSCACHE */ |
95 | 103 | static inline int cifs_fscache_register(void) { return 0; } |
96 | 104 | static inline void cifs_fscache_unregister(void) {} |
... | ... | @@ -130,6 +138,11 @@ |
130 | 138 | |
131 | 139 | static inline void cifs_readpage_to_fscache(struct inode *inode, |
132 | 140 | struct page *page) {} |
141 | + | |
142 | +static inline void cifs_fscache_readpages_cancel(struct inode *inode, | |
143 | + struct list_head *pages) | |
144 | +{ | |
145 | +} | |
133 | 146 | |
134 | 147 | #endif /* CONFIG_CIFS_FSCACHE */ |
135 | 148 |
fs/cifs/inode.c
... | ... | @@ -120,6 +120,33 @@ |
120 | 120 | cifs_i->invalid_mapping = true; |
121 | 121 | } |
122 | 122 | |
123 | +/* | |
124 | + * copy nlink to the inode, unless it wasn't provided. Provide | |
125 | + * sane values if we don't have an existing one and none was provided | |
126 | + */ | |
127 | +static void | |
128 | +cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | |
129 | +{ | |
130 | + /* | |
131 | + * if we're in a situation where we can't trust what we | |
132 | + * got from the server (readdir, some non-unix cases) | |
133 | + * fake reasonable values | |
134 | + */ | |
135 | + if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) { | |
136 | + /* only provide fake values on a new inode */ | |
137 | + if (inode->i_state & I_NEW) { | |
138 | + if (fattr->cf_cifsattrs & ATTR_DIRECTORY) | |
139 | + set_nlink(inode, 2); | |
140 | + else | |
141 | + set_nlink(inode, 1); | |
142 | + } | |
143 | + return; | |
144 | + } | |
145 | + | |
146 | + /* we trust the server, so update it */ | |
147 | + set_nlink(inode, fattr->cf_nlink); | |
148 | +} | |
149 | + | |
123 | 150 | /* populate an inode with info from a cifs_fattr struct */ |
124 | 151 | void |
125 | 152 | cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) |
... | ... | @@ -134,7 +161,7 @@ |
134 | 161 | inode->i_mtime = fattr->cf_mtime; |
135 | 162 | inode->i_ctime = fattr->cf_ctime; |
136 | 163 | inode->i_rdev = fattr->cf_rdev; |
137 | - set_nlink(inode, fattr->cf_nlink); | |
164 | + cifs_nlink_fattr_to_inode(inode, fattr); | |
138 | 165 | inode->i_uid = fattr->cf_uid; |
139 | 166 | inode->i_gid = fattr->cf_gid; |
140 | 167 | |
... | ... | @@ -541,6 +568,7 @@ |
541 | 568 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); |
542 | 569 | fattr->cf_createtime = le64_to_cpu(info->CreationTime); |
543 | 570 | |
571 | + fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); | |
544 | 572 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { |
545 | 573 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; |
546 | 574 | fattr->cf_dtype = DT_DIR; |
... | ... | @@ -548,7 +576,8 @@ |
548 | 576 | * Server can return wrong NumberOfLinks value for directories |
549 | 577 | * when Unix extensions are disabled - fake it. |
550 | 578 | */ |
551 | - fattr->cf_nlink = 2; | |
579 | + if (!tcon->unix_ext) | |
580 | + fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK; | |
552 | 581 | } else if (fattr->cf_cifsattrs & ATTR_REPARSE) { |
553 | 582 | fattr->cf_mode = S_IFLNK; |
554 | 583 | fattr->cf_dtype = DT_LNK; |
555 | 584 | |
... | ... | @@ -561,11 +590,15 @@ |
561 | 590 | if (fattr->cf_cifsattrs & ATTR_READONLY) |
562 | 591 | fattr->cf_mode &= ~(S_IWUGO); |
563 | 592 | |
564 | - fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); | |
565 | - if (fattr->cf_nlink < 1) { | |
566 | - cifs_dbg(1, "replacing bogus file nlink value %u\n", | |
593 | + /* | |
594 | + * Don't accept zero nlink from non-unix servers unless | |
595 | + * delete is pending. Instead mark it as unknown. | |
596 | + */ | |
597 | + if ((fattr->cf_nlink < 1) && !tcon->unix_ext && | |
598 | + !info->DeletePending) { | |
599 | + cifs_dbg(1, "bogus file nlink value %u\n", | |
567 | 600 | fattr->cf_nlink); |
568 | - fattr->cf_nlink = 1; | |
601 | + fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK; | |
569 | 602 | } |
570 | 603 | } |
571 | 604 |
fs/cifs/readdir.c
fs/cifs/sess.c
... | ... | @@ -32,88 +32,6 @@ |
32 | 32 | #include <linux/slab.h> |
33 | 33 | #include "cifs_spnego.h" |
34 | 34 | |
35 | -/* | |
36 | - * Checks if this is the first smb session to be reconnected after | |
37 | - * the socket has been reestablished (so we know whether to use vc 0). | |
38 | - * Called while holding the cifs_tcp_ses_lock, so do not block | |
39 | - */ | |
40 | -static bool is_first_ses_reconnect(struct cifs_ses *ses) | |
41 | -{ | |
42 | - struct list_head *tmp; | |
43 | - struct cifs_ses *tmp_ses; | |
44 | - | |
45 | - list_for_each(tmp, &ses->server->smb_ses_list) { | |
46 | - tmp_ses = list_entry(tmp, struct cifs_ses, | |
47 | - smb_ses_list); | |
48 | - if (tmp_ses->need_reconnect == false) | |
49 | - return false; | |
50 | - } | |
51 | - /* could not find a session that was already connected, | |
52 | - this must be the first one we are reconnecting */ | |
53 | - return true; | |
54 | -} | |
55 | - | |
56 | -/* | |
57 | - * vc number 0 is treated specially by some servers, and should be the | |
58 | - * first one we request. After that we can use vcnumbers up to maxvcs, | |
59 | - * one for each smb session (some Windows versions set maxvcs incorrectly | |
60 | - * so maxvc=1 can be ignored). If we have too many vcs, we can reuse | |
61 | - * any vc but zero (some servers reset the connection on vcnum zero) | |
62 | - * | |
63 | - */ | |
64 | -static __le16 get_next_vcnum(struct cifs_ses *ses) | |
65 | -{ | |
66 | - __u16 vcnum = 0; | |
67 | - struct list_head *tmp; | |
68 | - struct cifs_ses *tmp_ses; | |
69 | - __u16 max_vcs = ses->server->max_vcs; | |
70 | - __u16 i; | |
71 | - int free_vc_found = 0; | |
72 | - | |
73 | - /* Quoting the MS-SMB specification: "Windows-based SMB servers set this | |
74 | - field to one but do not enforce this limit, which allows an SMB client | |
75 | - to establish more virtual circuits than allowed by this value ... but | |
76 | - other server implementations can enforce this limit." */ | |
77 | - if (max_vcs < 2) | |
78 | - max_vcs = 0xFFFF; | |
79 | - | |
80 | - spin_lock(&cifs_tcp_ses_lock); | |
81 | - if ((ses->need_reconnect) && is_first_ses_reconnect(ses)) | |
82 | - goto get_vc_num_exit; /* vcnum will be zero */ | |
83 | - for (i = ses->server->srv_count - 1; i < max_vcs; i++) { | |
84 | - if (i == 0) /* this is the only connection, use vc 0 */ | |
85 | - break; | |
86 | - | |
87 | - free_vc_found = 1; | |
88 | - | |
89 | - list_for_each(tmp, &ses->server->smb_ses_list) { | |
90 | - tmp_ses = list_entry(tmp, struct cifs_ses, | |
91 | - smb_ses_list); | |
92 | - if (tmp_ses->vcnum == i) { | |
93 | - free_vc_found = 0; | |
94 | - break; /* found duplicate, try next vcnum */ | |
95 | - } | |
96 | - } | |
97 | - if (free_vc_found) | |
98 | - break; /* we found a vcnumber that will work - use it */ | |
99 | - } | |
100 | - | |
101 | - if (i == 0) | |
102 | - vcnum = 0; /* for most common case, ie if one smb session, use | |
103 | - vc zero. Also for case when no free vcnum, zero | |
104 | - is safest to send (some clients only send zero) */ | |
105 | - else if (free_vc_found == 0) | |
106 | - vcnum = 1; /* we can not reuse vc=0 safely, since some servers | |
107 | - reset all uids on that, but 1 is ok. */ | |
108 | - else | |
109 | - vcnum = i; | |
110 | - ses->vcnum = vcnum; | |
111 | -get_vc_num_exit: | |
112 | - spin_unlock(&cifs_tcp_ses_lock); | |
113 | - | |
114 | - return cpu_to_le16(vcnum); | |
115 | -} | |
116 | - | |
117 | 35 | static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB) |
118 | 36 | { |
119 | 37 | __u32 capabilities = 0; |
... | ... | @@ -128,7 +46,7 @@ |
128 | 46 | CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4, |
129 | 47 | USHRT_MAX)); |
130 | 48 | pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); |
131 | - pSMB->req.VcNumber = get_next_vcnum(ses); | |
49 | + pSMB->req.VcNumber = __constant_cpu_to_le16(1); | |
132 | 50 | |
133 | 51 | /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ |
134 | 52 |