2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * IRIX inode operations
22 * afs_syscall_icreatename64
35 * afs_syscall_ilistinode64
39 #include <afsconfig.h>
40 #include "afs/param.h"
43 #include "afs/sysincludes.h" /* Standard vendor system headers */
44 #include "afsincludes.h" /* Afs-based standard headers */
45 #include "afs/osi_inode.h"
46 #include "afs/afs_stats.h" /* statistics stuff */
48 #define BAD_IGET -1000
51 * SGI dependent system calls
55 * `INODESPECIAL' type inodes are ones that describe volumes.
57 #define INODESPECIAL 0xffffffff /* ... from ../vol/viceinode.h */
61 afsidestroy(struct inode
*ip
)
64 kmem_free(ip
->i_afs
, sizeof(struct afsparms
));
69 extern int xfs_fstype
;
72 getinode(struct vfs
*vfsp
, dev_t dev
, ino_t inode
, struct inode
**ipp
)
78 igetinode(struct vfs
*vfsp
, dev_t dev
, ino_t inode
, struct inode
**ipp
)
86 #define SET_XFS_ERROR(POS, DEV, INO) \
87 XFS_IGET_EPOS = (POS), XFS_IGET_DEV = (DEV), XFS_IGET_INO = (INO)
90 xfs_getinode(struct vfs
*vfsp
, dev_t dev
, ino_t inode
, struct xfs_inode
**ipp
)
96 vfsp
= vfs_devsearch(dev
, xfs_fstype
);
98 SET_XFS_ERROR(1, dev
, inode
);
103 if (error
= xfs_iget((((struct mount
*)
104 ((vfsp
)->vfs_bh
.bh_first
)->bd_pdata
)), (void *)0,
105 (xfs_ino_t
) inode
, XFS_ILOCK_SHARED
, &ip
,
107 SET_XFS_ERROR(3, vfsp
->vfs_dev
, inode
);
115 /* xfs_igetinode now returns an unlocked inode. This is fine, since we
116 * have a refcount on the holding vnode.
119 xfs_igetinode(struct vfs
*vfsp
, dev_t dev
, ino_t inode
,
120 struct xfs_inode
**ipp
)
122 struct xfs_inode
*ip
;
127 AFS_STATCNT(igetinode
);
130 if (error
= xfs_getinode(vfsp
, dev
, inode
, &ip
)) {
134 xfs_iunlock(ip
, XFS_ILOCK_SHARED
);
136 vattr
.va_mask
= AT_STAT
;
137 AFS_VOP_GETATTR(vp
, &vattr
, 0, OSI_GET_CURRENT_CRED(), error
);
139 SET_XFS_ERROR(4, vp
->v_vfsp
->vfs_dev
, inode
);
143 if (vattr
.va_nlink
== 0 || vattr
.va_type
!= VREG
) {
144 SET_XFS_ERROR(5, vp
->v_vfsp
->vfs_dev
, inode
);
153 /**************************************************************************
154 * inode creation routines.
156 ***************************************************************************/
167 icreate(struct icreateargs
*uap
, rval_t
* rvp
)
173 afs_syscall_icreate(dev
, near_inode
, param1
, param2
, param3
, param4
, rvp
)
174 afs_uint32 dev
, near_inode
, param1
, param2
, param3
, param4
;
180 /* inode creation routines for icreatename64 entry point.
181 * Create a name in the namespace as well as the inode.
184 #include <afs/xfsattrs.h>
185 #include <sys/attributes.h>
187 extern char *int_to_base64(char *, int);
189 /* Lock against races creating/removing directory - vos zap RO, vos create RW*/
190 kmutex_t afs_vol_create_lock
;
191 int afs_vol_create_lock_inited
= 0;
192 #define AFS_LOCK_VOL_CREATE() { \
193 if (!afs_vol_create_lock_inited) { \
194 mutex_init(&afs_vol_create_lock, MUTEX_DEFAULT, \
195 "afs_vol_create_lock"); \
196 afs_vol_create_lock_inited = 1; \
198 mutex_enter(&afs_vol_create_lock); \
200 #define AFS_UNLOCK_VOL_CREATE() mutex_exit(&afs_vol_create_lock)
204 * Create an AFS inode in the XFS name space. If required create the proper
205 * containing directory. See sys/xfsattrs.h for the details on the naming
206 * conventions and the usage of file and directory attributes.
208 * The inode parameters are stored in an XFS attribute called "AFS". In
209 * addition gid is set to XFS_VICEMAGIC and uid is set to the low 31 bits
210 * of the RW volume id. This is so inode verification in iinc and idec
211 * don't need to get the attribute. Note that only the low 31 bits are set.
212 * This is because chmod only accepts up to MAX_UID and chmod is used
213 * to correct these values in xfs_ListViceInodes.
216 xfs_icreatename64(struct vfs
*vfsp
, int datap
, int datalen
,
217 afs_inode_params_t params
, ino_t
* inop
)
219 #define AFS_PNAME_SIZE 16
222 b64_string_t stmp1
, stmp2
;
223 afs_xfs_attr_t attrs
;
225 int name_version
= AFS_XFS_NAME_VERS
;
226 int code
= 0, unused
;
229 int rw_vno
; /* volume ID of parent volume */
236 /* Get vnode for directory which will contain new inode. */
237 if (datalen
>= AFS_PNAME_SIZE
)
240 AFS_COPYINSTR((char *)datap
, path
, AFS_PNAME_SIZE
- 1, &junk
, unused
);
245 rw_vno
= (params
[1] == INODESPECIAL
) ? params
[3] : params
[0];
249 strcat(path
, AFS_INODE_DIR_NAME
);
250 strcat(path
, int_to_base64(stmp1
, rw_vno
));
252 if (params
[1] == INODESPECIAL
)
253 AFS_LOCK_VOL_CREATE();
255 code
= gop_lookupname(path
, AFS_UIOSYS
, FOLLOW
, &dvp
);
256 if (code
== ENOENT
) {
257 /* Maybe it's an old directory name format. */
258 AFS_COPYINSTR((char *)datap
, name
, AFS_PNAME_SIZE
- 1, &junk
, unused
);
260 strcat(name
, int_to_base64(stmp1
, rw_vno
));
261 code
= gop_lookupname(name
, AFS_UIOSYS
, FOLLOW
, &dvp
);
263 /* Use old name format. */
265 name_version
= AFS_XFS_NAME_VERS1
;
269 if (code
== ENOENT
) {
270 afs_xfs_dattr_t dattr
;
271 /* make directory. */
274 AFS_VN_OPEN(path
, UIO_SYSSPACE
, FCREAT
| FEXCL
, 0700, &dvp
,
277 if (code
== EEXIST
) {
278 /* someone beat us to it? */
279 code
= gop_lookupname(path
, AFS_UIOSYS
, NO_FOLLOW
, &dvp
);
282 AFS_UNLOCK_VOL_CREATE();
287 memset(&dattr
, 0, sizeof(dattr
));
288 dattr
.atd_version
= AFS_XFS_ATD_VERS
;
289 dattr
.atd_volume
= rw_vno
;
290 AFS_VOP_ATTR_SET(dvp
, AFS_XFS_DATTR
, (char *)&dattr
,
291 SIZEOF_XFS_DATTR_T
, ATTR_ROOT
| ATTR_CREATE
,
292 OSI_GET_CURRENT_CRED(), code
);
296 (void)vn_remove(path
, UIO_SYSSPACE
, RMDIRECTORY
);
297 AFS_UNLOCK_VOL_CREATE();
302 vattr
.va_mask
= AT_FSID
| AT_NODEID
; /* gets a guick return using FSID */
303 AFS_VOP_GETATTR(dvp
, &vattr
, 0, OSI_GET_CURRENT_CRED(), code
);
309 memset(&attrs
, 0, sizeof(attrs
));
310 attrs
.at_pino
= vattr
.va_nodeid
;
313 /* Create the desired file. Use up to ten tries to create a unique name. */
314 (void)strcpy(name
, path
);
315 (void)strcat(name
, "/.");
316 (void)strcat(name
, int_to_base64(stmp2
, params
[2]));
317 s
= &name
[strlen(name
)];
319 attrs
.at_tag
= 0; /* Initial guess at a unique tag. */
320 for (i
= 0; i
< 10; i
++) {
323 strcat(s
, int_to_base64(stmp1
, attrs
.at_tag
));
325 AFS_VN_OPEN(name
, UIO_SYSSPACE
, FCREAT
| FEXCL
, 0600, &vp
,
327 if (!code
|| code
!= EEXIST
)
332 /* Unlock the creation process since the directory now has a file in it. */
333 if (params
[1] == INODESPECIAL
)
334 AFS_UNLOCK_VOL_CREATE();
337 /* Set attributes. */
338 memcpy((char *)attrs
.at_param
, (char *)params
,
339 sizeof(afs_inode_params_t
));
340 attrs
.at_attr_version
= AFS_XFS_ATTR_VERS
;
341 attrs
.at_name_version
= name_version
;
342 AFS_VOP_ATTR_SET(vp
, AFS_XFS_ATTR
, (char *)&attrs
, SIZEOF_XFS_ATTR_T
,
343 ATTR_ROOT
| ATTR_CREATE
, OSI_GET_CURRENT_CRED(),
347 vattr
.va_uid
= AFS_XFS_VNO_CLIP(params
[0]);
348 vattr
.va_gid
= XFS_VICEMAGIC
;
349 vattr
.va_mask
= AT_MODE
| AT_UID
| AT_GID
;
350 AFS_VOP_SETATTR(vp
, &vattr
, 0, OSI_GET_CURRENT_CRED(), code
);
353 vattr
.va_mask
= AT_NODEID
;
354 AFS_VOP_GETATTR(vp
, &vattr
, 0, OSI_GET_CURRENT_CRED(), code
);
357 *inop
= vattr
.va_nodeid
;
362 /* remove partially created file. */
363 (void)vn_remove(name
, UIO_SYSSPACE
, RMFILE
);
365 /* and directory if volume special file. */
367 AFS_LOCK_VOL_CREATE();
368 (void)vn_remove(path
, UIO_SYSSPACE
, RMDIRECTORY
);
369 AFS_UNLOCK_VOL_CREATE();
375 /* afs_syscall_icreatename64
376 * This is the icreatename64 entry point used by the XFS
380 afs_syscall_icreatename64(int dev
, int datap
, int datalen
, int paramp
,
384 afs_inode_params_t param
;
390 if (!afs_suser(NULL
))
393 vfsp
= vfs_devsearch(dev
, VFS_FSTYPE_ANY
);
398 AFS_COPYIN((char *)paramp
, (char *)param
, sizeof(afs_inode_params_t
),
400 if (vfsp
->vfs_fstype
== xfs_fstype
) {
401 code
= xfs_icreatename64(vfsp
, datap
, datalen
, param
, &ino
);
405 AFS_COPYOUT((char *)&ino
, (char *)inop
, sizeof(ino_t
), code
);
413 * iopen system calls -- open an inode for reading/writing
414 * Restricted to super user.
431 afs_syscall_iopen(int dev
, ino_t inode
, int usrmod
, rval_t
* rvp
)
439 AFS_STATCNT(afs_syscall_iopen
);
440 if (!afs_suser(NULL
))
442 vfsp
= vfs_devsearch(dev
, xfs_fstype
);
446 if (vfsp
->vfs_fstype
== xfs_fstype
) {
447 struct xfs_inode
*xip
;
448 if (error
= xfs_igetinode(vfsp
, (dev_t
) dev
, inode
, &xip
))
451 if (error
= vfile_alloc((usrmod
+ 1) & (FMASK
), &fp
, &fd
)) {
456 osi_Panic("afs_syscall_iopen: bad fstype = %d\n", vfsp
->vfs_fstype
);
464 iopen(struct iopenargs
*uap
, rval_t
* rvp
)
467 return (afs_syscall_iopen
468 (uap
->dev
, (ino_t
) uap
->inode
, uap
->usrmod
, rvp
));
472 iopen64(struct iopenargs64
*uap
, rval_t
* rvp
)
475 return (afs_syscall_iopen
476 (uap
->dev
, (ino_t
) ((uap
->inode_hi
<< 32) | uap
->inode_lo
),
481 * Support for iinc() and idec() system calls--increment or decrement
483 * Restricted to super user.
484 * Only VICEMAGIC type inodes.
489 * XFS iinc/idec code. Uses 64 bit inode numbers.
492 xfs_iincdec64(struct vfs
*vfsp
, ino_t inode
, int inode_p1
, int amount
)
497 afs_xfs_attr_t attrs
;
498 int length
= SIZEOF_XFS_ATTR_T
;
499 afs_xfs_dattr_t dattr
;
505 xfs_iget((((struct mount
*)((vfsp
)->vfs_bh
.bh_first
)->bd_pdata
)),
506 (void *)0, (xfs_ino_t
) inode
, XFS_ILOCK_SHARED
, &ip
,
512 xfs_iunlock(ip
, XFS_ILOCK_SHARED
);
514 vattr
.va_mask
= AT_GID
| AT_UID
| AT_MODE
;
515 AFS_VOP_GETATTR(vp
, &vattr
, 0, OSI_GET_CURRENT_CRED(), code
);
519 if (!code
&& (vattr
.va_gid
!= XFS_VICEMAGIC
))
522 if (!code
&& (AFS_XFS_VNO_CLIP(inode_p1
) != vattr
.va_uid
))
530 nlink
= vattr
.va_mode
& AFS_XFS_MODE_LINK_MASK
;
536 vattr
.va_mode
&= ~AFS_XFS_MODE_LINK_MASK
;
537 vattr
.va_mode
|= nlink
;
538 vattr
.va_mask
= AT_MODE
;
539 AFS_VOP_SETATTR(vp
, &vattr
, 0, OSI_GET_CURRENT_CRED(), code
);
544 b64_string_t stmp1
, stmp2
;
548 length
= SIZEOF_XFS_ATTR_T
;
549 AFS_VOP_ATTR_GET(vp
, AFS_XFS_ATTR
, (char *)&attrs
, &length
, ATTR_ROOT
,
550 OSI_GET_CURRENT_CRED(), code
);
553 if (length
!= SIZEOF_XFS_ATTR_T
554 || attrs
.at_attr_version
!= AFS_XFS_ATTR_VERS
)
557 /* Get the vnode for the directory this file is in. */
561 code
= xfs_getinode(vp
->v_vfsp
, NULL
, attrs
.at_pino
, &ip
);
566 xfs_iunlock(ip
, XFS_ILOCK_SHARED
);
568 /* Verify directory attributes. */
569 length
= SIZEOF_XFS_DATTR_T
;
570 AFS_VOP_ATTR_GET(dvp
, AFS_XFS_DATTR
, (char *)&dattr
, &length
,
571 ATTR_ROOT
, OSI_GET_CURRENT_CRED(), code
);
573 if (length
!= SIZEOF_XFS_DATTR_T
574 || dattr
.atd_version
!= AFS_XFS_ATD_VERS
)
583 strcat(path
, int_to_base64(stmp1
, attrs
.at_param
[2]));
585 strcat(path
, int_to_base64(stmp1
, attrs
.at_tag
));
587 AFS_VOP_REMOVE(dvp
, path
, OSI_GET_CURRENT_CRED(), code
);
591 vattr
.va_mask
= AT_NLINK
;
592 AFS_VOP_GETATTR(dvp
, &vattr
, 0, OSI_GET_CURRENT_CRED(), code2
);
594 if (vattr
.va_nlink
== 2) {
595 vnode_t
*ddvp
; /* parent of volume directory. */
596 /* Try to remove the directory if this is a volume
597 * special file. It's ok to fail.
599 AFS_VOP_LOOKUP(dvp
, "..", &ddvp
, NULL
,
600 0, OSI_GET_CURRENT_RDIR(),
601 OSI_GET_CURRENT_CRED(), code2
);
606 if (attrs
.at_name_version
== AFS_XFS_NAME_VERS2
)
607 strcpy(path
, AFS_INODE_DIR_NAME
);
611 (attrs
.at_param
[1] ==
612 INODESPECIAL
) ? attrs
.
613 at_param
[3] : attrs
.at_param
[0]);
615 AFS_LOCK_VOL_CREATE();
616 AFS_VOP_RMDIR(ddvp
, path
, OSI_GET_CURRENT_CDIR(),
617 OSI_GET_CURRENT_CRED(), code2
);
618 AFS_UNLOCK_VOL_CREATE();
631 iincdec64(int dev
, int inode_hi
, int inode_lo
, int inode_p1
, int amount
)
635 if (!afs_suser(NULL
))
637 vfsp
= vfs_devsearch(dev
, VFS_FSTYPE_ANY
);
642 if (vfsp
->vfs_fstype
== xfs_fstype
) {
647 return xfs_iincdec64(vfsp
, inode
, inode_p1
, amount
);
653 afs_syscall_idec64(int dev
, int inode_hi
, int inode_lo
, int inode_p1
)
655 return iincdec64(dev
, inode_hi
, inode_lo
, inode_p1
, -1);
659 afs_syscall_iinc64(int dev
, int inode_hi
, int inode_lo
, int inode_p1
)
661 return iincdec64(dev
, inode_hi
, inode_lo
, inode_p1
, 1);
671 iinc(struct iincargs
*uap
, rval_t
* rvp
)
678 idec(struct iincargs
*uap
, rval_t
* rvp
)
684 /* afs_syscall_ilistinode64
685 * Gathers up all required info for ListViceInodes in one system call.
688 afs_syscall_ilistinode64(int dev
, int inode_hi
, int inode_lo
, int datap
,
697 afs_xfs_attr_t attrs
;
702 if (!afs_suser(NULL
))
704 vfsp
= vfs_devsearch(dev
, xfs_fstype
);
709 AFS_COPYIN((char *)datalenp
, &idatalen
, sizeof(int), code
);
710 if (idatalen
< sizeof(i_list_inode_t
)) {
711 idatalen
= sizeof(i_list_inode_t
);
712 AFS_COPYOUT((char *)datalenp
, (char *)&idatalen
, sizeof(int), code
);
715 idatalen
= sizeof(i_list_inode_t
);
716 AFS_COPYOUT((char *)datalenp
, (char *)&idatalen
, sizeof(int), code
);
718 AFS_COPYIN((char *)datap
, (char *)&data
, sizeof(i_list_inode_t
), code
);
719 if (data
.ili_version
!= AFS_XFS_ILI_VERSION
) {
720 data
.ili_version
= AFS_XFS_ILI_VERSION
;
721 AFS_COPYOUT((char *)&data
, (char *)datap
, sizeof(i_list_inode_t
),
731 xfs_iget((((struct mount
*)((vfsp
)->vfs_bh
.bh_first
)->bd_pdata
)),
732 (void *)0, (xfs_ino_t
) inode
, XFS_ILOCK_SHARED
, &ip
,
738 xfs_iunlock(ip
, XFS_ILOCK_SHARED
);
740 length
= SIZEOF_XFS_ATTR_T
;
742 AFS_VOP_ATTR_GET(vp
, AFS_XFS_ATTR
, (char *)&attrs
, &length
, ATTR_ROOT
,
743 OSI_GET_CURRENT_CRED(), code
);
749 if (attrs
.at_attr_version
!= AFS_XFS_ATTR_VERS
)
754 vattr
.va_mask
= AT_STAT
;
755 AFS_VOP_GETATTR(vp
, &vattr
, 0, OSI_GET_CURRENT_CRED(), code
);
759 memset(&data
, 0, sizeof(data
));
760 data
.ili_info
.inodeNumber
= inode
;
761 data
.ili_info
.byteCount
= vattr
.va_size
;
762 data
.ili_info
.linkCount
= (vattr
.va_mode
& AFS_XFS_MODE_LINK_MASK
);
763 memcpy((char *)data
.ili_info
.param
, (char *)attrs
.at_param
,
764 sizeof(data
.ili_info
.param
));
765 data
.ili_attr_version
= attrs
.at_attr_version
;
766 data
.ili_name_version
= attrs
.at_name_version
;
767 data
.ili_tag
= attrs
.at_tag
;
768 data
.ili_pino
= attrs
.at_pino
;
769 data
.ili_vno
= vattr
.va_uid
;
770 data
.ili_magic
= vattr
.va_gid
;
771 AFS_COPYOUT((char *)&data
, (char *)datap
, sizeof(data
), code
);