Diff for /xfs-linux/linux-2.6/xfs_super.c between versions 1.402 and 1.403

version 1.402, 2007/10/15 03:59:33 version 1.403, 2007/11/05 05:10:46
Line 50 Line 50
 #include "xfs_vnodeops.h"  #include "xfs_vnodeops.h"
 #include "xfs_vfsops.h"  #include "xfs_vfsops.h"
 #include "xfs_version.h"  #include "xfs_version.h"
   #include "xfs_log_priv.h"
   
 #include <linux/namei.h>  #include <linux/namei.h>
 #include <linux/init.h>  #include <linux/init.h>
Line 88  xfs_args_allocate( Line 89  xfs_args_allocate(
         return args;          return args;
 }  }
   
   #define MNTOPT_LOGBUFS  "logbufs"       /* number of XFS log buffers */
   #define MNTOPT_LOGBSIZE "logbsize"      /* size of XFS log buffers */
   #define MNTOPT_LOGDEV   "logdev"        /* log device */
   #define MNTOPT_RTDEV    "rtdev"         /* realtime I/O device */
   #define MNTOPT_BIOSIZE  "biosize"       /* log2 of preferred buffered io size */
   #define MNTOPT_WSYNC    "wsync"         /* safe-mode nfs compatible mount */
   #define MNTOPT_INO64    "ino64"         /* force inodes into 64-bit range */
   #define MNTOPT_NOALIGN  "noalign"       /* turn off stripe alignment */
   #define MNTOPT_SWALLOC  "swalloc"       /* turn on stripe width allocation */
   #define MNTOPT_SUNIT    "sunit"         /* data volume stripe unit */
   #define MNTOPT_SWIDTH   "swidth"        /* data volume stripe width */
   #define MNTOPT_NOUUID   "nouuid"        /* ignore filesystem UUID */
   #define MNTOPT_MTPT     "mtpt"          /* filesystem mount point */
   #define MNTOPT_GRPID    "grpid"         /* group-ID from parent directory */
   #define MNTOPT_NOGRPID  "nogrpid"       /* group-ID from current process */
   #define MNTOPT_BSDGROUPS    "bsdgroups"    /* group-ID from parent directory */
   #define MNTOPT_SYSVGROUPS   "sysvgroups"   /* group-ID from current process */
   #define MNTOPT_ALLOCSIZE    "allocsize"    /* preferred allocation size */
   #define MNTOPT_NORECOVERY   "norecovery"   /* don't run XFS recovery */
   #define MNTOPT_BARRIER  "barrier"       /* use writer barriers for log write and
                                            * unwritten extent conversion */
   #define MNTOPT_NOBARRIER "nobarrier"    /* .. disable */
   #define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */
   #define MNTOPT_64BITINODE   "inode64"   /* inodes can be allocated anywhere */
   #define MNTOPT_IKEEP    "ikeep"         /* do not free empty inode clusters */
   #define MNTOPT_NOIKEEP  "noikeep"       /* free empty inode clusters */
   #define MNTOPT_LARGEIO     "largeio"    /* report large I/O sizes in stat() */
   #define MNTOPT_NOLARGEIO   "nolargeio"  /* do not report large I/O sizes
                                            * in stat(). */
   #define MNTOPT_ATTR2    "attr2"         /* do use attr2 attribute format */
   #define MNTOPT_NOATTR2  "noattr2"       /* do not use attr2 attribute format */
   #define MNTOPT_FILESTREAM  "filestreams" /* use filestreams allocator */
   #define MNTOPT_QUOTA    "quota"         /* disk quotas (user) */
   #define MNTOPT_NOQUOTA  "noquota"       /* no quotas */
   #define MNTOPT_USRQUOTA "usrquota"      /* user quota enabled */
   #define MNTOPT_GRPQUOTA "grpquota"      /* group quota enabled */
   #define MNTOPT_PRJQUOTA "prjquota"      /* project quota enabled */
   #define MNTOPT_UQUOTA   "uquota"        /* user quota (IRIX variant) */
   #define MNTOPT_GQUOTA   "gquota"        /* group quota (IRIX variant) */
   #define MNTOPT_PQUOTA   "pquota"        /* project quota (IRIX variant) */
   #define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
   #define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
   #define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
   #define MNTOPT_QUOTANOENF  "qnoenforce" /* same as uqnoenforce */
   #define MNTOPT_DMAPI    "dmapi"         /* DMI enabled (DMAPI / XDSM) */
   #define MNTOPT_XDSM     "xdsm"          /* DMI enabled (DMAPI / XDSM) */
   #define MNTOPT_DMI      "dmi"           /* DMI enabled (DMAPI / XDSM) */
   
   STATIC unsigned long
   suffix_strtoul(char *s, char **endp, unsigned int base)
   {
           int     last, shift_left_factor = 0;
           char    *value = s;
   
           last = strlen(value) - 1;
           if (value[last] == 'K' || value[last] == 'k') {
                   shift_left_factor = 10;
                   value[last] = '\0';
           }
           if (value[last] == 'M' || value[last] == 'm') {
                   shift_left_factor = 20;
                   value[last] = '\0';
           }
           if (value[last] == 'G' || value[last] == 'g') {
                   shift_left_factor = 30;
                   value[last] = '\0';
           }
   
           return simple_strtoul((const char *)s, endp, base) << shift_left_factor;
   }
   
   STATIC int
   xfs_parseargs(
           struct xfs_mount        *mp,
           char                    *options,
           struct xfs_mount_args   *args,
           int                     update)
   {
           char                    *this_char, *value, *eov;
           int                     dsunit, dswidth, vol_dsunit, vol_dswidth;
           int                     iosize;
           int                     ikeep = 0;
   
           args->flags |= XFSMNT_BARRIER;
           args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
   
           if (!options)
                   goto done;
   
           iosize = dsunit = dswidth = vol_dsunit = vol_dswidth = 0;
   
           while ((this_char = strsep(&options, ",")) != NULL) {
                   if (!*this_char)
                           continue;
                   if ((value = strchr(this_char, '=')) != NULL)
                           *value++ = 0;
   
                   if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
                           if (!value || !*value) {
                                   cmn_err(CE_WARN,
                                           "XFS: %s option requires an argument",
                                           this_char);
                                   return EINVAL;
                           }
                           args->logbufs = simple_strtoul(value, &eov, 10);
                   } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
                           if (!value || !*value) {
                                   cmn_err(CE_WARN,
                                           "XFS: %s option requires an argument",
                                           this_char);
                                   return EINVAL;
                           }
                           args->logbufsize = suffix_strtoul(value, &eov, 10);
                   } else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
                           if (!value || !*value) {
                                   cmn_err(CE_WARN,
                                           "XFS: %s option requires an argument",
                                           this_char);
                                   return EINVAL;
                           }
                           strncpy(args->logname, value, MAXNAMELEN);
                   } else if (!strcmp(this_char, MNTOPT_MTPT)) {
                           if (!value || !*value) {
                                   cmn_err(CE_WARN,
                                           "XFS: %s option requires an argument",
                                           this_char);
                                   return EINVAL;
                           }
                           strncpy(args->mtpt, value, MAXNAMELEN);
                   } else if (!strcmp(this_char, MNTOPT_RTDEV)) {
                           if (!value || !*value) {
                                   cmn_err(CE_WARN,
                                           "XFS: %s option requires an argument",
                                           this_char);
                                   return EINVAL;
                           }
                           strncpy(args->rtname, value, MAXNAMELEN);
                   } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
                           if (!value || !*value) {
                                   cmn_err(CE_WARN,
                                           "XFS: %s option requires an argument",
                                           this_char);
                                   return EINVAL;
                           }
                           iosize = simple_strtoul(value, &eov, 10);
                           args->flags |= XFSMNT_IOSIZE;
                           args->iosizelog = (uint8_t) iosize;
                   } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {
                           if (!value || !*value) {
                                   cmn_err(CE_WARN,
                                           "XFS: %s option requires an argument",
                                           this_char);
                                   return EINVAL;
                           }
                           iosize = suffix_strtoul(value, &eov, 10);
                           args->flags |= XFSMNT_IOSIZE;
                           args->iosizelog = ffs(iosize) - 1;
                   } else if (!strcmp(this_char, MNTOPT_GRPID) ||
                              !strcmp(this_char, MNTOPT_BSDGROUPS)) {
                           mp->m_flags |= XFS_MOUNT_GRPID;
                   } else if (!strcmp(this_char, MNTOPT_NOGRPID) ||
                              !strcmp(this_char, MNTOPT_SYSVGROUPS)) {
                           mp->m_flags &= ~XFS_MOUNT_GRPID;
                   } else if (!strcmp(this_char, MNTOPT_WSYNC)) {
                           args->flags |= XFSMNT_WSYNC;
                   } else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) {
                           args->flags |= XFSMNT_OSYNCISOSYNC;
                   } else if (!strcmp(this_char, MNTOPT_NORECOVERY)) {
                           args->flags |= XFSMNT_NORECOVERY;
                   } else if (!strcmp(this_char, MNTOPT_INO64)) {
                           args->flags |= XFSMNT_INO64;
   #if !XFS_BIG_INUMS
                           cmn_err(CE_WARN,
                                   "XFS: %s option not allowed on this system",
                                   this_char);
                           return EINVAL;
   #endif
                   } else if (!strcmp(this_char, MNTOPT_NOALIGN)) {
                           args->flags |= XFSMNT_NOALIGN;
                   } else if (!strcmp(this_char, MNTOPT_SWALLOC)) {
                           args->flags |= XFSMNT_SWALLOC;
                   } else if (!strcmp(this_char, MNTOPT_SUNIT)) {
                           if (!value || !*value) {
                                   cmn_err(CE_WARN,
                                           "XFS: %s option requires an argument",
                                           this_char);
                                   return EINVAL;
                           }
                           dsunit = simple_strtoul(value, &eov, 10);
                   } else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
                           if (!value || !*value) {
                                   cmn_err(CE_WARN,
                                           "XFS: %s option requires an argument",
                                           this_char);
                                   return EINVAL;
                           }
                           dswidth = simple_strtoul(value, &eov, 10);
                   } else if (!strcmp(this_char, MNTOPT_64BITINODE)) {
                           args->flags &= ~XFSMNT_32BITINODES;
   #if !XFS_BIG_INUMS
                           cmn_err(CE_WARN,
                                   "XFS: %s option not allowed on this system",
                                   this_char);
                           return EINVAL;
   #endif
                   } else if (!strcmp(this_char, MNTOPT_NOUUID)) {
                           args->flags |= XFSMNT_NOUUID;
                   } else if (!strcmp(this_char, MNTOPT_BARRIER)) {
                           args->flags |= XFSMNT_BARRIER;
                   } else if (!strcmp(this_char, MNTOPT_NOBARRIER)) {
                           args->flags &= ~XFSMNT_BARRIER;
                   } else if (!strcmp(this_char, MNTOPT_IKEEP)) {
                           ikeep = 1;
                           args->flags &= ~XFSMNT_IDELETE;
                   } else if (!strcmp(this_char, MNTOPT_NOIKEEP)) {
                           args->flags |= XFSMNT_IDELETE;
                   } else if (!strcmp(this_char, MNTOPT_LARGEIO)) {
                           args->flags2 &= ~XFSMNT2_COMPAT_IOSIZE;
                   } else if (!strcmp(this_char, MNTOPT_NOLARGEIO)) {
                           args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
                   } else if (!strcmp(this_char, MNTOPT_ATTR2)) {
                           args->flags |= XFSMNT_ATTR2;
                   } else if (!strcmp(this_char, MNTOPT_NOATTR2)) {
                           args->flags &= ~XFSMNT_ATTR2;
                   } else if (!strcmp(this_char, MNTOPT_FILESTREAM)) {
                           args->flags2 |= XFSMNT2_FILESTREAMS;
                   } else if (!strcmp(this_char, MNTOPT_NOQUOTA)) {
                           args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA);
                           args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA);
                   } else if (!strcmp(this_char, MNTOPT_QUOTA) ||
                              !strcmp(this_char, MNTOPT_UQUOTA) ||
                              !strcmp(this_char, MNTOPT_USRQUOTA)) {
                           args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
                   } else if (!strcmp(this_char, MNTOPT_QUOTANOENF) ||
                              !strcmp(this_char, MNTOPT_UQUOTANOENF)) {
                           args->flags |= XFSMNT_UQUOTA;
                           args->flags &= ~XFSMNT_UQUOTAENF;
                   } else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
                              !strcmp(this_char, MNTOPT_PRJQUOTA)) {
                           args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
                   } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
                           args->flags |= XFSMNT_PQUOTA;
                           args->flags &= ~XFSMNT_PQUOTAENF;
                   } else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
                              !strcmp(this_char, MNTOPT_GRPQUOTA)) {
                           args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
                   } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
                           args->flags |= XFSMNT_GQUOTA;
                           args->flags &= ~XFSMNT_GQUOTAENF;
                   } else if (!strcmp(this_char, MNTOPT_DMAPI)) {
                           args->flags |= XFSMNT_DMAPI;
                   } else if (!strcmp(this_char, MNTOPT_XDSM)) {
                           args->flags |= XFSMNT_DMAPI;
                   } else if (!strcmp(this_char, MNTOPT_DMI)) {
                           args->flags |= XFSMNT_DMAPI;
                   } else if (!strcmp(this_char, "ihashsize")) {
                           cmn_err(CE_WARN,
           "XFS: ihashsize no longer used, option is deprecated.");
                   } else if (!strcmp(this_char, "osyncisdsync")) {
                           /* no-op, this is now the default */
                           cmn_err(CE_WARN,
           "XFS: osyncisdsync is now the default, option is deprecated.");
                   } else if (!strcmp(this_char, "irixsgid")) {
                           cmn_err(CE_WARN,
           "XFS: irixsgid is now a sysctl(2) variable, option is deprecated.");
                   } else {
                           cmn_err(CE_WARN,
                                   "XFS: unknown mount option [%s].", this_char);
                           return EINVAL;
                   }
           }
   
           if (args->flags & XFSMNT_NORECOVERY) {
                   if ((mp->m_flags & XFS_MOUNT_RDONLY) == 0) {
                           cmn_err(CE_WARN,
                                   "XFS: no-recovery mounts must be read-only.");
                           return EINVAL;
                   }
           }
   
           if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) {
                   cmn_err(CE_WARN,
           "XFS: sunit and swidth options incompatible with the noalign option");
                   return EINVAL;
           }
   
           if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
                   cmn_err(CE_WARN,
                           "XFS: cannot mount with both project and group quota");
                   return EINVAL;
           }
   
           if ((args->flags & XFSMNT_DMAPI) && *args->mtpt == '\0') {
                   printk("XFS: %s option needs the mount point option as well\n",
                           MNTOPT_DMAPI);
                   return EINVAL;
           }
   
           if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
                   cmn_err(CE_WARN,
                           "XFS: sunit and swidth must be specified together");
                   return EINVAL;
           }
   
           if (dsunit && (dswidth % dsunit != 0)) {
                   cmn_err(CE_WARN,
           "XFS: stripe width (%d) must be a multiple of the stripe unit (%d)",
                           dswidth, dsunit);
                   return EINVAL;
           }
   
           /*
            * Applications using DMI filesystems often expect the
            * inode generation number to be monotonically increasing.
            * If we delete inode chunks we break this assumption, so
            * keep unused inode chunks on disk for DMI filesystems
            * until we come up with a better solution.
            * Note that if "ikeep" or "noikeep" mount options are
            * supplied, then they are honored.
            */
           if (!(args->flags & XFSMNT_DMAPI) && !ikeep)
                   args->flags |= XFSMNT_IDELETE;
   
           if ((args->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
                   if (dsunit) {
                           args->sunit = dsunit;
                           args->flags |= XFSMNT_RETERR;
                   } else {
                           args->sunit = vol_dsunit;
                   }
                   dswidth ? (args->swidth = dswidth) :
                             (args->swidth = vol_dswidth);
           } else {
                   args->sunit = args->swidth = 0;
           }
   
   done:
           if (args->flags & XFSMNT_32BITINODES)
                   mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
           if (args->flags2)
                   args->flags |= XFSMNT_FLAGS2;
           return 0;
   }
   
   struct proc_xfs_info {
           int     flag;
           char    *str;
   };
   
   STATIC int
   xfs_showargs(
           struct xfs_mount        *mp,
           struct seq_file         *m)
   {
           static struct proc_xfs_info xfs_info_set[] = {
                   /* the few simple ones we can get from the mount struct */
                   { XFS_MOUNT_WSYNC,              "," MNTOPT_WSYNC },
                   { XFS_MOUNT_INO64,              "," MNTOPT_INO64 },
                   { XFS_MOUNT_NOALIGN,            "," MNTOPT_NOALIGN },
                   { XFS_MOUNT_SWALLOC,            "," MNTOPT_SWALLOC },
                   { XFS_MOUNT_NOUUID,             "," MNTOPT_NOUUID },
                   { XFS_MOUNT_NORECOVERY,         "," MNTOPT_NORECOVERY },
                   { XFS_MOUNT_OSYNCISOSYNC,       "," MNTOPT_OSYNCISOSYNC },
                   { XFS_MOUNT_ATTR2,              "," MNTOPT_ATTR2 },
                   { XFS_MOUNT_FILESTREAMS,        "," MNTOPT_FILESTREAM },
                   { XFS_MOUNT_DMAPI,              "," MNTOPT_DMAPI },
                   { XFS_MOUNT_GRPID,              "," MNTOPT_GRPID },
                   { 0, NULL }
           };
           static struct proc_xfs_info xfs_info_unset[] = {
                   /* the few simple ones we can get from the mount struct */
                   { XFS_MOUNT_IDELETE,            "," MNTOPT_IKEEP },
                   { XFS_MOUNT_COMPAT_IOSIZE,      "," MNTOPT_LARGEIO },
                   { XFS_MOUNT_BARRIER,            "," MNTOPT_NOBARRIER },
                   { XFS_MOUNT_SMALL_INUMS,        "," MNTOPT_64BITINODE },
                   { 0, NULL }
           };
           struct proc_xfs_info    *xfs_infop;
   
           for (xfs_infop = xfs_info_set; xfs_infop->flag; xfs_infop++) {
                   if (mp->m_flags & xfs_infop->flag)
                           seq_puts(m, xfs_infop->str);
           }
           for (xfs_infop = xfs_info_unset; xfs_infop->flag; xfs_infop++) {
                   if (!(mp->m_flags & xfs_infop->flag))
                           seq_puts(m, xfs_infop->str);
           }
   
           if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
                   seq_printf(m, "," MNTOPT_ALLOCSIZE "=%dk",
                                   (int)(1 << mp->m_writeio_log) >> 10);
   
           if (mp->m_logbufs > 0)
                   seq_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs);
           if (mp->m_logbsize > 0)
                   seq_printf(m, "," MNTOPT_LOGBSIZE "=%dk", mp->m_logbsize >> 10);
   
           if (mp->m_logname)
                   seq_printf(m, "," MNTOPT_LOGDEV "=%s", mp->m_logname);
           if (mp->m_rtname)
                   seq_printf(m, "," MNTOPT_RTDEV "=%s", mp->m_rtname);
   
           if (mp->m_dalign > 0)
                   seq_printf(m, "," MNTOPT_SUNIT "=%d",
                                   (int)XFS_FSB_TO_BB(mp, mp->m_dalign));
           if (mp->m_swidth > 0)
                   seq_printf(m, "," MNTOPT_SWIDTH "=%d",
                                   (int)XFS_FSB_TO_BB(mp, mp->m_swidth));
   
           if (mp->m_qflags & (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD))
                   seq_puts(m, "," MNTOPT_USRQUOTA);
           else if (mp->m_qflags & XFS_UQUOTA_ACCT)
                   seq_puts(m, "," MNTOPT_UQUOTANOENF);
   
           if (mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD))
                   seq_puts(m, "," MNTOPT_PRJQUOTA);
           else if (mp->m_qflags & XFS_PQUOTA_ACCT)
                   seq_puts(m, "," MNTOPT_PQUOTANOENF);
   
           if (mp->m_qflags & (XFS_GQUOTA_ACCT|XFS_OQUOTA_ENFD))
                   seq_puts(m, "," MNTOPT_GRPQUOTA);
           else if (mp->m_qflags & XFS_GQUOTA_ACCT)
                   seq_puts(m, "," MNTOPT_GQUOTANOENF);
   
           if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
                   seq_puts(m, "," MNTOPT_NOQUOTA);
   
           return 0;
   }
 __uint64_t  __uint64_t
 xfs_max_file_offset(  xfs_max_file_offset(
         unsigned int            blockshift)          unsigned int            blockshift)

Removed from v.1.402  
changed lines
  Added in v.1.403


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>