app-emulation/runc: Remove old
[gentoo.git] / sys-fs / ntfs3g / files / ntfs3g-2014.2.15-fix-fstrim-applied-to-partitons.patch
1 From c26a519da1ed182e7cfd67e7a353932dda53d811 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Jean-Pierre=20Andr=C3=A9?= <jpandre@users.sourceforge.net>
3 Date: Mon, 4 Aug 2014 17:39:50 +0200
4 Subject: [PATCH] Fixed fstrim(8) applied to partitions
5
6 The new way goes via /sys/dev/block/MAJOR:MINOR to map partitions to
7 devices and get discard parameters of the parent device. It also ensures
8 that the partition is aligned to the discard block size.
9
10 Contributed by Richard W.M. Jones
11 ---
12  libntfs-3g/ioctl.c | 140 ++++++++++++++++++++++++++---------------------------
13  1 file changed, 68 insertions(+), 72 deletions(-)
14
15 diff --git a/libntfs-3g/ioctl.c b/libntfs-3g/ioctl.c
16 index bbbceb9..eb7c8e7 100644
17 --- a/libntfs-3g/ioctl.c
18 +++ b/libntfs-3g/ioctl.c
19 @@ -66,8 +66,6 @@
20  #include <linux/fs.h>
21  #endif
22  
23 -#include <dirent.h>
24 -
25  #include "compat.h"
26  #include "debug.h"
27  #include "bitmap.h"
28 @@ -135,17 +133,14 @@ static int read_u64(const char *path, u64 *n)
29  }
30  
31  /* Find discard limits for current backing device.
32 - * XXX Kernel makes this a pain in the neck.
33   */
34 -static int fstrim_limits(ntfs_volume *vol, u64 *discard_granularity,
35 +static int fstrim_limits(ntfs_volume *vol,
36 +                       u64 *discard_alignment,
37 +                       u64 *discard_granularity,
38                         u64 *discard_max_bytes)
39  {
40         struct stat statbuf;
41 -       DIR *dir;
42 -       struct dirent *d;
43 -       char path[80];
44 -       char line[64];
45 -       char dev[64];
46 +       char path1[80], path2[80];
47         int ret;
48  
49         /* Stat the backing device.  Caller has ensured it is a block device. */
50 @@ -155,82 +150,78 @@ static int fstrim_limits(ntfs_volume *vol, u64 *discard_granularity,
51                 return -errno;
52         }
53  
54 -       /* Now look for a /sys/block/<dev>/dev file which contains
55 -        * "major:minor\n".
56 +       /* For whole devices,
57 +        * /sys/dev/block/MAJOR:MINOR/discard_alignment
58 +        * /sys/dev/block/MAJOR:MINOR/queue/discard_granularity
59 +        * /sys/dev/block/MAJOR:MINOR/queue/discard_max_bytes
60 +        * will exist.
61 +        * For partitions, we also need to check the parent device:
62 +        * /sys/dev/block/MAJOR:MINOR/../queue/discard_granularity
63 +        * /sys/dev/block/MAJOR:MINOR/../queue/discard_max_bytes
64          */
65 -       snprintf(dev, sizeof dev, "%d:%d\n",
66 +       snprintf(path1, sizeof path1, "/sys/dev/block/%d:%d",
67                 major(statbuf.st_rdev), minor(statbuf.st_rdev));
68  
69 -       dir = opendir("/sys/block");
70 -       if (dir == NULL) {
71 -               ntfs_log_debug("fstrim_limits: could not open /sys/block\n");
72 -               return -errno;
73 +       snprintf(path2, sizeof path2, "%s/discard_alignment", path1);
74 +       ret = read_u64(path2, discard_alignment);
75 +       if (ret) {
76 +               if (ret != -ENOENT)
77 +                       return ret;
78 +               else
79 +                       /* We would expect this file to exist on all
80 +                        * modern kernels.  But for the sake of very
81 +                        * old kernels:
82 +                        */
83 +                       goto not_found;
84         }
85 -       for (;;) {
86 -               errno = 0;
87 -               d = readdir(dir);
88 -               if (!d) break;
89  
90 -               snprintf(path, sizeof path, "/sys/block/%s/dev", d->d_name);
91 -               ret = read_line(path, line, sizeof line);
92 -               if (ret)
93 -                       continue;
94 -               if (strcmp(line, dev) == 0)
95 -                       goto found;
96 +       snprintf(path2, sizeof path2, "%s/queue/discard_granularity", path1);
97 +       ret = read_u64(path2, discard_granularity);
98 +       if (ret) {
99 +               if (ret != -ENOENT)
100 +                       return ret;
101 +               else {
102 +                       snprintf(path2, sizeof path2,
103 +                               "%s/../queue/discard_granularity", path1);
104 +                       ret = read_u64(path2, discard_granularity);
105 +                       if (ret) {
106 +                               if (ret != -ENOENT)
107 +                                       return ret;
108 +                               else
109 +                                       goto not_found;
110 +                       }
111 +               }
112         }
113  
114 -       /* Check readdir didn't fail. */
115 -       if (errno != 0) {
116 -               ret = -errno;
117 -               ntfs_log_debug("fstrim_limits: readdir failed\n");
118 -               goto out;
119 +       snprintf(path2, sizeof path2, "%s/queue/discard_max_bytes", path1);
120 +       ret = read_u64(path2, discard_max_bytes);
121 +       if (ret) {
122 +               if (ret != -ENOENT)
123 +                       return ret;
124 +               else {
125 +                       snprintf(path2, sizeof path2,
126 +                               "%s/../queue/discard_max_bytes", path1);
127 +                       ret = read_u64(path2, discard_max_bytes);
128 +                       if (ret) {
129 +                               if (ret != -ENOENT)
130 +                                       return ret;
131 +                               else
132 +                                       goto not_found;
133 +                       }
134 +               }
135         }
136  
137 +       return 0;
138 +
139 +not_found:
140         /* If we reach here then we didn't find the device.  This is
141          * not an error, but set discard_max_bytes = 0 to indicate
142          * that discard is not available.
143          */
144 +       *discard_alignment = 0;
145         *discard_granularity = 0;
146         *discard_max_bytes = 0;
147 -       ntfs_log_debug("fstrim_limits: /sys/block entry corresponding to device %s not found\n",
148 -               vol->dev->d_name);
149 -       ret = 0;
150 -       goto out;
151 -
152 -found:
153 -       /* Found the device at /sys/block/ + d->d_name */
154 -       snprintf (path, sizeof path,
155 -               "/sys/block/%s/queue/discard_granularity",
156 -               d->d_name);
157 -       ret = read_u64(path, discard_granularity);
158 -       if (ret) {
159 -               ntfs_log_debug("fstrim_limits: could not read %s\n", path);
160 -               goto out;
161 -       }
162 -
163 -       snprintf (path, sizeof path,
164 -               "/sys/block/%s/queue/discard_max_bytes",
165 -               d->d_name);
166 -       ret = read_u64(path, discard_max_bytes);
167 -       if (ret) {
168 -               ntfs_log_debug("fstrim_limits: could not read %s\n", path);
169 -               goto out;
170 -       }
171 -
172 -       ntfs_log_debug("fstrim_limits: device %s discard granularity = %llu max_bytes = %llu\n",
173 -               d->d_name,
174 -               (unsigned long long) *discard_granularity,
175 -               (unsigned long long) *discard_max_bytes);
176 -
177 -       ret = 0;
178 -out:
179 -       if (closedir (dir) == -1) {
180 -               ret = -errno;
181 -               ntfs_log_debug("fstrim_limits: closedir failed\n");
182 -               return ret;
183 -       }
184 -
185 -       return ret;
186 +       return 0;
187  }
188  
189  #define FSTRIM_BUFSIZ 4096
190 @@ -247,7 +238,7 @@ static int fstrim(ntfs_volume *vol, void *data)
191         u64 start = range->start;
192         u64 len = range->len;
193         u64 minlen = range->minlen;
194 -       u64 discard_granularity, discard_max_bytes;
195 +       u64 discard_alignment, discard_granularity, discard_max_bytes;
196         u8 *buf = NULL;
197         LCN start_buf;
198         int ret;
199 @@ -279,9 +270,14 @@ static int fstrim(ntfs_volume *vol, void *data)
200                 return -EOPNOTSUPP;
201         }
202  
203 -       ret = fstrim_limits(vol, &discard_granularity, &discard_max_bytes);
204 +       ret = fstrim_limits(vol, &discard_alignment,
205 +                       &discard_granularity, &discard_max_bytes);
206         if (ret)
207                 return ret;
208 +       if (discard_alignment != 0) {
209 +               ntfs_log_debug("fstrim: backing device is not aligned for discards\n");
210 +               return -EOPNOTSUPP;
211 +       }
212         if (discard_granularity > vol->cluster_size) {
213                 ntfs_log_debug("fstrim: discard granularity of backing device is larger than cluster size\n");
214                 return -EOPNOTSUPP;
215 -- 
216 1.9.3
217