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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).