From: Goffredo Baroncelli <kreijack@libero.it>
To: Hugo Mills <hugo@carfax.org.uk>,
kreijack@inwind.it, Jan Schmidt <list.btrfs@jan-o-sch.net>,
linux-btrfs <linux-btrfs@vger.kernel.org>
Subject: Re: [btrfs-progs] [bug][patch V2] Leaking file handle in scrub_fs_info()
Date: Tue, 05 Jun 2012 19:26:34 +0200 [thread overview]
Message-ID: <4FCE414A.10106@libero.it> (raw)
In-Reply-To: <20120605110107.GF15986@carfax.org.uk>
[-- Attachment #1: Type: text/plain, Size: 10246 bytes --]
Hi Hugo,
I was not able to reproduce your error with my repository: I pulled it
without problem.
However, enclosed you can find the patch (as attachment) with the Jan
suggestions about the spaces. You can pull the patch also from my repo (
same branch: fd-leaking). Moreover I inserted the patch as inlined.
Hoping that helps.
--------------------
commit b73abc9465d3a105b5f8f464f2867543a638e5e2
Author: Goffredo Baroncelli <kreijack@inwind.it>
Date: Tue Jun 5 19:11:06 2012 +0200
scrub_fs_info( ) file handle leaking
The function scrub_fs_info( ) closes and reopen a file handle
passed as argument, when a caller uses the file handle even after the
call.
The function scrub_fs_info( ) is updated to remove the file handle
argument, and instead uses a private own file handle.
The callers are updated to not pass the argument.
diff --git a/cmds-scrub.c b/cmds-scrub.c
index c4503f4..6313e02 100644
--- a/cmds-scrub.c
+++ b/cmds-scrub.c
@@ -979,19 +979,26 @@ static int scrub_device_info(int fd, u64 devid,
return ret ? -errno : 0;
}
-static int scrub_fs_info(int fd, char *path,
+static int scrub_fs_info(char *path,
struct btrfs_ioctl_fs_info_args *fi_args,
struct btrfs_ioctl_dev_info_args **di_ret)
{
int ret = 0;
int ndevs = 0;
int i = 1;
+ int fd;
struct btrfs_fs_devices *fs_devices_mnt = NULL;
struct btrfs_ioctl_dev_info_args *di_args;
char mp[BTRFS_PATH_NAME_MAX + 1];
memset(fi_args, 0, sizeof(*fi_args));
+ fd = open_file_or_dir(path);
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: can't access to '%s'\n", path);
+ return -1;
+ }
+
ret = ioctl(fd, BTRFS_IOC_FS_INFO, fi_args);
if (ret && errno == EINVAL) {
/* path is no mounted btrfs. try if it's a device */
@@ -1010,28 +1017,36 @@ static int scrub_fs_info(int fd, char *path,
if (fd < 0)
return -errno;
} else if (ret) {
+ close(fd);
return -errno;
}
- if (!fi_args->num_devices)
+ if (!fi_args->num_devices) {
+ close(fd);
return 0;
+ }
di_args = *di_ret = malloc(fi_args->num_devices * sizeof(*di_args));
- if (!di_args)
+ if (!di_args) {
+ close(fd);
return -errno;
+ }
for (; i <= fi_args->max_id; ++i) {
BUG_ON(ndevs >= fi_args->num_devices);
ret = scrub_device_info(fd, i, &di_args[ndevs]);
if (ret == -ENODEV)
continue;
- if (ret)
+ if (ret) {
+ close(fd);
return ret;
+ }
++ndevs;
}
BUG_ON(ndevs == 0);
+ close(fd);
return 0;
}
@@ -1155,7 +1170,7 @@ static int scrub_start(int argc, char **argv, int
resume)
return 12;
}
- ret = scrub_fs_info(fdmnt, path, &fi_args, &di_args);
+ ret = scrub_fs_info(path, &fi_args, &di_args);
if (ret) {
ERR(!do_quiet, "ERROR: getting dev info for scrub failed: "
"%s\n", strerror(-ret));
@@ -1586,7 +1601,6 @@ static int cmd_scrub_status(int argc, char **argv)
.sun_family = AF_UNIX,
};
int ret;
- int fdmnt;
int i;
int print_raw = 0;
int do_stats_per_dev = 0;
@@ -1615,13 +1629,7 @@ static int cmd_scrub_status(int argc, char **argv)
path = argv[optind];
- fdmnt = open_file_or_dir(path);
- if (fdmnt < 0) {
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
- return 12;
- }
-
- ret = scrub_fs_info(fdmnt, path, &fi_args, &di_args);
+ ret = scrub_fs_info(path, &fi_args, &di_args);
if (ret) {
fprintf(stderr, "ERROR: getting dev info for scrub failed: "
"%s\n", strerror(-ret));
@@ -1698,7 +1706,6 @@ static int cmd_scrub_status(int argc, char **argv)
out:
free_history(past_scrubs);
free(di_args);
- close(fdmnt);
if (fdres > -1)
close(fdres);
On 06/05/2012 01:01 PM, Hugo Mills wrote:
> Hi, Goffredo,
>
> I'm trying to do a new integration branch, and the patch inline in
> the text is corrupt (plus it has a massively verbose commit message):
>
> Applying: Leaking file handle in scrub_fs_info()
> fatal: corrupt patch at line 74
> Patch failed at 0001 Leaking file handle in scrub_fs_info()
>
> Normally, I'd use your git repo to get round the fact that every
> single patch you send by mail is whitespace-damaged, but:
>
> error: Unable to find 337bfb3250203a66b953ffcf7804418cb7c72052 under http://cassiopea.homelinux.net/git/btrfs-progs-unstable.git
> Cannot obtain needed commit 337bfb3250203a66b953ffcf7804418cb7c72052
> while processing commit ee3832b47a4b1d1dce8d1cacc802db32901b8c45.
> error: Fetch failed.
>
> Plus Jan had some suggested tweaks regarding whitespace -- could
> you re-roll the patch and maybe see what you can do to fix your git
> repo? (Or at least use git-send-email to send the patch so it doesn't
> get mangled).
>
> Thanks,
> Hugo.
>
> On Tue, Apr 24, 2012 at 08:43:23PM +0200, Goffredo Baroncelli wrote:
>> I was giving a look to the function scrub_fs_info( ), and to me it seems
>> that could be a potential file handle leaking problem.
>>
>>
>> In fact:
>>
>> static int scrub_fs_info(int fd, char *path,
>> struct btrfs_ioctl_fs_info_args *fi_args,
>> struct btrfs_ioctl_dev_info_args **di_ret)
>> {
>>
>> [...]
>>
>> ret = ioctl(fd, BTRFS_IOC_FS_INFO, fi_args);
>> if (ret && errno == EINVAL) {
>> /* path is no mounted btrfs. try if it's a device */
>> [...]
>> close(fd); <--- Here the
>> file handle is
>> closed
>>
>> fd = open_file_or_dir(mp); <--- then it is
>> re-opened
>> if (fd < 0)
>> return -errno;
>> } else if (ret) {
>> return -errno;
>> }
>> [...]
>>
>> But in the rest of the function:
>> a) the file handle is not closed
>> b) the (new) file handle isn't returned
>>
>> The function "scrub_fs_info()" is called from the functions
>> 1) cmd_scrub_status(), which doesn't use the file handle after the call
>> to the cmd_scrub_status() [except for a close()]. So no problem at all.
>> 2) scrub_start(), which uses the file handle after the call to the
>> cmd_scrub_status() functions.
>>
>> My suggestions is to change scrub_fs_info() to accept only the path.
>> Then it open (and closes) its own (and private) the file descriptor.
>>
>> Instead scrub_start(), opens a file descriptor after the call to the
>> scrub_fs_info() function.
>>
>> What do you think ?
>>
>> BR
>> G.Baroncelli
>>
>> You can pull the patch below from
>>
>> http://cassiopea.homelinux.net/git/btrfs-progs-unstable.git
>>
>> branch
>>
>> fd-leaking
>>
>> -----
>>
>> diff --git a/cmds-scrub.c b/cmds-scrub.c
>> index c4503f4..486768c 100644
>> --- a/cmds-scrub.c
>> +++ b/cmds-scrub.c
>> @@ -979,19 +979,26 @@ static int scrub_device_info(int fd, u64 devid,
>> return ret ? -errno : 0;
>> }
>>
>> -static int scrub_fs_info(int fd, char *path,
>> +static int scrub_fs_info( char *path,
>> struct btrfs_ioctl_fs_info_args *fi_args,
>> struct btrfs_ioctl_dev_info_args **di_ret)
>> {
>> int ret = 0;
>> int ndevs = 0;
>> int i = 1;
>> + int fd;
>> struct btrfs_fs_devices *fs_devices_mnt = NULL;
>> struct btrfs_ioctl_dev_info_args *di_args;
>> char mp[BTRFS_PATH_NAME_MAX + 1];
>>
>> memset(fi_args, 0, sizeof(*fi_args));
>>
>> + fd = open_file_or_dir(path);
>> + if (fd < 0) {
>> + fprintf(stderr, "ERROR: can't access to '%s'\n", path);
>> + return -1;
>> + }
>> +
>> ret = ioctl(fd, BTRFS_IOC_FS_INFO, fi_args);
>> if (ret && errno == EINVAL) {
>> /* path is no mounted btrfs. try if it's a device */
>> @@ -1010,28 +1017,36 @@ static int scrub_fs_info(int fd, char *path,
>> if (fd < 0)
>> return -errno;
>> } else if (ret) {
>> + close(fd);
>> return -errno;
>> }
>>
>> - if (!fi_args->num_devices)
>> + if (!fi_args->num_devices){
>> + close(fd);
>> return 0;
>> + }
>>
>> di_args = *di_ret = malloc(fi_args->num_devices * sizeof(*di_args));
>> - if (!di_args)
>> + if (!di_args){
>> + close(fd);
>> return -errno;
>> + }
>>
>> for (; i <= fi_args->max_id; ++i) {
>> BUG_ON(ndevs >= fi_args->num_devices);
>> ret = scrub_device_info(fd, i, &di_args[ndevs]);
>> if (ret == -ENODEV)
>> continue;
>> - if (ret)
>> + if (ret){
>> + close(fd);
>> return ret;
>> + }
>> ++ndevs;
>> }
>>
>> BUG_ON(ndevs == 0);
>>
>> + close(fd);
>> return 0;
>> }
>>
>> @@ -1155,7 +1170,7 @@ static int scrub_start(int argc, char **argv, int
>> resume)
>> return 12;
>> }
>>
>> - ret = scrub_fs_info(fdmnt, path, &fi_args, &di_args);
>> + ret = scrub_fs_info(path, &fi_args, &di_args);
>> if (ret) {
>> ERR(!do_quiet, "ERROR: getting dev info for scrub failed: "
>> "%s\n", strerror(-ret));
>> @@ -1586,7 +1601,6 @@ static int cmd_scrub_status(int argc, char **argv)
>> .sun_family = AF_UNIX,
>> };
>> int ret;
>> - int fdmnt;
>> int i;
>> int print_raw = 0;
>> int do_stats_per_dev = 0;
>> @@ -1615,13 +1629,7 @@ static int cmd_scrub_status(int argc, char **argv)
>>
>> path = argv[optind];
>>
>> - fdmnt = open_file_or_dir(path);
>> - if (fdmnt < 0) {
>> - fprintf(stderr, "ERROR: can't access to '%s'\n", path);
>> - return 12;
>> - }
>> -
>> - ret = scrub_fs_info(fdmnt, path, &fi_args, &di_args);
>> + ret = scrub_fs_info(path, &fi_args, &di_args);
>> if (ret) {
>> fprintf(stderr, "ERROR: getting dev info for scrub failed: "
>> "%s\n", strerror(-ret));
>> @@ -1698,7 +1706,6 @@ static int cmd_scrub_status(int argc, char **argv)
>> out:
>> free_history(past_scrubs);
>> free(di_args);
>> - close(fdmnt);
>> if (fdres > -1)
>> close(fdres);
>>
>>
>>
>>
>>
>>
>
[-- Attachment #2: fd-leaking.diff --]
[-- Type: text/x-patch, Size: 2707 bytes --]
diff --git a/cmds-scrub.c b/cmds-scrub.c
index c4503f4..6313e02 100644
--- a/cmds-scrub.c
+++ b/cmds-scrub.c
@@ -979,19 +979,26 @@ static int scrub_device_info(int fd, u64 devid,
return ret ? -errno : 0;
}
-static int scrub_fs_info(int fd, char *path,
+static int scrub_fs_info(char *path,
struct btrfs_ioctl_fs_info_args *fi_args,
struct btrfs_ioctl_dev_info_args **di_ret)
{
int ret = 0;
int ndevs = 0;
int i = 1;
+ int fd;
struct btrfs_fs_devices *fs_devices_mnt = NULL;
struct btrfs_ioctl_dev_info_args *di_args;
char mp[BTRFS_PATH_NAME_MAX + 1];
memset(fi_args, 0, sizeof(*fi_args));
+ fd = open_file_or_dir(path);
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: can't access to '%s'\n", path);
+ return -1;
+ }
+
ret = ioctl(fd, BTRFS_IOC_FS_INFO, fi_args);
if (ret && errno == EINVAL) {
/* path is no mounted btrfs. try if it's a device */
@@ -1010,28 +1017,36 @@ static int scrub_fs_info(int fd, char *path,
if (fd < 0)
return -errno;
} else if (ret) {
+ close(fd);
return -errno;
}
- if (!fi_args->num_devices)
+ if (!fi_args->num_devices) {
+ close(fd);
return 0;
+ }
di_args = *di_ret = malloc(fi_args->num_devices * sizeof(*di_args));
- if (!di_args)
+ if (!di_args) {
+ close(fd);
return -errno;
+ }
for (; i <= fi_args->max_id; ++i) {
BUG_ON(ndevs >= fi_args->num_devices);
ret = scrub_device_info(fd, i, &di_args[ndevs]);
if (ret == -ENODEV)
continue;
- if (ret)
+ if (ret) {
+ close(fd);
return ret;
+ }
++ndevs;
}
BUG_ON(ndevs == 0);
+ close(fd);
return 0;
}
@@ -1155,7 +1170,7 @@ static int scrub_start(int argc, char **argv, int resume)
return 12;
}
- ret = scrub_fs_info(fdmnt, path, &fi_args, &di_args);
+ ret = scrub_fs_info(path, &fi_args, &di_args);
if (ret) {
ERR(!do_quiet, "ERROR: getting dev info for scrub failed: "
"%s\n", strerror(-ret));
@@ -1586,7 +1601,6 @@ static int cmd_scrub_status(int argc, char **argv)
.sun_family = AF_UNIX,
};
int ret;
- int fdmnt;
int i;
int print_raw = 0;
int do_stats_per_dev = 0;
@@ -1615,13 +1629,7 @@ static int cmd_scrub_status(int argc, char **argv)
path = argv[optind];
- fdmnt = open_file_or_dir(path);
- if (fdmnt < 0) {
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
- return 12;
- }
-
- ret = scrub_fs_info(fdmnt, path, &fi_args, &di_args);
+ ret = scrub_fs_info(path, &fi_args, &di_args);
if (ret) {
fprintf(stderr, "ERROR: getting dev info for scrub failed: "
"%s\n", strerror(-ret));
@@ -1698,7 +1706,6 @@ static int cmd_scrub_status(int argc, char **argv)
out:
free_history(past_scrubs);
free(di_args);
- close(fdmnt);
if (fdres > -1)
close(fdres);
next prev parent reply other threads:[~2012-06-05 17:26 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-04-24 18:43 [btrfs-progs] [bug][patch] Leaking file handle in scrub_fs_info() Goffredo Baroncelli
2012-04-25 9:39 ` Jan Schmidt
2012-04-25 19:07 ` Goffredo Baroncelli
2012-06-05 11:01 ` Hugo Mills
2012-06-05 17:26 ` Goffredo Baroncelli [this message]
2012-06-05 18:19 ` [btrfs-progs] [bug][patch V2] " Hugo Mills
2012-06-05 20:12 ` Goffredo Baroncelli
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4FCE414A.10106@libero.it \
--to=kreijack@libero.it \
--cc=hugo@carfax.org.uk \
--cc=kreijack@inwind.it \
--cc=linux-btrfs@vger.kernel.org \
--cc=list.btrfs@jan-o-sch.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.