source: gpfs_3.1_ker2.6.20/lpp/mmfs/src/gpl-linux/kx.c @ 16

Last change on this file since 16 was 16, checked in by rock, 16 years ago
File size: 28.3 KB
Line 
1/***************************************************************************
2 *
3 * Copyright (C) 2001 International Business Machines
4 * All rights reserved.
5 *
6 * This file is part of the GPFS mmfslinux kernel module.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 *  1. Redistributions of source code must retain the above copyright notice,
13 *     this list of conditions and the following disclaimer.
14 *  2. Redistributions in binary form must reproduce the above copyright
15 *     notice, this list of conditions and the following disclaimer in the
16 *     documentation and/or other materials provided with the distribution.
17 *  3. The name of the author may not be used to endorse or promote products
18 *     derived from this software without specific prior written
19 *     permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *************************************************************************** */
33/* @(#)39       1.56.1.2  src/avs/fs/mmfs/ts/kernext/gpl-linux/kx.c, mmfs, avs_rgpfs24, rgpfs24s007a 10/25/06 17:52:27 */
34
35#include <Shark-gpl.h>
36
37#ifdef MODULE
38#include <linux/module.h>
39#endif
40#include <linux/string.h>
41#include <linux/version.h>
42#include <linux/kernel.h>
43#include <linux/errno.h>
44#include <linux/sched.h>
45#include <linux/fs.h>
46#include <linux/dcache.h>
47#include <linux/file.h>
48#include <linux/stat.h>
49#include <linux/fcntl.h>
50
51
52#ifndef GPFS_ARCH_X86_64
53/* grab stuff for madvise */
54#define __KERNEL_SYSCALLS__
55#endif
56#include <linux/unistd.h>
57#include <linux/mman.h>
58
59#include <verdep.h>
60#include <cxiSystem.h>
61#include <cxi2gpfs.h>
62#include <cxiCred.h>
63
64#include <linux2gpfs.h>
65#include <Trace.h>
66#include <cxiMode.h>
67#include <cxiTSFattr.h>
68#include <cxiVFSStats.h>
69
70#ifdef API_32BIT
71
72/* Equivalent structure for stat64 at 32-bit user level (for API remapping) */
73/* gcc doesn't align double words with i386/ia32 like it does for ia64, so
74 * we need to adjust for this. */
75/* Ideally we would include a header file with this definition (ia32.h) instead
76   of defining it ourselves, but this typically breaks things
77   (such as with x86_64). */
78typedef struct stat64_user32 {
79  UInt64 st_dev;
80  UInt32 __pad1;
81  UInt32 __st_ino;
82  UInt32 st_mode;
83  UInt32 st_nlink;
84  UInt32 st_uid;
85  UInt32 st_gid;
86  UInt64 st_rdev;
87  UInt32 __pad2;
88  UInt32 st_size_lower;     /* break up st_size to avoid extra padding */
89  UInt32 st_size_upper;     /* w/ little Endian ordering */
90  UInt32 st_blksize;
91  UInt64 st_blocks;
92  UInt32 st_atime;
93  UInt32 __unused1;
94  UInt32 st_mtime;
95  UInt32 __unused2;
96  UInt32 st_ctime;
97  UInt32 __unused3;
98  UInt64 st_ino;
99} stat64_user32;
100#endif /* API_32BIT */
101
102/* check if inode belongs to GPFS */
103#define GPFS_TYPE(IP) (!(iP) ? false : \
104                        (!(iP->i_sb) ? false : \
105                          (!(iP->i_sb->s_type) ? false : \
106                            !strcmp(iP->i_sb->s_type->name, "gpfs"))))
107
108int
109kxPoll(void* fdListP, int nFDs, int timeoutMS)
110{
111  return -ENOSYS;
112}
113
114int cleanupFD = 0;
115
116extern struct super_block *shutdownSuperP;
117
118#ifdef API_32BIT
119static void
120vstat32(cxiVattr_t *vattrp, struct stat64_user32 *statbuf)
121{
122  ENTER(0);
123  memset(statbuf, 0, sizeof(struct stat64_user32));
124
125  statbuf->st_dev         = vattrp->va_dev;
126  statbuf->st_ino         = vattrp->va_serialno;
127  statbuf->st_mode        = vattrp->va_mode;
128  statbuf->st_nlink       = vattrp->va_nlink;
129  statbuf->st_uid         = vattrp->va_uid;
130  statbuf->st_gid         = vattrp->va_gid;
131  statbuf->st_rdev        = vattrp->va_rdev;
132  statbuf->st_size_upper  = High32(vattrp->va_size);
133  statbuf->st_size_lower  = Low32(vattrp->va_size);
134  statbuf->st_atime       = vattrp->va_atime.tv_sec;
135  statbuf->st_mtime       = vattrp->va_mtime.tv_sec;
136  statbuf->st_ctime       = vattrp->va_ctime.tv_sec;
137  statbuf->st_blksize     = vattrp->va_blocksize;
138  statbuf->st_blocks      = vattrp->va_blocks;
139  /* STAT64_HAS_BROKEN_ST_INO is set on i386 ... */
140  statbuf->__st_ino       = vattrp->va_serialno;
141  EXIT(0);
142}
143#endif /* API_32BIT */
144
145void static
146vstat(cxiVattr_t *vattrp, struct stat64 *statbuf)
147{
148  ENTER(0);
149  memset(statbuf, 0, sizeof(struct stat64));
150
151  statbuf->st_dev         = vattrp->va_dev;
152  statbuf->st_ino         = vattrp->va_serialno;
153  statbuf->st_mode        = vattrp->va_mode;
154  statbuf->st_nlink       = vattrp->va_nlink;
155  statbuf->st_uid         = vattrp->va_uid;
156  statbuf->st_gid         = vattrp->va_gid;
157  statbuf->st_rdev        = vattrp->va_rdev;
158  statbuf->st_size        = vattrp->va_size;
159  statbuf->st_atime       = vattrp->va_atime.tv_sec;
160  statbuf->st_mtime       = vattrp->va_mtime.tv_sec;
161  statbuf->st_ctime       = vattrp->va_ctime.tv_sec;
162  statbuf->st_blksize     = vattrp->va_blocksize;
163  statbuf->st_blocks      = vattrp->va_blocks;
164
165#ifdef STAT64_HAS_BROKEN_ST_INO
166  /* Linux has 2 struct stat64 definitions:
167      1) /usr/include/asm/stat.h
168      2) /usr/include/bits/stat.h
169     Of course, they differ
170      1) st_dev & st_rdev is 2 bytes in (1) and 8 bytes in (2),
171         but the 2 definitions overlap.
172      2) st_ino is 8 bytes in (1) and 4 bytes in (2)
173         and they are in different places!
174    Fortunately, (1) defines an ifdef telling us to assign st_ino
175    to a second variable which just happens to exactly match the
176    definition in (2). */
177  statbuf->__st_ino       = vattrp->va_serialno;
178#endif
179  EXIT(0);
180}
181
182#ifdef GPFS_ARCH_PPC64
183void static
184vstat_ppc64(cxiVattr_t *vattrp, struct stat *statbuf)
185{
186  ENTER(0);
187  memset(statbuf, 0, sizeof(struct stat));
188                                                                               
189  statbuf->st_dev         = vattrp->va_dev;
190  statbuf->st_ino         = vattrp->va_serialno;
191  statbuf->st_mode        = vattrp->va_mode;
192  statbuf->st_nlink       = vattrp->va_nlink;
193  statbuf->st_uid         = vattrp->va_uid;
194  statbuf->st_gid         = vattrp->va_gid;
195  statbuf->st_rdev        = vattrp->va_rdev;
196  statbuf->st_size        = vattrp->va_size;
197  statbuf->st_atime       = vattrp->va_atime.tv_sec;
198  statbuf->st_mtime       = vattrp->va_mtime.tv_sec;
199  statbuf->st_ctime       = vattrp->va_ctime.tv_sec;
200  statbuf->st_blksize     = vattrp->va_blocksize;
201  statbuf->st_blocks      = vattrp->va_blocks;
202  EXIT(0);
203}
204#endif /* GPFS_ARCH_PPC64 */
205
206/* a call to return exact file status information
207 * using the file's pathname;
208 */
209int
210tsstat(char *pathname, struct stat64 *statP)
211{
212  struct gpfsVfsData_t *privVfsP;
213  cxiNode_t *cnP;
214  int code = 0;
215  int rc = 0;
216  struct nameidata nd;
217  struct inode *iP;
218  Boolean relePath = false;
219  cxiVattr_t vattr;
220#ifdef GPFS_ARCH_PPC64
221  struct stat statbuf;
222#else
223  struct stat64 statbuf;
224#endif
225#ifdef API_32BIT
226  stat64_user32 statbuf32;
227#endif
228
229  ENTER(0);
230  if (pathname == NULL || statP == NULL)
231  {
232    code = 1;
233    rc = EINVAL;
234    goto xerror;
235  }
236
237  rc = user_path_walk(pathname, &nd);
238  if (rc)
239  {
240    rc = -rc;
241    code = 2;
242    goto xerror;
243  }
244  relePath = true;
245
246  iP = nd.dentry->d_inode;
247  DBGASSERT(iP != NULL);
248
249  TRACE2(TRACE_VNODE, 1, TRCID_LINUXOPS_TSSTAT_ENTER,
250         "tsstat enter: iP 0x%lX statP 0x%lX\n", iP, statP);
251
252  if (!GPFS_TYPE(iP))
253  {
254    code = 3;
255    rc = EINVAL;
256    goto xerror;
257  }
258
259  privVfsP = VP_TO_PVP(iP);
260  if (privVfsP == NULL)
261  {
262    code = 4;
263    rc = ENOENT;
264    goto xerror;
265  }
266  cnP = VP_TO_CNP(iP);
267
268  rc = gpfs_ops.gpfsGetattr(privVfsP, cnP, &vattr, true);
269  vattr.va_rdev = cxiDev32ToDev(vattr.va_rdev);
270
271  if (rc == 0)
272  {
273#ifdef API_32BIT
274    /* Need to remap? */
275    if (cxiIS64U((char *)statP))
276    {
277      vstat(&vattr, &statbuf);
278
279      rc = cxiCopyOut((char *)&statbuf, (char *)statP, sizeof(struct stat64));
280    }
281    else
282    {
283      /* Need to remap for 32-bit API call */
284      vstat32(&vattr, &statbuf32);
285
286      rc = cxiCopyOut((char *)&statbuf32, (char *)statP,
287                      sizeof(struct stat64_user32));
288    }
289#else
290
291#ifdef GPFS_ARCH_PPC64
292    /* On ppc64, struct stat64 layout is different for a 64-bit user app and
293       kernel, and we can't use it for copying data out.  However, struct stat
294       has the same layout in kernel and 64-bit userspace, and is identical
295       to struct stat64 in 64-bit userspace, so we use it for copyout. */
296    vstat_ppc64(&vattr, &statbuf);
297#else
298    vstat(&vattr, &statbuf);
299#endif
300    rc = cxiCopyOut((char *)&statbuf, (char *)statP, sizeof(statbuf));
301
302#endif /* API_32BIT */
303    if (rc != 0)
304    {
305      code = 5;
306      goto xerror;
307    }
308  }
309
310xerror:
311  if (relePath)
312    path_release(&nd);
313
314  TRACE2(TRACE_VNODE, 1, TRCID_LINUXOPS_TSSTAT_EXIT,
315         "tsstat exit: code %d rc %d\n", code, rc);
316  EXIT(0);
317  return -rc;
318}
319
320int
321tsfstat(int fileDesc, struct stat64 *statP)
322{
323  struct gpfsVfsData_t *privVfsP;
324  cxiNode_t *cnP;
325  struct file *fP;
326  struct inode *iP;
327  int code = 0;
328  int rc;
329  Boolean releFile = false;
330  cxiVattr_t vattr;
331#ifdef GPFS_ARCH_PPC64
332  struct stat statbuf;
333#else
334  struct stat64 statbuf;
335#endif
336#ifdef API_32BIT
337  struct stat64_user32 statbuf32;
338#endif /* API_32BIT */
339
340  ENTER(0);
341  if (statP == NULL)
342  {
343    code = 1;
344    rc = EINVAL;
345    goto xerror;
346  }
347
348  fP = fget(fileDesc);
349  if (!fP)
350  {
351    code = 2;
352    rc = EBADF;
353    goto xerror;
354  }
355  releFile = true;
356
357  iP = fP->f_dentry->d_inode;
358  DBGASSERT(iP != NULL);
359
360  TRACE4(TRACE_VNODE, 1, TRCID_LINUXOPS_TSFSTAT_ENTER,
361         "tsfstat enter: fd %d fP 0x%lX iP 0x%lX statP 0x%lX\n",
362         fileDesc, fP, iP, statP);
363
364  if (!GPFS_TYPE(iP))
365  {
366    code = 3;
367    rc = EINVAL;
368    goto xerror;
369  }
370
371  privVfsP = VP_TO_PVP(iP);
372  if (privVfsP == NULL)
373  {
374    code = 4;
375    rc = ENOENT;
376    goto xerror;
377  }
378  cnP = VP_TO_CNP(iP);
379
380  rc = gpfs_ops.gpfsGetattr(privVfsP, cnP, &vattr, true);
381  vattr.va_rdev = cxiDev32ToDev(vattr.va_rdev);
382
383  if (rc == 0)
384  {
385#ifdef API_32BIT
386    /* Need to remap? */
387    if (cxiIS64U((char *)statP))
388    {
389      vstat(&vattr, &statbuf);
390
391      rc = cxiCopyOut((char *)&statbuf, (char *)statP, sizeof(struct stat64));
392    }
393    else
394    {
395      /* Need to remap for 32-bit API call */
396      vstat32(&vattr, &statbuf32);
397
398      rc = cxiCopyOut((char *)&statbuf32, (char *)statP,
399                      sizeof(struct stat64_user32));
400    }
401#else
402
403#ifdef GPFS_ARCH_PPC64
404    /* On ppc64, struct stat64 layout is different for a 64-bit user app and
405       kernel, and we can't use it for copying data out.  However, struct stat
406       has the same layout in kernel and 64-bit userspace, and is identical
407       to struct stat64 in 64-bit userspace, so we use it for copyout. */
408    vstat_ppc64(&vattr, &statbuf);
409#else
410    vstat(&vattr, &statbuf);
411#endif
412    rc = cxiCopyOut((char *)&statbuf, (char *)statP, sizeof(statbuf));
413
414#endif /* API_32BIT */
415    if (rc != 0)
416    {
417      code = 5;
418      goto xerror;
419    }
420  }
421
422xerror:
423  if (releFile)
424    fput(fP);
425
426  TRACE2(TRACE_VNODE, 1, TRCID_LINUXOPS_TSFSTAT_EXIT,
427         "tsfstat exit: code %d rc %d\n", code, rc);
428  EXIT(0);
429  return -rc;
430}
431
432int
433tsfattr(int fileDesc, int command, void *argP,
434        tsfattrReasonCodeInfo *rCodeP)
435{
436  struct gpfsVfsData_t *privVfsP;
437  cxiNode_t *cnP;
438  struct MMFSVInfo *vinfoP = NULL;
439  ext_cred_t eCred;
440  struct file *fP;
441  struct inode *iP;
442  int reason = 0;
443  int code = 0;
444  int flags;
445  int rc;
446  Boolean releFile = false;
447
448  VFS_STAT_START(tsfattrCall);
449  ENTER(0);
450
451#ifdef SMB_LOCKS_TEST
452  /* hack to test setSMBOplock via tsfattr call */
453  if (command == 999)
454  {
455    int args[2];
456    int oplockGranted;
457    struct file *fP;
458
459    rc = cxiCopyIn((char *)argP, (char *)args, sizeof(args));
460    if (rc)
461      return -rc;
462
463    /* Obtain the file pointer from the descriptor */
464    fP = fget(fileDesc);
465    if (!fP)
466      return -EBADF;
467
468    rc = setSMBOplock(fP, fP->private_data, args[0], args[1],
469                      (void *)0xdeadbeef, &oplockGranted, false);
470
471    fput(fP);
472
473    if (rc)
474      return rc;
475    return oplockGranted;
476  }
477#endif
478
479  /* if rCodeP was specified then immediately reset reason field */
480  if (rCodeP != NULL)
481  {
482    rc = cxiCopyOut((char*)&reason, (char*)&(rCodeP->reason), sizeof(reason));
483    if (rc != 0)
484    {
485      code = 1;
486      goto xerror;
487    }
488  }
489
490  fP = fget(fileDesc);
491  if (!fP)
492  {
493    code = 2;
494    rc = EBADF;
495    goto xerror;
496  }
497  releFile = true;
498
499  iP = fP->f_dentry->d_inode;
500  DBGASSERT(iP != NULL);
501
502  flags = cxiOpenFlagsXlate(fP->f_flags);
503
504  TRACE8(TRACE_VNODE, 1, TRCID_LINUXOPS_TSFATTR_ENTER,
505         "tsfattr enter: fd %d fP 0x%lX f_flags 0x%X flags 0x%X "
506         "iP 0x%lX command %d argP 0x%lX rCodeP 0x%lX\n",
507         fileDesc, fP, fP->f_flags, flags, iP, 
508         command, argP, rCodeP);
509
510  switch (iP->i_mode & S_IFMT)
511  {
512    case S_IFREG:
513    case S_IFDIR:
514      vinfoP = (struct MMFSVInfo *)fP->private_data;
515      break;
516
517    case S_IFLNK:
518    case S_IFBLK:
519    case S_IFCHR:
520    case S_IFIFO:
521    case S_IFSOCK:
522      /* At the moment we do have have any file ops enabled for the
523       * special files on Linux, and thus we don't have an OpenFile object
524       * or vinfoP stored in fP.  This means that a special file can't
525       * have e.g. ACLs associated with it.  Fixing this properly will
526       * require a redesign of our LFS interface.  For now, just fix the
527       * kernel panic caused by invalid vinfoP. */
528      vinfoP = NULL;
529      if ((command != REMOTE_STAT) &&   // UIDREMAP
530          (command != GET_XATTR) &&     // GPFS_LINUX
531          (command != SET_XATTR))       // GPFS_LINUX
532      {
533        code = 5;
534        rc = ENOSYS;
535        goto xerror;
536      }
537      break;
538  }
539
540  if (!GPFS_TYPE(iP))
541  {
542    code = 3;
543    rc = EINVAL;
544    goto xerror;
545  }
546
547  privVfsP = VP_TO_PVP(iP);
548  if (privVfsP == NULL)
549  {
550    code = 4;
551    rc = ENOENT;
552    goto xerror;
553  }
554  cnP = VP_TO_CNP(iP);
555
556  setCred(&eCred);
557
558  rc = gpfs_ops.gpfsFattr(privVfsP, cnP, vinfoP, flags, command, argP,
559                          rCodeP, &eCred);
560
561xerror:
562  if (releFile)
563    fput(fP);
564
565  TRACE2(TRACE_VNODE, 1, TRCID_LINUXOPS_TSFATTR_EXIT,
566         "tsfattr exit: code %d rc %d\n", code, rc);
567
568  VFS_STAT_STOP;
569  EXIT(0);
570  return -rc;
571}
572
573int
574tsfsattr(int command, void *argP)
575{
576  int rc;
577
578  VFS_STAT_START(tsfattrCall);
579  ENTER(0);
580
581  TRACE1(TRACE_VNODE, 1, TRCID_LINUXOPS_TSFSATTR_ENTER,
582        "tsfsattr enter: command %s\n",tsfsattrcmd_id2name(command));
583
584  rc = gpfs_ops.gpfsFsAttr(command, argP);
585
586  TRACE1(TRACE_VNODE, 1, TRCID_LINUXOPS_TSFSATTR_EXIT,
587         "tsfsattr exit: rc %d\n", rc);
588
589  VFS_STAT_STOP;
590  EXIT(0);
591  return -rc;
592}
593
594int
595tsattr(char *pathname, int command, void *argP,
596       tsfattrReasonCodeInfo *rCodeP)
597{
598  struct gpfsVfsData_t *privVfsP;
599  cxiNode_t *cnP;
600  int code = 0;
601  int rc = 0;
602  int reason = 0;       /* local reason code for resetting caller's */
603  ext_cred_t eCred;
604  struct nameidata nd;
605  struct inode *iP;
606  Boolean relePath = false;
607
608  /* if rCodeP was specified then immediately reset reason field */
609  ENTER(0);
610  if (rCodeP != NULL)
611  {
612    rc = cxiCopyOut((char*)&reason, (char*)&(rCodeP->reason), sizeof(reason));
613    if (rc != 0)
614    {
615      code = 1;
616      goto xerror;
617    }
618  }
619
620  rc = user_path_walk(pathname, &nd);
621  if (rc)
622  {
623    rc = -rc;
624    code = 2;
625    goto xerror;
626  }
627  relePath = true;
628
629  iP = nd.dentry->d_inode;
630  DBGASSERT(iP != NULL);
631
632  TRACE4(TRACE_VNODE, 1, TRCID_LINUXOPS_TSATTR_ENTER,
633         "tsattr enter: iP 0x%lX command %d argP 0x%lX rCodeP 0x%lX\n",
634         iP, command, argP, rCodeP);
635
636  if (!GPFS_TYPE(iP))
637  {
638    code = 3;
639    rc = EINVAL;
640    goto xerror;
641  }
642
643  privVfsP = VP_TO_PVP(iP);
644  if (privVfsP == NULL)
645  {
646    code = 4;
647    rc = ENOENT;
648    goto xerror;
649  }
650  cnP = VP_TO_CNP(iP);
651
652  setCred(&eCred);
653  rc = gpfs_ops.gpfsFattr(privVfsP, cnP, NULL, 0, command, argP, rCodeP,
654                          &eCred);
655
656xerror:
657  if (relePath)
658    path_release(&nd);
659
660  TRACE2(TRACE_VNODE, 1, TRCID_LINUXOPS_TSATTR_EXIT,
661         "tsattr exit: code %d rc %d\n", code, rc);
662
663  EXIT(0);
664  return -rc;
665}
666
667int
668kxGetACL(char *pathname, int flags, void *aclP)
669{
670  int rc = 0;
671  int code = 0;
672  cxiNode_t *cnP;
673  struct gpfsVfsData_t *privVfsP;
674  ext_cred_t eCred;
675  struct nameidata nd;
676  struct inode *iP;
677  Boolean relePath = false;
678
679  /* Verify input exists */
680  ENTER(0);
681  if (pathname == NULL || aclP == NULL)
682  {
683    code = 1;
684    rc = EINVAL;
685    goto xerror;
686  }
687
688  rc = user_path_walk(pathname, &nd);
689  if (rc)
690  {
691    rc = -rc;
692    code = 2;
693    goto xerror;
694  }
695  relePath = true;
696
697  iP = nd.dentry->d_inode;
698  DBGASSERT(iP != NULL);
699
700  if (!GPFS_TYPE(iP))
701  {
702    code = 3;
703    rc = EINVAL;
704    goto xerror;
705  }
706
707  privVfsP = VP_TO_PVP(iP);
708  if (privVfsP == NULL)
709  {
710    code = 4;
711    rc = ENOENT;
712    goto xerror;
713  }
714
715  cnP = VP_TO_CNP(iP);
716
717  /* Retrieve the ACL data */
718  setCred(&eCred);
719  rc = gpfs_ops.gpfsGetAcl(privVfsP, cnP, flags, aclP, &eCred);
720
721xerror:
722  if (relePath)
723    path_release(&nd);
724
725  TRACE2(TRACE_VNODE, 1, TRCID_LINUXOPS_KXGETACL_EXIT,
726         "kxGetACL exit: code %d rc %d\n", code, rc);
727  EXIT(0);
728  return -rc;
729}
730
731int
732kxPutACL(char *pathname, int flags, void *aclP)
733{
734  int rc = 0;
735  int code = 0;
736  cxiNode_t *cnP;
737  struct gpfsVfsData_t *privVfsP;
738  ext_cred_t eCred;
739  struct nameidata nd;
740  struct inode *iP;
741  Boolean relePath = false;
742
743  /* Verify input exists */
744  ENTER(0);
745  if (pathname == NULL || aclP == NULL)
746  {
747    code = 1;
748    rc = EINVAL;
749    goto xerror;
750  }
751
752  rc = user_path_walk(pathname, &nd);
753  if (rc)
754  {
755    rc = -rc;
756    code = 2;
757    goto xerror;
758  }
759  relePath = true;
760
761  iP = nd.dentry->d_inode;
762  DBGASSERT(iP != NULL);
763
764  if (!GPFS_TYPE(iP))
765  {
766    code = 3;
767    rc = EINVAL;
768    goto xerror;
769  }
770
771  privVfsP = VP_TO_PVP(iP);
772  if (privVfsP == NULL)
773  {
774    code = 4;
775    rc = ENOENT;
776    goto xerror;
777  }
778
779  cnP = VP_TO_CNP(iP);
780
781  /* Put the ACL data */
782  setCred(&eCred);
783  rc = gpfs_ops.gpfsPutAcl(privVfsP, cnP, flags, aclP, &eCred);
784
785xerror:
786  if (relePath)
787    path_release(&nd);
788
789  TRACE2(TRACE_VNODE, 1, TRCID_LINUXOPS_KXPUTACL_EXIT,
790         "kxPutACL exit: code %d rc %d\n", code, rc);
791  EXIT(0);
792  return -rc;
793}
794
795#if !defined(GPFS_ARCH_X86_64) && !defined(GPFS_ARCH_IA64)
796/* madvise is handled as a kernel extension / ioctl call until support
797   is provided by glibc */
798//static inline _syscall3(int,madvise,void*,addr,size_t,len,int,advice);
799#endif
800
801int
802kxMadvise(void* addr, size_t len, int advice)
803{
804#if defined(GPFS_ARCH_X86_64) || defined(GPFS_ARCH_IA64)
805  /* kxMadvise should never be called since glibc has madvice */
806  return -ENOSYS;
807#else
808//  return madvise(addr, len, advice);
809//    return stub_syscall2(__NR_madvise, len, advice);
810//    return sys_madvise(addr, len, advice);
811  return -ENOSYS;
812#endif
813}
814
815/* Get the kernel thread ID. */
816cxiThreadId
817kxGetThreadID()
818{
819  return (cxiThreadId)current->pid;
820}
821
822#ifdef GPFS_QUOTACTL
823int kxQuotactl(char *pathname, int cmd, int qid, void *bufferP)
824{
825  int rc = 0;
826  int code = 0;
827  cxiNode_t *cnP;
828  struct gpfsVfsData_t *privVfsP;
829  ext_cred_t  eCred;
830  ext_cred_t *credP = NULL;
831  struct nameidata nd;
832  struct inode *iP;
833  Boolean relePath = false;
834  ulong len;
835
836  ENTER(0);
837
838  TRACE4(TRACE_VNODE, 2, TRCID_LINUXOPS_TSQUOTACTL_K,
839         "kxQuotactl: enter cmd 0x%x, qid %d, pathname 0x%x, euid %d\n",
840          cmd, qid, pathname, current->euid);
841
842  /* Verify input exists */
843  if (pathname == NULL)
844  {
845    code = 1; // EBUF_ERROR
846    rc = EINVAL;
847    goto xerror;
848  }
849
850  TRACE0(TRACE_VNODE, 2, TRCID_LINUXOPS_TSQUOTACTL_K1,
851       "kxQuotactl at [1]\n");
852
853  rc = user_path_walk(pathname, &nd);
854
855  TRACE1(TRACE_VNODE, 2, TRCID_LINUXOPS_TSQUOTACTL_K2,
856        "kxQuotactl at [2] user_path_walk rc %d\n",
857         rc);
858
859  if (rc)
860  {
861    rc = -rc;
862    code = 3;
863    goto xerror;
864  }
865
866  relePath = true;
867
868  iP = nd.dentry->d_inode;
869  DBGASSERT(iP != NULL);
870
871  if (!GPFS_TYPE(iP))
872  {
873    code = 3;
874    rc = EINVAL;
875    goto xerror;
876  }
877
878  privVfsP = VP_TO_PVP(iP);
879  if (privVfsP == NULL)
880  {
881    code = 4;
882    rc = ENOENT;
883    goto xerror;
884  }
885
886  cnP = VP_TO_CNP(iP);
887
888  setCred(&eCred);
889  credP = &eCred;
890 
891  TRACE4(TRACE_VNODE, 2, TRCID_LINUXOPS_TSQUOTACTL_K6,
892         "kxQuotactl: gpfs_ops.gpfsQuotactl, cmd 0x%x, qid %d, credP 0x%x, bufferP 0x%x\n",
893         cmd, qid, credP, bufferP);
894
895  rc = gpfs_ops.gpfsQuotactl(privVfsP, cmd, qid, bufferP, credP);
896
897  TRACE1(TRACE_VNODE, 2, TRCID_LINUXOPS_TSQUOTACTL_K7,
898         "kxQuotactl: gpfs_ops.gpfsQuotactl rc %d\n", rc);
899xerror:
900  if (relePath)
901    path_release(&nd);
902
903  TRACE3(TRACE_VNODE, 1, TRCID_LINUXOPS_TSQUOTACTL_EXIT,
904         "kxQuotactl exit: code %d rc %d, pathname %s\n", 
905         code, rc, pathname ? pathname : "?");
906
907  EXIT(0);
908
909  return -rc;
910}
911#endif /* GPFS_QUOTACTL */
912
913#ifdef SMB_LOCKS
914/* Exchange control between Samba, GPFS */
915int
916setSMBOpenLockControl(void *vP, void *infoP, int command, int lockmode)
917{
918  struct inode *iP;
919  struct gpfsVfsData_t *privVfsP;
920  struct MMFSVInfo *vinfoP;
921  struct file *fP = (struct file *)vP;
922  int rc = EINVAL;
923
924  ENTER(0);
925
926  TRACE2(TRACE_VNODE, 9, TRCID_SMBOPENLOCKCONTROL_ENTERL,
927         "setSMBOpenLockControl entry - command %d, mode 0x%x",
928         command, lockmode);
929
930  vinfoP = (struct MMFSVInfo *)fP->private_data;
931
932  iP = fP->f_dentry->d_inode;
933  DBGASSERT(iP != NULL);
934
935  if (!GPFS_TYPE(iP))
936  {
937    rc = 0;
938    goto xerror;
939  }
940
941  privVfsP = VP_TO_PVP(iP);
942
943  rc = gpfs_ops.SMBOpenLockControl(command, lockmode, iP->i_ino, vinfoP,
944                                   privVfsP);
945
946xerror:
947
948  TRACE1(TRACE_VNODE, 1, TRCID_SMBOPENLOCKCONTROL_EXITL,
949         "setSMBOpLockControl exit: rc %d\n", rc);
950
951  EXIT(0);
952  return (rc);
953}
954
955#include <oplock.h>
956#include <asm/uaccess.h>
957int
958setSMBOplock(void *vP, void *infoP, int accessWant, int oplockWant,
959             void *breakArgP, int *oplockGrantedP, Boolean isAsync)
960{
961  struct file *filp = (struct file *)vP;
962  struct gpfsVfsData_t *privVfsP;
963  cxiNode_t *cnP;
964  struct MMFSVInfo *vinfoP;
965  struct file *fP;
966  struct inode *iP;
967  int reason = 0;
968  int code = 0;
969  int flags;
970  int rc;
971  Boolean releFile = false;
972
973  /* get file pointer and inode */
974  ENTER(0);
975  fP = filp;
976  if (!fP)
977  {
978    code = 2;
979    rc = EBADF;
980    goto xerror;
981  }
982
983  get_file(fP);
984
985  releFile = true;
986
987  vinfoP = (struct MMFSVInfo *)fP->private_data;
988
989  iP = fP->f_dentry->d_inode;
990  DBGASSERT(iP != NULL);
991
992  TRACE5(TRACE_VNODE, 1, TRCID_LINUXOPS_SETSMBOPLOCK_E,
993         "setSMBOplock enter: fP 0x%lX acc %d oplock %d argP 0x%lX async %d\n",
994         fP, accessWant, oplockWant, breakArgP, isAsync);
995
996  if (!GPFS_TYPE(iP))
997  {
998    code = 3;
999    rc = EINVAL;
1000    goto xerror;
1001  }
1002
1003  privVfsP = VP_TO_PVP(iP);
1004  if (privVfsP == NULL)
1005  {
1006    code = 4;
1007    rc = ENOENT;
1008    goto xerror;
1009  }
1010  cnP = VP_TO_CNP(iP);
1011
1012  rc = gpfs_ops.gpfsSetSMBOplock(privVfsP, cnP, vinfoP, accessWant, oplockWant,
1013                                 breakArgP, oplockGrantedP, isAsync);
1014
1015xerror:
1016  if (releFile)
1017    fput(fP);
1018
1019  TRACE2(TRACE_VNODE, 1, TRCID_LINUXOPS_SETSMBOPLOCK_X,
1020         "setSMBOplock exit: granted %d rc %d", *oplockGrantedP, rc);
1021
1022  EXIT(0);
1023  return -rc;
1024}
1025
1026/* Share/Delegate interface for Samba */
1027int
1028kxGetShare(int fd, unsigned int share, unsigned int deny)
1029{
1030  int rc;
1031  struct file *fP = NULL;
1032  struct inode *iP;
1033  struct MMFSVInfo *vinfoP;
1034  struct gpfsVfsData_t *privVfsP;
1035  int shareWant;
1036
1037  /* To be called from our Samba vfs_op library only. */
1038  ENTER(0);
1039  if (!cxiIsSambaThread())
1040  {
1041    rc = EPERM;
1042    goto xerror;
1043  }
1044
1045  fP = fget(fd);
1046  if (!fP || !fP->f_dentry || !fP->f_dentry->d_inode)
1047  {
1048    rc = EINVAL;
1049    goto xerror;
1050  }
1051
1052  vinfoP = (struct MMFSVInfo *)fP->private_data;
1053
1054  iP = fP->f_dentry->d_inode;
1055  if (!iP || !(privVfsP = VP_TO_PVP(iP)))
1056  {
1057    rc = EBADF;
1058    goto xerror;
1059  }
1060
1061  if (!GPFS_TYPE(iP))
1062  {
1063    rc = 0;
1064    goto xerror;
1065  }
1066
1067  shareWant = ALLOW_SHARE_DELETE;
1068
1069  TRACE6(TRACE_VNODE, 1, TRCID_LINUX_SHARE_ENTER,
1070         "kxGetShare: enter fd %d fP 0x%lX ino %d infoP 0x%lX access 0x%X "
1071         "deny 0x%X\n", fd, fP, iP->i_ino, vinfoP, share, deny);
1072
1073  /* Translate (and validate) the Samba share/deny arguments to our shareWant */
1074
1075  rc = EINVAL; /* setup for XLATE_SAMBA_ACCESS/DENY */
1076
1077  XLATE_SAMBA_ACCESS(share, shareWant);
1078  XLATE_SAMBA_DENY(deny, shareWant);
1079
1080  /* Call to make the reservation */
1081  if ((share != 0) || (deny != 0))
1082    rc = gpfs_ops.gpfsReserveShare(fP, vinfoP, privVfsP, 0, shareWant, NULL,NULL);
1083  else
1084    rc = 0;
1085
1086  /* give back any pre-existing rights */
1087  if ((rc == 0) && (0 != (coMask & ~shareWant)))
1088    rc = gpfs_ops.gpfsReserveShare(fP, vinfoP, privVfsP, RESERVE_DOWNGRADE, 
1089                                   coMask & ~shareWant, NULL, NULL);
1090xerror:
1091  if (fP)
1092    fput(fP);
1093
1094  TRACE1(TRACE_VNODE, 1, TRCID_LINUX_SHARE_EXIT, 
1095         "kxGetShare: exit rc %d\n", rc);
1096
1097  EXIT(0);
1098  return -rc;
1099}
1100
1101int
1102kxGetDelegation(int fd, unsigned int delegate_access,
1103                void *cb_token, void *cookie)
1104{
1105  int rc = 0;
1106  int code = 0;
1107  int flags = 0;
1108  struct file *fP = NULL;
1109  struct inode *iP;
1110  struct MMFSVInfo *vinfoP;
1111  struct gpfsVfsData_t *privVfsP;
1112  int oplockWant;
1113
1114  /* To be called from our Samba vfs_op library only. */
1115  ENTER(0);
1116  if (!cxiIsSambaThread())
1117  {
1118    rc = EPERM;
1119    goto xerror;
1120  }
1121
1122#if 0
1123  /* As long as Samba write leases are not as strict as NFSv4 write
1124     delegations (are not required to be revoked on stat) we can
1125     allow them.
1126  */
1127  if (delegate_access == CXI_DELEGATE_WRITE)
1128  {
1129    rc = EOPNOTSUPP;
1130    goto xerror;
1131  }
1132#endif
1133
1134  fP = fget(fd);
1135  if (!fP || !fP->f_dentry || !fP->f_dentry->d_inode)
1136  {
1137    rc = EINVAL;
1138    goto xerror;
1139  }
1140
1141  vinfoP = (struct MMFSVInfo *)fP->private_data;
1142
1143  iP = fP->f_dentry->d_inode;
1144  if (!iP || !(privVfsP = VP_TO_PVP(iP)))
1145  {
1146    rc = EBADF;
1147    goto xerror;
1148  }
1149
1150  if (!GPFS_TYPE(iP))
1151  {
1152    rc = 0;
1153    goto xerror;
1154  }
1155
1156
1157  TRACE5(TRACE_VNODE, 1, TRCID_DELEGATE_ENTER,
1158         "kxGetDelegation: enter fd %d fP 0x%lX ino %d vinfoP 0x%lX "
1159         "delegate 0x%x\n", fd, fP, iP->i_ino, vinfoP, delegate_access);
1160
1161  /* Translate (and validate) the Samba delegate argument to our oplock flags */
1162
1163  /* setup for XLATE_SAMBA_DELEGATE */
1164  rc = EINVAL;
1165  oplockWant = 0;
1166
1167  if (delegate_access == CXI_DELEGATE_NONE)
1168    flags = RESERVE_DOWNGRADE;
1169
1170  XLATE_SAMBA_DELEGATE(delegate_access, oplockWant);
1171
1172  rc = gpfs_ops.gpfsReserveDelegation(fP, vinfoP, privVfsP, oplockWant, 
1173                                      flags, iP, NULL);
1174
1175xerror:
1176  if (fP)
1177    fput(fP);
1178
1179  TRACE1(TRACE_VNODE, 1, TRCID_DELEGATE_EXIT,
1180         "kxGetDelegation: exit rc %d\n", rc);
1181
1182  EXIT(0);
1183  return -rc;
1184}
1185#endif
1186
1187/* called from umount helper before calling umount system call  */
1188
1189#define UMOUNT_BEGIN 0
1190#define UMOUNT_END 1
1191int kxUMount(int type, char *pathname, int force, int *ret_err)
1192{
1193    char kxnode[CXI_MAXPATHLEN+1];
1194    int rc = 0;
1195    int dmrc = 0;
1196    int code = 0;
1197    ulong len;
1198    struct cxiNode_t  *cnP = NULL;
1199    struct gpfsVfsData_t *privVfsP = NULL;
1200    void       *ndP = NULL;
1201    Boolean doDMEvents = false;
1202
1203    ENTER(0);
1204    rc = cxiCopyInstr(pathname, kxnode, CXI_MAXPATHLEN, &len);
1205    LOGASSERT(rc == 0);
1206    TRACE4(TRACE_VNODE, 1, TRCID_KXUMOUNT_ENT,
1207         "kxUMount: enter type %d path %s force %d  ret_err %d\n",
1208          type,kxnode,force,*ret_err);
1209   
1210#ifdef DMAPI
1211    rc = cxiPathToVfsP((void **)&privVfsP,pathname, &ndP, (void **)&cnP, true);
1212    if (rc)
1213    {
1214      code = 1;
1215      goto exit;
1216    }         
1217   
1218    /* Generate PREUNMOUNT event for normal mounts. For force unmount
1219     it is generated from gpfs_s_umount_begin.
1220     umount helper calls with UMOUNT_BEGIN before calling umount
1221     system call.
1222    */
1223
1224    if ( type == UMOUNT_BEGIN && !force)
1225    {
1226       dmrc = gpfs_ops.gpfsDmUnmountEvent(true,force,privVfsP,cnP,
1227                                        &doDMEvents, NULL, NULL, NULL, 0);
1228       if (doDMEvents )
1229         *ret_err = 1;
1230       else
1231         *ret_err = 0;
1232    }
1233
1234  /*
1235    umount helper calls with UMOUNT_END if umount system call fails.
1236    */
1237
1238    if ( type == UMOUNT_END )
1239       dmrc = gpfs_ops.gpfsDmUnmountEvent(false,force,privVfsP,cnP,
1240                                     &doDMEvents, NULL, NULL, NULL, *ret_err);
1241
1242#endif
1243exit:
1244    if (ndP)
1245      cxiPathRel(ndP);
1246
1247    TRACE4(TRACE_VNODE, 1, TRCID_KXUMOUNT_EXT,
1248         "kxUMount: exit dmrc %d  ret_err %d rc %d code %d\n",
1249          dmrc,*ret_err,rc,code);
1250     EXIT(0);
1251     return rc;
1252}
1253
1254
Note: See TracBrowser for help on using the repository browser.