~n-muench/ubuntu/precise/open-vm-tools/open-vm-tools.raring-precise.backport

« back to all changes in this revision

Viewing changes to lib/syncDriver/syncDriverLinux.c

  • Committer: Package Import Robot
  • Author(s): Nate Muench
  • Date: 2012-01-23 16:09:45 UTC
  • mfrom: (1.4.6) (2.4.26 sid)
  • Revision ID: package-import@ubuntu.com-20120123160945-b6s0r1vkcovucpf3
Tags: 2011.12.20-562307-0ubuntu1
* Merge latest upstream git tag. Fixes building on Precise
  (LP: #898289, LP: #905612)

* Items merged from Debian unstable:
  - debian/control:
    + open-vm-tools recommends open-vm-dkms. (LP: #598933)
    + open-vm-tools now suggests open-vm-toolbox. (LP: #604998)
  (From 2011.08.21-471295-1 release)
  - Updating maintainer and uploaders fields.
  - Removing vcs fields.
  - Removing references to Daniel's old email address.
  - Updating years in copyright file.
  - Updating to standards version 3.9.2.
  - Updating to debhelper version 8.
  - Switching to source format 3.0 (quilt).
  - Removing manual chrpath setting.
  - Removing exclusion from plugins from debhelper shlibs.
  - Rediffing kvers.patch.
  (From 2011.09.23-491607-1 release)
  - Marking binary architecture-dependend packages as linux and kfreebsd
  only.
  - Removing liburiparser-dev from build-depends as upstream dropped
  unity support.
  - Building with libproc-dev on amd64 again.
  - Dropping disabling of dnet support.
  (From 2011.09.23-491607-2 release)
  - Adding doxygen to build-depends for api documentation.
  - Adding libcunit1-dev to build-depends for test suites.
  - Minimizing rules file.
  - Adding open-vm-tools-dev package, containing only the api
    documentation for now.
  (From 2011.09.23-491607-3 release)
  - Sorting overrides in rules alphabetically.
  - Compacting copyright file.
  - Adding udev rule to set timeout for vmware scsi devices
  (From 2011.12.20-562307-1 release)
  - Adding patch to correct typo in upstreams dkms configuration

* Remaining Changes:
  - Remove Stable part of version numbering.
  - debian folder:
    + Re-added open-vm-dkms.postinst & open-vm-dkms.prerm.
      * Allows dkms modules to compile upon installation.
  - debian/control:
    + Re-add open-vm-source and make into a transitional package
      for open-vm-toolbox.
    + Return dependancies that were moved to open-vm-tools back to
      open-vm-toolbox.
  - debian/rules and debian/open-vm-toolbox.lintian-overrides:
    + Make vmware-user-suid-wrapper suid-root
  - debian/rules:
    + Added CFLAGS field with -Wno-deprecated-declarations
      * Will suppress issues with glib 2.31 or later.
    + Add line to copy vmware-xdg-detect-de into place.
    + Install vmware-user.desktop through toolbox package.
  - debian/open-vm-tools.init:
    + Re-add 'modprobe [-r] vmblock'.
    + Add 'modprobe [-r] vmxnet'.
      * Incase it's not loaded during boot.
    + Remove and re-add pcnet32 module
      * Will be done before (remove) and after (readd) vmxnet module
        is added.
      * If vmxnet doesn't exist (aka modules fail to build), pcnet32 can be
        still used for network connectivity.
      * Workaround until a better fix can be done.
  - Re-add gnome-session to debian/local/xautostart.conf
  - Manpages removed (from debian/manpages):
    + vmmemctl.9
    + vmxnet3.9
    + Remove references to manpages that have been removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 2011 VMware, Inc. All rights reserved.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of the GNU Lesser General Public License as published
 
6
 * by the Free Software Foundation version 2.1 and no later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
10
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
 
11
 * License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public License
 
14
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 
15
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/**
 
20
 * @file syncDriverLinux.c
 
21
 *
 
22
 * A sync driver backend that uses the Linux "FIFREEZE" and "FITHAW" ioctls
 
23
 * to freeze and thaw file systems.
 
24
 */
 
25
 
 
26
#include <errno.h>
 
27
#include <fcntl.h>
 
28
#include <stdlib.h>
 
29
#include <string.h>
 
30
#include <unistd.h>
 
31
#include <linux/fs.h>
 
32
#include <sys/ioctl.h>
 
33
#include "debug.h"
 
34
#include "dynbuf.h"
 
35
#include "strutil.h"
 
36
#include "syncDriverInt.h"
 
37
 
 
38
/* Out toolchain headers are somewhat outdated and don't define these. */
 
39
#if !defined(FIFREEZE)
 
40
#  define FIFREEZE        _IOWR('X', 119, int)    /* Freeze */
 
41
#  define FITHAW          _IOWR('X', 120, int)    /* Thaw */
 
42
#endif
 
43
 
 
44
 
 
45
typedef struct LinuxDriver {
 
46
   SyncHandle  driver;
 
47
   size_t      fdCnt;
 
48
   int        *fds;
 
49
} LinuxDriver;
 
50
 
 
51
 
 
52
/*
 
53
 *******************************************************************************
 
54
 * LinuxFiThaw --                                                         */ /**
 
55
 *
 
56
 * Thaws the file systems monitored by the given handle. Tries to thaw all the
 
57
 * file systems even if an error occurs in one of them.
 
58
 *
 
59
 * @param[in] handle Handle returned by the freeze call.
 
60
 *
 
61
 * @return A SyncDriverErr.
 
62
 *
 
63
 *******************************************************************************
 
64
 */
 
65
 
 
66
static SyncDriverErr
 
67
LinuxFiThaw(const SyncDriverHandle handle)
 
68
{
 
69
   size_t i;
 
70
   LinuxDriver *sync = (LinuxDriver *) handle;
 
71
   SyncDriverErr err = SD_SUCCESS;
 
72
 
 
73
   for (i = 0; i < sync->fdCnt; i++) {
 
74
      if (ioctl(sync->fds[i], FITHAW) == -1) {
 
75
         err = SD_ERROR;
 
76
      }
 
77
   }
 
78
 
 
79
   return err;
 
80
}
 
81
 
 
82
 
 
83
/*
 
84
 *******************************************************************************
 
85
 * LinuxFiClose --                                                        */ /**
 
86
 *
 
87
 * Closes the file descriptors used for freezing, and frees memory associated
 
88
 * with the handle.
 
89
 *
 
90
 * @param[in] handle Handle to close.
 
91
 *
 
92
 *******************************************************************************
 
93
 */
 
94
 
 
95
static void
 
96
LinuxFiClose(SyncDriverHandle handle)
 
97
{
 
98
   LinuxDriver *sync = (LinuxDriver *) handle;
 
99
   size_t i;
 
100
 
 
101
   for (i = 0; i < sync->fdCnt; i++) {
 
102
      close(sync->fds[i]);
 
103
   }
 
104
   free(sync->fds);
 
105
   free(sync);
 
106
}
 
107
 
 
108
 
 
109
/*
 
110
 *******************************************************************************
 
111
 * LinuxDriver_Freeze --                                                  */ /**
 
112
 *
 
113
 * Tries to freeze the filesystems using the Linux kernel's FIFREEZE ioctl.
 
114
 *
 
115
 * If the first attempt at using the ioctl fails, assume that it doesn't exist
 
116
 * and return SD_UNAVAILABLE, so that other means of freezing are tried.
 
117
 *
 
118
 * @param[in]  paths    Paths to freeze (colon-separated).
 
119
 * @param[out] handle   Handle to use for thawing.
 
120
 *
 
121
 * @return A SyncDriverErr.
 
122
 *
 
123
 *******************************************************************************
 
124
 */
 
125
 
 
126
SyncDriverErr
 
127
LinuxDriver_Freeze(const char *paths,
 
128
                   SyncDriverHandle *handle)
 
129
{
 
130
   char *path;
 
131
   int fd;
 
132
   size_t count = 0;
 
133
   unsigned int index = 0;
 
134
   Bool first = TRUE;
 
135
   DynBuf fds;
 
136
   LinuxDriver *sync = NULL;
 
137
   SyncDriverErr err = SD_SUCCESS;
 
138
 
 
139
   DynBuf_Init(&fds);
 
140
 
 
141
   Debug(LGPFX "Freezing using Linux ioctls...\n");
 
142
 
 
143
   sync = calloc(1, sizeof *sync);
 
144
   if (sync == NULL) {
 
145
      return SD_ERROR;
 
146
   }
 
147
 
 
148
   sync->driver.thaw = LinuxFiThaw;
 
149
   sync->driver.close = LinuxFiClose;
 
150
 
 
151
   /*
 
152
    * Iterate through the requested paths. If we get an error for the first
 
153
    * path, and it's not EPERM, assume that the ioctls are not available in
 
154
    * the current kernel.
 
155
    */
 
156
   while ((path = StrUtil_GetNextToken(&index, paths, ":")) != NULL) {
 
157
      fd = open(path, O_RDONLY);
 
158
      if (fd == -1) {
 
159
         switch (errno) {
 
160
         case EACCES:
 
161
            /*
 
162
             * We sometimes get access errors to virtual filesystems mounted
 
163
             * as users with permission 700, so just ignore these.
 
164
             */
 
165
            Debug(LGPFX "cannot access mounted directory '%s'.\n", path);
 
166
            free(path);
 
167
            continue;
 
168
 
 
169
         case EIO:
 
170
            /*
 
171
             * A mounted HGFS filesystem with the backend disabled will give
 
172
             * us these; probably could use a better way to detect HFGS, but
 
173
             * this should be enough. Just skip.
 
174
             */
 
175
            Debug(LGPFX "I/O error reading directory '%s'.\n", path);
 
176
            free(path);
 
177
            continue;
 
178
 
 
179
         default:
 
180
            Debug(LGPFX "failed to open '%s': %d (%s)\n",
 
181
                  path, errno, strerror(errno));
 
182
            err = SD_ERROR;
 
183
            free(path);
 
184
            goto exit;
 
185
         }
 
186
      }
 
187
 
 
188
      if (ioctl(fd, FIFREEZE) == -1) {
 
189
         int ioctlerr = errno;
 
190
         /*
 
191
          * If the ioctl does not exist, Linux will return ENOTTY. If it's not
 
192
          * supported on the device, we get EOPNOTSUPP. Ignore the latter,
 
193
          * since freezing does not make sense for all fs types, and some
 
194
          * Linux fs drivers may not have been hooked up in the running kernel.
 
195
          *
 
196
          * Also ignore EBUSY since we may try to freeze the same superblock
 
197
          * more than once depending on the OS configuration (e.g., usage of
 
198
          * bind mounts).
 
199
          */
 
200
         close(fd);
 
201
         if (ioctlerr != EBUSY && ioctlerr != EOPNOTSUPP) {
 
202
            Debug(LGPFX "failed to freeze '%s': %d (%s)\n",
 
203
                  path, ioctlerr, strerror(ioctlerr));
 
204
            err = first && ioctlerr == ENOTTY ? SD_UNAVAILABLE : SD_ERROR;
 
205
            free(path);
 
206
            break;
 
207
         }
 
208
      } else {
 
209
         Debug(LGPFX "successfully froze '%s'.\n", path);
 
210
         if (!DynBuf_Append(&fds, &fd, sizeof fd)) {
 
211
            if (ioctl(fd, FITHAW) == -1) {
 
212
               Warning(LGPFX "failed to thaw '%s': %d (%s)\n",
 
213
                       path, errno, strerror(errno));
 
214
            }
 
215
            free(path);
 
216
            close(fd);
 
217
            err = SD_ERROR;
 
218
            break;
 
219
         }
 
220
         count++;
 
221
      }
 
222
 
 
223
      free(path);
 
224
      first = FALSE;
 
225
   }
 
226
 
 
227
exit:
 
228
   sync->fds = DynBuf_Detach(&fds);
 
229
   sync->fdCnt = count;
 
230
 
 
231
   if (err != SD_SUCCESS) {
 
232
      LinuxFiThaw(&sync->driver);
 
233
      LinuxFiClose(&sync->driver);
 
234
   } else {
 
235
      *handle = &sync->driver;
 
236
   }
 
237
   return err;
 
238
}
 
239