8
8
#include <linux/fs.h>
9
9
#include <linux/ext2_fs.h>
10
10
#include <linux/magic.h>
11
+ #include <linux/namei.h>
11
12
12
13
#include "cache.h"
13
14
#include "xdr3.h"
@@ -220,10 +221,126 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
220
221
}
221
222
222
223
/*
223
- * With NFSv3, CREATE processing is a lot easier than with NFSv2.
224
- * At least in theory; we'll see how it fares in practice when the
225
- * first reports about SunOS compatibility problems start to pour in...
224
+ * Implement NFSv3's unchecked, guarded, and exclusive CREATE
225
+ * semantics for regular files. Except for the created file,
226
+ * this operation is stateless on the server.
227
+ *
228
+ * Upon return, caller must release @fhp and @resfhp.
226
229
*/
230
+ static __be32
231
+ nfsd3_create_file (struct svc_rqst * rqstp , struct svc_fh * fhp ,
232
+ struct svc_fh * resfhp , struct nfsd3_createargs * argp )
233
+ {
234
+ struct iattr * iap = & argp -> attrs ;
235
+ struct dentry * parent , * child ;
236
+ __u32 v_mtime , v_atime ;
237
+ struct inode * inode ;
238
+ __be32 status ;
239
+ int host_err ;
240
+
241
+ if (isdotent (argp -> name , argp -> len ))
242
+ return nfserr_exist ;
243
+ if (!(iap -> ia_valid & ATTR_MODE ))
244
+ iap -> ia_mode = 0 ;
245
+
246
+ status = fh_verify (rqstp , fhp , S_IFDIR , NFSD_MAY_EXEC );
247
+ if (status != nfs_ok )
248
+ return status ;
249
+
250
+ parent = fhp -> fh_dentry ;
251
+ inode = d_inode (parent );
252
+
253
+ host_err = fh_want_write (fhp );
254
+ if (host_err )
255
+ return nfserrno (host_err );
256
+
257
+ fh_lock_nested (fhp , I_MUTEX_PARENT );
258
+
259
+ child = lookup_one_len (argp -> name , parent , argp -> len );
260
+ if (IS_ERR (child )) {
261
+ status = nfserrno (PTR_ERR (child ));
262
+ goto out ;
263
+ }
264
+
265
+ if (d_really_is_negative (child )) {
266
+ status = fh_verify (rqstp , fhp , S_IFDIR , NFSD_MAY_CREATE );
267
+ if (status != nfs_ok )
268
+ goto out ;
269
+ }
270
+
271
+ status = fh_compose (resfhp , fhp -> fh_export , child , fhp );
272
+ if (status != nfs_ok )
273
+ goto out ;
274
+
275
+ v_mtime = 0 ;
276
+ v_atime = 0 ;
277
+ if (argp -> createmode == NFS3_CREATE_EXCLUSIVE ) {
278
+ u32 * verifier = (u32 * )argp -> verf ;
279
+
280
+ /*
281
+ * Solaris 7 gets confused (bugid 4218508) if these have
282
+ * the high bit set, as do xfs filesystems without the
283
+ * "bigtime" feature. So just clear the high bits.
284
+ */
285
+ v_mtime = verifier [0 ] & 0x7fffffff ;
286
+ v_atime = verifier [1 ] & 0x7fffffff ;
287
+ }
288
+
289
+ if (d_really_is_positive (child )) {
290
+ status = nfs_ok ;
291
+
292
+ switch (argp -> createmode ) {
293
+ case NFS3_CREATE_UNCHECKED :
294
+ if (!d_is_reg (child ))
295
+ break ;
296
+ iap -> ia_valid &= ATTR_SIZE ;
297
+ goto set_attr ;
298
+ case NFS3_CREATE_GUARDED :
299
+ status = nfserr_exist ;
300
+ break ;
301
+ case NFS3_CREATE_EXCLUSIVE :
302
+ if (d_inode (child )-> i_mtime .tv_sec == v_mtime &&
303
+ d_inode (child )-> i_atime .tv_sec == v_atime &&
304
+ d_inode (child )-> i_size == 0 ) {
305
+ break ;
306
+ }
307
+ status = nfserr_exist ;
308
+ }
309
+ goto out ;
310
+ }
311
+
312
+ if (!IS_POSIXACL (inode ))
313
+ iap -> ia_mode &= ~current_umask ();
314
+
315
+ host_err = vfs_create (& init_user_ns , inode , child , iap -> ia_mode , true);
316
+ if (host_err < 0 ) {
317
+ status = nfserrno (host_err );
318
+ goto out ;
319
+ }
320
+
321
+ /* A newly created file already has a file size of zero. */
322
+ if ((iap -> ia_valid & ATTR_SIZE ) && (iap -> ia_size == 0 ))
323
+ iap -> ia_valid &= ~ATTR_SIZE ;
324
+ if (argp -> createmode == NFS3_CREATE_EXCLUSIVE ) {
325
+ iap -> ia_valid = ATTR_MTIME | ATTR_ATIME |
326
+ ATTR_MTIME_SET | ATTR_ATIME_SET ;
327
+ iap -> ia_mtime .tv_sec = v_mtime ;
328
+ iap -> ia_atime .tv_sec = v_atime ;
329
+ iap -> ia_mtime .tv_nsec = 0 ;
330
+ iap -> ia_atime .tv_nsec = 0 ;
331
+ }
332
+
333
+ set_attr :
334
+ status = nfsd_create_setattr (rqstp , fhp , resfhp , iap );
335
+
336
+ out :
337
+ fh_unlock (fhp );
338
+ if (child && !IS_ERR (child ))
339
+ dput (child );
340
+ fh_drop_write (fhp );
341
+ return status ;
342
+ }
343
+
227
344
static __be32
228
345
nfsd3_proc_create (struct svc_rqst * rqstp )
229
346
{
@@ -239,9 +356,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp)
239
356
dirfhp = fh_copy (& resp -> dirfh , & argp -> fh );
240
357
newfhp = fh_init (& resp -> fh , NFS3_FHSIZE );
241
358
242
- resp -> status = do_nfsd_create (rqstp , dirfhp , argp -> name , argp -> len ,
243
- & argp -> attrs , newfhp , argp -> createmode ,
244
- (u32 * )argp -> verf , NULL , NULL );
359
+ resp -> status = nfsd3_create_file (rqstp , dirfhp , newfhp , argp );
245
360
return rpc_success ;
246
361
}
247
362
0 commit comments