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 * afs_vnop_dirops.c - make and remove directories
20 #include <afsconfig.h>
21 #include "afs/param.h"
26 #include "afs/sysincludes.h" /* Standard vendor system headers */
27 #include "afsincludes.h" /* Afs-based standard headers */
28 #include "afs/afs_stats.h" /* statistics */
29 #include "afs/afs_cbqueue.h"
30 #include "afs/nfsclient.h"
31 #include "afs/afs_osidnlc.h"
33 extern afs_rwlock_t afs_xvcache;
34 extern afs_rwlock_t afs_xcbhash;
36 /* don't set CDirty in here because RPC is called synchronously */
39 afs_mkdir(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
40 register struct vcache **avcp, struct AFS_UCRED *acred)
43 register afs_int32 code;
44 register struct conn *tc;
45 struct VenusFid newFid;
46 register struct dcache *tdc;
47 afs_size_t offset, len;
48 register struct vcache *tvc;
49 struct AFSStoreStatus InStatus;
50 struct AFSFetchStatus OutFidStatus, OutDirStatus;
51 struct AFSCallBack CallBack;
52 struct AFSVolSync tsync;
54 struct afs_fakestat_state fakestate;
58 AFS_STATCNT(afs_mkdir);
59 afs_Trace2(afs_iclSetp, CM_TRACE_MKDIR, ICL_TYPE_POINTER, adp,
60 ICL_TYPE_STRING, aname);
62 if ((code = afs_InitReq(&treq, acred)))
64 afs_InitFakeStat(&fakestate);
66 if (strlen(aname) > AFSNAMEMAX) {
71 if (!afs_ENameOK(aname)) {
78 code = afs_EvalFakeStat(&adp, &fakestate, &treq);
81 code = afs_VerifyVCache(adp, &treq);
85 /** If the volume is read-only, return error without making an RPC to the
88 if (adp->states & CRO) {
93 if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
94 /*printf("Network is down in afs_mkdir\n");*/
98 InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE | AFS_SETGROUP;
99 InStatus.ClientModTime = osi_Time();
100 InStatus.UnixModeBits = attrs->va_mode & 0xffff; /* only care about protection bits */
101 InStatus.Group = (afs_int32) acred->cr_gid;
102 tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);
103 ObtainWriteLock(&adp->lock, 153);
105 tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
107 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_MAKEDIR);
111 RXAFS_MakeDir(tc->id, (struct AFSFid *)&adp->fid.Fid, aname,
112 &InStatus, (struct AFSFid *)&newFid.Fid,
113 &OutFidStatus, &OutDirStatus, &CallBack,
117 CallBack.ExpirationTime += now;
118 /* DON'T forget to Set the callback value... */
122 (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_MAKEDIR,
127 ObtainWriteLock(&afs_xcbhash, 490);
128 afs_DequeueCallback(adp);
129 adp->states &= ~CStatd;
130 ReleaseWriteLock(&afs_xcbhash);
131 osi_dnlc_purgedp(adp);
133 ReleaseWriteLock(&adp->lock);
138 /* otherwise, we should see if we can make the change to the dir locally */
140 ObtainWriteLock(&tdc->lock, 632);
141 if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
142 /* we can do it locally */
143 ObtainWriteLock(&afs_xdcache, 294);
144 code = afs_dir_Create(tdc, aname, &newFid.Fid);
145 ReleaseWriteLock(&afs_xdcache);
147 ZapDCE(tdc); /* surprise error -- use invalid value */
152 ReleaseWriteLock(&tdc->lock);
155 adp->m.LinkCount = OutDirStatus.LinkCount;
156 newFid.Cell = adp->fid.Cell;
157 newFid.Fid.Volume = adp->fid.Fid.Volume;
158 ReleaseWriteLock(&adp->lock);
159 /* now we're done with parent dir, create the real dir's cache entry */
160 tvc = afs_GetVCache(&newFid, &treq, NULL, NULL);
169 afs_PutFakeStat(&fakestate);
170 code = afs_CheckCode(code, &treq, 26);
177 /* don't set CDirty in here because RPC is called synchronously */
178 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
179 afs_rmdir(OSI_VC_DECL(adp), char *aname, struct vnode *cdirp,
180 struct AFS_UCRED *acred)
182 afs_rmdir(OSI_VC_DECL(adp), char *aname, struct AFS_UCRED *acred)
185 struct vrequest treq;
186 register struct dcache *tdc;
187 register struct vcache *tvc = NULL;
188 register afs_int32 code;
189 register struct conn *tc;
190 afs_size_t offset, len;
191 struct AFSFetchStatus OutDirStatus;
192 struct AFSVolSync tsync;
193 struct afs_fakestat_state fakestate;
197 AFS_STATCNT(afs_rmdir);
199 afs_Trace2(afs_iclSetp, CM_TRACE_RMDIR, ICL_TYPE_POINTER, adp,
200 ICL_TYPE_STRING, aname);
202 if ((code = afs_InitReq(&treq, acred)))
204 afs_InitFakeStat(&fakestate);
206 if (strlen(aname) > AFSNAMEMAX) {
213 code = afs_EvalFakeStat(&adp, &fakestate, &treq);
217 code = afs_VerifyVCache(adp, &treq);
221 /** If the volume is read-only, return error without making an RPC to the
224 if (adp->states & CRO) {
229 if (AFS_IS_DISCONNECTED && !AFS_IS_LOGGING) {
234 tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1); /* test for error below */
235 ObtainWriteLock(&adp->lock, 154);
237 ObtainSharedLock(&tdc->lock, 633);
238 if (tdc && (adp->states & CForeign)) {
239 struct VenusFid unlinkFid;
241 unlinkFid.Fid.Vnode = 0;
242 code = afs_dir_Lookup(tdc, aname, &unlinkFid.Fid);
244 afs_int32 cached = 0;
246 unlinkFid.Cell = adp->fid.Cell;
247 unlinkFid.Fid.Volume = adp->fid.Fid.Volume;
248 if (unlinkFid.Fid.Unique == 0) {
250 afs_LookupVCache(&unlinkFid, &treq, &cached, adp, aname);
252 ObtainReadLock(&afs_xvcache);
253 tvc = afs_FindVCache(&unlinkFid, 0, 1 /* do xstats */ );
254 ReleaseReadLock(&afs_xvcache);
260 tc = afs_Conn(&adp->fid, &treq, SHARED_LOCK);
262 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEDIR);
265 RXAFS_RemoveDir(tc->id, (struct AFSFid *)&adp->fid.Fid, aname,
266 &OutDirStatus, &tsync);
272 (tc, code, &adp->fid, &treq, AFS_STATS_FS_RPCIDX_REMOVEDIR,
277 ReleaseSharedLock(&tdc->lock);
281 ObtainWriteLock(&afs_xcbhash, 491);
282 afs_DequeueCallback(adp);
283 adp->states &= ~CStatd;
284 ReleaseWriteLock(&afs_xcbhash);
285 osi_dnlc_purgedp(adp);
287 ReleaseWriteLock(&adp->lock);
290 /* here if rpc worked; update the in-core link count */
291 adp->m.LinkCount = OutDirStatus.LinkCount;
293 UpgradeSToWLock(&tdc->lock, 634);
294 if (afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
295 /* we can do it locally */
296 code = afs_dir_Delete(tdc, aname);
298 ZapDCE(tdc); /* surprise error -- invalid value */
303 ReleaseWriteLock(&tdc->lock);
304 afs_PutDCache(tdc); /* drop ref count */
309 osi_dnlc_purgedp(tvc); /* get rid of any entries for this directory */
311 osi_dnlc_remove(adp, aname, 0);
314 ObtainWriteLock(&tvc->lock, 155);
315 tvc->states &= ~CUnique; /* For the dfs xlator */
316 ReleaseWriteLock(&tvc->lock);
319 ReleaseWriteLock(&adp->lock);
320 /* don't worry about link count since dirs can not be hardlinked */
326 afs_PutFakeStat(&fakestate);
327 code = afs_CheckCode(code, &treq, 27);