diff options
| -rw-r--r-- | fs/cifs/cifssmb.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 5b400730c213..4ee522b3f66f 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -86,7 +86,31 @@ static struct { | |||
| 86 | #endif /* CONFIG_CIFS_WEAK_PW_HASH */ | 86 | #endif /* CONFIG_CIFS_WEAK_PW_HASH */ |
| 87 | #endif /* CIFS_POSIX */ | 87 | #endif /* CIFS_POSIX */ |
| 88 | 88 | ||
| 89 | /* Forward declarations */ | 89 | #ifdef CONFIG_HIGHMEM |
| 90 | /* | ||
| 91 | * On arches that have high memory, kmap address space is limited. By | ||
| 92 | * serializing the kmap operations on those arches, we ensure that we don't | ||
| 93 | * end up with a bunch of threads in writeback with partially mapped page | ||
| 94 | * arrays, stuck waiting for kmap to come back. That situation prevents | ||
| 95 | * progress and can deadlock. | ||
| 96 | */ | ||
| 97 | static DEFINE_MUTEX(cifs_kmap_mutex); | ||
| 98 | |||
| 99 | static inline void | ||
| 100 | cifs_kmap_lock(void) | ||
| 101 | { | ||
| 102 | mutex_lock(&cifs_kmap_mutex); | ||
| 103 | } | ||
| 104 | |||
| 105 | static inline void | ||
| 106 | cifs_kmap_unlock(void) | ||
| 107 | { | ||
| 108 | mutex_unlock(&cifs_kmap_mutex); | ||
| 109 | } | ||
| 110 | #else /* !CONFIG_HIGHMEM */ | ||
| 111 | #define cifs_kmap_lock() do { ; } while(0) | ||
| 112 | #define cifs_kmap_unlock() do { ; } while(0) | ||
| 113 | #endif /* CONFIG_HIGHMEM */ | ||
| 90 | 114 | ||
| 91 | /* Mark as invalid, all open files on tree connections since they | 115 | /* Mark as invalid, all open files on tree connections since they |
| 92 | were closed when session to server was lost */ | 116 | were closed when session to server was lost */ |
| @@ -1503,7 +1527,9 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
| 1503 | } | 1527 | } |
| 1504 | 1528 | ||
| 1505 | /* marshal up the page array */ | 1529 | /* marshal up the page array */ |
| 1530 | cifs_kmap_lock(); | ||
| 1506 | len = rdata->marshal_iov(rdata, data_len); | 1531 | len = rdata->marshal_iov(rdata, data_len); |
| 1532 | cifs_kmap_unlock(); | ||
| 1507 | data_len -= len; | 1533 | data_len -= len; |
| 1508 | 1534 | ||
| 1509 | /* issue the read if we have any iovecs left to fill */ | 1535 | /* issue the read if we have any iovecs left to fill */ |
| @@ -2069,7 +2095,9 @@ cifs_async_writev(struct cifs_writedata *wdata) | |||
| 2069 | * and set the iov_len properly for each one. It may also set | 2095 | * and set the iov_len properly for each one. It may also set |
| 2070 | * wdata->bytes too. | 2096 | * wdata->bytes too. |
| 2071 | */ | 2097 | */ |
| 2098 | cifs_kmap_lock(); | ||
| 2072 | wdata->marshal_iov(iov, wdata); | 2099 | wdata->marshal_iov(iov, wdata); |
| 2100 | cifs_kmap_unlock(); | ||
| 2073 | 2101 | ||
| 2074 | cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); | 2102 | cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); |
| 2075 | 2103 | ||
