xfs_quota: correctly initialise the default path
PATCH 1/1 xfs_quota: correctly initialise the default path
From: Dave Chinner <[email protected]>
When we initial xfs_quota, we place lots of information into the fs_table. This includes all the devices/mount points the user has specified as a global command line parameter to report on, as well as all the paths under project quota control.
There is a "current path" pointer (fs_path) maintained by the code that points somewhere into the fs_table. After the table is initialised, fs_path always points to the last entry in the table, and hence has to be re-initialised to point at the desired entry before it can be used properly.
In the case of xfs_quota, if the command passed on the command line is a non-global command, the command is called multiple times, each time after the libxcmd args_command() callback is run. That starts with an index of 0, and until the callback returns zero it will keep passing whatever the last returned value was into the callback.
xfs_quota supplies such a callback, and it's purpose is to iterate over the fs_table setting fs_path to the next mount point in the table. IOWs, non-global quota functions get called once for each mount point specified on the command line. However, it also means that for global functions, the fs_path pointer is not re-initialised and hence if there are project quotas configured the fs_path pointer does not point to a mount point andhence commands may malfunction..
The problem that demonstrated this is the report function. It does it's own fs_table iteration if the command requires it, and so only should be called once to avoid outputting the same information multiple times. That's what the previous patch fixed by making the command global, but this now has the effect of making commands that need to operate on the device specified on the global command rely on the fs_path variable pointing at that device.
Further, commands executed by the interactive method are always treated as global commands, so the report command never worked as a global command in the presence of a configured project quota setup.
Fix the problem by initialising the fs_path pointer correctly.
--- quota/init.c | 9 +++++++++ 1 file changed, 9 insertions(+)
quota/init.c +9 -0
@@ -140,6 +140,15 @@ init(init_commands ();add_args_command (init_args_command); + +/* +* Ensure that global commands don't end up with an invalid path pointer +* by setting the default device at the first specified on the CLI +*/ +if (argc != optind) + fs_path =fs_table_lookup (argv[optind],FS_MOUNT_POINT ); +else + fs_path = &fs_table[0 ]; }int
Signature · 6 lines
1.7.10 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Quoted 36 lines · Dave Chinner
From: Dave Chinner <[email protected]>
When we initial
xfs_quota, we place lots of information into thefs_table. This includes all the devices/mount points the user has specified as a global command line parameter to report on, as well as all the paths under project quota control.There is a "current path" pointer (
fs_path) maintained by the code that points somewhere into thefs_table. After the table is initialised,fs_pathalways points to the last entry in the table, and hence has to be re-initialised to point at the desired entry before it can be used properly.In the case of
xfs_quota, if the command passed on the command line is a non-global command, the command is called multiple times, each time after the libxcmdargs_command()callback is run. That starts with an index of 0, and until the callback returns zero it will keep passing whatever the last returned value was into the callback.
xfs_quotasupplies such a callback, and it's purpose is to iterate over thefs_tablesettingfs_pathto the next mount point in the table. IOWs, non-global quota functions get called once for each mount point specified on the command line. However, it also means that for global functions, thefs_pathpointer is not re-initialised and hence if there are project quotas configured thefs_pathpointer does not point to a mount point andhence commands may malfunction..The problem that demonstrated this is the report function. It does it's own
fs_tableiteration if the command requires it, and so only should be called once to avoid outputting the same information multiple times. That's what the previous patch fixed by making the command global, but this now has the effect of making commands that need to operate on the device specified on the global command rely on thefs_pathvariable pointing at that device.
Quoted 5 lines
Further, commands executed by the interactive method are always treated as global commands, so the report command never worked as a global command in the presence of a configured project quota setup.
Fix the problem by initialising the
fs_pathpointer correctly.
tl;dr ;) I'm all for detailed commit messages but you lost me there. If I were searching for this fix I'd have no idea what behavior this commit actually . . . fixes. :)
Can you say:
a) what the "previous patch" commit was, and
b) what commandline triggers this problem, and what the result is?
Sorry if I'm dense,
-Eric
Quoted 16 lines
Signed-off-by Dave Chinner <[email protected]>--- quota/init.c | 9 +++++++++ 1 file changed, 9 insertions(+)quota/init.c +2
-0@@ -140,6 +140,15 @@ init(init_commands ();add_args_command (init_args_command); + +/*
quota/init.c init( · line 154
Quoted 10 lines
quota/init.c +7
-0+* Ensure that global commands don't end up with an invalid path pointer +* by setting the default device at the first specified on the CLI +*/ +if (argc != optind) + fs_path =fs_table_lookup (argv[optind],FS_MOUNT_POINT ); +else + fs_path = &fs_table[0 ]; }int
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Quoted 41 lines · Eric Sandeen
Quoted 40 lines · Dave Chinner
From: Dave Chinner <[email protected]>
When we initial
xfs_quota, we place lots of information into thefs_table. This includes all the devices/mount points the user has specified as a global command line parameter to report on, as well as all the paths under project quota control.There is a "current path" pointer (
fs_path) maintained by the code that points somewhere into thefs_table. After the table is initialised,fs_pathalways points to the last entry in the table, and hence has to be re-initialised to point at the desired entry before it can be used properly.In the case of
xfs_quota, if the command passed on the command line is a non-global command, the command is called multiple times, each time after the libxcmdargs_command()callback is run. That starts with an index of 0, and until the callback returns zero it will keep passing whatever the last returned value was into the callback.
xfs_quotasupplies such a callback, and it's purpose is to iterate over thefs_tablesettingfs_pathto the next mount point in the table. IOWs, non-global quota functions get called once for each mount point specified on the command line. However, it also means that for global functions, thefs_pathpointer is not re-initialised and hence if there are project quotas configured thefs_pathpointer does not point to a mount point andhence commands may malfunction..The problem that demonstrated this is the report function. It does it's own
fs_tableiteration if the command requires it, and so only should be called once to avoid outputting the same information multiple times. That's what the previous patch fixed by making the command global, but this now has the effect of making commands that need to operate on the device specified on the global command rely on thefs_pathvariable pointing at that device.Further, commands executed by the interactive method are always treated as global commands, so the report command never worked as a global command in the presence of a configured project quota setup.
Quoted 5 lines
Quoted 1 line
Fix the problem by initialising the
fs_pathpointer correctly.tl;dr ;) I'm all for detailed commit messages but you lost me there. If I were searching for this fix I'd have no idea what behavior this commit actually . . . fixes. :)
Which indicates just how twisty the maze is. I'll try o describe the call chain for you, because the bug is a result of interactions in 4 different files linked indirectly by callbacks.
Let's see:
quota/init.c:: main()quota/init.c:: init()
parse argv/argc
add_command("report -p")libxcmd/paths.c:: fs_table_initialise("/dev/vdb", NULL pquota args)
inserts devices in fs_table
walks /proc/mounts if none
inserts projects in fs_table
walks /etc/projid if none
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
fs_path>>>> leavesfs_pathpointing at last table entry
libxcmd/command.c:: add_args_command(quota/init.c::init_args_command)quota/init.c:: main()libxcmd/command.c:: command_loop()
walks CLI commands
if (!GLOBAL_CMD) {
j = 0;
while (j == arg_command(j))quota/init.c:: init_args_command()
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
!GLOBAL
fs_pathinit >>>>>fs_path= fs_table[j];
command(argv, argc)
} else {Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
No
fs_pathinit! >>>>>
command(argv, argc)quota/report.c:: report_f()
parse command choose report typequota/report.c:: report_any_type()
walks fstable
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
match fails >>>>>> finds specific
fs_pathmatch or
(-a) dumps the entire fs_tablelibxcmd/command.c:: fs_cursor_initialise()libxcmd/command.c:: mnt = fs_cursor_next_entry()
if (user)quota/report.c:: report_user_mount()
if (group)quota/report.c:: report_group_mount()
if (project)quota/report.c:: report_project_mount()
Quoted 3 lines
Can you say:
a) what the "previous patch" commit was, and
Hasn't been committed yet, so I can't put a commit in the description.
Quoted 1 line
b) what commandline triggers this problem, and what the result is?
The simplest demonstration is this:
Old behaviour:
# xfs_quota -x -D /tmp/6345.projects -P /tmp/6345.projid -c path /mnt/scratch
Filesystem Pathname
000 /mnt/scratch /dev/vdb (pquota)
[001] /mnt/scratch /dev/vdb (project 1, scrach)Which leaves fs_path pointing at the project quota path, not the mount point.
Patched behaviour:
$ sudo ~/xfs_quota -x -D /tmp/6345.projects -P /tmp/6345.projid -c path /mnt/scratch
Filesystem Pathname
[000] /mnt/scratch /dev/vdb (pquota)
001 /mnt/scratch /dev/vdb (project 1, scrach)Which points the fs_path back at the mount point. The current dev tree xfs_quota code behaves like this:
# xfs_quota -x -c "report -p" /dev/vdb
Project quota on /mnt/scratch (/dev/vdb)
Blocks
Project ID Used Soft Hard Warn/Grace
---------- --------------------------------------------------
root 4 0 0 00 [--------]
scrach 540 100 500 00 [--none--]# xfs_quota -x /dev/vdb xfs_quota> report -p
xfs_quota>
Which shows that it is broken for interactive behaviour.
After the GLOBAL_CMD fix for the report command, the CLI is also broken:
# xfs_quota -x -c "report -p" /dev/vdb
#
After this fix:
# xfs_quota -x -c "report -p" /dev/vdb
Project quota on /mnt/scratch (/dev/vdb)
Blocks
Project ID Used Soft Hard Warn/Grace
---------- --------------------------------------------------
root 4 0 0 00 [--------]
scrach 540 100 500 00 [--none--]# xfs_quota -x /dev/vdb
xfs_quota> report -p
Project quota on /mnt/scratch (/dev/vdb)
Blocks
Project ID Used Soft Hard Warn/Grace
---------- --------------------------------------------------
root 4 0 0 00 [--------]
scrach 540 100 500 00 [--none--]xfs_quota>
It all works again. And, well, I figured that was all too much to put in a commit message...
Quoted 1 line
Sorry if I'm dense,
Not at all, it's convoluted code because it is generic enough to be used by multiple tools, and until you understand the general structure of it you will hurt your brian looking at it.
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Quoted 7 lines · Dave Chinner
From: Dave Chinner<[email protected]>
When we initial
xfs_quota, we place lots of information into thefs_table. This includes all the devices/mount points the user has specified as a global command line parameter to report on, as well as all the paths under project quota control.
Quoted 5 lines
There is a "current path" pointer (
fs_path) maintained by the code that points somewhere into thefs_table. After the table is initialised,fs_pathalways points to the last entry in the table, and hence has to be re-initialised to point at the desired entry before it can be used properly.
...
fun code read :)
quota/init.c init( · line 149
Quoted 9 lines
init_commands(); add_args_command(init_args_command);quota/init.c +7
-0+ +/* +* Ensure that global commands don't end up with an invalid path pointer +* by setting the default device at the first specified on the CLI +*/ +if (argc != optind) + fs_path =fs_table_lookup (argv[optind],FS_MOUNT_POINT );
fs_table_lookup() can return NULL - especially the way I type.
--Mark.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
quota/init.c init( · line 149
Quoted 4 lines · Dave Chinner
From: Dave Chinner<[email protected]>
quota/init.c +2
-0+if (argc != optind) + fs_path =fs_table_lookup (argv[optind],FS_MOUNT_POINT );
If specified device is not in the table, then the program will give an error before getting here, so this cannot return a NULL as I previously was concerned about. So this does in fact look good.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs