On Sun, Jan 05, 2014 at 06:26:11PM +0000, Hugo Mills wrote:
> On Sun, Jan 05, 2014 at 05:55:27PM +0000, Hugo Mills wrote:
> > The structure for BTRFS_SET_RECEIVED_IOCTL packs differently on 32-bit
> > and 64-bit systems. This means that it is impossible to use btrfs
> > receive on a system with a 64-bit kernel and 32-bit userspace, because
> > the structure size (and hence the ioctl number) is different.
> > 
> > This patch adds a compatibility structure and ioctl to deal with the
> > above case.
> 
>    Oops, forgot to mention -- this has been compile tested, but not
> actually run yet. The machine in question is several miles away and is
> a production machine (it's my work desktop, and I can't afford much
> downtime on it).

   ... And it doesn't even compile properly, now I come to build a
.deb. I'm still interested in comments about the general approach, but
the specific patch is a load of balls.

   Hugo.

>    Hugo.
> 
> > Signed-off-by: Hugo Mills <h...@carfax.org.uk>
> > ---
> >  fs/btrfs/ioctl.c | 95 
> > +++++++++++++++++++++++++++++++++++++++++++++++++++-----
> >  1 file changed, 87 insertions(+), 8 deletions(-)
> > 
> > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> > index 21da576..e186439 100644
> > --- a/fs/btrfs/ioctl.c
> > +++ b/fs/btrfs/ioctl.c
> > @@ -57,6 +57,32 @@
> >  #include "send.h"
> >  #include "dev-replace.h"
> >  
> > +#ifdef CONFIG_64BIT
> > +/* If we have a 32-bit userspace and 64-bit kernel, then the UAPI
> > + * structures are incorrect, as the timespec structure from userspace
> > + * is 4 bytes too small. We define these alternatives here to teach
> > + * the kernel about the 32-bit struct packing.
> > + */
> > +struct btrfs_ioctl_timespec {
> > +   __u64 sec;
> > +   __u32 nsec;
> > +} ((__packed__));
> > +
> > +struct btrfs_ioctl_received_subvol_args {
> > +   char    uuid[BTRFS_UUID_SIZE];  /* in */
> > +   __u64   stransid;               /* in */
> > +   __u64   rtransid;               /* out */
> > +   struct btrfs_ioctl_timespec stime; /* in */
> > +   struct btrfs_ioctl_timespec rtime; /* out */
> > +   __u64   flags;                  /* in */
> > +   __u64   reserved[16];           /* in */
> > +} ((__packed__));
> > +#endif
> > +
> > +#define BTRFS_IOC_SET_RECEIVED_SUBVOL_32 _IOWR(BTRFS_IOCTL_MAGIC, 37, \
> > +                           struct btrfs_ioctl_received_subvol_args_32)
> > +
> > +
> >  static int btrfs_clone(struct inode *src, struct inode *inode,
> >                    u64 off, u64 olen, u64 olen_aligned, u64 destoff);
> >  
> > @@ -4313,10 +4339,69 @@ static long btrfs_ioctl_quota_rescan_wait(struct 
> > file *file, void __user *arg)
> >     return btrfs_qgroup_wait_for_completion(root->fs_info);
> >  }
> >  
> > +#ifdef CONFIG_64BIT
> > +static long btrfs_ioctl_set_received_subvol_32(struct file *file,
> > +                                           void __user *arg)
> > +{
> > +   struct btrfs_ioctl_received_subvol_args_32 *args32 = NULL;
> > +   struct btrfs_ioctl_received_subvol_args *args64 = NULL;
> > +   int ret = 0;
> > +
> > +   args32 = memdup_user(arg, sizeof(*args32));
> > +   if (IS_ERR(args32)) {
> > +           ret = PTR_ERR(args32);
> > +           args32 = NULL;
> > +           goto out;
> > +   }
> > +
> > +   args64 = malloc(sizeof(*args64));
> > +   if (IS_ERR(args64)) {
> > +           ret = PTR_ERR(args64);
> > +           args64 = NULL;
> > +           goto out;
> > +   }
> > +
> > +   memcpy(args64->uuid, args32->uuid, BTRFS_UUID_SIZE);
> > +   args64->stransid = args32->stransid;
> > +   args64->rtransid = args32->rtransid;
> > +   args64->stime.sec = args32->stime.sec;
> > +   args64->stime.nsec = args32->stime.nsec;
> > +   args64->rtime.sec = args32->rtime.sec;
> > +   args64->rtime.nsec = args32->rtime.nsec;
> > +   args64->flags = args32->flags;
> > +
> > +   ret = _btrfs_ioctl_set_received_subvol(file, args64);
> > +
> > +out:
> > +   kfree(args32);
> > +   kfree(args64);
> > +   return ret;
> > +}
> > +#endif
> > +
> >  static long btrfs_ioctl_set_received_subvol(struct file *file,
> >                                         void __user *arg)
> >  {
> >     struct btrfs_ioctl_received_subvol_args *sa = NULL;
> > +   int ret = 0;
> > +
> > +   sa = memdup_user(arg, sizeof(*sa));
> > +   if (IS_ERR(sa)) {
> > +           ret = PTR_ERR(sa);
> > +           sa = NULL;
> > +           goto out;
> > +   }
> > +
> > +   ret = _btrfs_ioctl_set_received_subvol(file, sa);
> > +
> > +out:
> > +   kfree(sa);
> > +   return ret;
> > +}
> > +
> > +static long _btrfs_ioctl_set_received_subvol(struct file *file,
> > +                                       struct 
> > btrfs_ioctl_received_subvol_args *sa)
> > +{
> >     struct inode *inode = file_inode(file);
> >     struct btrfs_root *root = BTRFS_I(inode)->root;
> >     struct btrfs_root_item *root_item = &root->root_item;
> > @@ -4346,13 +4431,6 @@ static long btrfs_ioctl_set_received_subvol(struct 
> > file *file,
> >             goto out;
> >     }
> >  
> > -   sa = memdup_user(arg, sizeof(*sa));
> > -   if (IS_ERR(sa)) {
> > -           ret = PTR_ERR(sa);
> > -           sa = NULL;
> > -           goto out;
> > -   }
> > -
> >     /*
> >      * 1 - root item
> >      * 2 - uuid items (received uuid + subvol uuid)
> > @@ -4411,7 +4489,6 @@ static long btrfs_ioctl_set_received_subvol(struct 
> > file *file,
> >             ret = -EFAULT;
> >  
> >  out:
> > -   kfree(sa);
> >     up_write(&root->fs_info->subvol_sem);
> >     mnt_drop_write_file(file);
> >     return ret;
> > @@ -4572,6 +4649,8 @@ long btrfs_ioctl(struct file *file, unsigned int
> >             return btrfs_ioctl_balance_progress(root, argp);
> >     case BTRFS_IOC_SET_RECEIVED_SUBVOL:
> >             return btrfs_ioctl_set_received_subvol(file, argp);
> > +   case BTRFS_IOC_SET_RECEIVED_SUBVOL_32:
> > +           return btrfs_ioctl_set_received_subvol_32(file, argp);
> >     case BTRFS_IOC_SEND:
> >             return btrfs_ioctl_send(file, argp);
> >     case BTRFS_IOC_GET_DEV_STATS:
> 

-- 
=== Hugo Mills: hugo@... carfax.org.uk | darksatanic.net | lug.org.uk ===
  PGP key: 65E74AC0 from wwwkeys.eu.pgp.net or http://www.carfax.org.uk
         --- Nothing right in my left brain. Nothing left in ---         
                             my right brain.                             

Attachment: signature.asc
Description: Digital signature

Reply via email to