diff options
Diffstat (limited to 'recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.12/0010-CIFS-Do-not-kmalloc-under-the-flocks-spinlock.patch')
-rw-r--r-- | recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.12/0010-CIFS-Do-not-kmalloc-under-the-flocks-spinlock.patch | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.12/0010-CIFS-Do-not-kmalloc-under-the-flocks-spinlock.patch b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.12/0010-CIFS-Do-not-kmalloc-under-the-flocks-spinlock.patch new file mode 100644 index 00000000..150144c3 --- /dev/null +++ b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.12/0010-CIFS-Do-not-kmalloc-under-the-flocks-spinlock.patch | |||
@@ -0,0 +1,140 @@ | |||
1 | From 6fc4721b47d58ae599a4bb37869d4bfd41f70511 Mon Sep 17 00:00:00 2001 | ||
2 | From: Pavel Shilovsky <piastry@etersoft.ru> | ||
3 | Date: Mon, 5 Mar 2012 09:39:20 +0300 | ||
4 | Subject: [PATCH 10/42] CIFS: Do not kmalloc under the flocks spinlock | ||
5 | |||
6 | commit d5751469f210d2149cc2159ffff66cbeef6da3f2 upstream. | ||
7 | |||
8 | Reorganize the code to make the memory already allocated before | ||
9 | spinlock'ed loop. | ||
10 | |||
11 | Reviewed-by: Jeff Layton <jlayton@redhat.com> | ||
12 | Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> | ||
13 | Signed-off-by: Steve French <sfrench@us.ibm.com> | ||
14 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||
15 | --- | ||
16 | fs/cifs/file.c | 69 +++++++++++++++++++++++++++++++++++++++++++++----------- | ||
17 | 1 file changed, 56 insertions(+), 13 deletions(-) | ||
18 | |||
19 | diff --git a/fs/cifs/file.c b/fs/cifs/file.c | ||
20 | index 4dd9283..5e64748 100644 | ||
21 | --- a/fs/cifs/file.c | ||
22 | +++ b/fs/cifs/file.c | ||
23 | @@ -920,16 +920,26 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | ||
24 | for (lockp = &inode->i_flock; *lockp != NULL; \ | ||
25 | lockp = &(*lockp)->fl_next) | ||
26 | |||
27 | +struct lock_to_push { | ||
28 | + struct list_head llist; | ||
29 | + __u64 offset; | ||
30 | + __u64 length; | ||
31 | + __u32 pid; | ||
32 | + __u16 netfid; | ||
33 | + __u8 type; | ||
34 | +}; | ||
35 | + | ||
36 | static int | ||
37 | cifs_push_posix_locks(struct cifsFileInfo *cfile) | ||
38 | { | ||
39 | struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); | ||
40 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); | ||
41 | struct file_lock *flock, **before; | ||
42 | - struct cifsLockInfo *lck, *tmp; | ||
43 | + unsigned int count = 0, i = 0; | ||
44 | int rc = 0, xid, type; | ||
45 | + struct list_head locks_to_send, *el; | ||
46 | + struct lock_to_push *lck, *tmp; | ||
47 | __u64 length; | ||
48 | - struct list_head locks_to_send; | ||
49 | |||
50 | xid = GetXid(); | ||
51 | |||
52 | @@ -940,29 +950,55 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | ||
53 | return rc; | ||
54 | } | ||
55 | |||
56 | + lock_flocks(); | ||
57 | + cifs_for_each_lock(cfile->dentry->d_inode, before) { | ||
58 | + if ((*before)->fl_flags & FL_POSIX) | ||
59 | + count++; | ||
60 | + } | ||
61 | + unlock_flocks(); | ||
62 | + | ||
63 | INIT_LIST_HEAD(&locks_to_send); | ||
64 | |||
65 | + /* | ||
66 | + * Allocating count locks is enough because no locks can be added to | ||
67 | + * the list while we are holding cinode->lock_mutex that protects | ||
68 | + * locking operations of this inode. | ||
69 | + */ | ||
70 | + for (; i < count; i++) { | ||
71 | + lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL); | ||
72 | + if (!lck) { | ||
73 | + rc = -ENOMEM; | ||
74 | + goto err_out; | ||
75 | + } | ||
76 | + list_add_tail(&lck->llist, &locks_to_send); | ||
77 | + } | ||
78 | + | ||
79 | + i = 0; | ||
80 | + el = locks_to_send.next; | ||
81 | lock_flocks(); | ||
82 | cifs_for_each_lock(cfile->dentry->d_inode, before) { | ||
83 | + if (el == &locks_to_send) { | ||
84 | + /* something is really wrong */ | ||
85 | + cERROR(1, "Can't push all brlocks!"); | ||
86 | + break; | ||
87 | + } | ||
88 | flock = *before; | ||
89 | + if ((flock->fl_flags & FL_POSIX) == 0) | ||
90 | + continue; | ||
91 | length = 1 + flock->fl_end - flock->fl_start; | ||
92 | if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK) | ||
93 | type = CIFS_RDLCK; | ||
94 | else | ||
95 | type = CIFS_WRLCK; | ||
96 | - | ||
97 | - lck = cifs_lock_init(flock->fl_start, length, type, | ||
98 | - cfile->netfid); | ||
99 | - if (!lck) { | ||
100 | - rc = -ENOMEM; | ||
101 | - goto send_locks; | ||
102 | - } | ||
103 | + lck = list_entry(el, struct lock_to_push, llist); | ||
104 | lck->pid = flock->fl_pid; | ||
105 | - | ||
106 | - list_add_tail(&lck->llist, &locks_to_send); | ||
107 | + lck->netfid = cfile->netfid; | ||
108 | + lck->length = length; | ||
109 | + lck->type = type; | ||
110 | + lck->offset = flock->fl_start; | ||
111 | + i++; | ||
112 | + el = el->next; | ||
113 | } | ||
114 | - | ||
115 | -send_locks: | ||
116 | unlock_flocks(); | ||
117 | |||
118 | list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) { | ||
119 | @@ -979,11 +1015,18 @@ send_locks: | ||
120 | kfree(lck); | ||
121 | } | ||
122 | |||
123 | +out: | ||
124 | cinode->can_cache_brlcks = false; | ||
125 | mutex_unlock(&cinode->lock_mutex); | ||
126 | |||
127 | FreeXid(xid); | ||
128 | return rc; | ||
129 | +err_out: | ||
130 | + list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) { | ||
131 | + list_del(&lck->llist); | ||
132 | + kfree(lck); | ||
133 | + } | ||
134 | + goto out; | ||
135 | } | ||
136 | |||
137 | static int | ||
138 | -- | ||
139 | 1.7.9.4 | ||
140 | |||