Re: [f2fs-dev] [PATCH 1/2] add cotnfigure option --with-root-libdir

2018-08-29 Thread Theodore Y. Ts'o
On Wed, Aug 29, 2018 at 02:04:55PM -0700, Jaegeuk Kim wrote:
> Thank you so much for kind explanation. This is really awesome especially for
> newbies like me. This gives answers to me for all my own stupid questions like
> why I need to investigate all the lib changes in order to determine bumping
> current/revision/age numbers or not.
> 
> I'd definitely like to follow this rule to avoid any verion changes later, as
> I expect the next release will be the last major update. For dependency parts,
> I'll study and practice them for a while.

If you are going to be making one less major update, this is the
perfect time to make sure that data structures are allocated by the
library, and are (ideally) opaque to the calling application (so they
only manipulate structure poitners).  That is, the structure
definition is not exposed in the public header file, and you use
accessor functions to set and get fields in the structure.

If you can't do that for all data structures, if you can do that with
your primary data structure that's going to make your life much easier
in the long term.  For ext2fs, that's the file systme handle.  It's
created by ext2fs_open(), and it's passed to all other library
functions as the first argument.

The other thing you might want to consider doing is adding a magic
number to the beginning of each structure.  That way you can tell if
the wrong structure gets passed to a library.  It's also helpful for
doing the equivalent of subclassing in C.

This is how we do it in libext2fs --- we use com_err to define the
magic numbers:

error_table ext2

ec  EXT2_ET_BASE,
"EXT2FS Library version @E2FSPROGS_VERSION@"

ec  EXT2_ET_MAGIC_EXT2FS_FILSYS,
"Wrong magic number for ext2_filsys structure"

ec  EXT2_ET_MAGIC_BADBLOCKS_LIST,
"Wrong magic number for badblocks_list structure"
...

And then every single structure starts like so:

struct struct_ext2_filsys {
errcode_t   magic;
...

struct ext2_struct_inode_scan {
errcode_t   magic;
...

And then before we use any pointer we do this:

if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
return EXT2_ET_MAGIC_EXT2_FILE;

Anyway, you don't have to do any of this, but if you're thinking about
making a big major version number bump, this is a great opportunity to
do some of these things.

> BTW, can I archive this like in f2fs-tools/VERSIONING?

Sure, feel free!

- Ted

--
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH 1/2] add cotnfigure option --with-root-libdir

2018-08-29 Thread Jaegeuk Kim
Thank you so much for kind explanation. This is really awesome especially for
newbies like me. This gives answers to me for all my own stupid questions like
why I need to investigate all the lib changes in order to determine bumping
current/revision/age numbers or not.

I'd definitely like to follow this rule to avoid any verion changes later, as
I expect the next release will be the last major update. For dependency parts,
I'll study and practice them for a while.

BTW, can I archive this like in f2fs-tools/VERSIONING?

Thanks,

On 08/28, Theodore Y. Ts'o wrote:
> On Tue, Aug 28, 2018 at 09:59:44AM -0700, Jaegeuk Kim wrote:
> > 
> > https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
> > 
> > I understood that, if there is no interface change but some implementation
> > changes, I need to bump revision. If new interface is added, for example, I
> > need to bump current while revision=0 and age++.
> 
> So part of the problem here is that libtool is doing something really
> strange because they are trying to use some abstract concept that is
> OS-independent.  I don't use libtool because I find it horribly
> complex and doesn't add enough value to be worth the complexity.
> 
> So I'll tell you how things work with respect to Linux's ELF version
> numbering system.  Translating this to libtool's wierd "current,
> revision, age" terminology is left as an exercise to the reader.  I've
> looked at the libtool documentation, and it confuses me horribly.
> Reading it, I suspect it's wrong, but I don't have the time to
> experiment to confirm that the documentation is wrong and how it
> diverges from the libtool implementation.
> 
> So let me explain things using the ELF shared library terminology,
> which is "major version, minor version, patchlevel".  This shows up in
> the library name:
> 
>   libudev.so.1.6.11
> 
> So in this example, the major version number is 1, the minor version
> is 6, and the patchlevel is 11.  The patchlevel is entirely optional,
> and many packages don't use it at all.  The minor number is also
> mostly useless on Linux, but it's still there for historical reasons.
> The patchlevel and minor version numbers were useful back for SunOS
> (and Linux a.out shared library), back when there weren't rpm and dpkg
> as package managers.
> 
> So many modern Linux shared libraries will only use the major and
> minor version numbers, e.g:
> 
>   libext2fs.so.2.4
> 
> The only thing you really need to worry about is the major version
> number, really.  The minor version is *supposed* to change when new
> interfaces has changed (but I and most other people don't do that any
> more).  But the big deal is that the major number *must* get bumped if
> an existing interface has *changed*.
> 
> So let's talk about the major version number, and then we'll talk
> about why the minor version number isn't really a big deal for Linux.
> 
> So if you change any of the library's function signatures --- and this
> includes changing a type from a 32-bit integer to a 64-bit integer,
> that's an ABI breakage, and so you must bump the major version number
> so that a program that was linked against libfoo.so.4 doesn't try to
> use libfoo.so.5.  That's really the key --- will a program linked
> against the previous version library break if it links against the
> newer version.  If it does, then you need to bump the version number.
> 
> So for structures, if you change any of the existing fields, or if the
> application program allocates the structure --- either by declaring it
> on the stack, or via malloc() --- and you expand the structure,
> obviously that will cause problem, and so that's an ABI break.
> 
> If however, you arrange to have structures allocated by the library,
> and struct members are always added at the end, then an older program
> won't have any problems.  You can guarantee this by simply only using
> a pointer to the struct in your public header files, and defining the
> struct in a private header file that is not available to userspace
> programs.
> 
> Similarly, adding new functions never breaks the ABI.  That's because
> older program won't try to use the newer interfaces.  So if I need to
> change an interface to a function, what I'll generally do is to define
> a new function, and then implement the older function in terms of the
> newer one.  For example:
> 
> extern errcode_t ext2fs_open(const char *name, int flags, int superblock,
>unsigned int block_size, io_manager manager,
>ext2_filsys *ret_fs);
>
> extern errcode_t ext2fs_open2(const char *name, const char *io_options,
> int flags, int superblock,
> unsigned int block_size, io_manager manager,
> ext2_filsys *hret_fs);
> 
> As far as the minor version numbers are concerned, the dynamic linker
> doesn't use it.  In SunOS 4, if you